Можно ли использовать аннотации данных для проверки параметров, передаваемых в метод действия контроллера? - PullRequest
8 голосов
/ 27 апреля 2010

Я использую аннотации данных для проверки моей модели в ASP.NET MVC. Это хорошо работает для методов действий, которые имеют сложные параметры, например,

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


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

Что делать, если я хочу передать одну строку в метод действия (как показано ниже). Есть ли способ использовать аннотации данных или мне нужно будет обернуть строку в класс?

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

Ответы [ 4 ]

2 голосов
/ 15 мая 2015

Создайте свою собственную модель ...

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

И измените свою подпись вашего контроллера на стороне сервера:

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

Если ваш клиентский код уже работал, вам не нужно его менять ... Обратите внимание, что свойства вашей Модели совпадают с параметром, который вы передаете сейчас (string param1, string param2) ... чувствительны к регистру ...

EDIT : Я имею в виду, что вы можете назвать свой контроллер следующим образом:

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

2 голосов
/ 27 апреля 2010

Я не верю, что есть метод аннотаций данных к тому, что вы предлагаете. Однако если вы хотите, чтобы проверка выполнялась до того, как будет вызван метод действия, рассмотрите возможность добавления к параметру настраиваемого атрибута подшивки модели и укажите конкретную подшивку модели, которую хотите использовать.

Пример:

public ActionResult MyAction [ModelBinder(typeof(StringBinder)] string param1, [ModelBinder(typeof(StringBinder2)] string param2)
{
  .........
}
1 голос
/ 17 июля 2017

С ActionFilterAttribute можно использовать DataAnnotation для параметров действия. Это позволяет вам делать такие вещи:

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

Смотрите решение здесь: https://blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/

Он использует фильтр действий для прохождения всех параметров действий запроса и выполнения для них аннотаций данных (если они есть).


РЕДАКТИРОВАТЬ: Решение выше работает только в .NET Core. Я сделал слегка измененную версию, которая работает на .NET Framework 4.5 (может работать на более старых версиях)

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));
                }
            }
        }
    }
}
0 голосов
/ 04 сентября 2017
  1. Создайте свой собственный атрибут фильтра:

    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. Используйте это глобально:

    new HttpConfiguration { Filters = { new ModelValidationAttribute() } };
    
...