2016-05-17 29 views
1

我有下面的类:'多的行动中发现' 错误与REST的Web API路由

public class GetLogsRequestDto 
{ 
    public LogLevel Level { get; set; } 

    public LogSortOrder SortOrder { get; set; } 
} 

我有以下2个动作的Web API控制器(LogsController):

async Task<IHttpActionResult> Get([FromUri]int id) 

async Task<IHttpActionResult> Get([FromUri]GetLogsRequestDto dto) 

第一个用于检索特定日志,第二个用于检索日志列表。当我通过/ logs/123对特定日志进行GET请求时,它会正确调用第一个操作,同样,如果我为/ logs发出GET请求,它会正确调用第二个操作(该类中定义的属性是可选的并且不需要总是提供)。

不过,我想改变第一个GET方法,因此使用类,而不是INT id参数,像这样(注意它指定一个不同的(单)型以上的第二招):

async Task<IHttpActionResult> Get([FromUri]GetLogRequestDto dto) 

GetLogRequestDto类看起来是这样的:

public class GetLogRequestDto 
{ 
    [Required] 
    [Range(100, int.MaxValue)] 
    public int Id { get; set; } 
} 

我的这种做法背后的原因,是因为这样我可以有模型的验证通过我的标准ModelStateValidationActionFilter,并且也把这个类中,R内的任何特定的验证属性而不是使用'int id'参数方法时,则必须执行验证。

当我虽然实行这一做法,尝试调用/日志/ 1,我得到以下错误:

Multiple actions were found that match the request

它不是用作这2种方法PARAMS的2种不同类型之间的区别。

我已经配置缺省路由是:

config.Routes.MapHttpRoute(
       name: "controller-id", 
       routeTemplate: "{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
       ); 

我想不通为什么会出现一个问题 - 为什么它的一种方式而不是其他。

回答

0

使用GET请求来处理一个基本类型参​​数的复杂类型(这也是该路线的一部分)是不是一个好主意。

通过使用此方法,框架将无法将您的路由参数绑定到该复杂类型(路由定义需要参数id必须是简单类型)。

我强烈建议您恢复您的更改并使id参数再次变为int

作为一个替代方法您可以按照this great post和实施一项行动过滤器,可以验证由验证装饰了你的方法参数属性,即使是简单的类型。

这是马克Vincze的博客文章表示用于验证动作参数的动作过滤器属性的摘录:

public class ValidateActionParametersAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext context) 
    { 
     var descriptor = context.ActionDescriptor as ControllerActionDescriptor; 

     if (descriptor != null) 
     { 
      var parameters = descriptor.MethodInfo.GetParameters(); 

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

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

     base.OnActionExecuting(context); 
    } 

    private void EvaluateValidationAttributes(ParameterInfo parameter, object argument, ModelStateDictionary modelState) 
    { 
     var validationAttributes = parameter.CustomAttributes; 

     foreach (var attributeData in validationAttributes) 
     { 
      var attributeInstance = CustomAttributeExtensions.GetCustomAttribute(parameter, attributeData.AttributeType); 

      var validationAttribute = attributeInstance as ValidationAttribute; 

      if (validationAttribute != null) 
      { 
       var isValid = validationAttribute.IsValid(argument); 
       if (!isValid) 
       { 
        modelState.AddModelError(parameter.Name, validationAttribute.FormatErrorMessage(parameter.Name)); 
       } 
      } 
     } 
    } 
}