Pap*_*ndy 322 c# asp.net-mvc overloading
我很想知道你是否可以重载ASP.NET MVC中的控制器方法.每当我尝试时,我都会收到以下错误.这两种方法接受不同的论点.这是不能做的事吗?
控制器类型'MyController'上的当前操作请求'MyMethod'在以下操作方法之间是不明确的:
JD *_*ley 199
如果希望代码执行重载,可以使用该属性.
[ActionName("MyOverloadedName")]
Run Code Online (Sandbox Code Playgroud)
但是,你必须为同一个http方法使用不同的动作名称(正如其他人所说).所以这就是语义.您希望在代码或属性中使用该名称吗?
Phil有一篇与此相关的文章:http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx
tva*_*son 69
是.我已经能够通过将每个控制器方法的HttpGet/ HttpPost(或等效AcceptVerbs属性)设置为不同的东西来实现,即,HttpGet或者HttpPost,但不是两者.这样它就可以根据请求的类型判断使用哪种方法.
[HttpGet]
public ActionResult Show()
{
...
}
[HttpPost]
public ActionResult Show( string userName )
{
...
}
Run Code Online (Sandbox Code Playgroud)
我的一个建议是,对于这样的情况,将有一个私有实现,你的两个公共Action方法都依赖于它来避免重复代码.
小智 41
这是你可以做的其他事情......你想要一个能够有参数的方法而不是.
为什么不尝试这个......
public ActionResult Show( string username = null )
{
...
}
Run Code Online (Sandbox Code Playgroud)
这对我有用......在这一种方法中,您可以实际测试以查看是否有传入参数.
Shi*_*ala 20
不,不,不.去试试下面的控制器代码,我们将"LoadCustomer"重载.
public class CustomerController : Controller
{
//
// GET: /Customer/
public ActionResult LoadCustomer()
{
return Content("LoadCustomer");
}
public ActionResult LoadCustomer(string str)
{
return Content("LoadCustomer with a string");
}
}
Run Code Online (Sandbox Code Playgroud)
如果您尝试调用"LoadCustomer"操作,则会出现错误,如下图所示.

多态性是C#编程的一部分,而HTTP是一种协议.HTTP不了解多态性.HTTP适用于概念或URL,URL只能具有唯一的名称.所以HTTP不实现多态.
为了解决这个问题,我们需要使用"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");
}
}
Run Code Online (Sandbox Code Playgroud)
因此,现在如果您调用URL"Customer/LoadCustomer",将调用"LoadCustomer"操作,并使用URL结构"Customer/LoadCustomerByName"调用"LoadCustomer(string str)".


上面的答案我已经从这个代码项目文章 - > MVC Action重载
Ian*_*cer 15
要解决此问题,您可以编写一个ActionMethodSelectorAttribute检查MethodInfo每个操作的内容并将其与发布的Form值进行比较,然后拒绝任何表单值不匹配的方法(当然不包括按钮名称).
这是一个例子: - http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/
但是,这不是一个好主意.
kee*_*ney 14
据我所知,在使用不同的http方法时,你只能使用相同的方法.
即
[AcceptVerbs("GET")]
public ActionResult MyAction()
{
}
[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{
}
Run Code Online (Sandbox Code Playgroud)
我已经在MVC5 的属性路由的帮助下实现了这一点.不可否认,我是使用WebForms进行十年Web开发的MVC新手,但以下内容对我有用.与接受的答案不同,这允许所有重载的操作由同一视图文件呈现.
首先在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 }
);
}
}
Run Code Online (Sandbox Code Playgroud)
(可选)使用默认路由前缀装饰控制器类.
[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
//.......
Run Code Online (Sandbox Code Playgroud)
然后使用通用路径和参数来装饰您的控制器操作,这些操作相互重叠.使用类型约束参数,您可以使用具有不同类型ID的相同URI格式.
[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)
{
//.....
}
Run Code Online (Sandbox Code Playgroud)
希望这有助于并且不会导致某人走上错误的道路.:-)
您可以使用单个ActionResult来处理Post和Get:
public ActionResult Example() {
if (Request.HttpMethod.ToUpperInvariant() == "GET") {
// GET
}
else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
// Post
}
}
Run Code Online (Sandbox Code Playgroud)
如果您的Get和Post方法具有匹配的签名,则很有用。
我刚刚遇到这个问题,尽管它现在已经很老了,但它仍然非常相关。具有讽刺意味的是,这个帖子中一个正确的评论是由一位自称是 MVC 初学者的人在写这篇文章时发表的。甚至 ASP.NET 文档也不完全正确。我有一个大项目,我成功地重载了动作方法。
如果理解路由,除了简单的 {controller}/{action}/{id} 默认路由模式之外,很明显可以使用任何独特的模式来映射控制器操作。这里有人讲多态说:“HTTP不懂多态”,但是路由和HTTP没有关系。简单地说,它是一种字符串模式匹配机制。
使这项工作的最佳方法是使用路由属性,例如:
[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
}
}
Run Code Online (Sandbox Code Playgroud)
这些操作将处理像/cars/usa/new-york和/cars/usa/texas/dallas这样的url ,它们将分别映射到第一个和第二个索引操作。
检查这个示例控制器,很明显它超出了上面提到的默认路由模式。如果您的 url 结构与您的代码命名约定完全匹配,则默认设置效果很好,但情况并非总是如此。代码应该描述域,但 url 通常需要更进一步,因为它们的内容应该基于其他标准,例如 SEO 要求。
默认路由模式的好处是它会自动创建唯一的路由。这是由编译器强制执行的,因为 url 将匹配唯一的控制器类型和成员。滚动您自己的路线模式需要仔细考虑以确保唯一性并且它们有效。
重要说明一个缺点是,当基于动作名称时,例如使用 UrlHelper.Action 时,使用路由为重载动作生成 url 不起作用。但如果使用命名路由,例如 UrlHelper.RouteUrl,它确实有效。根据备受推崇的消息来源,使用命名路由是无论如何都要走的路(http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/)。
祝你好运!