@dmitrievMV

Как сделать глобальный фильтр который проверит ModelState?

Можно ли создать аттрибут для екшена который будет всегда проверять валидность входящей модели? чтоб не писать в каждом екшене
if (!ModelState.IsValid)
            {
                return View(vm);
            }
написал вот такой фильтр
public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.Controller.ViewData.ModelState.IsValid == false)
            {
                filterContext.Result = new ViewResult();
            }
        }
    }
но он теряет модель, и тогда весь смысл теряется.
  • Вопрос задан
  • 218 просмотров
Решения вопроса 1
@dmitrievMV Автор вопроса
Я понял в чем моя ошибка.
Во 1 я уверен что у меня на выходе всегда одно представление.
Во 2 я уверен что это представление принимает модель которая входит.
В 3 я уверен что входит только 1 параметр.
А это не всегда так. В общем если принять во внимание такие условия то у меня вышел такой фильтр:
public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.Controller.ViewData.ModelState.IsValid == false)
            {
                if (filterContext.ActionParameters.Count == 1)
                {
                    filterContext.Controller.ViewData.Model = filterContext.ActionParameters.FirstOrDefault().Value;
                    filterContext.Result = new ViewResult
                    {
                        ViewData = filterContext.Controller.ViewData
                    };
                }
                else
                {
                    throw new HttpException(400, "validation model error");
                }
            }
        }
    }


Входящая модель находится в filterContext.ActionParameters словаре. В ViewData можно положить новый ViewDataDictionary передав в его конструктор модель но тогда потеряем ошибки валидации. Попробую использовать такой фильтр, может его нужно будет доработать.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
yamaoto
@yamaoto
la programmeur
Предлагаю вот такую связку
//фильтр для валидации
public class ValidateModelAttribute: Attribute, IActionFilter
    {
        public bool AllowMultiple { get; } = false;

        public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext,
            CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            //примерно таким способом у меня все работает
            if (!actionContext.ModelState.IsValid)
            {
                // получаем ошибки валидации по пути actionContext.ModelState[0..i].Error[0..j].ErrorMessage
                var errors = (
                    from error in actionContext.ModelState
                    select new ErrorData("", error.Value.Errors[0].ErrorMessage) {Subject = error.Key}).ToArray();
                throw new MyAwesomeValidationException("0x015", "Ошибка валидации") {ErrorData = errors};
            }
            return null;
        }
    }
//фильтр для ошибок
 public class MyAwesomeExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            var result = new ApiResult<ErrorData[]>() { Result = false };
            var sp= actionExecutedContext.Exception as MyAwesomeException;
            if (sp!= null)
            {
                result.Error = sp.Message;
                result.ErrorCode = sp.Code;
                result.Data = sp.ErrorData;
            }
            else
            {
                result.Error = actionExecutedContext.Exception.Message;
                result.ErrorCode = "";
            }
            actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.OK);
            actionExecutedContext.Response.Content = new ObjectContent<ApiResult<ErrorData[]>>(result,new JsonMediaTypeFormatter());            
        }
    }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы