ASP.NET MVC to ignore “.html” at the end of all url

后端 未结 7 647
心在旅途
心在旅途 2021-01-04 18:52

I am new to asp.net mvc and now struggling with url routing. I\'m using asp.net mvc 3 RC2.

How can I create a url routing that IGNORES the very end

相关标签:
7条回答
  • 2021-01-04 19:34

    If you are using IIS 7, you should look at Dan Atkinson's answer.

    I'm using IIS 6, so, in my case, I have the option to install isapi rewrite for IIS 6 or create custom route. I prefer to create my simple custom route class

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

    RegisterRoutes method in Global.asax

    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
        );
    
    }
    
    0 讨论(0)
  • 2021-01-04 19:37

    You could handle this in IIS instead of ASP.NET MVC using IIS Url rewriting. See for example: http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/

    0 讨论(0)
  • 2021-01-04 19:39

    Using the Application_BeginRequest, will allow you to intercept all incoming requests, and allow you to trim the extension. Make sure to ignore requests for your content, such as .css, .js, .jpg, etc. Otherwise those requests will have their extensions trimmed as well.

    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);
                    }
                }
            }
    
    0 讨论(0)
  • 2021-01-04 19:44

    I started to work on this question as a weekend assignment :D
    below code will work as requested in question. please refer below references

    1] MyUrlRoute Class : 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;
        }
    }
    

    }

    in global.asax.cs add below code

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

    working as expected.

    possibly you can improve if/elseif code.

    0 讨论(0)
  • 2021-01-04 19:48

    You just need to tweak the default route in Global.asax.cs, try this:

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

    The {extension} value from the url will be included in the route data, but you can just safely ignore it if you don't need it

    0 讨论(0)
  • 2021-01-04 19:50

    I'm not sure if you're using IIS7, but if so, then I would recommend a rewrite rule which checks for urls ending in .xyz and then doing a rewrites for them without the .xyz.

    Something like this:

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

    This will handle the use cases you suggested. Anything that ends with an extension and some characters will be rewritten to a url without the extension. The benefit of this is that you will only need one route because everything goes into your application without one.

    0 讨论(0)
提交回复
热议问题