ASP.NET MVC在所有url的末尾忽略“.html”

时间:2010-12-15 11:35:58

标签: asp.net-mvc url-routing

我是asp.net mvc的新手,现在正在努力使用url路由。我正在使用asp.net mvc 3 RC2。

如何在网址中创建 IGNORES 最终扩展名的网址路由。扩展名可以是:.html.aspx.php.anything

例如,这些网址:

/Home.html
/Home.en
/Home.fr
/Home

应该转到Home控制器?

又一个例子:

/Home/About.html
/Home/About.en
/Home/About.fr
/Home/About

应该转到Home控制器和About操作。

谢谢你:)

7 个答案:

答案 0 :(得分:6)

我不确定你是否在使用IIS7,但如果是这样,那么我会推荐一个重写规则来检查以.xyz结尾的网址,然后在没有.xyz的情况下对它们进行重写}。

这样的事情:

<rewrite>
  <rules>
    <rule name="HtmlRewrite">
      <match url="(.*)(\.\w+)$" />
      <action type="Rewrite" url="{R:1}" />
    </rule>
  </rules>
</rewrite>

这将处理您建议的用例。任何以扩展名和某些字符结尾的内容都将被重写为没有扩展名的网址。这样做的好处是,您只需要一条路线,因为没有一条路线,一切都会进入您的应用程序。

答案 1 :(得分:3)

你只需要在Global.asax.cs中调整默认路由,试试这个:

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

来自网址的{extension}值将包含在路由数据中,但如果您不需要,可以放心地忽略它

答案 2 :(得分:1)

创建自己的路由类,或使用此正则路由路由实现:http://blog.sb2.fr/post/2009/01/03/Regular-Expression-MapRoute-With-ASPNET-MVC.aspx

答案 3 :(得分:1)

我开始把这个问题作为周末作业来处理: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&amp;pg=PA251&amp;lpg=PA251&amp;dq=.net+RouteBase&amp;source=bl&amp;ots=IQhFwmGOVw&amp;sig=0TgcFFgWyFRVpXgfGY1dIUc0VX4&amp;hl=en&amp;ei=z61UTMKwF4aWsgPHs7XbAg&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=6&amp;ved=0CC4Q6AEwBQ#v=onepage&amp;q=.net%20RouteBase&amp;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代码。

答案 4 :(得分:1)

可以使用IIS Url重写在IIS而不是ASP.NET MVC中处理此问题。例如,请参阅:http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/

答案 5 :(得分:1)

使用Application_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);
                }
            }
        }

答案 6 :(得分:0)

如果您使用的是IIS 7,则应该查看Dan Atkinson's answer

我正在使用IIS 6,因此,在我的情况下,我可以选择安装isapi rewrite for 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;
    }

}

<强> RouteCollectionExtensionHelper.cs

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;
    }
}
Global.asax

中的

RegisterRoutes 方法

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
    );

}