¿Puede sobrecargar los métodos del controlador en ASP.NET ¿MVC?


Tengo curiosidad por ver si puede sobrecargar los métodos del controlador en ASP.NET MVC. Cada vez que lo intento, obtengo el error a continuación. Los dos métodos aceptan argumentos diferentes. Es esto algo que no se puede hacer?

La solicitud actual de acción 'myMethod' en el tipo de controlador 'MyController' es ambigua entre los siguientes métodos de acción:

Author: Wayne Koorts, 2009-01-12

16 answers

Puede usar el atributo si desea que su código se sobrecargue.

[ActionName("MyOverloadedName")]

Pero, tendrá que usar un nombre de acción diferente para el mismo método http (como otros han dicho). Así que es sólo semántica en ese punto. ¿Preferirías tener el nombre en tu código o en tu atributo?

Phil tiene un artículo relacionado con esto: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx

 190
Author: JD Conley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-12 20:37:43

Sí. He sido capaz de hacer esto mediante el establecimiento de la HttpGet/HttpPost (o atributo AcceptVerbs equivalente) para cada método controlador a algo distinto, es decir, HttpGet o HttpPost, pero no ambos. De esa manera, puede decir en función del tipo de solicitud qué método usar.

[HttpGet]
public ActionResult Show()
{
   ...
}

[HttpPost]
public ActionResult Show( string userName )
{
   ...
}

Una sugerencia que tengo es que, para un caso como este, sería tener una implementación privada en la que ambos métodos de Acción pública se basen para evitar la duplicación de código.

 67
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-13 20:12:01

Aquí hay algo más que podrías hacer... desea un método que sea capaz de tener un parámetro y no.

¿Por qué no probar esto?..

public ActionResult Show( string username = null )
{
   ...
}

Esto ha funcionado para mí... y en este método, realmente puede probar para ver si tiene el parámetro entrante.


Actualizado para eliminar la sintaxis invalid nullable en la cadena y usar un valor de parámetro predeterminado.
 41
Author: Farrel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-18 22:15:05

No,No y No. Vaya y pruebe el código del controlador a continuación donde tenemos el" LoadCustomer " sobrecargado.

public class CustomerController : Controller
    {
        //
        // GET: /Customer/

        public ActionResult LoadCustomer()
        {
            return Content("LoadCustomer");
        }
        public ActionResult LoadCustomer(string str)
        {
            return Content("LoadCustomer with a string");
        }
    }

Si intenta invocar la acción "LoadCustomer" obtendrá un error como se muestra en la siguiente figura.

introduzca la descripción de la imagen aquí

El polimorfismo es una parte de la programación en C# mientras que HTTP es un protocolo. HTTP no entiende el polimorfismo. HTTP funciona en el concepto o URL y la URL solo puede tener un nombre único. Por lo tanto, HTTP no implementa polimorfismo.

Con el fin de fijar la igual necesitamos usar el atributo "ActionName".

public class CustomerController : Controller
    {
        //
        // GET: /Customer/

        public ActionResult LoadCustomer()
        {
            return Content("LoadCustomer");
        }

        [ActionName("LoadCustomerbyName")]
        public ActionResult LoadCustomer(string str)
        {
            return Content("LoadCustomer with a string");
        }
    }

Así que ahora si haces una llamada a URL "Customer/LoadCustomer" se invocará la acción "LoadCustomer" y con la estructura URL "Customer/LoadCustomerByName" se invocará la acción "LoadCustomer(string str)".

introduzca la descripción de la imagen aquí

introduzca la descripción de la imagen aquí

La respuesta anterior la he tomado de este artículo de codeproject > > MVC Action overloading

 18
Author: Shivprasad Koirala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-27 23:48:25

Para superar este problema, puede escribir un ActionMethodSelectorAttribute que examine el MethodInfo para cada acción y lo compare con los valores del formulario publicados y luego rechace cualquier método para el que los valores del formulario no coincidan (excluyendo el nombre del botón, por supuesto).

Aquí hay un ejemplo: - http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match /

PERO, esto no es una buena idea.

 15
Author: Ian Mercer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-22 17:10:37

Por lo que sé, solo se puede tener el mismo método cuando se usan diferentes métodos http.

Es decir,

[AcceptVerbs("GET")]
public ActionResult MyAction()
{

}

[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{

}
 13
Author: keeney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-12 20:35:08

He logrado esto con la ayuda de Enrutamiento de atributos en MVC5. Es cierto que soy nuevo en MVC viniendo de una década de desarrollo web utilizando formularios web, pero lo siguiente ha funcionado para mí. A diferencia de la respuesta aceptada, esto permite que todas las acciones sobrecargadas sean renderizadas por el mismo archivo de vista.

Primero habilite el Enrutamiento de atributos en App_Start/RouteConfig.cs.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );            
    }
}

Opcionalmente decora tu clase controller con un prefijo de ruta predeterminado.

[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
    //.......

Luego decorar sus acciones de controlador que se sobrecargan entre sí con una ruta común y parámetros para adaptarse. Con los parámetros de tipo restringido, puede usar el mismo formato URI con ID de diferentes tipos.

[HttpGet]
// Returns
public ActionResult Index()
{
    //.....
}

[HttpGet]
[Route("View")]
// Returns/View
public ActionResult View()
{
    // I wouldn't really do this but it proves the concept.
    int id = 7026;
    return View(id);
}

[HttpGet]
[Route("View/{id:int}")]
// Returns/View/7003
public ActionResult View(int id)
{
    //.....
}

[HttpGet]
[Route("View/{id:Guid}")]
// Returns/View/99300046-0ba4-47db-81bf-ba6e3ac3cf01
public ActionResult View(Guid id)
{
    //.....
}

Espero que esto ayude y no esté guiando a alguien por el camino equivocado. :-)

 9
Author: cookdn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-03 10:11:05

Podrías usar un solo ActionResult para tratar con Post y Get:

public ActionResult Example() {
   if (Request.HttpMethod.ToUpperInvariant() == "GET") {
    // GET
   }
   else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
     // Post  
   }
}

Útil si sus métodos Get y Post tienen firmas coincidentes.

 4
Author: DevDave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-03 14:49:39

Acabo de encontrar esta pregunta y, a pesar de que es bastante antigua ahora, sigue siendo muy relevante. Irónicamente, el único comentario correcto en este hilo fue publicado por un principiante confeso en MVC cuando escribió el post. Incluso el ASP.NET los documentos no son del todo correctos. Tengo un gran proyecto y con éxito sobrecargar los métodos de acción.

Si uno entiende el enrutamiento, más allá del simple patrón de ruta predeterminado {controller} / {action} / {id}, puede ser obvio que las acciones del controlador pueden ser mapeado usando cualquier patrón único. Alguien aquí habló del polimorfismo y dijo: "HTTP no entiende el polimorfismo", pero el enrutamiento no tiene nada que ver con HTTP. Es, en pocas palabras, un mecanismo para la coincidencia de patrones de encordado.

La mejor manera de hacer que esto funcione es usar los atributos de enrutamiento, por ejemplo:

[RoutePrefix("cars/{country:length(3)}")]
public class CarHireController
{
    [Route("{location}/{page:int=1}", Name = "CarHireLocation")]
    public ActionResult Index(string country, string location, int page)
    {
        return Index(country, location, null, page);
    }

    [Route("{location}/{subLocation}/{page:int=1}", Name = "CarHireSubLocation")]
    public ActionResult Index(string country, string location, string subLocation, int page)
    {
        //The main work goes here
    }
}

Estas acciones se encargarán de url como /cars/usa/new-york y /cars/usa/texas/dallas, que se asignarán a la primera y segunda acciones de índice respectivamente.

Examinando este ejemplo controlador es evidente que va más allá del patrón de ruta predeterminado mencionado anteriormente. El valor predeterminado funciona bien si la estructura de la url coincide exactamente con las convenciones de nomenclatura del código, pero este no siempre es el caso. El código debe ser descriptivo del dominio, pero las url a menudo necesitan ir más allá porque su contenido debe basarse en otros criterios, como los requisitos de SEO.

El beneficio del patrón de enrutamiento predeterminado es que crea automáticamente rutas únicas. Esto se hace cumplir por el compilador ya que las url coincidirán con tipos de controladores y miembros únicos. Rodar sus propios patrones de ruta requerirá un pensamiento cuidadoso para garantizar la singularidad y que funcionen.

Nota importante El único inconveniente es que el uso de enrutamiento para generar urls para acciones sobrecargadas no funciona cuando se basa en un nombre de acción, por ejemplo, cuando se utiliza UrlHelper.Acto. Pero funciona si se usan rutas con nombre, por ejemplo, UrlHelper.RouteUrl. Y el uso de rutas con nombre es, según fuentes muy respetadas, el camino a seguir de todos modos ( http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/).

¡Buena suerte!

 3
Author: DvS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-06 13:28:05

Necesitaba una sobrecarga para:

public ActionResult Index(string i);
public ActionResult Index(int groupId, int itemId);

Hubo pocos argumentos suficientes donde terminé haciendo esto:

public ActionResult Index(string i, int? groupId, int? itemId)
{
    if (!string.IsNullOrWhitespace(i))
    {
        // parse i for the id
    }
    else if (groupId.HasValue && itemId.HasValue)
    {
        // use groupId and itemId for the id
    }
}

No es una solución perfecta, especialmente si tienes muchos argumentos, pero funciona bien para mí.

 2
Author: Kasey Speakman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-10 21:57:00

Puede usar [ActionName ("NewActionName")] para usar el mismo método con un nombre diferente:

public class HomeController : Controller
{
    public ActionResult GetEmpName()
    {
        return Content("This is the test Message");
    }

    [ActionName("GetEmpWithCode")]
    public ActionResult GetEmpName(string EmpCode)
    {
        return Content("This is the test Messagewith Overloaded");
    }
}
 2
Author: Stephen Mooney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-30 06:45:14

También me he enfrentado al mismo problema en mi solicitud. Sin modificar ninguna información del método, he proporcionado [ActionName ("SomeMeaningfulName")] en la cabeza de la acción. problema resuelto

[ActionName("_EmployeeDetailsByModel")]
        public PartialViewResult _EmployeeDetails(Employee model)
        {
            // Some Operation                
                return PartialView(model);
            }
        }

[ActionName("_EmployeeDetailsByModelWithPagination")]
        public PartialViewResult _EmployeeDetails(Employee model,int Page,int PageSize)
        {

                // Some Operation
                return PartialView(model);

        }
 1
Author: ಅನಿಲ್,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-27 11:43:29

Crear el método base como virtual

public virtual ActionResult Index()

Crea el método sobrescrito como override

public override ActionResult Index()

Editar: Esto obviamente se aplica solo si el método override está en una clase derivada que parece no haber sido la intención del OP.

 0
Author: Andiih,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-01 07:49:22

Me gusta esta respuesta publicada en otro hilo

Esto se usa principalmente si hereda de otro controlador y desea anular una acction del controlador base

ASP.NET MVC-Sobreescribir una acción con diferentes parámetros

 0
Author: Keyjote,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:48

Solo se permite una firma pública para cada método del controlador. Si intenta sobrecargarlo, se compilará, pero obtendrá el error de tiempo de ejecución que ha experimentado.

Si no está dispuesto a usar verbos diferentes (como los atributos [HttpGet] y [HttpPost]) para diferenciar métodos sobrecargados (que funcionarán), o cambiar el enrutamiento, entonces lo que queda es que puede proporcionar otro método con un nombre diferente, o puede enviar dentro del método existente. Aca cómo lo hice:

Una vez llegué a una situación en la que tuve que mantener la compatibilidad hacia atrás. El método original esperaba dos parámetros, pero el nuevo solo tenía uno. Sobrecargar la forma en que esperaba no funcionó porque MVC ya no encontró el punto de entrada.

Para resolver eso, hice lo siguiente:

  1. Se cambiaron los 2 métodos de acción sobrecargados de público a privado
  2. Creó un nuevo método público que contenía "solo" 2 parámetros de cadena. Que uno actuó como un despachador, es decir:

    public ActionResult DoSomething(string param1, string param2)
    {
        if (string.IsNullOrEmpty(param2))
        {
            return DoSomething(ProductName: param1);
        }
        else
        {
            int oldId = int.Parse(param1);
            return DoSomething(OldParam: param1, OldId: oldId);
        }
    }
    
    
    private ActionResult DoSomething(string OldParam, int OldId)
    {
        // some code here
        return Json(result);
    }
    
    
    private ActionResult DoSomething(string ProductName)
    {
        // some code here
        return Json(result);
    }
    

Por supuesto, esto es un truco y debe ser refactorizado más tarde. Pero por el momento, funcionó para mí.

También puedes crear un despachador como:

public ActionResult DoSomething(string action, string param1, string param2)
{
    switch (action)
    {
        case "update":
            return UpdateAction(param1, param2);
        case "remove":
            return DeleteAction(param1);
    }
}

Puede ver que UpdateAction necesita 2 parámetros, mientras que DeleteAction solo necesita uno.

 0
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-06 07:47:29

Si esto es un intento de usar una acción GET para varias vistas que PUBLICAN varias acciones con diferentes modelos, entonces intente agregar una acción GET para cada acción POST que redirija a la primera GET para prevenir 404 en refresh.

Posibilidad remota pero escenario común.

 -1
Author: Panos Roditakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-12 16:19:58