C# 在ASP.NET MVC 4中路由到id为的索引
我希望使用默认的controller=Home和默认的action=Index来维护ASP.NET MVC 4现有的controller/action/id路由,但也允许controller/id路由到controller的Index方法,只要第二项不是已知的操作 例如,给定一个带有操作索引和发送的主控制器:C# 在ASP.NET MVC 4中路由到id为的索引,c#,asp.net,asp.net-mvc,asp.net-mvc-routing,C#,Asp.net,Asp.net Mvc,Asp.net Mvc Routing,我希望使用默认的controller=Home和默认的action=Index来维护ASP.NET MVC 4现有的controller/action/id路由,但也允许controller/id路由到controller的Index方法,只要第二项不是已知的操作 例如,给定一个带有操作索引和发送的主控制器: /Home/Send -> controller's Send method /Home -> controller's Index method /Home/Send/xyz
/Home/Send -> controller's Send method
/Home -> controller's Index method
/Home/Send/xyz -> controller's Send method with id = xyz
/Home/abc -> controller's Index method with id = abc
但是,如果我先定义其中一个路由,它会隐藏另一个路由。我该怎么做呢?在默认的泛型之前先做特定的。秩序很重要
routes.MapRoute(name: "single", url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { id = @"^[0-9]+$" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index",
id = UrlParameter.Optional }
);
我认为没有一个解决方案可以满足您的需求,因为您有两条相互竞争的路线。也许您可以定义一些特定的东西(以防您没有任何其他控制器)
如果您的操作列表(例如发送)是众所周知的,并且它们的(操作)名称不能与某些ID值相同,我们可以使用自定义约束实现:
public class MyRouteConstraint : IRouteConstraint
{
public readonly IList<string> KnownActions = new List<string>
{ "Send", "Find", ... }; // explicit action names
public bool Match(System.Web.HttpContextBase httpContext, Route route
, string parameterName, RouteValueDictionary values
, RouteDirection routeDirection)
{
// for now skip the Url generation
if (routeDirection.Equals(RouteDirection.UrlGeneration))
{
return false; // leave it on default
}
// try to find out our parameters
string action = values["action"].ToString();
string id = values["id"].ToString();
// id and action were provided?
var bothProvided = !(string.IsNullOrEmpty(action) || string.IsNullOrEmpty(id));
if (bothProvided)
{
return false; // leave it on default
}
var isKnownAction = KnownActions.Contains(action
, StringComparer.InvariantCultureIgnoreCase);
// action is known
if (isKnownAction)
{
return false; // leave it on default
}
// action is not known, id was found
values["action"] = "Index"; // change action
values["id"] = action; // use the id
return true;
}
摘要:在本例中,我们正在评估“action”参数的值
- 如果同时提供了1)操作和2)id,我们将不在这里处理它李>
- 如果这是已知的操作(在列表中,或反映…)
- 只有当操作名称未知时,我们才更改路由值:将操作设置为“Index”,将操作值设置为ID
注意:
action
名称和id
值必须是唯一的。。。那么这就行了这对我来说很有效:
1) 在RouteConfig中,我将此作为第一行:
routes.MapRoute(name: "single", url: "{controller}/{lastName}",
defaults: new { controller = "LeaveRequests", action = "Index" });
2) 在我的控制器中:
public ViewResult Index(string lastName)
{
if (lastName == null)
{
return //return somthing
}
else
{
return //return something
}
}
3) 当你呼叫控制器时
http://localhost:34333/leaveRequests/Simpsons
它会给你所有关于辛普森一家的请求
如果您呼叫http://localhost:34333/leaveRequests/
它将提供所有请求这对我有效
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default1",
url: "{id}",
defaults: new { controller ="Home", action ="Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller ="Home", action ="Index", id = UrlParameter.Optional }
);
最简单的方法是在控制器中创建两个动作方法。一个用于索引,一个用于发送,并将字符串id参数放在这两个参数上。由于您不能有重复或重载的操作方法,这就解决了这个问题。您的Index方法现在将处理id是否存在的索引或空白路径(null),并以这种方式处理视图。您的发送方法将与索引完全相同。然后,根据id是否为null,您可以按照自己的喜好进行路由、处理或重定向。这应在不更改RouteConfig.cs的情况下工作:
public ActionResult Index(string id) {if (id == null) Do A else Do B}
public ActionResult Send(string id) {if (id == null) Do A else Do B}
我为此挣扎了很长时间,这是最简单的解决方案。你是如何在RouteTable上定义路线的?@FelipeOriani我没有——如果我创建其中一个,它将尽可能隐藏另一个。不幸的是,我的id不必是数字。它是一个字符串,任何东西都可以。然后你可以在路由中消除约束。如果我消除了约束,那么针对控制器/操作(无id)的任何请求都将匹配控制器/id,而不是相应的操作。感谢并投票支持提述约束表达式。请您参考路由中可以使用的更多选项好吗?是否可以从中识别实际的控制器类类型,并查看操作是否匹配?我不想手动构建操作名称列表。有两个类似的问题(我参与了;)可以找到解决方案:。因为控制器名称是路由的一部分,所以某些反射。。。但大多数情况下,它必须通过自定义方法完成;(这里秩序很重要。
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default1",
url: "{id}",
defaults: new { controller ="Home", action ="Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller ="Home", action ="Index", id = UrlParameter.Optional }
);
public ActionResult Index(string id) {if (id == null) Do A else Do B}
public ActionResult Send(string id) {if (id == null) Do A else Do B}