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

。_饼干妹妹 提交于 2019-12-09 02:51:06

问题


I am using Data Annotations to validate my Model in ASP.NET MVC. This works well for action methods that has complex parameters e.g,

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


ActionResult MyAction(Params params)  
{  
   If(ModeState.IsValid)  
   {  
      // Do Something  
   }  
}

What if I want to pass a single string to an Action Method (like below). Is there a way to use Data Annotations or will I have to wrap the string into a class?

ActionResult MyAction(string param1, string param2)  
{  
   If(ModeState.IsValid)  
   {  
     // Do Something  
   }  
}  

回答1:


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)
{
  .........
}



回答2:


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




回答3:


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



回答4:


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


来源:https://stackoverflow.com/questions/2717250/is-it-possible-to-use-data-annotations-to-validate-parameters-passed-to-an-actio

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