Как я могу централизовать валидацию modelstate в asp.net mvc с помощью фильтров действий?
Я пишу этот код в нескольких местах и всегда повторяю эту логику:
public ActionResult MyMethod(MyModel collection)
{
if (!ModelState.IsValid)
{
return Json(false);//to read it from javascript, it always equal
}
else
{
try
{
//logic here
return Json(true);//or Json(false);
}
catch
{
return Json(false);//to read it from javascript, it always equal
}
}
}
Есть ли способ использования фильтров действий, чтобы не повторять try-catch
, спросить, действительна ли модель и return Json(false)
как ActionResult
?
Ответы
Ответ 1
Чтобы соответствовать REST, вы должны вернуть http bad request 400, чтобы указать, что неверный запрос (модель недопустима) вместо возврата Json(false)
.
Попробуйте этот атрибут из официальный сайт asp.net для веб-api:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
Версия для asp.net mvc может быть такой:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.Controller.ViewData.ModelState.IsValid)
{
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
}
}
Ответ 2
Если вы хотите сделать это в MVC6 или Mvc Core и не указав свой атрибут во всех своих методах действий, тогда вы это сделаете.
Сначала создайте ActionFilter
public class ModelStateValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting( ActionExecutingContext context )
{
if ( context.HttpContext.Request.Method == "POST" && !context.ModelState.IsValid )
context.Result = new BadRequestObjectResult( context.ModelState );
}
}
Теперь создайте соглашение, в котором вы будете применять этот ActionFilter ко всем вашим контроллерам.
public class ModelStateValidatorConvension : IApplicationModelConvention
{
public void Apply( ApplicationModel application )
{
foreach ( var controllerModel in application.Controllers )
{
controllerModel.Filters.Add( new ModelStateValidationFilterAttribute() );
}
}
}
И последнее, что нужно зарегистрировать это соглашение в MVC
public void ConfigureServices( IServiceCollection services )
{
services.Configure<MvcOptions>( x => x.Conventions.Add( new ModelStateValidatorConvension() ) );
}
Ответ 3
Вот как использовать код от Khanh TO (от официальный сайт asp.net):
Чтобы применить этот фильтр ко всем контроллерам веб-API, добавьте экземпляр фильтра в коллекцию HttpConfiguration.Filters во время конфигурации:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new ValidateModelAttribute());
// ...
}
}
Другой вариант - установить фильтр как атрибут для отдельных контроллеров или действий контроллера:
public class ProductsController : ApiController
{
[ValidateModel]
public HttpResponseMessage Post(Product product)
{
// ...
}
}