OData / OData/RESTier

[2.0] ChangeSets and Data Validation

Open
#705 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
481
Forks
136
PR merge metrics
No merged PRs in 30d

Description

In CustomizedValidator implementation, LocalValues reflects the change requests and Resource reflects the object's last state as expected, but the OriginalValues doesn't get filled which makes it impossible to compare old and new data for validation purposes.

csproj
<PackageReference Include="Microsoft.Restier.AspNetCore" Version="1.0.0-ci-20211128-172920" />
<PackageReference Include="Microsoft.Restier.EntityFrameworkCore" Version="1.0.0-ci-20211128-172920" />
startup.cs
routeServices.AddChainedService<IChangeSetItemFilter, CustomizedSubmitProcessor>();
CustomizedValidator.cs
public class CustomizedValidator : IChangeSetItemValidator
{
	private IChangeSetItemValidator Inner { get; set; }

	public Task ValidateChangeSetItemAsync(SubmitContext context, ChangeSetItem item, Collection<ChangeSetItemValidationResult> validationResults, CancellationToken cancellationToken)
	{
		if (item is not DataModificationItem dataModificationItem)
		{
			return Inner.ValidateChangeSetItemAsync(context, item, validationResults, cancellationToken);
		}

		object entity = dataModificationItem.Resource;
		bool isNewRequest = dataModificationItem.OriginalValues == null && dataModificationItem.ResourceKey == null;
		bool isUpdateRequest = dataModificationItem.OriginalValues != null && dataModificationItem.LocalValues != null;
		bool isDeleteRequest = dataModificationItem.LocalValues == null;

		if (isUpdateRequest && entity is Organization organization)
		{
			dataModificationItem.LocalValues.TryGetValue("ParentId",out object localValueParentId);
			dataModificationItem.OriginalValues.TryGetValue("ParentId", out object originalValueParentId);
			bool changeExists = localValueParentId is not null && originalValueParentId is not null && localValueParentId != originalValueParentId;

			if (organization.ParentId is not null && !changeExists)
			{
				var changeSetValidationResult = new ChangeSetItemValidationResult
				{
					Message = "You can not change this record's `ParentId`.  It is not `null`.",
					Severity = EventLevel.Error,
					PropertyName = dataModificationItem.ResourceSetName + dataModificationItem.ResourceKey,
					Target = entity
				};
				validationResults.Add(changeSetValidationResult);
			}
			using (var service = context.GetApiService<SmartProcureApi>())
			{
				var existingRecordParentId = service.DbContext.Organizations.Where(o => o.Id.Equals(organization.Id)).FirstOrDefault()?.ParentId;
				if (existingRecordParentId != null && organization.ParentId!=existingRecordParentId)
				{

				}
			}
		}

		return Inner.ValidateChangeSetItemAsync(context, item, validationResults, cancellationToken);
	}
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with CustomizedValidator.cs and the DataModificationItem values described in the report, using the csproj package references and startup.cs registration to reproduce the change-set validation path. Inspect why OriginalValues is null while LocalValues and Resource are populated; done means validators can compare old and new data for update requests.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.