我的webapi项目中有以下路由定义。我有问题,其中一个参数未通过。例如;
当我调用/ Controller / Action / param2 / startdate / enddate时,我为param2传递的值是param1,反之亦然。问题是,RoutingModule无法检测到提供的路由值是否为param2而不是param1 < / p>
如果我在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
});
由于
答案 0 :(得分:15)
要解决您的问题,您必须考虑以下事项:
/
之外的东西作为分隔符,使路线的某些部分可以区分由于您没有告诉您网址的外观,我会向您展示我自己的示例。
假设您有一个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
的方法,依此类推。但是,在网址模板中加入Controller
和Action
后,您必须使用[HttpXxx]
属性使您的方法可用于所需的HTTP方法。
在第一个示例中,我认为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
如果您希望第一个网址匹配以下参数:
param1 = 12; param2 = 22; startDate = 2014-12-01; endData = 2014-12-31
和第二个像这样:
param1 = 12; param2 = null; startDate = 2014-12-01; endData = 2014-12-31
您需要注册两条路线,一条路线将匹配每个可能的网址结构,即
// for the 1st
routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}"
// for the 2nd
routeTemplate: "api/{controller}/{action}/{param1}/{startDate}/{endDate}"
请注意,在这种情况下,两个路由是互斥的,即单个URL只能匹配其中一个路由,因此您可以在任何其他路由中注册它们。
但是,您必须注意第二个网址没有定义param2
的值,TestAction
方法需要它。这不起作用:您必须在控制器的方法和路径注册中包含此参数的默认值:
int? param2 = null
(C#要求可选参数为最后一个参数)。defaults: new { param2 = RouteParameter.Optional }
这是解决中间问题中可选参数的方法。通常,您需要定义多个路由,具体取决于有多少可选参数,并在Web API操作方法中使用默认值声明此参数。
注意:正如我上面所写,在MVC中,您无需在方法参数中指定默认值即可使用
指定路由参数的约束有两个结果:
您只需在路线注册中添加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-1
或2015-12-30
,但不匹配1920-12-30
。您应该根据需要调整正则表达式。
此时我已经解释了如何支持可选参数,以及如何为它们指定格式(约束),以匹配路由模板。
定义可选参数的常用方法是在URL模板的末尾执行此操作,在这种情况下,如果路径中缺少参数,则它们必须全部位于路径的末尾。 (比较中间的可选项:它们需要不同的路线)。
在此示例中,如果要使param2
以及startDate
和endDate
可选,则必须在路由注册中定义它们,并在其中设置默认参数值行动方法。
最终代码如下所示:
[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
}
);
请注意,在这种情况下:
Multiparam2
路由,则会错误地处理这样的网址:http://localhost:1179/api/test/testaction/1/2014-12-12/2015-1-1
,param1=1; param2="2014-12-12"; startDate="2015-1-1"
。 (您可以通过对仅接受数字的param2的附加约束来避免这种情况,例如param2=@"\d+"
)startDate
和endDate
的默认值。您可以小心处理不同位置的默认参数:
如果您仔细计划路线的样子,您可以通过一些路线和可选参数获得所需的信息。
答案 1 :(得分:0)
JotaBe的回答很好而且很完整。只是要考虑参数是否可选,就必须编写routeTemplate并按从最低参数到最高参数的顺序进行。
就像:
// for the 1st
routeTemplate: "api/{controller}/{action}/{param1}/{startDate}/{endDate}"
// for the 2nd
routeTemplate: "api/{controller}/{action}/{param1}/{param2}/{startDate}/{endDate}"