使用 URL 重写时的 Url.Action 不正确

Posted

技术标签:

【中文标题】使用 URL 重写时的 Url.Action 不正确【英文标题】:Incorrect Url.Action when URL rewrite is used 【发布时间】:2011-08-13 15:56:01 【问题描述】:

当我使用 URL 重写时,我从 Action 方法得到一个不正确的 URL。

我在 web.config 中有这个重写规则:

<rule name="Old Objects 2" stopProcessing="true">
  <match url="^transportbilar/(nya|begagnade|miljobilar)/(.*)$" ignoreCase="true"/>
  <action type="Rewrite" url="/transportbilar/R:2"/>
</rule>

这会将/transportbilar/nya/fiat/7s76s8dg 之类的 URL 重写为 /transportbilar/fiat/7s76s8dg,这可以正常工作,但 Url.Action 会因此而感到困惑。

我使用这样的表达式在页面中创建一个 URL:

url.Action("Slideshow", "Object", new  id = objectId );

当不使用 URL 重写时(直接浏览到页面),这会生成正确的 URL /Object/Slideshow/7s76s8dg,但是当使用 URL 重写时,Action 方法会将页面 URL 的第一部分添加到生成的 URL,并生成不正确的 URL /transportbilar/Object/Slideshow/7s76s8dg

我认为我可以在重写规则中执行重定向,这样可以避免请求 URL 发生变化时出现的问题,但是有没有办法在不将其更改为重定向的情况下使其工作?

编辑:

我认为可能相关的路线如下(按此顺序添加):

transportbilar/handlare/id/criteria
transportbilar/handlare
transportbilar
transportbilar/sokresultat/criteria
transportbilar/brand/id/criteria
controller/action/id

最后一条路线将捕获 url /Object/Slideshow/7s76s8dg,倒数第二条将捕获 /transportbilar/fiat/7s76s8dg

【问题讨论】:

transportbilar 是虚拟目录吗? 你设置了哪些路由?此外,由于您使用的是 MVC,因此您可能应该使用路由而不是 IIS 重写模块。如果您需要进行用户身份验证,您会遇到更多问题。看看learn.iis.net/page.aspx/496/… @diamandiev:不,它根本不是目录,它是路线的一部分。 @Musaul:我已经添加了我认为可能会影响上述内容的路线。 【参考方案1】:

嗯.. 不要认为我可以帮助您获得基于重写的解决方案。我在内部猜测 IIS/ASP.NET 可能会遇到当您尝试破解路由中的正则表达式映射时可能遇到的问题 - 即 URL.Action 无法从控制器/操作组合中确定正确的反向映射。

您可以查看以下关于您的 URL 的内容,如果这可以为​​您提供有关问题所在的任何提示...

<%= Request.Path %>
<%= Request.RawUrl %>
<%= Request.ServerVariables["HTTP_URL"] %>

...查看该阶段是否正在添加`/transportbilar'。

无论如何,我都会认真地重定向旧版 URL。这种方法将您当前的实际系统与遗留系统隔离开来,尤其是因为您的路线集合似乎已经足够复杂了。

【讨论】:

我把这些放在页面中,RawUrl 包含原始 URL,另一个包含重写后的 URL。这是 IIS 中的错误吗? “破解正则表达式映射”是什么意思? 所以看起来它的 rewriter 正在将 /Object/Slideshow/7s76s8dg 更改为 /transportbilar/Object/Slideshow/7s76s8dg。我会尝试隔离该规则并在具有类似 URL 的单独上下文/网站中尝试它,以查看问题是否可以在那里复制。 正则表达式路由...iridescence.no/post/… @Musaul:不,更改 URL 的不是重写器,而是由 Action 方法生成的 URL。这是用于创建 URL 的路由 controller/action/id,因为这是在 URL 中使用控制器和操作的唯一路由。我没有在路由中使用任何正则表达式。 请求对象中的 URL 不应受url.action 的影响,它们是在 mvc 开始处理请求之前在传入请求中设置的。但是,它们会受到重写模块的影响。如果在那个阶段已经发生了这种情况,mvc 很可能会看到错误的 url,并将其映射到不同的控制器。【参考方案2】:

使用路由而不是 URL 重写,毕竟您使用的是 MVC。

查看这篇关于路由的文章:

http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx

【讨论】:

我已经在使用路由,如果我也将其添加为路由,它们会发生冲突。根据我添加它们的顺序,Action 方法将在我想要 /transportbilar/fiat/7s76s8dg 时生成 URL /transportbilar/nya/fiat/7s76s8dg,或者 URL /transportbilar/nya/fiat/7s76s8dg 将被误解,因此我最终得到 id fiat 而不是 @ 987654327@. 删除 URL 重写并且只使用路由。我不明白为什么那行不通。 Controller=transportbilar Action=fiat Id=7s76s8dg 你不能像这样创建多条路线吗? ... /transportbilar/nya/action/id, /transportbilar/begagnade/action/id 并且它们都由同一个控制器处理吗? ...或者您是否尝试使用 url 重写作为速记? 这行不通,因为我想同时处理/transportbilar/nya/fiat/7s76s8dg/transportbilar/fiat/7s76s8dg @Musaul:如果路线遵循相同的模式,那没问题,而且我已经有多个类似的路线。问题是我有旧版本的网址,其中包含nya/begagnade,而新版本没有这种区别。【参考方案3】:

Url 是否为旧版 Url 重写内容?

您是否可以放弃 Url 重写并使用带有约束的路由。比如:

routes.MapRoute(
    "OldObject2",
    "transportbilar/mycondition/make/id",
    new  controller = "Object", action = "Slideshow" ,
    new
    
        mycondition = "nya|begagnade|miljobila"
    
);

我不确定您的应用正在做什么,因此上述内容可能无法 100% 理解,但应该让您了解我的想法...

【讨论】:

我已经尝试过了,但是使用了三个不同的路线。问题在于,同时拥有transportbilar/nya/make/idtransportbilar/make/id 这样的路线是行不通的。根据添加的顺序,路由映射或 Action 方法使用错误的路由来解码/编码 URL。 @Guffa,你为什么不把mycondition 设为可选? @Gaby aka G. Petrioli:我试过了,但解析 URL 或计算操作都不起作用。【参考方案4】:

这对我有用(从另一个答案中借了一点):

routes.MapRoute(
    "NewRoute",
    "transportbilar/make/id",
    new  controller = "Home", action = "Test" 
);
routes.MapRoute(
    "OldRoute",
    "transportbilar/mycondition/make/id",
    new  controller = "Home", action = "Test" ,
    new
    
        mycondition = "nya|begagnade|miljobila"
    
);

新的先行,所以辅助方法可以解决它。但两者都转到相同的控制器和操作。

<p>@html.ActionLink("link", "Test", new  make = "testmake4", id = 5)</p>

在旧 URL 和新 URL 上,这都解析为 /transportbilar/testmake4/5

【讨论】:

感谢您为测试它所做的努力。我已经尝试过(之前和现在再次),并且两个 URL 都解析为第一条路线。它可能在您的测试中有效,因为获取 make="nya" 和 id="testmarke4" 不会导致错误,但是当将 make 发送到控制器方法中的 id 参数时我会收到错误并且它不能已解析。 确保您没有将 id 参数标记为可选。这可能会导致它匹配错误的规则。 也只是仔细检查了两种情况下的值都是正确的。 (MVC 3)【参考方案5】:

您可以使用这些功能来避免这些问题:

    public static string UrlAction(string actionName) 
        return String.Format("/0", actionName);
    

    public static string UrlAction(string actionName, string controllerName) 
        return String.Format("/0/1", controllerName, actionName);
    

    public static string UrlAction(string actionName, string controllerName, RouteValueDictionary routeValues) 
        string url = String.Format("/0/1", controllerName, actionName);

        var parameters = routeValues.Select(s => string.Format("0=1", s.Key, s.Value))
            .Aggregate((current, next) => string.Format("0&1", current, next));

        return url+"?"+parameters;
    

【讨论】:

以上是关于使用 URL 重写时的 Url.Action 不正确的主要内容,如果未能解决你的问题,请参考以下文章

使用 Url.action() 传递动态 javascript 值

尝试创建友好且“可破解”的 url 时使用 Url.Action() 时遇到问题

URL.Action 在构造 URL 时包含 id

使用 Url.Action (ASP.NET MVC) 将分号附加到 href URL

使用 Url.action 调用控制器方法时仅获取第一个参数值。

URL::action 在 jquery ajax 中不起作用