Asp.net mvc ASP.NET MVC将忽略“0”;。html";在所有url的末尾
我是asp.net mvc新手,现在正在努力解决url路由问题。我正在使用asp.NETMVC3RC2 如何创建一个忽略url中最末端扩展名的url路由。扩展名可以是:Asp.net mvc ASP.NET MVC将忽略“0”;。html";在所有url的末尾,asp.net-mvc,url-routing,Asp.net Mvc,Url Routing,我是asp.net mvc新手,现在正在努力解决url路由问题。我正在使用asp.NETMVC3RC2 如何创建一个忽略url中最末端扩展名的url路由。扩展名可以是:.html,.aspx,.php,。任何内容 例如,这些URL: /Home.html /Home.en /Home.fr /Home 是否应转到主页控制器 还有一个例子: /Home/About.html /Home/About.en /Home/About.fr /Home/About 应转到主页控制器和关于操作 谢谢:)
.html
,.aspx
,.php
,。任何内容
例如,这些URL:
/Home.html
/Home.en
/Home.fr
/Home
是否应转到主页
控制器
还有一个例子:
/Home/About.html
/Home/About.en
/Home/About.fr
/Home/About
应转到主页
控制器和关于
操作
谢谢:)您只需在Global.asax.cs中调整默认路由,请尝试以下操作:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}.{extension}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
url中的{extension}值将包含在路由数据中,但是如果您不需要它,您可以安全地忽略它。创建您自己的路由类,或者使用此正则表达式路由实现:我开始将此问题作为周末作业来处理:D
下面的代码将按照问题中的要求工作。请参考以下参考资料 1] MyUrlRoute类:RouteBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcIgnoreUrl
{
#region //References
// SO question /http://stackoverflow.com/questions/4449449/asp-net-mvc-to-ignore-html-at-the-end-of-all-url
// Implementing Custom Base entry - Pro Asp.Net MVc Framework
//- http://books.google.com/books?id=tD3FfFcnJxYC&pg=PA251&lpg=PA251&dq=.net+RouteBase&source=bl&ots=IQhFwmGOVw&sig=0TgcFFgWyFRVpXgfGY1dIUc0VX4&hl=en&ei=z61UTMKwF4aWsgPHs7XbAg&sa=X&oi=book_result&ct=result&resnum=6&ved=0CC4Q6AEwBQ#v=onepage&q=.net%20RouteBase&f=false
// SO previous Question on ihttphandler - http://stackoverflow.com/questions/3359816/can-asp-net-routing-be-used-to-create-clean-urls-for-ashx-ihttphander-handle
// phil haack's Route Debugger http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
#endregion
public class MyUrlRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//~/Account/LogOn
//~/Home.aspx - Works fine
//~/home/index.aspx -Works Fine
//http://localhost:57282/home/index/1/2/3 - Works fine
//http://localhost:57282/Account/Register http://localhost:57282/Account/LogOn - Works Fine
string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
//check null for URL
const string defaultcontrollername = "Home";
string[] spliturl = url.Split("//".ToCharArray());
string controllername = String.Empty;
string actionname = "Index";
if (spliturl.Length == 2) //for ~/home.aspx and ~/
{
if (String.IsNullOrEmpty(spliturl[1])) //TODO: http://localhost:57282/ not working - to make it working
{
controllername = defaultcontrollername;
}
else
{
controllername = spliturl[1];
if (controllername.Contains("."))
{
controllername = controllername.Substring(0, controllername.LastIndexOf("."));
}
}
}
else if (spliturl.Length == 3) // For #/home/index.aspx and /home/about
{
controllername = spliturl[1];
actionname = spliturl[2];
if (actionname.Contains("."))
{
actionname = actionname.Substring(0, actionname.LastIndexOf("."));
}
}
else //final block in final case sned it to Home Controller
{
controllername = defaultcontrollername;
}
RouteData rd = new RouteData(this, new MvcRouteHandler());
rd.Values.Add("controller", controllername);
rd.Values.Add("action", actionname);
rd.Values.Add("url", url);
return rd;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
}
在global.asax.cs中添加以下代码
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new MyUrlRoute()); // Add before your default Routes
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
按预期工作
可能您可以改进if/elseif代码。您可以在IIS中处理此问题,而不是在ASP.NET MVC中使用IIS Url重写。例如,请参阅:我不确定您是否正在使用IIS7,但如果是这样,我建议使用重写规则,检查以
.xyz
结尾的URL,然后在不使用.xyz
的情况下对其进行重写
大概是这样的:
<rewrite>
<rules>
<rule name="HtmlRewrite">
<match url="(.*)(\.\w+)$" />
<action type="Rewrite" url="{R:1}" />
</rule>
</rules>
</rewrite>
这将处理您建议的用例。任何以扩展名和某些字符结尾的内容都将被重写为不带扩展名的url。这样做的好处是,您只需要一条路由,因为所有内容都进入应用程序而没有路由。使用
应用程序_BeginRequest
,将允许您拦截所有传入请求,并允许您修剪扩展。确保忽略对内容的请求,如.css、.js、.jpg等。否则这些请求的扩展名也会被删除
protected void Application_BeginRequest(object sender, EventArgs e)
{
String originalPath = HttpContext.Current.Request.Url.AbsolutePath;
//Ignore content files (e.g. .css, .js, .jpg, .png, etc.)
if (!Regex.Match(originalPath, "^/[cC]ontent").Success)
{
//Search for a file extension (1 - 5 charaters long)
Match match = Regex.Match(originalPath, "\\.[a-zA-Z0-9]{1,5}$");
if (match.Success)
{
String modifiedPath = String.Format("~{0}", originalPath.Replace(match.Value, String.Empty));
HttpContext.Current.RewritePath(modifiedPath);
}
}
}
如果您使用的是IIS 7,则应查看 我使用的是IIS 6,因此,在我的情况下,我可以选择安装或创建自定义路由。我更喜欢创建简单的自定义路由类 AndraRoute.cs
// extend Route class,
// so that we can manipulate original RouteData
// by overriding method GetRouteDate
public class AndraRoute : Route
{
// constructor
public AndraRoute(
string url,
RouteValueDictionary defaults,
RouteValueDictionary constraints,
IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler)
{
}
// get original RouteData
// check if any route data value has extension '.html' or '.anything'
// remove the extension
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var data = base.GetRouteData(httpContext);
if (data == null) return null;
// from original route data, check
foreach (var pair in data.Values)
{
if (pair.Value.ToString().Contains('.'))
{
var splits = pair.Value.ToString().Split('.');
if (splits[1] == "html" || splits[1] == "anything")
{
data.Values[pair.Key] = splits[0];
}
break;
}
}
return data;
}
}
public static class RouteCollectionExtensionHelper
{
public static Route MapAndraRoute(this RouteCollection routes,
string name, string url, object defaults, object constraints,
string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
var route = new AndraRoute(url,
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints),
new MvcRouteHandler());
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens = new RouteValueDictionary();
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
}
RouteCollectionExtensionHelper.cs
// extend Route class,
// so that we can manipulate original RouteData
// by overriding method GetRouteDate
public class AndraRoute : Route
{
// constructor
public AndraRoute(
string url,
RouteValueDictionary defaults,
RouteValueDictionary constraints,
IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler)
{
}
// get original RouteData
// check if any route data value has extension '.html' or '.anything'
// remove the extension
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var data = base.GetRouteData(httpContext);
if (data == null) return null;
// from original route data, check
foreach (var pair in data.Values)
{
if (pair.Value.ToString().Contains('.'))
{
var splits = pair.Value.ToString().Split('.');
if (splits[1] == "html" || splits[1] == "anything")
{
data.Values[pair.Key] = splits[0];
}
break;
}
}
return data;
}
}
public static class RouteCollectionExtensionHelper
{
public static Route MapAndraRoute(this RouteCollection routes,
string name, string url, object defaults, object constraints,
string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
var route = new AndraRoute(url,
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints),
new MvcRouteHandler());
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens = new RouteValueDictionary();
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
}
全局.asax中的registerOutes方法
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("Content/{*pathInfo}");
routes.MapAndraRoute(
"Product",
"product/{id}/{slug}",
new { controller = "product", action = "detail" },
null, null
);
routes.MapAndraRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "home", action = "index", id = UrlParameter.Optional },
null, null
);
}
这意味着我必须为“{controller}.{extension}/{action}/{id}”和“{controller}/{action}/{id}.{extension}”再次创建。你有没有更好的主意,因为我不想调整我所有的路线:(好吧,这些是不同的路由,所以它们需要这样设置,我没有更好的建议。您是使用默认路由还是有许多自定义路由?目前,只有来自模板的默认路由。但稍后将添加更多路由并将此规则应用于它们。这看起来难以置信且不必要。url路由与r一样工作这是一个相当好的技巧!!我需要更多的阅读,但我认为框架一定在做类似的事情…当然不是对我。如果你有任何更好的解决方案,这个悬赏将一直持续到明天,适用于任何IIS版本:DOk。实际上没有任何其他的解决方案。只有下面提到的解决方案覆盖“RouteData作为GetRouteData(HttpContextBase httpContext)”适用于任何IIS版本:)