Mvc의 컨트롤러에서 다른 컨트롤러를 호출하는 방법


153

컨트롤러 A에서 컨트롤러 B 조치 FileUploadMsgView를 호출하고 이에 대한 매개 변수를 전달해야합니다.

 Code---its not going to the controller B's FileUploadMsgView().
    In ControllerA
  private void Test()
    {

        try
        {//some codes here
            ViewBag.FileUploadMsg = "File uploaded successfully.";
            ViewBag.FileUploadFlag = "2";

            RedirectToAction("B", "FileUploadMsgView", new { FileUploadMsg = "File   uploaded successfully" });
        }

     In ControllerB receiving part
  public ActionResult FileUploadMsgView(string FileUploadMsg)
    {
         return View();
    }

3
나는이 질문이 오래되었다는 것을 알고 있지만 내 의견으로는 에드 채플의 대답을 가장 좋은 것으로 표시해야합니다. 타이슨의 모습은 해킹처럼 보이지만 여전히 유효하지만 왜 원래대로 사용할 수있을 때 해결 방법을 사용해야합니까? 원하는 결과를 얻으십시오
Anders M.

1
@AndersM. Ed의 답변은 리디렉션을 수행합니다. 솔루션을 검색하는이 질문을 찾았을 때 원하는 것이 아닙니다.
mxmissile

@mxmissile은 거시기가 아니지만 Ed의 대답은 업로드 된 내용을 기반으로 반환되는보기를 원하기 때문에 asker가 필요로하는 것입니다. 나는 asker가 그의 질문을 공식화하는 데 더 나은 작업을 수행 할 수 있다는 데 동의합니다 (이것이 맞습니까? ) Tiesons의 답변이 도움이 되더라도 그의 영어가 제한적일 수는 있지만 이것을 알 수는 없습니다. 그러나 좋은 답변은 Ed의 답변이 요구자가 필요로하는 것을 가장 잘 반영한다는 사실을 바꾸지 않습니다
Anders M.

2
@AndersM. 나는 내 댓글 표현은 그냥 ... 나쁜 이해 :-) 나는 결과가 아니었다 점을 강조해야 내가 원하는합니다.
mxmissile

@AndersM. 질문자는 Tieson의 답변을 가장 잘 받아들 였으므로 왜 당신이 그를 결정할 것인지 잘 모르겠습니다. Tieson이 내게 준 대답은 Ed의 대답보다 더 많은 도움이되었습니다. SO는 한 사람을 돕는 것이 아니라 비슷한 문제가있는 모든 사람을 돕는 것입니다. 그렇다면 왜 Tieson의 답변을 맨 위에 두지 않겠습니까?
Kevin Voorn

답변:


106

컨트롤러는 클래스 일뿐입니다. 새로운 클래스이며 다른 클래스 멤버와 마찬가지로 액션 메서드를 호출하십시오.

var result = new ControllerB().FileUploadMsgView("some string");


76
이 작업을 수행하면 ControllerContext, Request 및 friends가 누락되지 않습니까?
cirrus

20
컨트롤러의 인스턴스화는 수명주기가 애플리케이션의 다른 부분에 의해 제어 될 수 있으므로 좋지 않습니다. 예를 들어 IoC 컨테이너를 사용할 때는 모든 오염 물질을 주입해야합니다.
Mo Valipour

48
IoC를 사용하는 경우var controller = DependencyResolver.Current.GetService<ControllerB>();
mxmissile을

3
@mxmissile 여기에 의견이 아닌 새로운 답변으로 추가 할 가치가 있습니다.
Tieson T.

2
@ilasno "제어의 반전"이라는 용어에 익숙하십니까? 요점은 컨트롤러에 생성자에 주입 해야하는 구성 요소가있는 경우 DependencyResolver와 같은 것을 서비스 로케이터로 사용하지 않으면 내 대답이 실제로 작동하지 않는다는 것입니다.
Tieson T.

202

@mxmissile이 허용 된 답변에 대한 의견에서 말했듯이 컨트롤러는 IoC에 대해 설정된 종속성이 누락되어 있고을 갖지 않기 때문에 컨트롤러를 새로 시작해서는 안됩니다 HttpContext.

대신 다음과 같이 컨트롤러 인스턴스를 가져와야합니다.

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);

정확히 내가 찾던 것. IoC를 사용하지 않는 사람들은 여전히 HttpContext주사를 받지 않습니다 .
brichins

var controller유형이 지정됩니다 ( ControllerB예).
DLeh

1
이것은 나를 닫게하지만, 발생하는 한 가지 문제는 내 경우 controller.MyAction ()이 사용되지 않는 User.Identity를 참조한다는 것입니다.
Robert H. Bourdeau

1
@ilasno 내가 요즘 MVC에 녹슨 해요,하지만 난 당신이 실제로해야한다는 의미 생각 IOC의이 완전히 채워 컨트롤러 객체를 얻기 위해 설정 (예 : 관련 HttpContext). 필자는 IoC 없이이 접근 방식 사용 하여 "얕은"컨트롤러 개체 (특정 기능에 액세스해야 함)를 얻었으며 처음에는 부품이 "누락 된"이유에 대해 혼란 스러웠습니다. [외부 :이 방법을 사용하면서 문제를 해결했지만 해당 기능을 공유 클래스로 리팩토링했을 것입니다.] IoC 설정 및 선택에 대해서는 다른 기사 / SO 질문을 참조해야합니다.
brichins December

3
어떤 사람들은 무의미한 편집을 수행하지 못합니다. 누군가가 변수 "controller"를 "ctrlr"로 변경하여 답변을 편집 했으므로 "ctrlr.ControllerContext = new ControllerContext (this.Request.RequestContext, ctrl)를 읽어야합니다. ; " 해당 사용자가 올바르게 편집 한 경우
JoeSharp

62

샘플은 유사 코드처럼 보입니다. 다음 의 결과 를 반환 해야합니다 RedirectToAction.

return RedirectToAction("B", 
                        "FileUploadMsgView",
                        new { FileUploadMsg = "File uploaded successfully" });

4
대상 작업이 POST 만 허용하면 작동하지 않습니다.
Marco Alves

13
이것은 302를 반환하여 서버에 또 다른 히트를 발생시킵니다.
rboarman

16

@DLeh는 오히려 사용이라고 말합니다.

var controller = DependencyResolver.Current.GetService<ControllerB>();

그러나 컨트롤러에 컨트롤러를 제공하는 것은 특히 User개체, Server개체 또는 HttpContext'자식'컨트롤러 내부 에 액세스해야 할 때 중요 합니다 .

코드 줄을 추가했습니다.

controller.ControllerContext = new ControllerContext(Request.RequestContext, controller);

그렇지 않으면 System.Web을 사용하여 현재 컨텍스트에 액세스 Server하거나 초기 객체에 액세스 할 수 있습니다

NB : 프레임 워크 버전 4.6 (Mvc5)을 타겟팅하고 있습니다.


4
View (..) 또는 PartialView (...)를 사용하는 컨트롤러에서 작업을 호출하려고하면 ASP.NET이 뷰를 찾는 방법을 알 수 있도록 routeData를 수동으로 변경해야합니다. controller.RouteData.Values["controller"] = "Home";controller.RouteData.Values["action"] = "Index";HomeController의 Index 액션에서 결과를 반환하려고한다고 가정합니다.
Steven

@Steven 나는이 값들을 this오히려 적용해야했다 controller. 궁극적으로 결과는 로컬 컨트롤러 (이것)를 통해 되돌아 와서보기를 찾으려고 노력합니다.
aaaantoine

또한 DependencyResolver.Current.GetService <ControllerB> ()에서 Url 속성이 초기화되지 않는다고 덧붙였습니다. 따라서 현재 컨트롤러에서 수동으로 복사해야합니다.
Ralfeus

타겟팅 작업에서 return View("ViewName");대신return View();
mNejkO

9

리졸버가 자동으로 그렇게하십시오.

내부 A 컨트롤러 :

public class AController : ApiController
{
    private readonly BController _bController;

    public AController(
    BController bController)
    {
        _bController = bController;
    }

    public httpMethod{
    var result =  _bController.OtherMethodBController(parameters);
    ....
    }

}

2
가장 깨끗한 답변이지만 컨트롤러 컨텍스트를 새 컨트롤러로 설정해야합니다.
Mafii

8

누구나 .net 코어 에서이 작업을 수행하는 방법을 찾고 있다면 시작시 컨트롤러를 추가하여 달성했습니다.

services.AddTransient<MyControllerIwantToInject>();

그런 다음 다른 컨트롤러에 주입

public class controllerBeingInjectedInto : ControllerBase
{
    private readonly MyControllerIwantToInject _myControllerIwantToInject

     public controllerBeingInjectedInto(MyControllerIwantToInject myControllerIwantToInject)
{
       _myControllerIwantToInject = myControllerIwantToInject;
      }

그럼 그냥 그렇게 불러 _myControllerIwantToInject.MyMethodINeed();


4

이것은 RedirectToAction()복잡한 클래스 객체를 전달하지 않는 것을 찾은 후에 정확히 찾고있는 것입니다.

예를 들어, 컨트롤러 에서 IndexComparison메소드 를 호출하고 LifeCycleEffectsResultsmodel이라는 복잡한 클래스 객체를 전달 하고 싶습니다 .

실패한 코드는 다음과 같습니다.

return RedirectToAction("IndexComparison", "LifeCycleEffectsResults", model);

주목할만한 점은 문자열, 정수 등 이이 컨트롤러 방법으로의 여행에서 살아남 았지만 일반 목록 객체는 C 메모리 누수를 연상시키는 것으로 고통 받고 있다는 것입니다.

위에서 권장 한대로 다음 코드로 교체했습니다.

var controller = DependencyResolver.Current.GetService<LifeCycleEffectsResultsController>();

var result = controller.IndexComparison(model);
return result;

모든 것이 지금 의도 한대로 작동하고 있습니다. 길을 이끌어 주셔서 감사합니다.


3

Dleh의 답변 은 정확하며 IoC에 대한 종속성을 설정하지 않고 다른 컨트롤러의 인스턴스를 얻는 방법을 설명합니다

그러나 이제이 다른 컨트롤러에서 메소드를 호출해야합니다.
전체 답변은 다음과 같습니다.

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);

//Call your method
ActionInvoker.InvokeAction(controller.ControllerContext, "MethodNameFromControllerB_ToCall");

매개 변수가 필요한 경우 조치 "MethodNameFromControllerB_ToCall"을 어떻게 호출합니까? 예를 들어 MethodNameFromControllerB_ToCall (int somenum, string sometext)?
Patee Gutee

3

나는 그것이 오래되었다는 것을 알고 있지만, 당신은 할 수 있습니다 :

  • 서비스 계층 만들기
  • 거기에 방법을 이동
  • 두 컨트롤러의 호출 방법

2

문제가 전화하는 경우. 이 메소드를 사용하여 호출 할 수 있습니다.

yourController obj= new yourController();

obj.yourAction();

1
!! 대신 작업 결과를 기대하는 경우 어떻게합니까? var res = new ControllerB().SetUpTimer(new TimeSpan(23, 20, 00));
DirtyBit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.