Search code examples
c#asp.net-coreactionfilterattribute

ASP.NET Core and ActionFilter


I move old MVC 5 application to Core, old application has code:

public class ValidateApiModelStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            foreach (var key in actionContext.ModelState.Keys)
            {
                result.Add(key, String.Join(", ", actionContext.ModelState[key].Errors.Select(p => p.ErrorMessage)));
            }
            // 422 Unprocessable Entity Explained
            actionContext.Response = actionContext.Request.CreateResponse<Dictionary<string, string>>((HttpStatusCode)422, result);
        }
    }
}

so, it means, that if model state is not valid, then we return dictionary with errors and 422 status code (client's requirements).

I try to rewrite it the following way:

[ProducesResponseType(422)]
public class ValidateApiModelStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            foreach (var key in context.ModelState.Keys)
            {
                result.Add(key, String.Join(", ", context.ModelState[key].Errors.Select(p => p.ErrorMessage)));
            }

            // 422 Unprocessable Entity Explained
            context.Result = new ActionResult<Dictionary<string, string>>(result);
        }
    }
}

but it can't be compiled:

Cannot implicitly convert type Microsoft.AspNetCore.Mvc.ActionResult<System.Collections.Generic.Dictionary<string, string>> to Microsoft.AspNetCore.Mvc.IActionResult

how to do it?


Solution

  • Contrary to belief ActionResult<TValue> is not derived from IActionResult. Thus the error.

    Return new ObjectResult and set status code as desired.

    [ProducesResponseType(422)]
    public class ValidateApiModelStateAttribute : ActionFilterAttribute {
        public override void OnActionExecuting(ActionExecutingContext context) {
            if (!context.ModelState.IsValid) {
                var result = new Dictionary<string, string>();
                foreach (var key in context.ModelState.Keys) {
                    result.Add(key, String.Join(", ", context.ModelState[key].Errors.Select(p => p.ErrorMessage)));
                }
    
                // 422 Unprocessable Entity Explained
                context.Result = new ObjectResult(result) { StatusCode = 422 };
            }
        }
    }