M
M
Mikhail2016-10-24 10:28:46
ASP.NET
Mikhail, 2016-10-24 10:28:46

How to make a global filter that checks ModelState?

Is it possible to create an attribute for an action that will always check the validity of the incoming model? so as not to write in every action

if (!ModelState.IsValid)
            {
                return View(vm);
            }
wrote this filter
public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.Controller.ViewData.ModelState.IsValid == false)
            {
                filterContext.Result = new ViewResult();
            }
        }
    }
but he loses the model, and then the whole meaning is lost.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Mikhail, 2016-10-24
@dmitrievMV

I figured out what my mistake is.
In 1, I am sure that I always have one view at the output.
In 2 I am sure that this view accepts the model that is included.
In 3, I'm sure that only 1 parameter is included.
And this is not always the case. In general, if we take into account such conditions, then I got the following filter:

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");
                }
            }
        }
    }

The incoming model is in the filterContext.ActionParameters dictionary. In ViewData, you can put a new ViewDataDictionary by passing a model to its constructor, but then we will lose validation errors. I'll try to use such a filter, maybe it will need to be finalized.

A
Anatoliy Mikhailov, 2016-10-24
@yamaoto

I propose this link

//фильтр для валидации
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());            
        }
    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question