无法使ActionLink或RouteLink生成正确的URL

本文关键字:URL RouteLink ActionLink | 更新日期: 2023-09-27 17:58:28

我是ASP.NET MVC的新手(使用版本3),无法使ActionLinkRouteLink按预期工作。在这个应用程序中,一个事件可以有很多活动,我希望使用来路由到它们

/事件/1/活动/事件/1/活动/索引(与以前相同)/事件/1/活动/详细信息/5

这两个助手生成的HTML看起来总是这样:

/事件/1

这是代码

查看Razor HTML

@Html.RouteLink("View Sessions", "SubControllerIndex",
    new { eventId = Model.Id, controller = "Activity", action = "Index" })
@Html.ActionLink("View Sessions", "Index", "Activity", new { eventId = Model.Id }, null)

路线映射

routes.MapRoute(
    "SubControllerIndex",
    "Event/{eventId}/{controller}",
    new { controller = "Activity", action = "Index" },
    new { eventId = @"'d+" }
);
routes.MapRoute(
    "ActivityIndex",
    "Event/{eventId}/{controller}/{action}/{id}",
    new { controller = "Activity", action = "Index", id = UrlParameter.Optional },
    new { eventId = @"'d+", id = @"'d*" }
);
routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
    new { id = @"'d*" }
);

活动控制器

public ActionResult Index(long eventId)
{
    var activities = _context.Activities.Where(a => a.Event.Id == eventId).ToList();
    return View(activities);
}

你知道我在这里做错了什么吗?

无法使ActionLink或RouteLink生成正确的URL

路由系统为路由生成/Event/1而不是/Event/1/Activity/Index的原因

routes.MapRoute(
   "ActivityIndex",
   "Event/{eventId}/{controller}/{action}/{id}",
   new { controller = "Activity", action = "Index", id = UrlParameter.Optional },
   new { eventId = @"'d+", id = @"'d*" }
);

是因为在生成url时,系统不会在url中包含任何默认值。在这种情况下,控制器的默认值为"活动",而操作的默认值则为"索引"。因此,

@Html.RouteLink("View Sessions", "SubControllerIndex",
    new { eventId = Model.Id, controller = "Activity", action = "Index" })

将生成CCD_ 5而不是CCD_。如果单击链接,您仍然应该转到ActivityController上的Index操作方法。

正如mrydengren所指出的,ActionLink和RouteLink方法将去掉与默认值相同的参数。然后URL应该指向你所指向的操作。

如果你仍然想使用完整的URL,你可以创建一个没有默认值的路由,并使用RouteLink创建与该路由的链接。

// Either add this at the end as a new route, or replace the one you already have.
routes.MapRoute("ActivityIndexWithoutParams",
    "Event/{eventId/controller/action/id},
    new{},
    new{ eventId = @"'d+", id = @"'d*"}
    );

现在您可以使用RouteLink方法创建正确的路线:

@Html.RouteLink("View Sessions", "ActivityIndexWithoutParameters",
    new {eventid = Model.Id, controller = "activity", action = "index"}
    );

当我将项目切换到使用区域时,我试图(不断尝试)找到为什么我的自定义RouteBase实现不能在出站路由(生成URL的路由)上工作的答案时,遇到了这个问题。

在分析MVC源代码时,我终于找到了答案:你必须让你的自定义RouteBase实现实现IRouteWithArea,这样框架才能知道你的自定义路由属于哪个区域

public class CustomRoute: RouteBase, IRouteWithArea
{
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
         // Implement custom virtual path (url) here
    }
    #region IRouteWithArea Members
    public string Area
    {
        get { return "Store"; }
    }
    #endregion
}

请记住,路由是"贪婪的",第一个匹配将是被处理的路由,因此您需要丢失第一个路由条目,否则将永远无法到达第二个。

这是我能看到你需要做的唯一更改,否则也没关系,如下所示,在视图中添加一个操作链接;

@Html.ActionLink("View Sessions", "Details", "Activity", new { eventId = 12, id = 22 }, null)

您应该看到它在链接中生成了正确的URL。