2022. 10. 11. 15:30

컨트롤러에서 다른 컨트롤러 호출 시 리퀘스트(Request)나 리스폰스(Response) 처리 안 되는 문제가 있습니다.

(리퀘스트는 이런 문제가 적은데 리스폰스는 무조건 발생합니다.) 

이런 문제 때문에 인증도 되지 않습니다.

 

 

1. 문제의 발견

이것은 당연한 것이 외부에서 웹서버를 통해 API(컨트롤러)를 호출할 때는

1) 헤더에 이것저것 정보들이 들어가고

2) 웹서버는 정보를 처리하고 하는 과정에서 'HttpContext'정보가 입력됩니다.

 

 

하지만 컨트롤러를 직접 생성하면 'HttpContext'가 null이 됩니다.

그러니 A컨트롤러에서 B컨트롤러를 호출하게 되면 'HttpContext'가 null되는 것이죠.

 

 

아래 코드를 따라 해 봅시다.

요청을 받는 쪽 컨트롤러(B 컨트롤러)에서 이렇게 하고

[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
    var aaa = this.ControllerContext;

    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
    })
    .ToArray();
}

 

 

요청을 하는 쪽 컨트롤러(A 컨트롤러)에서 아래와 같이 호출해봅시다.

[HttpGet]
public IEnumerable<WeatherForecast> Get1()
{
    WeatherForecastController weatherForecastController
        = new WeatherForecastController();

    return weatherForecastController.Get();
}

 

이제 'Get1'을 호출해보면......

 

'HttpContext'가 null로 옵니다.

'HttpContext'가 없으면 요청자의 정보를 받을 수 없으므로

리스폰스(Response)나 리퀘스트(Request) 처리는 물론

인증 관련 처리를 할 수 없습니다.

 

 

2. 해결 방법

컨트롤러를 생성할 때 'HttpContext'를 전달하면 됩니다.

 

2-1. 자신의 'HttpContext'를 전달하기

가장 좋은 방법은 자기가 받는 'HttpContext'를 그대로 전달하는 것입니다.

 

1) B컨트롤러를 생성하고

2) 'ControllerContext'속성에 자기 'HttpContext'를 넣어주면 됩니다.

 

[HttpGet]
public IEnumerable<WeatherForecast> Get2()
{
    WeatherForecastController weatherForecastController
        = new WeatherForecastController();

    weatherForecastController.ControllerContext = this.ControllerContext;

    return weatherForecastController.Get();
}

 

'this.ControllerContext'로 자신의 'HttpContext'를 가져올 수 있습니다.

 

 

2-2. 'ActionContext' 생성해서 전달하기

'HttpContext'의 내용을 직접 컨트롤하려면

'ActionContext'를 생성해서 내용을 넣어주면 됩니다.

[HttpGet]
public IEnumerable<WeatherForecast> Get3()
{
    WeatherForecastController weatherForecastController
        = new WeatherForecastController();

    weatherForecastController.ControllerContext
        = new ControllerContext(new ActionContext());

    return weatherForecastController.Get();
}

 

'ActionContext'를 생성하면 처음에는 내용이 없으니 직접 넣어줘야 합니다.

 

 

마무리

참고 : stackoverflow - How to mock the Request on Controller in ASP.Net MVC?

 

가능하면 컨트롤러에서 다른 컨트롤러를 호출하지 않는 것이 좋습니다.

같은 기능을 사용할 때는 따로 클래스로 빼서 개체를 만들어 사용하는 것이 좋죠.