C# 您能在ASP.NET MVC中重载控制器方法吗?
我很想知道您是否可以在ASP.NET MVC中重载控制器方法。每当我尝试时,我都会得到下面的错误。这两个方法接受不同的参数。这是不能做的吗 当前对控制器类型“MyController”的操作“MyMethod”的请求在以下操作方法之间不明确:C# 您能在ASP.NET MVC中重载控制器方法吗?,c#,asp.net-mvc,overloading,C#,Asp.net Mvc,Overloading,我很想知道您是否可以在ASP.NET MVC中重载控制器方法。每当我尝试时,我都会得到下面的错误。这两个方法接受不同的参数。这是不能做的吗 当前对控制器类型“MyController”的操作“MyMethod”的请求在以下操作方法之间不明确: 据我所知,在使用不同的http方法时,只能使用相同的方法 i、 e 对。通过将每个控制器方法的HttpGet/HttpPost(或等效的AcceptVerbs属性)设置为不同的属性,即HttpGet或HttpPost,但不能两者都设置。这样,它就可以根据请
据我所知,在使用不同的http方法时,只能使用相同的方法 i、 e
对。通过将每个控制器方法的
HttpGet
/HttpPost
(或等效的AcceptVerbs
属性)设置为不同的属性,即HttpGet
或HttpPost
,但不能两者都设置。这样,它就可以根据请求的类型判断使用哪种方法
[HttpGet]
public ActionResult Show()
{
...
}
[HttpPost]
public ActionResult Show( string userName )
{
...
}
我的一个建议是,对于这样的情况,应该有一个私有实现,您的两个公共操作方法都依赖该实现来避免代码重复。如果希望代码重载,可以使用该属性
[ActionName("MyOverloadedName")]
但是,您必须为同一http方法使用不同的操作名称(正如其他人所说)。所以这只是语义上的问题。您希望在代码中使用名称还是在属性中使用名称
Phil有一篇与此相关的文章:要解决这个问题,您可以编写一个
ActionMethodSelectorAttribute
,检查每个操作的MethodInfo
,并将其与发布的表单值进行比较,然后拒绝表单值不匹配的任何方法(当然,按钮名称除外)
以下是一个例子:-
但是,这不是一个好主意。您还可以做一些其他事情。。。您需要一个能够有参数而不是参数的方法 为什么不试试这个
public ActionResult Show( string username = null )
{
...
}
这对我很有用。。。在这个方法中,您可以实际测试,看看是否有传入参数
更新以删除字符串上的无效可空语法,并使用默认参数值。将基本方法创建为虚拟方法
public virtual ActionResult Index()
将被重写的方法创建为override
public override ActionResult Index()
编辑:这显然只适用于覆盖方法位于派生类中的情况,而派生类似乎不是OP的意图。您可以使用单个
操作结果
来处理Post
和Get
:
public ActionResult Example() {
if (Request.HttpMethod.ToUpperInvariant() == "GET") {
// GET
}
else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
// Post
}
}
如果您的
Get
和Post
方法具有匹配的签名,则此方法非常有用。我需要重载:
public ActionResult Index(string i);
public ActionResult Index(int groupId, int itemId);
我最后这样做的理由很少:
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
}
}
这不是一个完美的解决方案,特别是如果你有很多争论,但它对我来说很好。我喜欢在另一个帖子中发布这个答案 这主要用于从另一个控制器继承,并希望覆盖来自基本控制器的帐户
否、否和否。请尝试下面的控制器代码,其中“LoadCustomer”重载
public class CustomerController : Controller
{
//
// GET: /Customer/
public ActionResult LoadCustomer()
{
return Content("LoadCustomer");
}
public ActionResult LoadCustomer(string str)
{
return Content("LoadCustomer with a string");
}
}
如果您尝试调用“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");
}
}
因此,如果现在调用URL“Customer/LoadCustomer”,将调用“LoadCustomer”操作,并使用URL结构“Customer/LoadCustomerByName”调用“LoadCustomer(string str)”
我从这篇codeproject文章中得到的上述答案-->我是在MVC5的帮助下实现的。诚然,我是MVC的新手,使用WebForms进行了十年的web开发,但以下几点对我很有用。与接受的答案不同,这允许所有重载操作由同一视图文件呈现 首先在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 }
);
}
}
可以选择使用默认路由前缀装饰控制器类
[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
//.......
然后用一个共同的路线和参数来装饰控制器的动作,使它们彼此过载。使用类型约束参数,可以对不同类型的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)
{
//.....
}
希望这会有所帮助,不会让别人走上错误的道路。:-) 我刚刚遇到这个问题,尽管它现在已经很老了,但它仍然非常相关。具有讽刺意味的是,这篇文章中的一条正确评论是由一位自称是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
}
}
这些操作将处理URL,如/cars/usa/new york
和/cars/usa/texas/dallas
,它们将分别映射到第一个和第二个索引操作
通过检查这个示例控制器,很明显它超出了上面提到的默认路由模式。如果您的url结构与您的代码命名约定完全匹配,则默认设置效果良好,但情况并非总是如此。代码应该是对域的描述,但是URL通常需要更进一步,因为它们的内容应该基于其他标准,比如SEO要求
默认路由模式的好处是它会自动创建唯一的路由。这是由编译器强制执行的,因为URL将匹配唯一的控制器类型和成员。滚动你自己的路线模式
[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
}
}
[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);
}
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");
}
}
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);
}
public ActionResult DoSomething(string action, string param1, string param2)
{
switch (action)
{
case "update":
return UpdateAction(param1, param2);
case "remove":
return DeleteAction(param1);
}
}