Search code examples
asp.netasp.net-mvcasp.net-core.net-coreunobtrusive-validation

.Net Core display model validation with validation filter


I created a basic .Net Core Mvc application and I want to automatically set ModelState.IsValid for all my action here is the code of Validation Filter

public class ValidationFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (!context.ModelState.IsValid)
        {
        }

        await next();
    }
}

and here is my action code

[HttpPost]
    public IActionResult AddUser(LoginRequestViewModel loginRequestViewModel)
    {
        return View(loginRequestViewModel);
    }

What should I return to display the errors in the asp-validation-for? Without using any javascript code..


Solution

  • According to the test of your code, global filtering can be achieved. Need to make ValidationFilter a global filter in startup.cs.

    services.AddControllersWithViews(option=>
                {
                    option.Filters.Add(new ValidationFilter());
                });
    

    Then, create a model.

     public class LoginRequestViewModel
        {
            [MinLength(3)]
            public string username { get; set; }
            public string email { get; set; }
    }
    

    Define error messages in ValidationFilter.

    public class ValidationFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (!context.ModelState.IsValid)
            {
                //Customize your error message
                string messages = string.Join("; ",context.ModelState.Values
                         .SelectMany(x => x.Errors)
                         .Select(x => !string.IsNullOrWhiteSpace(x.ErrorMessage) ? x.ErrorMessage : x.Exception.Message.ToString()));
                context.RouteData.Values.Add("mes", messages);
            }
            
            await next();
        }
    }
    

    In action, get RouteData.

    [HttpPost]
            public IActionResult AddUser(LoginRequestViewModel loginRequestViewModel)
            {
                ViewData["error"]= RouteData.Values["mes"];
                return View(loginRequestViewModel);
            }
    

    Create AddUser.cshtml and use form.

     @model solution921.Controllers.LoginRequestViewModel
    <form action="/home/AddUser" method="post">
    @ViewData["error"]
        <input type="text" name="username" value="" />
        <span asp-validation-for="username"></span>
        <input type="text" name="email" value="" />
        <input type="submit" name="" value="sub" />
    </form>
    

    It can return correct validation. enter image description here