c# - Enrutamiento en ASP.NET MVC, mostrando nombre de usuario en URL
asp.net-mvc routes (2)
Estoy tratando de hacer una ruta para poder mostrar el nombre de usuario en la URL de esta manera:
Aquí está mi routeconfig:
routes.MapRoute(
name: "users", // Route name
url: "{username}", // URL with parameters
defaults: new { controller = "Home", action = "Index", username = "" } // Parameter defaults
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Aquí está mi HomeController:
public ActionResult Index(string username = "Test")
{
return View();
}
En primer lugar, la URL no ha cambiado.
Cuando configuro
username = "Test"
dentro de mi route-config, la URL no cambia.
En segundo lugar, no puedo navegar a mis otros controladores. Si cambio la URL a http://localhost123/Welcome , no pasa nada. Debería redirigirme a una nueva página.
¿Qué estoy haciendo mal aquí?
Si cambio el orden de las rutas, puedo navegar a otras páginas, pero el nombre de usuario no se muestra en la URL.
Busqué en Google y todas las respuestas sobre este tema dicen que debería usar una ruta como la anterior.
Debe clasificar la url para diferentes secciones de su sitio web para que el mecanismo de coincidencia de patrones de url sea fluido. Por ejemplo, en su caso, coloque una categoría ''perfil'' o cualquier otra cosa. Ahora su url de solicitud se verá como http://localhost1234/profile/john y la ruta será
routes.MapRoute(
name: "users", // Route name
url: "Profile/{username}", // URL with parameters
defaults: new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Para obtener más información, siga el enlace Enrutamiento en MVC
Por sí solo, su enrutamiento no funcionará porque si la url era
.../Product
lo que significa que quería navegar al método
Index()
de
ProductController
, coincidiría con su primera ruta (y
ProductController
que "Producto" es el
username
. Debe agregar una restricción de ruta a sus definiciones de ruta que devuelva
true
si el
username
es válido y
false
si no (en cuyo caso intentará las siguientes rutas para encontrar una coincidencia).
Suponiendo que tiene un
UserController
con los siguientes métodos
// match http://..../Bryan
public ActionResult Index(string username)
{
// displays the home page for a user
}
// match http://..../Bryan/Photos
public ActionResult Photos(string username)
{
// displays a users photos
}
Entonces las definiciones de ruta deben ser
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "User",
url: "{username}",
defaults: new { controller = "User", action = "Index" },
constraints: new { username = new UserNameConstraint() }
);
routes.MapRoute(
name: "UserPhotos",
url: "{username}/Photos",
defaults: new { controller = "User", action = "Photos" },
constraints: new { username = new UserNameConstraint() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Test", action = "Index", id = UrlParameter.Optional }
);
}
public class UserNameConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
List<string> users = new List<string>() { "Bryan", "Stephen" };
// Get the username from the url
var username = values["username"].ToString().ToLower();
// Check for a match (assumes case insensitive)
return users.Any(x => x.ToLower() == username);
}
}
}
Si la url es
.../Bryan
, coincidirá con la ruta del
User
y ejecutará el método
Index()
en
UserController
(y el valor del
username
de
username
será
"Bryan"
)
Si la url es
.../Stephen/Photos
, coincidirá con la ruta
UserPhotos
y ejecutará el método
Photos()
en
UserController
(y el valor del
username
de
username
será
"Stephen"
)
Si la url es
.../Product/Details/4
, la restricción de ruta devolverá falso para las primeras 2 definiciones de ruta y ejecutará el método
Details()
de
ProductController
Si la url es
.../Peter
o
.../Peter/Photos
y no hay ningún usuario con
username = "Peter"
, devolverá
404 Not Found
Tenga en cuenta que el código de muestra anterior codifica a los usuarios, pero en realidad llamará a un servicio que devuelve una colección que contiene los nombres de usuario válidos.
Para evitar golpear la base de datos en cada solicitud, debe considerar usar
MemoryCache
para almacenar en caché la colección.
El código primero verificará si existe, y si no lo completa, luego verificará si la colección contiene el
username
.
También deberá asegurarse de que la memoria caché se invalide si se agrega un nuevo usuario.