[英]How to set different routes for the same Controller method with different parameters?
I have the ReportController that llooks like this: 我有看起来像这样的ReportController:
public IActionResult ReportDetails(int? reportId){
....
}
and 和
public IActionResult ReportDetails(int? reportId, bool ? approved) {
....
}
and I tried to do some routing, bu it failed. 我尝试做一些路由,但失败了。 Actual code written in Startup.cs:
用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?}");
});
As I have seen I need to match the following URL's: 如我所见,我需要匹配以下URL:
/Report/ReportDetails?reportId=7 for the first and / Report / ReportDetails?reportId = 7为第一个
/Report/ReportDetails?reportId=7&approved=True for second / Report / ReportDetails?reportId = 7&approved =真是秒
You can create an ActionMethodSelectorAttribute
. 您可以创建一个
ActionMethodSelectorAttribute
。 In your controller you can add your attribute to both methods to enable matching the correct method to the URL. 在控制器中,您可以将属性添加到两个方法中,以使正确的方法与URL匹配。
You could for example make a ParameterExistsAttribute
that decides if the method is suitable and then use 例如,您可以创建一个
ParameterExistsAttribute
来确定该方法是否合适,然后使用
[ParameterExists('approved', false)]
public IActionResult ReportDetails(int? reportId){
....
}
[ParameterExists('approved', true)]
public IActionResult ReportDetails(int? reportId, bool ? approved) {
....
}
The puzzle on how to implement such an attribute remains an exercise to the reader. 有关如何实现此类属性的难题仍然是读者的一项练习。 (It's not so difficult.)
(不是那么困难。)
As an example here's an attribute that selects an API call, based on the value of a parameter. 举例来说,这是一个根据参数值选择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);
}
}
You can't do that, like have 2 methods with identical name with different parameters, because you should get AmbiguousActionException . 您不能那样做,就像有两个名称相同但参数不同的方法一样,因为您应该获得AmbiguousActionException 。
ASP Core Action Selector does not care about Action's parameters during select action. 在选择操作期间,ASP核心操作选择器不关心操作的参数。 Therefore you can't have 2 actions correspond one route template.
因此,您不能有2个动作对应一个路由模板。 The only workaround is to play with action constraints (like HttpGet and HttpPost).
唯一的解决方法是使用操作约束(例如HttpGet和HttpPost)。 You can check it yourself on GitHub .
您可以在GitHub上自行检查 。 (See SelectBestCandidate method)
(请参见SelectBestCandidate方法)
Theoretically if parameters matters the logic to choose between actions based on parameters should be in SelectBestActions method, but it ignores parameters. 从理论上讲,如果参数很重要,则应在SelectBestActions方法中使用基于参数在操作之间进行选择的逻辑,但它将忽略参数。
In you case good option seems to be to have just 1 method: 在您的情况下,好的选择似乎只有一种方法:
public IActionResult ReportDetails(int? reportId, bool? approved) {
....
}
and then check if approved is NULL ( /Report/ReportDetails?reportId=7 ), then implement 1st logic, otherwise( /Report/ReportDetails?reportId=7&approved=True ) implement 2nd logic. 然后检查是否认可的数据为NULL( / Report / ReportDetails?reportId = 7 ),然后执行第一种逻辑,否则( / Report / ReportDetails?reportId = 7&approved = True )实现第二种逻辑。 If logic contains many lines you can extract them in new method and call it.
如果逻辑包含许多行,则可以在新方法中提取它们并调用它。
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)
}
You could use RouteAttribute 您可以使用RouteAttribute
[Route("ReportDetails/{reportId}")]
public IActionResult ReportDetails(int? reportId){
....
[Route("ReportDetails/{reportId}/{approved}")]
public IActionResult ReportDetails(int? reportId, bool ? approved) {
....
Your URLs would then be; 您的网址应为;
/Report/ReportDetails/7 for the first and / Report / ReportDetails / 7,第一个和
/Report/ReportDetails/7/True for second / Report / ReportDetails / 7 / True秒
This will work with the default startup.cs 这将与默认的startup.cs一起使用
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.