Код: Выделить всё
[HttpPost]
public async Task ValidateTestFormAsync([FromBody] ValidationRequest
personValidationRequest)
{
Request.EnableBuffering();
Request.Body.Seek(0, SeekOrigin.Begin);
string requestContent;
using (var reader = new StreamReader(Request.Body, Encoding.UTF8, true, 1024, true))
{
requestContent = await reader.ReadToEndAsync();
}
return Json(requestContent);
}
Код: Выделить всё
app.Use((context, next) =>
{
context.Request.EnableBuffering();
return next();
});
По сути, я просто пытаюсь запустить пользовательская проверка, при которой я удаляю любые сообщения об ошибках для полей/свойств, которые не были отправлены в сообщении, поскольку MVC всегда проверяет полную модель, и я пытаюсь выполнить POST поле за полем, чтобы объединить их с клиентской библиотекой, которую я пишу.< /p>
РЕДАКТИРОВАТЬ:
Я пытался сфокусировать этот вопрос, но вот полный объем:
Код: Выделить всё
[HttpPost]
public async Task ValidateTestFormAsync([FromBody] ValidationRequest
personValidationRequest)
{
return Json(personValidationRequest.ToValidationResponse(ModelState));
}
public static class ValidationResponeFormatter
{
///
/// Takes a validation request of a model along with the current validated modelState and performs validation on the entire model including
/// calling .Validate (nullifying the default MVC short circuiting). TBD: Remove validation errors that weren't actually posted.
///
/// The model of the data to be validated, which has either validation attributes, a custom validation method via implementing
/// IValidatableObject, or both.
/// The validation request formatted as required for svl to use.
/// The model state supplied from the controller action.
///
public static ValidationResponse ToValidationResponse(this ValidationRequest request, ModelStateDictionary modelState) where T : class
{
var response = new ValidationResponse
{
Request = request
};
if(modelState.IsValid)
{
return response;
}
foreach (var validationError in modelState)
{
//trims the first nested key since the keys will always be pre-pended with Fields. due to the nesting of the model inside a ValidationRequest
var responseError = new FieldValidationError() { Field = validationError.Key.Split('.')[1] };
foreach (var error in validationError.Value.Errors)
{
if (!string.IsNullOrEmpty(error.ErrorMessage))
{
responseError.Failures.Add(error.ErrorMessage);
}
if (error.Exception != null)
{
responseError.Failures.AddRange(error.Exception.GetNestedExceptions());
}
}
response.Errors.Add(responseError);
}
//Default validation short circuits if any validation attributes fail, the modelState would then only have attribute validation errors.
//The below block manually includes any custom validations, nullifying that short circuiting.
if (typeof(T).GetInterface(nameof(IValidatableObject)) != null)
{
var validationContext = new ValidationContext(request.Fields);
var manualValidations = ((IValidatableObject)request.Fields).Validate(validationContext).ToList();
foreach (var validatedField in manualValidations)
{
//get error for only the first member name, otherwise the same error would be shown for two fields.
var memberName = validatedField.MemberNames.FirstOrDefault();
var existingFieldError = response.Errors.FirstOrDefault(x => x.Field == memberName);
if(existingFieldError == null)
{
//all errors not assigned to a specific property/field get categorized under a _default area
//to avoid this be sure to declare a membername when yielding ValidationResults in your custom Validate method
existingFieldError = new FieldValidationError() { Field = memberName ?? "_default" };
response.Errors.Add(existingFieldError);
}
//adds the validation message if it doesn't already exist, which is possible if the default model validation did not encounter
//any attribute validation failures, then the custom validate method would have already run
if(existingFieldError.Failures.All(x => x != validatedField.ErrorMessage) && !string.IsNullOrEmpty(validatedField.ErrorMessage))
{
existingFieldError.Failures.Add(validatedField.ErrorMessage);
}
}
}
return response;
}
public static IEnumerable GetNestedExceptions(this Exception ex)
{
if (ex == null)
{
throw new ArgumentNullException("GetNestedExceptions exception parameter is null");
}
var innerException = ex;
do
{
yield return innerException.Message;
innerException = innerException.InnerException;
}
while (innerException != null);
}
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... out-middle