简体   繁体   English

在ASP.NET MVC 4中使用id路由到索引

[英]Routing to index with id in ASP.NET MVC 4

I'd like to maintain ASP.NET MVC 4's existing controller/action/id routing with default controller = Home and default action = Index, but also enable controller/id to route to the controller's index method as long as the second item is not a known action. 我想维护ASP.NET MVC 4的现有控制器/动作/ id路由,默认控制器= Home和默认动作=索引,但是只要第二项不是,就可以使控制器/ id路由到控制器的索引方法一个已知的行动。

For example, given a controller Home with actions Index and Send: 例如,给定一个带有动作索引和发送的控制器Home:

/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

However, if I define either route first, it hides the other one. 但是,如果我先定义任一路线,它会隐藏另一条路线。 How would I do this? 我该怎么做?

Do the specific one first before the default generic one. 在默认的通用版之前先执行特定的操作。 The order matters. 订单很重要。

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 }
);

In case, that the list of your actions (eg Send ) is well known, and their (action) names cannot be the same as some ID value, we can use our custom ConstraintImplementation: 如果你的行为列表(例如发送 )是众所周知的,并且它们的(动作)名称不能与某个ID值相同,我们可以使用我们的自定义ConstraintImplementation:

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;
  }

And the route map (before the default one - both must be provided), should look like this: 路线图(在默认值之前 - 都必须提供)应该如下所示:

routes.MapRoute(
  name: "DefaultMap",
  url: "{controller}/{action}/{id}",
  defaults: new { controller = string.Empty, action = "Index", id = string.Empty },
  constraints: new { lang = new MyRouteConstraint() }
);

Summary : In this case, we are evaluating the value of the "action" parameter. 简介 :在这种情况下,我们正在评估“action”参数的值。

  • if both 1) action and 2) id are provided, we won't handle it here. 如果提供1)动作和2)id,我们将不在此处理它。
  • nor if this is known action (in the list, or reflected...). 如果这是已知的动作(在列表中,或反映...)。
  • only if the action name is unknown, let's change the route values: set action to "Index" and action value to ID. 只有当动作名称未知时,让我们更改路线值:将动作设置为“索引”,将动作值设置为ID。

NOTE: action names and id values need to be unique... then this will work 注意: action名称和id值必须是唯一的...然后这将起作用

The easiest way is to simply create two Action methods in your Controller. 最简单的方法是在Controller中简单地创建两个Action方法。 One for Index and one for Send and place your string id parameter on both. 一个用于索引,一个用于发送,并将字符串id参数放在两者上。 Since you cannot have duplicate or overloaded action methods, that solves that problem. 由于您不能拥有重复或重载的操作方法,因此可以解决该问题。 Your Index method will now handle both index or blank paths where the id is present or not (null) and process your views that way. 您的Index方法现在将处理id存在与否的索引或空白路径(null)并以这种方式处理您的视图。 Your Send method will do the exact same as Index. 您的Send方法将与Index完全相同。 You can then route, process, or redirect how you like, depending on if id is null. 然后,您可以根据id是否为null来路由,处理或重定向您的喜好。 This should work with no changes to RouteConfig.cs: 这应该不会更改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}

I had this struggle for a long time, and this was the simplest solution. 我这场斗争很长一段时间,这是最简单的解决方案。

I don't think there is a solution for your requirements, as you have two competing routes. 我认为没有针对您的要求的解决方案,因为您有两条竞争路线。 Maybe you can define something specific (in case you don't have any other controllers). 也许你可以定义一些特定的东西(如果你没有任何其他控制器)。

routes.MapRoute(
        name: "Send",
        url: "{controller}/Send/{id}",
        defaults: new { controller = "Home", id = UrlParameter.Optional }
    );
routes.MapRoute(
        name: "Home",
        url: "Home",
        defaults: new { controller = "Home", action = "Index" }

routes.MapRoute(
        name: "Index",
        url: "{controller}/{id}",
        defaults: new { controller = "Home", action= "Index", 
                           id = UrlParameter.Optional }
    );

routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index",
                                               id = UrlParameter.Optional }
    );

This what worked for me: 这对我有用:

1) In RouteConfig, I put this to be the first line: 1)在RouteConfig中,我把它作为第一行:

routes.MapRoute(name: "single", url: "{controller}/{lastName}",
            defaults: new { controller = "LeaveRequests", action = "Index" });

2) In my controller: 2)在我的控制器中:

public ViewResult Index(string lastName)
{
    if (lastName == null)
    {
        return //return somthing
    }
    else
    {
        return //return something
    }
 }

3) when you call the controller 3)当你打电话给控制器

http://localhost:34333/leaveRequests/Simpsons

it will give you all requests for Simpsons. 它将为您提供辛普森一家的所有要求。

if you call http://localhost:34333/leaveRequests/ it will give all requests 如果你调用http://localhost:34333/leaveRequests/它将提供所有请求

this is working for me 这对我有用

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 }
        );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM