[英]Multiple optional parameters routing
I have the following route definition in my webapi project. 我的webapi项目中有以下路由定义。 I have problem one of the parameter is not passed.
我有问题,其中一个参数未通过。 eg;
例如;
when i call /Controller/Action/param2/startdate/enddate the value i passed for param2 is taken for param1 and vice versa.The problem is, the RoutingModule can not detect that the provided route value is for param2 not param1 当我调用/ Controller / Action / param2 / startdate / enddate时,我为param2传递的值是param1,反之亦然。问题是,RoutingModule无法检测到提供的路由值是param2而不是param1
It works if i use querystring in the url but doesn't want to use querystring. 如果我在url中使用查询字符串但不想使用查询字符串,它可以工作。 Appreciate your help.
感谢您的帮助。
Is there any way to achieve what i expect? 有没有办法达到我的期望?
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
});
Thanks 谢谢
To solve your problem you must take into account this things: 要解决您的问题,您必须考虑以下事项:
/
as separator, to make parts of a route distinguishable /
作为分隔符之外的东西,使路线的某些部分可以区分 As you didn't tell how your URL looks like I'll show you my own examples. 由于您没有告诉您的网址如何,我会向您展示我自己的示例。
Let's suppose that you have a TestController
Web API Controller class with an action like this: 假设您有一个
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();
}
NOTE: with the default routes a Web API controller's method named GetXxx
is available to HTTP GET, a method named PostXxx
is available to HTTP POST and so on. 注意:对于HTTP GET,可以使用默认路由Web API控制器的名为
GetXxx
的方法,HTTP POST可以使用名为PostXxx
的方法,依此类推。 However, once you include Controller
and Action
in the URL template, you must use the [HttpXxx]
attributes to make your method available to the required HTTP method. 但是,一旦在URL模板中包含
Controller
和Action
,就必须使用[HttpXxx]
属性使您的方法可用于所需的HTTP方法。
In this first example, I suppose that both param1
, and param2
are integer numbers, and stardDate
and endDate
are dates: 在第一个例子中,我认为
param1
和param2
都是整数, stardDate
和endDate
是日期:
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
If you want the first URL to match parameters like these: 如果您希望第一个URL匹配以下参数:
param1 = 12; param2 = 22; startDate = 2014-12-01; endData = 2014-12-31
and the second like these: 第二个像这样:
param1 = 12; param2 = null; startDate = 2014-12-01; endData = 2014-12-31
You need to register two routes, one that will match each possible URL structure, ie 您需要注册两个路由,一个匹配每个可能的URL结构,即
// for the 1st
routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}"
// for the 2nd
routeTemplate: "api/{controller}/{action}/{param1}/{startDate}/{endDate}"
Note that, in this case, both routes are mutually exclusive, ie a single URL can match only one of the routes, so you can register them in any other. 请注意,在这种情况下,两个路由是互斥的,即单个URL只能匹配其中一个路由,因此您可以在任何其他路由中注册它们。
However, you must notice that the second URL doesn't define a value for param2
, and the TestAction
method requires it. 但是,您必须注意第二个URL没有为
param2
定义值, TestAction
方法需要它。 This wouldn't work: you must include a default value for this parameter, both in the controler's method and in the route registration: 这不起作用:您必须在控制器的方法和路径注册中包含此参数的默认值:
int? param2 = null
int? param2 = null
int? param2 = null
(C# requires optional parameter to be the last ones). int? param2 = null
(C#要求可选参数为最后一个)。 defaults: new { param2 = RouteParameter.Optional }
defaults: new { param2 = RouteParameter.Optional }
This is the way to solve the optional parameter in the middle problem. 这是解决中间问题中可选参数的方法。 In general, you'll need to define several routes, depending on how many optional parameters there are, and declare this parameters, with default values, in the Web API action method.
通常,您需要定义多个路由,具体取决于有多少可选参数,并在Web API操作方法中使用默认值声明此参数。
NOTE: as I wrote above, in MVC you don't need to specify a default value in the method parameter for this to work 注意:正如我上面所写,在MVC中,您无需在方法参数中指定默认值即可使用
Specifying constrains for a route parameter has two consequences: 指定路由参数的约束有两个结果:
You simply need to add a constraint
parameter on the route registration, like this: 您只需在路由注册上添加
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 { }
);
Note that it's necessary to specify a defaults
parameter, even if it's empty. 请注意,必须指定
defaults
参数,即使它是空的。
NOTE: the constraints in this case are a regex that only matches dates in the year 20XX, the month expressed as a single digit, or as 0x or 1x, and the date as a single digit or 0x, 1x, 2x or 3x, separated by dashes. 注意:在这种情况下的约束是一个正则表达式,只匹配20XX年份的日期,表示为单个数字的月份,或0x或1x,日期作为单个数字或0x,1x,2x或3x,分开破折号。 So this regex will match
2012-1-1
or 2015-12-30
, but not 1920-12-30
. 所以这个正则表达式将匹配
2012-1-1
或2015-12-30
,但不是1920-12-30
。 You should adapt the regex to your needs. 你应该根据你的需要调整正则表达式。
By this time I've explained how to support optional parameters, and how to specify formats (constraints) for them, to match a route template. 到这时我已经解释了如何支持可选参数,以及如何为它们指定格式(约束),以匹配路由模板。
The usual way to define optional parameters is to do it at the end of the URL template, and, in this case, if there are missing params in a route, they must be all at the end of the route. 定义可选参数的常用方法是在URL模板的末尾执行此操作,在这种情况下,如果路径中缺少参数,则它们必须全部位于路径的末尾。 (Compare this with optional in the middle: they require different routes).
(将其与中间的可选项进行比较:它们需要不同的路线)。
In this example, if you want to make optional the param2
, and the startDate
and endDate
, you must define them in the route registration, and set default parameter values in the action method. 在此示例中,如果要使
param2
和startDate
和endDate
可选,则必须在路径注册中定义它们,并在action方法中设置默认参数值。
The final code would look like this: 最终的代码如下所示:
[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
}
);
Note, that, in this case: 请注意,在这种情况下:
Multiparam2
route, it would erroneously handle an URL like this: http://localhost:1179/api/test/testaction/1/2014-12-12/2015-1-1
, with param1=1; param2="2014-12-12"; startDate="2015-1-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"
. param1=1; param2="2014-12-12"; startDate="2015-1-1"
。 (You could avoid this with an additional constraint on param2 that only accepts numbers, like param2=@"\\d+"
) param2=@"\\d+"
) startDate
and endDate
. startDate
和endDate
默认值。 You can handle default parameters in different positions by carefully: 您可以仔细处理不同位置的默认参数:
If you plan carefully how your routes look like, you can get what you need with a few routes and optional parameters. 如果您仔细计划路线的样子,您可以通过几条路线和可选参数获得所需的路线。
JotaBe answer was nice and complete. JotaBe答案很好而且完整。 Just you have to consider if parameters are optional you have to write routeTemplate with the order from lowest parameters to highest.
只需要考虑参数是否可选,您必须使用从最低参数到最高参数的顺序编写routeTemplate。
Just like : 就像 :
// 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.