ASP.NET MVC에서 컨트롤러 메소드를 과부하 할 수 있습니까?
-
22-07-2019 - |
문제
ASP.NET MVC에서 컨트롤러 메소드를 과부하 할 수 있는지 궁금합니다. 시도 할 때마다 아래에서 오류가 발생합니다. 두 가지 방법은 다른 인수를 받아들입니다. 이것은 할 수없는 일입니까?
컨트롤러 유형 'MyController'의 현재 행동 요청 'MyMethod'는 다음 작업 방법간에 모호합니다.
해결책
코드가 오버로드를하려면 속성을 사용할 수 있습니다.
[ActionName("MyOverloadedName")]
그러나 동일한 HTTP 방법에 대해 다른 동작 이름을 사용해야합니다 (다른 사람들이 말했듯이). 그래서 그것은 그 시점에서 의미론 일뿐입니다. 차라리 코드 나 속성에 이름이 있습니까?
Phil에는 다음과 관련된 기사가 있습니다. http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx
다른 팁
예. 나는 이것을 설정함으로써 이것을 할 수 있었다 HttpGet
/HttpPost
(또는 동등한 AcceptVerbs
속성) 각 컨트롤러 방법에 대해 별개의 것, 즉, HttpGet
또는 HttpPost
, 그러나 둘 다 아닙니다. 이렇게하면 사용해야 할 메소드의 요청 유형에 따라 알 수 있습니다.
[HttpGet]
public ActionResult Show()
{
...
}
[HttpPost]
public ActionResult Show( string userName )
{
...
}
내가 가진 한 가지 제안은 이와 같은 경우, 두 가지 공개 행동 방법이 복제 코드를 피하기 위해 의존하는 개인 구현이라는 것입니다.
다음은 당신이 할 수있는 일이 있습니다 ... 당신은 매개 변수를 가질 수있는 메소드를 원합니다.
이걸 시도해 보지 않겠습니까 ...
public ActionResult Show( string username = null )
{
...
}
이것은 저에게 효과적이었습니다 ... 그리고이 방법에서, 당신은 실제로 당신이 들어오는 매개 변수가 있는지 확인하기 위해 실제로 테스트 할 수 있습니다.
문자열에서 유효하지 않은 nullable 구문을 제거하고 기본 매개 변수 값을 사용하도록 업데이트되었습니다.
아니요, 아니요 및 아니요. "로드 커스토머"가 과부하 된 곳에서 아래 컨트롤러 코드를 사용해보십시오.
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"로 호출하면 "로드 커스토머"조치가 호출되고 URL 구조 "고객/LoadCustomerByName" "LoadCustomer (String STR)"가 호출됩니다.
위의 답변은이 CodeProject 기사 -> MVC 동작 과부하
이 문제를 극복하기 위해 ~할 수 있다 작성하십시오 ActionMethodSelectorAttribute
그것은 그것을 조사합니다 MethodInfo
각 조치에 대해 게시하고 게시 된 양식 값과 비교 한 다음 양식 값이 일치하지 않는 메소드 (물론 버튼 이름 제외)를 거부합니다.
예는 다음과 같습니다.- http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/
그러나 이것은 좋은 생각이 아닙니다.
내가 아는 한 다른 HTTP 방법을 사용할 때만 동일한 방법을 가질 수 있습니다.
즉
[AcceptVerbs("GET")]
public ActionResult MyAction()
{
}
[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{
}
나는 도움으로 이것을 달성했다 속성 라우팅 MVC5에서. 분명히 저는 WebForms를 사용하여 10 년간의 웹 개발에서 온 MVC를 처음 접했지만 다음은 저에게 효과가있었습니다. 허용 된 답변과 달리 이것은 모든 과부하 작업을 동일한보기 파일로 렌더링 할 수 있습니다.
먼저 APP_START/ROUNECONFIG.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)
{
//.....
}
이것이 도움이되고 누군가가 잘못된 길로 인도하지 않기를 바랍니다. :-)
당신은 싱글을 사용할 수 있습니다 ActionResult
둘 다 처리합니다 Post
그리고 Get
:
public ActionResult Example() {
if (Request.HttpMethod.ToUpperInvariant() == "GET") {
// GET
}
else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
// Post
}
}
당신의 경우 유용합니다 Get
그리고 Post
방법에는 일치하는 서명이 있습니다.
방금이 질문을 발견했는데 지금은 꽤 오래되었지만 여전히 매우 관련이 있습니다. 아이러니하게도,이 스레드의 올바른 의견은 그가 게시물을 썼을 때 MVC의 자백 초보자에 의해 게시되었습니다. ASP.NET 문서조차도 완전히 맞지 않습니다. 큰 프로젝트가 있고 액션 방법을 과부하시킵니다.
간단한 {컨트롤러}/{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과 같은 URL을 처리합니다 /cars/usa/new-york
그리고 /cars/usa/texas/dallas
, 이는 각각 첫 번째 및 두 번째 색인 작업에 매핑됩니다.
이 예제 컨트롤러를 살펴보면 위에서 언급 한 기본 경로 패턴을 넘어서는 것이 분명합니다. URL 구조가 코드 명명 규칙과 정확히 일치하는 경우 기본값이 잘 작동하지만 항상 그런 것은 아닙니다. 코드는 도메인을 설명해야하지만 URL은 종종 내용이 SEO 요구 사항과 같은 다른 기준을 기반으로하기 때문에 더 나아가 야합니다.
기본 라우팅 패턴의 이점은 자동으로 고유 한 경로를 생성한다는 것입니다. URL은 고유 한 컨트롤러 유형 및 멤버와 일치하므로 컴파일러에 의해 시행됩니다. 자신의 경로 패턴을 굴리면 독창성을 보장하고 작동하는 신중한 생각이 필요합니다.
중요 사항 한 가지 단점은 라우팅을 사용하여 오버로드 된 작업에 대한 URL을 생성하는 것이 조치 이름 (예 : urlhelper.action을 사용할 때 작동하지 않는다는 것입니다. 그러나 이름이 지정된 경로 (예 : urlhelper.routeurl)를 사용하는 경우 작동합니다. 그리고 명명 된 경로를 사용하는 것은 잘 존경받는 출처에 따르면 어쨌든가는 길입니다 (http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/).
행운을 빕니다!
ActionName ( "NewActionName")]을 사용하여 다른 이름의 동일한 메소드를 사용할 수 있습니다.
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 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
}
}
특히 많은 논쟁이 있다면 완벽한 해결책은 아니지만 나에게 잘 작동합니다.
응용 프로그램에서도 같은 문제에 직면했습니다. Modifiyig가없는 방법 정보가 없으면 Action Head에 [ActionName ( "Somemeaningfulname")]을 제공했습니다. 문제가 해결되었습니다
[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 virtual ActionResult Index()
재정의 메소드를 재정의로 만듭니다
public override ActionResult Index()
편집 : 이것은 OPERIDE 메소드가 OP의 의도가 아닌 것으로 보이는 파생 클래스에있는 경우에만 적용됩니다.
다른 스레드에 게시 된이 답변이 마음에 듭니다
다른 컨트롤러에서 상속하고 기본 컨트롤러에서 Acction을 무시하려는 경우 주로 사용됩니다.
각 컨트롤러 방법에 대해 허용되는 공개 서명은 하나뿐입니다. 과부하하려고하면 컴파일되지만 경험 한 런타임 오류가 발생합니다.
다른 동사를 기꺼이 사용하지 않는다면 ( [HttpGet]
그리고 [HttpPost]
속성) 오버로드 된 메소드를 구별하거나 라우팅을 변경하려면 다른 메소드에 다른 이름을 제공하거나 기존 메소드 내부에서 발송할 수 있다는 것입니다. 내가 한 방법은 다음과 같습니다.
나는 한 번 거꾸로 호환성을 유지 해야하는 상황에 빠졌다. 원래 방법은 두 개의 매개 변수를 예상했지만 새 방법에는 하나만있었습니다. MVC가 더 이상 진입 지점을 찾지 못했기 때문에 예상되는 방식을 과부하시키는 것은 작동하지 않았습니다.
그것을 해결하기 위해 다음을 수행했습니다.
- 2 개의 과부하 작업 방법을 공개에서 개인으로 변경했습니다.
"단지"2 문자열 매개 변수를 포함하는 하나의 새로운 공개 방법을 만들었습니다. 그 사람은 파견자 역할을했습니다.
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);
}
}
UpdateAction에는 2 개의 매개 변수가 필요하지만 deleteection은 하나만 필요합니다.
이것이 다른 모델을 가진 여러 동작에 게시하는 여러 뷰에 대해 하나의 GET 조치를 사용하려는 시도라면, 첫 번째 Get Get Get 404로 리디렉션되는 각 게시물 조치에 대해 GET 조치를 추가하십시오.
긴 샷이지만 일반적인 시나리오.