Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ASP.NET MVC 4中路由到id为的索引_C#_Asp.net_Asp.net Mvc_Asp.net Mvc Routing - Fatal编程技术网

C# 在ASP.NET MVC 4中路由到id为的索引

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

我希望使用默认的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 -> 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}