route net mvc multiple maphttproute examples attribute asp c# asp.net-mvc routes

c# - mvc - net core api route



.NET MVC Routing-bind 2 parĂ¡metros de routeMap (2)

Clase de selector de método de acción personalizado

Si yo fuera usted, escribiría un selector de método de acción y lo usaría para evitar ramificaciones en sus acciones. He escrito uno que separa las acciones que toman los parámetros opcionales (evitando así el código ramificado dentro de la acción: pruebas unitarias simplificadas). La ruta predeterminada de Asp.net MVC tiene un parámetro id opcional

{controller}/{action}/{id} id = UrlParameter.Optional

Entonces tiene sentido tener estos dos métodos de acción:

public ActionResult Index() { ... } public ActionResult Index(int id) { ... }

Lo logré escribiendo un filtro selector de acción personalizado. Aquí hay una publicación de blog detallada que describe todo y proporciona un código que puede ver.

¿Qué tal una solución para su problema?

En tu caso, esto significa que deberías escribir una clase de selector de método de acción personalizada llamada SubactionAttribute y luego simplemente decorar tus acciones con ella:

[Subaction("Details")] public ActionResult Members(long id) { var member = _payment.GetMember(id); return View("Members.Details", member); } [Subaction] // no name would mean default subaction (when not provided) public ActionResult Members() { var members = _payment.GetMembers().ToList(); return View("Members.List", members); }

No voy a escribir toda la clase por ti, pero solo te señalaré en la dirección correcta para que puedas seguir el mismo camino para llegar a donde te diriges:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public sealed class SubactionAttribute : ActionMethodSelectorAttribute { #region Properties /// <summary> /// Gets subaction name. /// </summary> public string Name { get; private set; } #endregion #region Constructors /// <summary> /// Initializes a new instance of the <see cref="SubactionAttribute"/> class. /// </summary> public SubactionAttribute() : this(null) { // does nothing } /// <summary> /// Initializes a new instance of the <see cref="SubactionAttribute"/> class. /// </summary> /// <param name="subactionName">Sub-action name</param> public SubactionAttribute(string subactionName) { this.Name = subactionName; } #endregion #region ActionMethodSelectorAttribute implementation /// <summary> /// Determines whether the action method selection is valid for the specified controller context. /// </summary> /// <param name="controllerContext">The controller context.</param> /// <param name="methodInfo">Information about the action method.</param> /// <returns> /// true if the action method selection is valid for the specified controller context; otherwise, false. /// </returns> public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } // get the value of subaction here string subName = /* this part you''ll have to write */ // determine whether subaction matches return this.Name == subName; } #endregion }

Necesito analizar una url como la siguiente

/controller/action/subaction/id

En este momento estoy usando un interruptor en subacción para ver lo que realmente se necesita hacer. P.EJ:

public ActionResult Members(string subaction, long id=0) { switch (subaction) { case "Details": var member = _payment.GetMember(id); return View("Members_details", member); default: var members = _payment.GetMembers().ToList(); return View("Members_list", members); } }

Esto funciona, pero prefiero tener acciones separadas para cada evento al que se accede directamente desde la ruta. Si es posible, me gustaría combinar la acción y la subacción en el mapa de ruta para acceder a la acción correcta.

  • / controller / action / llamaría a la acción ()
  • / controller / action / subaction llamaría action_subaction ()
  • / controller / action / subaction / id llamaría action_subaction (id)

¿Es eso posible directamente del mapa de ruta?


¿Estás diciendo que efectivamente quieres usar múltiples acciones de "Detalles" en el mismo controlador? Si este es el caso, entonces creo que esta es una buena razón para comenzar a dividir sus controladores.

Probablemente deberías comenzar con un Controlador llamado Miembros con Detalles y Lista de Acciones (o Índice)

/Members/Details/ID /Members/List/

¿Tienes una buena razón lógica para tenerlos a todos en el mismo controlador?

Alternativamente, podría llamarlo Acciones MemberDetails y MemberList y URL como ...

/Controller/MemberDetails/ID /Controller/MemberList/

Darle un código de ir:

[ActionName("Member/Details")] public ActionResult Members_Details(int id){ return View(); }