tag parameter net mvc asp asp.net-mvc url url-routing seo

asp.net-mvc - parameter - html tags asp net core



Soporte MVC de ASP.net para URL con guiones (8)

¿Hay alguna manera fácil de hacer que MvcRouteHandler convierta todos los guiones en las secciones de acción y de control de una URL entrante para subrayar, ya que los guiones no son compatibles con los métodos o nombres de clase.

Esto sería para poder soportar estructuras tales como sample.com/test-page/edit-details mapeando a Action edit_details y Controller test_pagecontroller mientras continúas usando el método MapRoute.

Entiendo que puedo especificar un atributo de nombre de acción y guiones de apoyo en los nombres de los controladores, que agregan rutas manualmente para lograr esto, pero estoy buscando una forma automática, así que guarde los errores al agregar nuevos controladores y acciones.


Desarrollé una biblioteca de código abierto NuGet para este problema que implícitamente convierte EveryMvc / Url en cada mvc / url.

Las URL discontinuas son mucho más amigables con el SEO y más fáciles de leer. ( Más en mi blog )

Paquete NuGet: https://www.nuget.org/packages/LowercaseDashedRoute/

Para instalarlo, simplemente abra la ventana de NuGet en el Visual Studio haciendo clic con el botón derecho en el Proyecto y seleccionando Administrador de paquetes NuGet, y en la pestaña "En línea" escriba "Ruta discontinua en minúsculas", y debería aparecer.

Alternativamente, puede ejecutar este código en la consola del Administrador de paquetes:

Install-Package LowercaseDashedRoute

Después de eso, debería abrir App_Start / RouteConfig.cs y comentar la ruta existente. LlameMapRoute (...) y agregue esto en su lugar:

routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}", new RouteValueDictionary( new { controller = "Home", action = "Index", id = UrlParameter.Optional }), new DashedRouteHandler() ) );

Eso es. Todas las URL son minúsculas, discontinuas y se convierten implícitamente sin que usted haga nada más.

URL del proyecto de código abierto: https://github.com/AtaS/lowercase-dashed-route


Gracias dsteuernol por esta respuesta, exactamente lo que estaba buscando. Sin embargo, descubrí que necesitaba mejorar el HyphenatedRouteHandler para cubrir el escenario donde el Controlador o el Área estaban implícitos desde la página actual. Por ejemplo, usando @ Html.ActionLink ("Mi enlace", "Índice")

Cambié el método GetHttpHandler a lo siguiente:

public class HyphenatedRouteHandler : MvcRouteHandler { /// <summary> /// Returns the HTTP handler by using the specified HTTP context. /// </summary> /// <param name="requestContext">The request context.</param> /// <returns> /// The HTTP handler. /// </returns> protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { requestContext.RouteData.Values["controller"] = ReFormatString(requestContext.RouteData.Values["controller"].ToString()); requestContext.RouteData.Values["action"] = ReFormatString(requestContext.RouteData.Values["action"].ToString()); // is there an area if (requestContext.RouteData.DataTokens.ContainsKey("area")) { requestContext.RouteData.DataTokens["area"] = ReFormatString(requestContext.RouteData.DataTokens["area"].ToString()); } return base.GetHttpHandler(requestContext); } private string ReFormatString(string hyphenedString) { // lets put capitals back in // change dashes to spaces hyphenedString = hyphenedString.Replace("-", " "); // change to title case hyphenedString = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(hyphenedString); // remove spaces hyphenedString = hyphenedString.Replace(" ", ""); return hyphenedString; } }

Volver a colocar las mayúsculas significaba que el controlador implícito o el área se dividen en guiones correctamente.


He resuelto una solución. El requestContext dentro de MvcRouteHandler contiene los valores para el controlador y la acción en la que puede hacer un simple reemplazo.

Public Class HyphenatedRouteHandler Inherits MvcRouteHandler Protected Overrides Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler requestContext.RouteData.Values("controller") = requestContext.RouteData.Values("controller").ToString.Replace("-", "_") requestContext.RouteData.Values("action") = requestContext.RouteData.Values("action").ToString.Replace("-", "_") Return MyBase.GetHttpHandler(requestContext) End Function End Class

Luego, todo lo que necesita para reemplazar las rutas.MapaRuta con rutas equivalentes.Agregue especificando el nuevo manejador de ruta. Esto es necesario ya que MapRoute no le permite especificar un manejador de ruta personalizado.

routes.Add(New Route("{controller}/{action}/{id}", New RouteValueDictionary(New With {.controller = "Home", .action = "Index", .id = ""}), New HyphenatedRouteHandler()))


Me doy cuenta de que esta es una pregunta bastante antigua, pero para mí esto es solo la mitad de la historia de aceptar url''s con guiones en ellos, la otra mitad está generando estas URL mientras aún se puede usar Html.ActionLink y otros ayudantes en el framework MVC. Lo resolví creando una clase de ruta personalizada similar, aquí está el código en caso de que ayude a cualquiera que venga desde una búsqueda en Google. También incluye la carcasa inferior de la url también.

public class SeoFriendlyRoute : Route { // constructor overrides from Route go here, there is 4 of them public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { var path = base.GetVirtualPath(requestContext, values); if (path != null) { var indexes = new List<int>(); var charArray = path.VirtualPath.Split(''?'')[0].ToCharArray(); for (int index = 0; index < charArray.Length; index++) { var c = charArray[index]; if (index > 0 && char.IsUpper(c) && charArray[index - 1] != ''/'') indexes.Add(index); } indexes.Reverse(); indexes.Remove(0); foreach (var index in indexes) path.VirtualPath = path.VirtualPath.Insert(index, "-"); path.VirtualPath = path.VirtualPath.ToLowerInvariant(); } return path; } }

luego, cuando agrega rutas, puede crear una extensión RouteCollection o simplemente usar lo siguiente en sus declaraciones de enrutamiento globales

routes.Add( new SeoFriendlyRoute("{controller}/{action}/{id}", new RouteValueDictionary( new { controller = "Default", action = "Index", id = "" }), new HyphenatedRouteHandler()) );


No sé de una manera sin escribir un mapa para cada url:

routes.MapRoute("EditDetails", "test-page/edit-details/{id}", new { controller = "test_page", action = "edit_details" });


Si actualiza su proyecto a MVC5, puede utilizar el enrutamiento de atributos.

[Route("controller/my-action")] public ActionResult MyAction() { return View(); }

Prefiero este enfoque a la solución aceptada, lo que te deja con guiones bajos en los nombres de tus acciones de control y ver nombres de archivos, y guiones en los ayudantes de Url.Action de tu vista. Prefiero la coherencia y no tener que recordar cómo se convierten los nombres.


Todo lo que necesita hacer en este caso es nombrar sus puntos de vista con los guiones como desea que aparezcan en la URL, eliminar los guiones en su controlador y luego agregar un atributo ActionName que contenga los guiones. No hay necesidad de tener guiones bajos en absoluto.

Tener una vista llamada edit-details.aspx

Y tenga un controlador como este:

[ActionName("edit-details")] public ActionResult EditDetails(int id) { // your code }


Versión de C # de John''s Post para cualquiera que lo prefiera: la versión C # y VB en mi blog

public class HyphenatedRouteHandler : MvcRouteHandler{ protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { requestContext.RouteData.Values["controller"] = requestContext.RouteData.Values["controller"].ToString().Replace("-", "_"); requestContext.RouteData.Values["action"] = requestContext.RouteData.Values["action"].ToString().Replace("-", "_"); return base.GetHttpHandler(requestContext); } }

... y la nueva ruta:

routes.Add( new Route("{controller}/{action}/{id}", new RouteValueDictionary( new { controller = "Default", action = "Index", id = "" }), new HyphenatedRouteHandler()) );

También puedes utilizar el siguiente método, pero ten en cuenta que deberás nombrar la vista Mi-Acción que puede ser molesta si te gusta dejar que visual studio genere automáticamente tus archivos de vista.

[ActionName("My-Action")] public ActionResult MyAction() { return View(); }