Ser*_*eit 13 asp.net-mvc routes asp.net-mvc-routing system.web.routing asp.net-mvc-3
我有一个ASP.NET MVC 3应用程序,用户可以发布建议,如果 " 如果 yada yada yada,bla bla 会更好 ".对于建议详细信息页面,我已经定义了一个很好的SEO友好路线如下:
routes.MapRoute(null, "suggestion/{id}/{it}/would-be-better-if-{if}",
new { controller = "suggestion", action = "details" });
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我希望修复"将会更好".
此路由适用于任何旧建议并生成类似链接suggestion/5/this-site/would-be-better-if-it-had-a-iphone-application,并且单击链接实际请求相应的详细信息页面.
我的一个朋友,具有讽刺意味的恰好是一个测试人员,已经设法,不由自主地发布了一条实际上打破了这条路线的建议:" 如果'总是在中间对齐,那么这个网站会更好 ".
为此建议生成的链接是
/suggestion/84/this-site/would-be-better-if-would-be-better-if-was-always-alligned-in-the-middle.
我已经尝试了Phil Haack的路由调试器,并确认该路由实际上会工作到suggestion/84/this-site/would-be-better-if-would-be-better-if-,所以第二个"将会更好 - 如果"实际上已被接受; 之后添加任何内容实际上会导致网址不匹配任何路由(感谢Omar -see评论 - 寻求帮助).
请记住,我真的不想改变路线定义,因为我认为这对于这个案例来说是一样好,SEO-wise.
那么,如何让文本等于路由的固定部分会阻止链接匹配路由?路线为何破裂?
我实际上对这个原因更感兴趣,因为我相信理解为什么会导致解决方案或至少正确理解一个相当有趣的问题.
我不确定它为什么会这样,但你可以使用这样的东西:
public interface IRouteRule
{
object ProcessIncoming(object value);
object ProcessOutgoing(object value);
}
public class StartsWithRouteRule : IRouteRule
{
public StartsWithRouteRule(string value)
{
Value = value;
}
public string Value { get; protected set; }
public object ProcessIncoming(object value)
{
var result = value as string;
if (result == null)
return null;
if (!result.StartsWith(Value))
return null;
return result.Substring(Value.Length);
}
public object ProcessOutgoing(object value)
{
var result = value as string;
if (result == null)
return null;
return Value + result;
}
}
public class ComplexRoute : Route
{
public ComplexRoute(string url, object defaults, object rules)
: this(url, new RouteValueDictionary(defaults), rules)
{ }
public ComplexRoute(string url, RouteValueDictionary defaults, object rules)
: base(url, defaults, new MvcRouteHandler())
{
Rules = new Dictionary<string, IRouteRule>();
foreach (var pair in new RouteValueDictionary(rules))
Rules.Add(pair.Key, (IRouteRule)pair.Value);
}
public Dictionary<string, IRouteRule> Rules { get; protected set; }
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var result = base.GetRouteData(httpContext);
if (result == null)
return null;
foreach (var pair in Rules)
{
var currentValue = result.Values[pair.Key];
if (currentValue == null)
return null;
var value = pair.Value.ProcessIncoming(currentValue);
if (value == null)
return null;
result.Values[pair.Key] = value;
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
values = new RouteValueDictionary(values);
foreach (var pair in Rules)
{
var currentValue = values[pair.Key];
if (currentValue == null)
return null;
var value = pair.Value.ProcessOutgoing(currentValue);
if (value == null)
return null;
values[pair.Key] = value;
}
return base.GetVirtualPath(requestContext, values);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
routes.Add(new ComplexRoute(
"suggestion/{id}/{it}/{if}",
new { controller = "suggestion", action = "details" },
new { @if = new StartsWithRouteRule("would-be-better-if-") }));
Run Code Online (Sandbox Code Playgroud)