ASP.NET MVC: Controller ถูกสร้างขึ้นสำหรับทุกคำขอหรือไม่


112

คำถามง่ายมาก: ตัวควบคุมใน ASP.NET ถูกสร้างขึ้นสำหรับทุกคำขอ HTTP หรือไม่หรือสร้างขึ้นเมื่อเริ่มต้นแอปพลิเคชันและใช้ซ้ำตลอดคำขอ

ตัวควบคุมจะถูกสร้างขึ้นสำหรับคำขอ HTTP เฉพาะหรือไม่

หากสมมติฐานก่อนหน้าของฉันถูกต้องฉันจะขึ้นอยู่กับมันได้หรือไม่? ฉันต้องการสร้างบริบทฐานข้อมูล (Entity Framework) ที่จะใช้งานได้สำหรับคำขอเดียวเท่านั้น ถ้าฉันสร้างเป็นคุณสมบัติที่เริ่มต้นในคอนสตรัคเตอร์ของคอนโทรลเลอร์จะมีการสร้างอินสแตนซ์ของบริบทใหม่สำหรับทุกคำขอหรือไม่


16
ใส่เบรกพอยต์ในคอนสตรัคเตอร์ของคุณและดูว่าคุณสามารถหาอะไรได้บ้าง ...
Greg B

10
@Greg B: ความคิดที่ดียกเว้นจะไม่บอกฉันว่ามันทำงานแบบนั้นตลอดเวลาหรือไม่ - หากสถานการณ์เปลี่ยนไปและตัวควบคุมบางตัวจะเปลี่ยนพฤติกรรมฉันมีข้อผิดพลาดที่อาจหาได้ยากจริงๆ ...
Rasto

@drasto คุณจะตรวจสอบได้อย่างไรว่ามันทำงานแบบนั้นตลอดไป? ตรวจสอบคำขอทุกใบสมัครของคุณ?
Greg B

4
@ ทอดด์สมิ ธ กรุณาลิงค์หรืออย่างน้อยชื่อเต็ม อักษรต้นไม้IoCยากสำหรับ Google ขอบคุณ.
Rasto

2
@drasto IoC = Inversion of control 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.Actionช่วย Html จะสร้างตัวควบคุมอื่น

เวอร์ชันสั้น ๆControllerActivator.Createเรียกว่า (สำหรับทุกคำขอ) เพื่อสร้างคอนโทรลเลอร์ (ซึ่งจะติดตั้งคอนโทรลเลอร์ใหม่ผ่าน DependencyResolver หรือผ่านทาง Activator หากไม่มีการตั้งค่า Resolver):

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));
    }
}

นี่คือรหัสโรงงานของ Controller:

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));
    }

สิ่งนี้อาจอยู่ภายใต้ข้อมูลที่มากเกินไป ... แต่ฉันต้องการแสดงให้เห็นว่าคุณได้รับคอนโทรลเลอร์ใหม่สำหรับทุกคำขอจริงๆ


@Daniel @drasto นี่คือการอ้างอิงaspnet.codeplex.com/SourceControl/changeset/view/63930#266503
Bala R

32

ฉันสร้างคอนสตรัคเตอร์ว่างสำหรับคอนโทรลเลอร์และใส่จุดพักในคอนสตรัคเตอร์ มันโดนทุกครั้งที่มีการร้องขอใหม่ ดังนั้นฉันคิดว่ามันถูกสร้างขึ้นสำหรับทุกคำขอ


3
+1 ฉันหวังว่าคุณจะพูดถูก แต่ฉันต้องการความรู้ที่ได้รับการอนุมัติที่ดีกว่าแค่ "ในทุกกรณีที่ฉันได้ลองใช้แล้ว" หากบางครั้งไม่ได้ผลเช่นนั้นจากเหตุผลบางประการนั่นหมายถึงข้อบกพร่อง
Rasto

6
@drasto: ไม่ต้องกังวล คอนโทรลเลอร์ได้รับการสร้างอินสแตนซ์สำหรับทุกคำขอ หน่วยความจำบางส่วนไม่สามารถใช้ซ้ำได้ แต่คุณไม่ควรกังวลเกี่ยวกับสถานะคอนโทรลเลอร์ (หากคุณมี) มันจะเริ่มต้นตามที่คาดไว้ แต่อาจมีสถานการณ์ที่ตัวควบคุมมากกว่าหนึ่งตัวจะได้รับการสร้างอินสแตนซ์ และนั่นคือเมื่อดูการกระทำของตัวควบคุมการโทร (เช่นHtml.RenderAction("action", "controller");)
Robert 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();
        }

    }

เห็นได้ชัดว่านี่ไม่ใช่สิ่งที่คุณต้องการ - ดังที่คุณกล่าวไว้ว่าคุณต้องการเพียงอินสแตนซ์เดียวทุกครั้งที่มีการเรียก แต่เป็นจุดที่ดีในการตรวจสอบสิ่งที่เกิดขึ้นในแต่ละครั้งและเพื่อให้แน่ใจว่าบริบทอื่นของคุณไม่มีอยู่ในขณะนี้

หวังว่านี่จะช่วยได้


2

ตัวควบคุมถูกสร้างขึ้นสำหรับทุกคำขอ ความมหัศจรรย์เกิดขึ้นในเส้นทางใน gobal.aspx เส้นทางการแมปจะกำหนด MVC ไปยังคอนโทรลเลอร์ที่จะสร้างและดำเนินการกับคอนโทรลเลอร์เพื่อเรียกใช้และพารามิเตอร์ที่จะส่งผ่านไปยังตัวควบคุม

http://www.asp.net/mvc/tutorials/asp-net-mvc-routing-overview-vb


จำเป็นต้องอ้างอิง - ไม่พบข้อมูลสนับสนุนในเอกสารที่เชื่อมโยง ขอบคุณ
Rasto
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.