2016-05-17 73 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)); 
       } 
      } 
     } 
    } 
}