我很好奇你是否可以重载控制器方法在ASP。净MVC。每当我尝试时,都会得到下面的错误。这两个方法接受不同的参数。这是做不到的事情吗?
当前对控制器类型“MyController”上的动作“MyMethod”的请求在以下动作方法之间是不明确的:
我很好奇你是否可以重载控制器方法在ASP。净MVC。每当我尝试时,都会得到下面的错误。这两个方法接受不同的参数。这是做不到的事情吗?
当前对控制器类型“MyController”上的动作“MyMethod”的请求在以下动作方法之间是不明确的:
当前回答
是的。我已经能够通过为每个控制器方法设置HttpGet/HttpPost(或等效的AcceptVerbs属性)来做到这一点,即HttpGet或HttpPost,但不是两者都有。这样它就可以根据请求的类型来判断使用哪个方法。
[HttpGet]
public ActionResult Show()
{
...
}
[HttpPost]
public ActionResult Show( string userName )
{
...
}
我的一个建议是,对于这种情况,应该有一个私有实现,你的两个公共Action方法都依赖于它,以避免重复代码。
其他回答
为了克服这个问题,你可以编写一个ActionMethodSelectorAttribute来检查每个动作的MethodInfo,并将其与发布的表单值进行比较,然后拒绝任何与表单值不匹配的方法(当然,不包括按钮名称)。
举个例子:- http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/
但是,这不是一个好主意。
你还可以这么做……您需要一个能够有参数而没有参数的方法。
为什么不试试这个……
public ActionResult Show( string username = null )
{
...
}
这对我很有效……在这个方法中,你可以测试是否有传入参数。
已更新以删除字符串上无效的nullable语法并使用默认参数值。
如果您希望代码进行重载,可以使用该属性。
[ActionName("MyOverloadedName")]
但是,您必须为相同的http方法使用不同的操作名称(正如其他人所说)。所以这只是语义上的。您希望在代码中使用名称还是属性中使用名称?
Phil有一篇相关的文章:http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx
This answer for those who struggling with the same issue. You can implement your own custom filter based on ActionMethodSelectorAttribute. Here I found the best solution for solving your question. Works fine on .net 5 project. If you try to implement the same logic as was in web api controllers then use Microsoft.AspNetCore.Mvc.WebApiCompatShim. This nuget package provides compatibility in ASP.NET Core MVC with ASP.NET Web API 2 to simplify migration of existing Web API implementations. Please check this answer but consider that starting with ASP.NET Core 3.0, the Microsoft.AspNetCore.Mvc.WebApiCompatShim package is no longer available.
我刚刚遇到了这个问题,尽管它现在已经很古老了,但它仍然非常相关。具有讽刺意味的是,这个帖子中唯一正确的评论是由一个自称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
}
}
这些操作将处理类似/cars/usa/new-york和/cars/usa/texas/dallas这样的url,它们将分别映射到第一个和第二个索引操作。
检查这个示例控制器,很明显它超出了上面提到的默认路由模式。如果您的url结构完全匹配您的代码命名约定,则默认值工作良好,但情况并非总是如此。代码应该对域名进行描述,但url通常需要更进一步,因为它们的内容应该基于其他标准,比如SEO要求。
默认路由模式的好处是它自动创建唯一的路由。这是由编译器强制执行的,因为url将匹配唯一的控制器类型和成员。使用自己的路线模式需要仔细考虑,以确保独特性和它们的工作。
重要提示:一个缺点是,使用路由为重载操作生成url在基于操作名称时不起作用,例如,当使用UrlHelper.Action时。但是,如果使用命名路由,例如UrlHelper.RouteUrl,它就可以工作。根据权威人士的说法,使用命名路线是正确的方法(http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/)。
好运!