ASP.NET MVC : 모든 요청에 ​​대해 컨트롤러가 생성됩니까?


112

아주 간단한 질문 : ASP.NET의 컨트롤러는 모든 HTTP 요청에 대해 생성됩니까, 아니면 응용 프로그램 시작시 생성되어 요청 전체에서 재사용됩니까?

컨트롤러는 특정 HTTP 요청에 대해서만 생성됩니까?

이전 가정이 맞다면 믿을 수 있습니까? 하나의 요청에만 적용되는 데이터베이스 컨텍스트 (Entity Framework)를 만들고 싶습니다. 컨트롤러의 생성자에서 초기화 된 속성으로 생성하면 모든 요청에 ​​대해 새로운 컨텍스트 인스턴스가 생성 될 수 있습니까?


16
생성자에 중단 점을 놓고 무엇을 찾을 수 있는지 확인하십시오.
Greg B

10
@Greg B : 항상 그렇게 작동하는지 알려주지 않는다는 점을 제외하면 좋은 아이디어입니다. 상황이 바뀌고 일부 컨트롤러가 동작을 변경하면 정말 찾기 어려울 수있는 버그가 있습니다 ...
Rasto

@drasto 항상 그렇게 작동하는지 어떻게 확인합니까? 신청서에 대한 모든 요청을 확인 하시겠습니까?
Greg B

4
@Todd Smith는 링크 나 최소한 성명을 부탁드립니다. 나무 글자 IoC 는 구글하기 어렵다. 감사합니다.
Rasto 2011 년

2
@drasto IoC = 제어 역전 en.wikipedia.org/wiki/Inversion_of_control
Bala R

답변:


103

의 모든 요청에 ​​대해 컨트롤러가 생성 ControllerFactory됩니다 (기본적으로 DefaultControllerFactory).

http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultcontrollerfactory.aspx

점을 유의 Html.ActionHTML을 도우미가 다른 컨트롤러를 생성합니다.

짧은 버전은 ControllerActivator.Create(모든 요청에 ​​대해) 컨트롤러를 생성하기 위해 호출됩니다 (Resolver가 설정되지 않은 경우 DependencyResolver 또는 Activator를 통해 새 컨트롤러를 초기화 함).

public IController Create(RequestContext requestContext, Type controllerType) 
{
    try 
    {
        return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
    }

더 긴 버전은 다음과 같습니다 (MvcHandler의 소스 코드는 다음과 같습니다).

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
    SecurityUtil.ProcessInApplicationTrust(() =>
    {
        IController controller;
        IControllerFactory factory;
        ProcessRequestInit(httpContext, out controller, out factory);

        try
        {
            controller.Execute(RequestContext);
        }
        finally
        {
            factory.ReleaseController(controller);
        }
    });
}

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
    // non-relevant code
    // Instantiate the controller and call Execute
    factory = ControllerBuilder.GetControllerFactory();
    controller = factory.CreateController(RequestContext, controllerName);
    if (controller == null)
    {
        throw new InvalidOperationException(
            String.Format(
                CultureInfo.CurrentCulture,
                MvcResources.ControllerBuilder_FactoryReturnedNull,
                factory.GetType(),
                controllerName));
    }
}

컨트롤러 공장 코드는 다음과 같습니다.

public virtual IController CreateController(RequestContext requestContext, string controllerName) 
{
    Type controllerType = GetControllerType(requestContext, controllerName);
    IController controller = GetControllerInstance(requestContext, controllerType);
    return controller;
}

기본적으로 이것을 호출합니다.

protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
{
    return ControllerActivator.Create(requestContext, controllerType);
}

ControllerActivator(이 코드는 DependencyResolver에게 인스턴스를 요청하거나 Activator 클래스를 사용합니다) 에서이 메서드를 호출합니다 .

public IController Create(RequestContext requestContext, Type controllerType) 
{
    try 
    {
        return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
    }

이것은 너무 많은 정보에 속할 수 있습니다. 그러나 저는 당신이 정말로 모든 요청에 ​​대해 새로운 컨트롤러를 얻는다는 것을 보여주고 싶었습니다.



32

컨트롤러에 대한 빈 생성자를 만들고 생성자에 중단 점을 넣었습니다. 새로운 요청이있을 때마다 맞았습니다. 그래서 모든 요청에 ​​대해 만들어 졌다고 생각합니다.


3
+1 귀하의 말이 옳기를 바라지 만 "내가 시도한 모든 경우에 효과가 있었던"것보다 더 잘 승인 된 지식을 원합니다. 어떤 이유로 인해 가끔 그렇게 작동하지 않으면 버그를 의미합니다.
Rasto 2011 년

6
@drasto : 걱정할 필요가 없습니다. 컨트롤러는 모든 요청에 ​​대해 인스턴스화됩니다. 일부 메모리는 재사용되지만 컨트롤러 상태에 대해 걱정할 필요는 없습니다 (있는 경우). 예상대로 초기화됩니다. 그러나 둘 이상의 컨트롤러가 인스턴스화되는 상황이있을 수 있습니다. 그리고 전망이 전화의 해당 컨트롤러 액션 (예. Html.RenderAction("action", "controller");)
로버트 Koritnik

@RobertKoritnik & Bala R, 질문이 있습니다. 작업 메서드가 뷰에 제공 한 후 Student 또는 List <Student>와 같이 생성 된 개체는 어떻게됩니까? 그들은 처분됩니까? 그리고 새로운 요청이 오면 이러한 객체는 어떻게됩니까?
Mahdi Alkhatib

3

컨트롤러는 특정 컨트롤러에서 작업이 수행 될 때 생성됩니다.

내 모든 컨트롤러가에서 상속하는 프로젝트 ApplicationController가 있으며 작업이 수행 될 때마다 ApplicationController" 현재 "컨트롤러에 관계없이 중단 점이 내부에 도달 합니다.

컨트롤러가 다음과 같이 생성 될 때마다 에이전트 (컨텍스트로 작동)를 초기화합니다.

    public IWidgetAgent widgetAgent { get; set; }

    public WidgetController()
    {
        if (widgetAgent == null)
        {
            widgetAgent = new WidgetAgent();
        }

    }

이것은 분명히 필요한 것이 아닙니다. 호출 될 때마다 단일 인스턴스 만 원한다고 언급했듯이. 그러나 매번 무슨 일이 일어나고 있는지 확인하고 컨텍스트의 다른 인스턴스가 현재 존재하지 않는지 확인하는 것이 좋습니다.

도움이 되었기를 바랍니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.