Is it possible to use Data Annotations to validate parameters passed to an Action method of a Controller?

混江龙づ霸主 提交于 2019-12-01 03:38:18
Tejs

I don't believe there is a Data Annotations method to what you are proposing. However, if you want your validation to happen before the action method is invoked, consider adding a custom model binder attribute to the parameter and specify a specific model binder you want to use.

Example:

public ActionResult MyAction [ModelBinder(typeof(StringBinder)] string param1, [ModelBinder(typeof(StringBinder2)] string param2)
{
  .........
}

Create your own model...

public class Params  
{  
    [Required] string param1 {get; set;}   
    [StringLength(50)] string param2 {get; set;}  
}

And change your signature of your server side controller:

[HttpGet]
ActionResult MyAction([FromUri] Params params)  
{  
    If(ModeState.IsValid)  
    {  
        // Do Something  
    }  
}  

If your client side code already worked you don't have to change it... Please, note that the properties of your Model are the same of the parameter you are passing now (string param1, string param2)... and they are case sensitive...

EDIT: I mean that you can call your controller in this way:

http://localhost/api/values/?param1=xxxx&param2=yyyy

With ActionFilterAttribute it is possible to use DataAnnotation on action parameters. This enables you to do things like this:

ActionResult MyAction([Required] string param1, [StringLength(50)] string param2)  
{  
   If(ModeState.IsValid)  
   {  
     // Do Something  
   }  
}

See the solution here: https://blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/

It uses an action filter to pass through all the action parameters of the query and execute the data annotations on them (if there is any).


EDIT: The solution above only works in .NET Core. I made a slightly modified version that works on .NET Framework 4.5 (might work on older versions)

public class ValidateActionParametersAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext context)
    {
        var parameters = context.ActionDescriptor.GetParameters();

        foreach (var parameter in parameters)
        {
            var argument = context.ActionArguments[parameter.ParameterName];

            EvaluateValidationAttributes(parameter, argument, context.ModelState);
        }

        base.OnActionExecuting(context);
    }

    private void EvaluateValidationAttributes(HttpParameterDescriptor parameter, object argument, ModelStateDictionary modelState)
    {
        var validationAttributes = parameter.GetCustomAttributes<ValidationAttribute>();

        foreach (var validationAttribute in validationAttributes)
        {
            if (validationAttribute != null)
            {
                var isValid = validationAttribute.IsValid(argument);
                if (!isValid)
                {
                    modelState.AddModelError(parameter.ParameterName, validationAttribute.FormatErrorMessage(parameter.ParameterName));
                }
            }
        }
    }
}
  1. Create your own filter attribute:

    public class ActionParameterValidationAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            actionContext
                .ActionDescriptor
                .GetParameters()
                .SelectMany(p => p.GetCustomAttributes<ValidationAttribute>().Select(a => new
                {
                    IsValid = a.IsValid(actionContext.ActionArguments[p.ParameterName]),
                    p.ParameterName,
                    ErrorMessage = a.FormatErrorMessage(p.ParameterName)
                }))
                .Where(_ => !_.IsValid)
                .ToList()
                .ForEach(_ => actionContext.ModelState.AddModelError(_.ParameterName, _.ErrorMessage));
    
            if (!actionContext.ModelState.IsValid)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
            }
        }
    }
    
  2. Use it globally:

    new HttpConfiguration { Filters = { new ModelValidationAttribute() } };
    
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!