2017-07-28 67 views
2

我有llooks這樣的ReportController:如何使用不同的參數爲同一個控制器方法設置不同的路由?

public IActionResult ReportDetails(int? reportId){ 
    .... 
} 

public IActionResult ReportDetails(int? reportId, bool ? approved) { 
    .... 
} 

,我試圖做一些路由,卜失敗。寫在Startup.cs實際代碼:

app.UseMvc(routes => 
      { 
       routes.MapRoute(
        name: "ReportDetailsValidation", 
        template: "descriptionValidation", 
        defaults: new { controller = "Report", action = "ReportDetails", reportId ="{reportId}", approved = "{approved}" } 
        ); 

       routes.MapRoute(
        name: "ReportDetails", 
        template: "description", 
        defaults: new { controller = "Report", action = "ReportDetails"} 
        ); 

       routes.MapRoute(
        name: "default", 
        template: "{controller=Home}/{action=Index}/{id?}"); 
      }); 

正如我所看到的,我需要符合以下網址:
/報告/ ReportDetails reportId = 7第一和
/報告/ ReportDetails ?reportId = 7 &批准=真爲第二

回答

0

你不能做到這一點,像有2種方法具有相同的名稱使用不同的參數,因爲你應該得到AmbiguousActionException

ASP核心操作選擇器在選擇操作期間不關心操作的參數。因此,不能有2個動作對應一個路由模板。唯一的解決方法是使用動作約束(如HttpGet和HttpPost)。 你可以check it yourself on GitHub。 (見SelectBestCandidate法)

理論上,如果參數重要的邏輯基礎上的參數應該是SelectBestActions方法操作之間選擇,但它忽略的參數。

在你的情況下很好的選擇似乎是剛剛1方法:

public IActionResult ReportDetails(int? reportId, bool? approved) { 
    .... 
} 

,然後檢查是否批准爲NULL(?/報告/ ReportDetails reportId = 7),然後執行第一個邏輯,否則(/Report/ReportDetails?reportId = 7 & approved = True)實現第2邏輯。如果邏輯包含很多行,則可以用新方法提取它們並調用它。

public IActionResult ReportDetails(int? reportId, bool? approved) { 
    if (approved != null) 
    { 
     //implement logic for 2nd case(approved=True) 
    } 
    //implement logic for 1st case (just reportId=7) 
} 
+0

在標準你會得到所提到的異常,但具有相同名稱的多個方法完全沒有問題。你只需要通過使用ActionMethodSelectorAttribute來幫助選擇過程(參見我的答案)。但是在這裏介紹的特定情況下,你是沒有必要的,並且使用默認參數更容易。 –

0

你可以按照這個link瞭解路由

[HttpGet("Report/ReportDetails/{reportId}")] 
[HttpGet("Report/ReportDetails/{reportId}/{approved}")] 
public IActionResult ReportDetails(int? reportId, bool ? approved) { 
.... 
} 
0

您可以創建一個ActionMethodSelectorAttribute。在您的控制器中,您可以將您的屬性添加到這兩種方法,以使正確的方法與URL匹配。

例如,你可以做一個ParameterExistsAttribute是決定是否該方法是合適的,然後使用

[ParameterExists('approved', false)] 
public IActionResult ReportDetails(int? reportId){ 
    .... 
} 

[ParameterExists('approved', true)] 
public IActionResult ReportDetails(int? reportId, bool ? approved) { 
    .... 
} 

如何實現這種屬性的謎題仍然是一個讀者做練習。 (這並不難)

作爲一個例子,這裏有一個基於參數值選擇API調用的屬性。

public class FormPostFilterAttribute : ActionMethodSelectorAttribute 
{ 
    private readonly string _elementId; 
    private readonly string _requiredValue; 

    public FormPostFilterAttribute(string elementId, string requiredValue) 
    { 
    _elementId = elementId; 
    _requiredValue = requiredValue; 
    } 

    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo) 
    { 
    if (string.IsNullOrEmpty(controllerContext.HttpContext.Request.Form[_elementId])) 
    { 
     return false; 
    } 

    return (controllerContext.HttpContext.Request.Form[_elementId] == _requiredValue); 
    } 
} 
0

你可以使用RouteAttribute

[Route("ReportDetails/{reportId}")] 
public IActionResult ReportDetails(int? reportId){ 
.... 
[Route("ReportDetails/{reportId}/{approved}")] 
public IActionResult ReportDetails(int? reportId, bool ? approved) { 
.... 

您的網址將被;

/報告/ ReportDetails/7的第一和

/報告/ ReportDetails/7 /真爲第二

這將默認startup.cs工作

app.UseMvc(routes => 
     { 
      routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 
     }); 
+0

是的,我想過這個,但正如我所提到的,我的鏈接是我指定的鏈接。我在視圖中使用@ Html.ActionLinkFor(我不明白爲什麼它使得網址的視圖名稱後沒有「/」)。我本來希望鏈接和你的一樣 –

相關問題