Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.0] ChangeSets and Data Validation #705

Open
cilerler opened this issue Mar 19, 2022 · 2 comments
Open

[2.0] ChangeSets and Data Validation #705

cilerler opened this issue Mar 19, 2022 · 2 comments
Milestone

Comments

@cilerler
Copy link
Contributor

cilerler commented Mar 19, 2022

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);
	}
}
@robertmclaws
Copy link
Collaborator

I'm not sure about why they designed it this way. The only way to make OriginalValues work in the pipeline is to load up the original object from the database, and then use the submitted data to then play the modifications and understand the differences.

This is the first implementation I've seen of anyone trying to use it the way it was designed. In my company's libraries, we do this sort of validation through the OnInserting/OnUpdating methods.

I would be interested in seeing if this architecture makes sense, because adding a database lookup on every call would slow the response rate down quite a bit.

@robertmclaws robertmclaws added this to the 2.0 milestone Dec 5, 2023
@robertmclaws
Copy link
Collaborator

robertmclaws commented Dec 5, 2023

We need to take a hard look at ChangeSets going into v2.

  • They should track the changes made through the pipeline process.
  • They should be able to load the values currently persisted in the DB (perhaps with a lock, if possible).
  • They should work well with Batches.
  • We should get rid of this stuff unless it's necessary.

If I come up with more "requirements" here, I'll add them.

@robertmclaws robertmclaws changed the title dataModificationItem.OriginalValues doesn't get filled [2.0] ChangeSets and Data Validation Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

2 participants