簡體   English   中英

多個可選參數路由

[英]Multiple optional parameters routing

我的webapi項目中有以下路由定義。 我有問題,其中一個參數未通過。 例如;

當我調用/ Controller / Action / param2 / startdate / enddate時,我為param2傳遞的值是param1,反之亦然。問題是,RoutingModule無法檢測到提供的路由值是param2而不是param1

如果我在url中使用查詢字符串但不想使用查詢字符串,它可以工作。 感謝您的幫助。

有沒有辦法達到我的期望?

config.Routes.MapHttpRoute(
    name: "RetrieveHistory",
    routeTemplate: "{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}",
    defaults: new
    {
        controller = "Vend",
        action = "RetrieveUtrnHistory",
        param1 = RouteParameter.Optional,
        param2 = RouteParameter.Optional,
        starDate = RouteParameter.Optional,
        endDate = RouteParameter.Optional
    });

謝謝

要解決您的問題,您必須考慮以下事項:

  • 您可以注冊多條路線。 可以處理URL的第一個注冊路由將處理它。
  • 你可以使用斜杠/作為分隔符之外的東西,使路線的某些部分可以區分
  • 您可以使用參數約束(通常是正則表達式)來更容易地發現參數是一種還是其他種類
  • 您可以為參數指定默認值,如果這樣做,操作方法必須具有默認值(除非MVC,只要求它們可以為空或引用類型)

由於您沒有告訴您的網址如何,我會向您展示我自己的示例。

假設您有一個TestController Web API Controller類,其操作如下:

// GET api/Test/TestAction/ ...
[HttpGet]
public object TestAction(int param1, DateTime startDate, DateTime endDate, 
                         int? param2 = null)
{
    return new
    {
        param1 = param1,
        param2 = param2,
        startDate = startDate,
        endDate = endDate
    }.ToString();
}

注意:對於HTTP GET,可以使用默認路由Web API控制器的名為GetXxx的方法,HTTP POST可以使用名為PostXxx的方法,依此類推。 但是,一旦在URL模板中包含ControllerAction ,就必須使用[HttpXxx]屬性使您的方法可用於所需的HTTP方法。

中間的可選參數

在第一個例子中,我認為param1param2都是整數, stardDateendDate是日期:

http://myhost/api/Mycontroller/Myaction/12/22/2014-12-01/2014-12-31
http://myhost/api/Mycontroller/Myaction/22/2014-12-01/2014-12-31

如果您希望第一個URL匹配以下參數:

param1 = 12; param2 = 22; startDate = 2014-12-01; endData = 2014-12-31

第二個像這樣:

param1 = 12; param2 = null; startDate = 2014-12-01; endData = 2014-12-31

您需要注冊兩個路由,一個匹配每個可能的URL結構,即

// for the 1st
routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}"
// for the 2nd
routeTemplate: "api/{controller}/{action}/{param1}/{startDate}/{endDate}"

請注意,在這種情況下,兩個路由是互斥的,即單個URL只能匹配其中一個路由,因此您可以在任何其他路由中注冊它們。

但是,您必須注意第二個URL沒有為param2定義值, TestAction方法需要它。 這不起作用:您必須在控制器的方法和路徑注冊中包含此參數的默認值:

  • 動作參數int? param2 = null int? param2 = null (C#要求可選參數為最后一個)。
  • 路由必須包含默認值: defaults: new { param2 = RouteParameter.Optional }

這是解決中間問題中可選參數的方法。 通常,您需要定義多個路由,具體取決於有多少可選參數,並在Web API操作方法中使用默認值聲明此參數。

注意:正如我上面所寫,在MVC中,您無需在方法參數中指定默認值即可使用

參數約束

指定路由參數的約束有兩個結果:

  1. 保證參數值具有預期的格式
  2. 最重要的是,如果格式是預期的格式,路由將只處理URL。 這樣可以幫助您提高URL的選擇性,從而使其更加靈活。

您只需在路由注冊上添加constraint參數,如下所示:

config.Routes.MapHttpRoute(
    name: "Multiparam2",
    routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}",
    constraints: new
    {
        startDate = @"20\d\d-[0-1]?\d-[0-3]?\d", // regex
        endDate = @"20\d\d-[0-1]?\d-[0-3]?\d" // regex
    },
    defaults: new object { }
);

請注意,必須指定defaults參數,即使它是空的。

注意:在這種情況下的約束是一個正則表達式,只匹配20XX年份的日期,表示為單個數字的月份,或0x或1x,日期作為單個數字或0x,1x,2x或3x,分開破折號。 所以這個正則表達式將匹配2012-1-12015-12-30 ,但不是1920-12-30 你應該根據你的需要調整正則表達式。

最后的可選參數

到這時我已經解釋了如何支持可選參數,以及如何為它們指定格式(約束),以匹配路由模板。

定義可選參數的常用方法是在URL模板的末尾執行此操作,在這種情況下,如果路徑中缺少參數,則它們必須全部位於路徑的末尾。 (將其與中間的可選項進行比較:它們需要不同的路線)。

在此示例中,如果要使param2startDateendDate可選,則必須在路徑注冊中定義它們,並在action方法中設置默認參數值。

最終的代碼如下所示:

[HttpGet]
public object TestAction(int param1, int? param2 = null, DateTime? startDate = null, 
                         DateTime? endDate = null)
{
    return new
    {
        param1 = param1,
        param2 = param2,
        startDate = startDate,
        endDate = endDate
    }.ToString();
}



config.Routes.MapHttpRoute(
    name: "Multiparam1",
    routeTemplate: "api/{controller}/{action}/{param1}/{startDate}/{endDate}",
    constraints: new
    {
        startDate = @"20\d\d-[0-1]?\d-[0-3]?\d",
        endDate = @"20\d\d-[0-1]?\d-[0-3]?\d"
    },
    defaults: new
    {
        param2 = RouteParameter.Optional,
        startDate = RouteParameter.Optional,
        endDate = RouteParameter.Optional
    }
);

config.Routes.MapHttpRoute(
    name: "Multiparam2",
    routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}",
    constraints: new
    {
        startDate = @"(20\d\d-[0-1]?\d-[0-3]?\d)?",
        endDate = @"(20\d\d-[0-1]?\d-[0-3]?\d)?"
    },
    defaults: new
    {
        startDate = RouteParameter.Optional,
        endDate = RouteParameter.Optional
    }
);

請注意,在這種情況下:

  1. 路線可能不匹配,因此必須按正確的順序進行登記,如圖所示。 如果您首先注冊Multiparam2路由,則會錯誤地處理如下URL: http://localhost:1179/api/test/testaction/1/2014-12-12/2015-1-1 ,其中param1=1; param2="2014-12-12"; startDate="2015-1-1" param1=1; param2="2014-12-12"; startDate="2015-1-1" param1=1; param2="2014-12-12"; startDate="2015-1-1" (您可以通過對param2的附加約束來避免這種情況,該約束僅接受數字,例如param2=@"\\d+"
  2. 該操作必須具有startDateendDate默認值。

結論

您可以仔細處理不同位置的默認參數:

  • 以正確的順序注冊路線
  • 定義路徑中的默認參數,以及控制器操作中的默認值
  • 使用約束

如果您仔細計划路線的樣子,您可以通過幾條路線和可選參數獲得所需的路線。

JotaBe答案很好而且完整。 只需要考慮參數是否可選,您必須使用從最低參數到最高參數的順序編寫routeTemplate。

就像 :

// for the 1st
routeTemplate: "api/{controller}/{action}/{param1}/{startDate}/{endDate}"

// for the 2nd
routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM