Asp.net mvc ASP.NET MVC将忽略“0”;。html";在所有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 应转到主页控制器和关于操作 谢谢:)

我是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
应转到
主页
控制器和
关于
操作


谢谢:)

您只需在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版本:)