2010-12-15 44 views
10

Soy nuevo en asp.net mvc y ahora tengo problemas con el enrutamiento url. Estoy usando asp.net mvc 3 RC2.ASP.NET MVC para ignorar ".html" al final de todas las direcciones url

¿Cómo puedo crear un enrutamiento url que IGNORES la extensión final en url. la extensión puede ser: .html, .aspx, .php, .anything.

Por ejemplo, estas URL:

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

debe ir a Home controlador?

un ejemplo más:

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

debe ir a Home controlador y About acción.

Gracias :)

Respuesta

6

No estoy seguro de si está utilizando IIS 7, pero si es así, entonces recomendaría una regla de reescritura que comprueba las direcciones URL que terminan en .xyz y luego haciendo un reescrituras para ellos sin la .xyz.

Algo como esto:

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

Este se encargará de los casos de uso que se sugieran. Todo lo que termine con una extensión y algunos caracteres se reescribirá en una url sin la extensión. El beneficio de esto es que solo necesitará una ruta porque todo entra en su aplicación sin una.

3

Sólo tiene que modificar la ruta predeterminada en Global.asax.cs, intente esto:

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

La extensión} {valor a partir de la URL se incluirán en el datos de la ruta, pero sólo puede pasar por alto que si no lo necesita

+0

significa que tengo que volver a crear para "{controller}. {Extension}/{action}/{id}" y para "{controller}/{action}/{id}. {Extension}". ¿tienes alguna idea mejor, porque no quiero modificar todas mis rutas :( –

+0

Bueno, esas son rutas distintas, por lo que deberán configurarse como tales, no tengo una mejor sugerencia. ¿Estás utilizando? la ruta predeterminada o tiene una multitud de rutas personalizadas? – JonoW

+0

actualmente, solo la ruta predeterminada desde la plantilla, pero luego agregará más rutas y les aplicará esta regla –

1

Empecé a trabajar en esta cuestión como una asignación de fin de semana: D
a continuación el código funcionará según lo solicitado en cuestión. consulte a continuación hace referencia a

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

}

en global.asax.cs añadir a continuación el código

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

    } 

funciona como se esperaba.

posiblemente pueda mejorar el código if/elseif.

+0

Esto se ve increíblemente e innecesariamente hacky . –

+0

el enrutamiento url funciona como se lo solicito, entonces es un buen truco !! Tengo que leer más, pero creo que el framework debe estar haciendo algo similar ... – swapneel

1

El uso del Application_BeginRequest le permitirá interceptar todas las solicitudes entrantes y le permitirá recortar la extensión. Asegúrese de ignorar las solicitudes de su contenido, como .css, .js, .jpg, etc. De lo contrario, las solicitudes tendrán sus extensiones recortadas también.

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

Si está utilizando IIS 7, debe consultar Dan Atkinson's answer.

Estoy usando IIS 6, entonces, en mi caso, tengo la opción de instalar isapi rewrite for IIS 6 o crear una ruta personalizada. Prefiero crear mi sencilla clase de ruta personalizada

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 método en el 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

+50 Bounty se concede a ...? – swapneel

+0

no para mí, por supuesto, esta recompensa permanecerá abierta hasta mañana si tienes una solución mejor para cualquier versión de IIS: D –

+0

Ok, realmente no hay ninguna otra solución en mente Solo la solución mencionada anteriormente reemplaza a "RouteData como GetRouteData (HttpContextBase httpContext)" que funciona para cualquier versión de IIS :) – swapneel

Cuestiones relacionadas