我有ASP.NET MVC路由问题。
我准备了以下路由表来映射这样的URL
mywebsite / myController的/ myaction / 14-longandprettyseoname
参数:
14 => id(整数)
longandprettyseoname - > seo_name(string)
routes.MapRoute(
"myname",
"mycontroller/myaction/{id}-{seo_name}",
new { controller = "mycontroller", action = "myaction", id = 0, seo_name = (string)null });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
它适用于上面的网址,但它有以下类型的网址
的问题mywebsite / myController的/ myaction / 14长和相当-SEO-名称
这有可能使它有效吗?
修改
"mycontroller/myaction/{seo_name}-{id}"
似乎正在运作
答案 0 :(得分:1)
最明显的方法是使用约束。
由于您的id是一个整数,您可以添加一个约束来查找整数值:
new { id = @"\d+" }
这是整个路线:
routes.MapRoute("myname","mycontroller/myaction/{id}-{seo_name}",
new { controller = "mycontroller", action = "myaction" },
new { id = @"\d+"});
答案 1 :(得分:1)
我的解决方案是将路线定义为:
routes.MapRoute("myname","mycontroller/myaction/{id}",
new { controller = "mycontroller", action = "myaction"});
并在HTTP处理程序中使用Regex解析id和seoname:
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(context));
var match = System.Text.RegularExpressions.Regex.Match((string)routeData.Values["id"], @"^(?<id>\d+)-(?<seoname>[\S\s]*)$");
if (!match.Success)
{
context.Response.StatusCode = 400;
context.Response.StatusDescription = "Bad Request";
return;
}
int id = Int32.Parse(match.Groups["id"].Value);
string seoname = match.Groups["seoname"].Value;
答案 2 :(得分:0)
我不认为该路线是可区分的,因为它无法确定要分割哪个“ - ”以指定{id}
和{seo-name}
。
如何使用下划线作为您的SEO名称?或者您可以使用SEO名称作为实际{id}
。如果SEO名称是唯一的,那么这是一个非常可行的选项,您可以将其用作数据库中该条目的伪主键(假设它从数据库中提取内容)
另外,利用Phil Haack的route debugger来查看哪些有效且无效。
答案 3 :(得分:0)
您可以做的是创建自定义控制器工厂。这样,您就可以使用自定义代码来决定何时需要调用哪个控制器。
public class CustomControllerFactory : IControllerFactory
{
#region IControllerFactory Members
public IController CreateController(RequestContext requestContext, string controllerName)
{
if (string.IsNullOrEmpty(controllerName))
throw new ArgumentNullException("controllerName");
//string language = requestContext.HttpContext.Request.Headers["Accept-Language"];
//can be used to translate controller name and get correct controller even when url is in foreign language
//format controller name
controllerName = String.Format("MyNamespace.Controllers.{0}Controller",controllerName.Replace("-","_"));
IController controller = Activator.CreateInstance(Type.GetType(controllerName)) as IController;
controller.ActionInvoker = new CustomInvoker(); //only when using custominvoker for actionname rewriting
return controller;
}
public void ReleaseController(IController controller)
{
if (controller is IDisposable)
(controller as IDisposable).Dispose();
else
controller = null;
}
#endregion
}
要使用此自定义controllerfactory,您应将其添加到global.asax
中protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
}
请注意,这仅适用于控制器,而不适用于操作...要在操作执行之前连接自定义重写,请使用以下代码:
public class CustomInvoker : ControllerActionInvoker
{
#region IActionInvoker Members
public override bool InvokeAction(ControllerContext controllerContext, string actionName)
{
return base.InvokeAction(controllerContext, actionName.Replace("-", "_"));
}
#endregion
}
我从this blog获得了大部分代码,并根据我的需要进行了调整。在我的情况下,我希望破折号在我的控制器名称中分隔单词,但是你不能在名称中创建带破折号的动作。
希望这有帮助!
答案 4 :(得分:0)
定义特定路线,例如:
routes.MapRoute(
"TandC", // Route controllerName
"CommonPath/{controller}/Terms-and-Conditions", // URL with parameters
new { controller = "Home", action = "Terms_and_Conditions" } // Parameter defaults
);
但是这条路线必须在之前注册您的默认路线。