ASP.NET MVC игнорировать ".html" в конце всех URL - PullRequest
10 голосов
/ 15 декабря 2010

Я новичок в asp.net mvc и теперь борюсь с маршрутизацией URL. Я использую asp.net MVC 3 RC2.

Как мне создать URL-маршрутизацию, которая IGNORES самое конечное расширение в URL расширение может быть: .html, .aspx, .php, .anything.

Например, эти URL:

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

должен перейти на Home контроллер?

еще один пример:

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

должен перейти на Home контроллер и About действие.

спасибо:)

Ответы [ 7 ]

6 голосов
/ 20 декабря 2010

Я не уверен, что вы используете IIS7, но если это так, то я бы порекомендовал правило перезаписи, которое проверяет URL-адреса, заканчивающиеся на .xyz, а затем выполняет перезапись для них без .xyz.

Примерно так:

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

Это обработает предложенные вами варианты использования. Все, что заканчивается расширением и некоторыми символами, будет переписано в URL без расширения. Преимущество этого состоит в том, что вам нужен только один маршрут, потому что все идет в ваше приложение без него.

3 голосов
/ 15 декабря 2010

Вам просто нужно настроить маршрут по умолчанию в Global.asax.cs, попробуйте это:

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

Значение {extension} из URL будет включено в данные маршрута, но вы можете просто проигнорировать его, если оно вам не нужно

1 голос
/ 22 декабря 2010

Использование 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);
                }
            }
        }
1 голос
/ 19 декабря 2010

Вы могли бы обработать это в IIS вместо ASP.NET MVC, используя переписывание URL-адреса IIS. См. Например: http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/

1 голос
/ 19 декабря 2010

Я начал работать над этим вопросом как задание на выходные дни: D
, приведенный ниже, код будет работать в соответствии с запросом.Пожалуйста, обратитесь ниже ссылки

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 //3174671/asp-net-mvc-ignorirovat-html-v-kontse-vseh-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.

1 голос
/ 15 декабря 2010

Либо создайте свой собственный класс маршрута, либо используйте эту реализацию маршрута в регулярном выражении: http://blog.sb2.fr/post/2009/01/03/Regular-Expression-MapRoute-With-ASPNET-MVC.aspx

0 голосов
/ 22 декабря 2010

Если вы используете IIS 7, вам следует посмотреть ответ Дэна Аткинсона .

Я использую IIS 6, поэтому в моем случае у меня есть возможность установить переписать isapi для 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;
    }
}

RegisterRoutes метод в 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
    );

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...