C# 多个可选参数路由
我的webapi项目中有以下路由定义。我有一个问题,其中一个参数没有传递。eg 当我调用/Controller/Action/param2/startdate/enddate时,我为param2传递的值将用于param1,反之亦然。问题是,RoutingModule无法检测到提供的路由值是否用于param2而不是param1 如果我在url中使用querystring,但不想使用querystring,那么它可以工作。谢谢你的帮助 有没有办法达到我的期望C# 多个可选参数路由,c#,asp.net-mvc-4,asp.net-web-api,url-routing,asp.net-web-api-routing,C#,Asp.net Mvc 4,Asp.net Web Api,Url Routing,Asp.net Web Api Routing,我的webapi项目中有以下路由定义。我有一个问题,其中一个参数没有传递。eg 当我调用/Controller/Action/param2/startdate/enddate时,我为param2传递的值将用于param1,反之亦然。问题是,RoutingModule无法检测到提供的路由值是否用于param2而不是param1 如果我在url中使用querystring,但不想使用querystring,那么它可以工作。谢谢你的帮助 有没有办法达到我的期望 config.Routes.MapHtt
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除外,因为MVC只要求这些参数为null或引用类型)
TestController
Web API控制器类,其操作如下:
// 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();
}
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 { }
);
[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
}
);
注意:使用默认路由,HTTP GET可以使用名为GetXxx
的Web API控制器方法,HTTP POST可以使用名为PostXxx
的方法,依此类推。但是,在URL模板中包含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
如果希望第一个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
第二个是这样的:
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
方法需要它。这不起作用:您必须在控制器的方法和路由注册中包含此参数的默认值:
- 动作参数
(C#要求可选参数为最后一个参数)int?param2=null
- 路由必须包括默认值:
defaults:new{param2=RouteParameter.Optional}
这是解决中间问题中可选参数的方法。通常,您需要根据可选参数的数量定义多个路由,并在WebAPI操作方法中使用默认值声明这些参数
注意:正如我在上面所写的,在MVC中,不需要在方法参数中指定默认值,就可以工作 参数约束 为管线参数指定约束有两个后果:约束
参数,如下所示:
// 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();
}
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 { }
);
[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
}
);
请注意,即使参数为空,也必须指定默认值
参数
注意:本例中的约束条件是一个正则表达式,它只匹配20XX年的日期、表示为一位数字或0x或1x的月份以及表示为一位数字或0x、1x、2x或3x的日期(用破折号分隔)。因此,该正则表达式将匹配2012-1-1
或2015-12-30
,但不匹配1920-12-30
。您应该根据自己的需要调整正则表达式
末尾的可选参数
至此,我已经解释了如何支持可选参数,以及如何为它们指定格式(约束),以匹配管线模板
定义可选参数的通常方法是在URL模板的末尾进行,在这种情况下,如果路由中缺少参数,则它们必须全部位于路由的末尾。(将此选项与中间的可选选项进行比较:它们需要不同的路线)
在本例中,如果要使param2
和startDate
和endDate
可选,则必须在路线注册中定义它们,并在操作方法中设置默认参数值
最终的代码如下所示:
// 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();
}
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 { }
);
[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
路由,它将错误地处理如下URL:http://localhost:1179/api/test/testaction/1/2014-12-12/2015-1-1
,参数为1;param2=“2014-12-12”;startDate=“2015-1-1”。(您可以通过对仅接受数字的param2附加约束来避免这种情况,如param2=@“\d+”
)startDate
和endDate
的默认值- 按正确的顺序注册路线
- 定义路由中的默认参数,以及控制器操作中的默认值
- 使用约束
如果你仔细规划你的路线,你可以通过一些路线和可选参数得到你所需要的。JotaBe的回答很好,很完整。只是你没有