Started reading https://support.aspnetzero.com/QA/Questions/2583 and could not find a way to open it again.
When sending a list or array of complex objects ABP will let you know the index of the object and the property that is having issues, I am trying to use ICustomValidate to hook up to this behavior and check for duplicates on the data, among other things that need a roundtrip to the DB
eg:
public class AddSkuInput : ICustomValidate
{
[MaxLength(35)]
[Required]
public string Sku { get; set; }
public void AddValidationErrors(CustomValidationContext context)
{
var skuManager = context.IocResolver.Resolve<ISkuManager>();
var productTypeManager = context.IocResolver.Resolve<IProductTypeManager>();
try
{
AsyncHelper.RunSync(() => skuManager.ValidateDuplicateSkuAsync(Sku));
}
catch (UserFriendlyException e)
{
context.Results.Add(new ValidationResult(e.Message));
}
}
}
//for brevity this is the ValidateDuplicateSkuAsync Method
public async Task ValidateDuplicateSkuAsync(string input)
{
if (await _skuRepository.GetAll().AnyAsync(p => p.Sku == input))
{
throw new UserFriendlyException($"SKU {input} already exists.");
}
}
With or without AsyncHelper it produces DbContext.Disposed Errors
Users normally send 100s of these items and I would like to deal with the majority of errors in batches too so I'd like to maintain the validation error structure like this response example:
{
"result": null,
"targetUrl": null,
"success": false,
"error": {
"code": 0,
"message": "Your request is not valid!",
"details": "The following errors were detected during validation.\r\n - The Sku field is required.\r\n - The Upc field is required.\r\n - The Upc field is required.\r\n",
"validationErrors": [
{
"message": "The Sku field is required.",
"members": [
"[0].Sku"
]
},
{
"message": "The Upc field is required.",
"members": [
"[0].Upc"
]
},
{
"message": "The Upc field is required.",
"members": [
"[1].Upc"
]
}
]
},
"unAuthorizedRequest": false,
"__abp": true
}
If keeping Database access out of the DTO is a must, how can i access the ValidationContext after the method has reached the AppService (or the DomainService) as I'd like to maintain the DataAnnotations style error result through every validation process.
3 Answer(s)
-
0
Hi @rbarbosa
You can manually begin a unitOfWork in ValidateDuplicateSkuAsync as exmplained here https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work#iunitofworkmanager.
You can also consider using DbLevel unique index for preventing duplicate records.
-
0
Thank you @ismcagdas that solves the UOW issue. Happy new year!
However I dont seem to be able to find a way to get the index of the property's parent when an array of them are being sent, as shown here:
https://github.com/aspnetboilerplate/aspnetboilerplate/blob/master/src/Abp.Web.Api/WebApi/Validation/WebApiActionInvocationValidator.cs#L33
public void AddValidationErrors(CustomValidationContext context) { var skuManager = context.IocResolver.Resolve<ISkuManager>(); var productTypeManager = context.IocResolver.Resolve<IProductTypeManager>(); // var actionContext = context.IocResolver.Resolve<HttpActionContext>(); try { AsyncHelper.RunSync(() => skuManager.ValidateDuplicateSkuAsync(Sku)); } catch (UserFriendlyException e) { context.Results.Add(new ValidationResult(e.Message, new[] {"Sku" })); } }
{ "result": null, "targetUrl": null, "success": false, "error": { "code": 0, "message": "Your request is not valid!", "details": "The following errors were detected during validation.\r\n - SKU duplicateSku already exists.\r\n - UPC: duplicateUpc already exists for a different SKU\r\n - Division: BadDivision not found.\r\n - SKU duplicateSku already exists.\r\n - UPC: duplicateUPC already exists for a different SKU\r\n", "validationErrors": [ { "message": "SKU duplicateSku already exists.", "members": [ "sku" ] }, { "message": "UPC: duplicateUpc already exists for a different SKU", "members": null }, { "message": "Division: badDivision not found.", "members": null }, { "message": "SKU duplicateSku already exists.", "members": [ "sku" ] }, { "message": "UPC: duplicateUpc already exists for a different SKU", "members": null } ] }, "unAuthorizedRequest": false, "__abp": true }
is it better to abandon this validation style?
-
0
I think it is because you are not providing the second parameter when adding ValidationResult;
context.Results.Add(new ValidationResult(e.Message));
If there will be 100s of items in request or requests, I would try to find another approach for validation. In that case, this approach will slow down your requests.