添加非mvc路由时Html.ActionLink构造错误链接

发布于 2024-08-05 10:57:16 字数 1181 浏览 6 评论 0原文

我这里有一个混合了 webform 和 mvc 的应用程序。我指定路由如下,

        routes.Add("AspxRoute", new Route("Upload/New", new WebFormRouteHandler<Page>("~/Uploads.aspx")));

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );   

以便“上传/新建”的虚拟路径实际上映射到 aspx Web 表单页面。

但我的问题是 Html.ActionLink("Test", "Controller", "Action") 现在呈现

/Upload/New?Controller=Controller&Action=Action

查看了 MVC 源代码后,我明白这是因为 ActionLink 调用 RouteCollection.GetVirtualPath(requestContext,routeName,mergedRouteValues),其中routeName留为空。不知何故,默认使用 AspxRoute 路由来构造 url。我尝试在“AspxRoute”之前添加另一条路由,但似乎它总是默认为非 MVC 路由处理程序。

当routeName为空时RouteCollection.GetVirtualPath如何表现?为什么我的情况会这样?

如何构建正确的 url?我需要编写新的 Htmlhelper 扩展吗?

干杯

I have an application here with a mix of webform and mvc. I specify the routing as below

        routes.Add("AspxRoute", new Route("Upload/New", new WebFormRouteHandler<Page>("~/Uploads.aspx")));

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );   

So that virtual path to "Upload/New" actually maps to an aspx webform page.

But my problem is that Html.ActionLink("Test", "Controller", "Action") now renders

/Upload/New?Controller=Controller&Action=Action

Having looked at the MVC source code, I understand that it is because ActionLink calls to RouteCollection.GetVirtualPath(requestContext, routeName, mergedRouteValues), where routeName is left to null. And somehow this defaults to use the AspxRoute route to construct the url. I tried to added another route before "AspxRoute", but it seems it always defaults to the non-mvc routehandler one.

How does RouteCollection.GetVirtualPath behave when routeName is null? And why is it behaving this way for my case?

How do I construct a correct url? Do I need to write a new Htmlhelper extension?

Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

场罚期间 2024-08-12 10:57:16

另一种选择是向您的 WebFormRoute 添加自定义约束。例如,您可以创建 IRouteConstraint 的实现来匹配 RouteDirection.IncomingRequest,然后使用它来确保该路由被服务器生成的路由(例如 ActionLink)忽略,但仍被客户端生成的请求使用。类似于:

public class IncomingOnlyRouteConstraint: IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.IncomingRequest)
        {
            return true;
        }
        return false;
    }
}

然后将约束添加到您的路线中:

routes.Add("AspxRoute", new Route("Upload/New", null, 
                            new RouteValueDictionary() { {"WebFormsConstraint", new IncomingOnlyRouteConstraint()} }, 
                            new WebFormRouteHandler<Page>("~/Uploads.aspx")));

当然,您可能更喜欢添加自己的约束样式,这对实现它的路线有很大限制,但这只是解决问题的一种方法的示例。

An alternative option would be to add a custom constraint to your WebFormRoute(s). For example, you could create an implementation of IRouteConstraint to match RouteDirection.IncomingRequest, then use it to ensure the route is ignored by Server-Generated routes (such as ActionLink) but still used by client-generated requests. Something like:

public class IncomingOnlyRouteConstraint: IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.IncomingRequest)
        {
            return true;
        }
        return false;
    }
}

And then add the constraint to your route:

routes.Add("AspxRoute", new Route("Upload/New", null, 
                            new RouteValueDictionary() { {"WebFormsConstraint", new IncomingOnlyRouteConstraint()} }, 
                            new WebFormRouteHandler<Page>("~/Uploads.aspx")));

Of course you may prefer to add your own style of constraint, this one is quite limiting on the route that implements it, but it's just an example of one way you could resolve the issue.

人心善变 2024-08-12 10:57:16

尝试:

<%=Html.RouteLink("Test", "Default", new {controller = "Controller", action = "Action"})%>

使用 RouteLink 而不是 ActionLink 允许您指定要使用的路由,在本例中是默认 MVC 路由映射,而不是您添加的自定义路由映射。

Try:

<%=Html.RouteLink("Test", "Default", new {controller = "Controller", action = "Action"})%>

Using RouteLink instead of ActionLink allows you to specify the route you want to use, which in this case is the Default MVC route mapping as opposed to the custom one you have added.

吃素的狼 2024-08-12 10:57:16

另外:确保您的默认路由是路由表中的最后一个条目。这是另一种简单的方法来结束您所获得的 html 操作链接。

Also: Make sure your Default route is the LAST entry in the routing table. That's another easy way to wind up with the sort of html action link you're getting.

一个人的夜不怕黑 2024-08-12 10:57:16

强制路由默认没有控制器:

var routeDefaults = new RouteValueDictionary() { { "controller", null } };
routes.Add("RouteName", new Route("some/path", routeDefaults, new SomeHandler()));

Force the route defaults to have no controller:

var routeDefaults = new RouteValueDictionary() { { "controller", null } };
routes.Add("RouteName", new Route("some/path", routeDefaults, new SomeHandler()));
单调的奢华 2024-08-12 10:57:16

我也经历过同样的事情,路线“入站”正常工作,但 Html.ActionLink() 选择了错误的路线。我通过添加路由约束来解决这个问题,以便控制器必须为空:

var constraints = new RouteValueDictionary()
{
    { "controller", string.Empty }
};

routes.Add(new Route("sso/server", null, constraints, new OpenIDServerRouteHandler()));

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

由于“控制器”路由值被限制为空,因此对 ActionLink() 的调用最终会忽略该路由。希望这对某人有帮助!

I experienced the same thing where the routes worked correctly "inbound", but Html.ActionLink() was picking the wrong route. I worked around it by adding a route constraint so that the controller must be empty:

var constraints = new RouteValueDictionary()
{
    { "controller", string.Empty }
};

routes.Add(new Route("sso/server", null, constraints, new OpenIDServerRouteHandler()));

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

Since the "controller" route value is restricted to nothing, a call to ActionLink() ends up ignoring the route. Hope this helps someone!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文