asp.net mvc ใส่คอนโทรลเลอร์ลงในโปรเจ็กต์แยกต่างหาก


107

ฉันเพิ่งเรียนรู้ asp.net mvc และฉันกำลังพยายามหาวิธีย้ายคอนโทรลเลอร์ไปไว้ในโปรเจ็กต์แยกต่างหาก โดยปกติเมื่อฉันเคยออกแบบเว็บแอป asp.net มาก่อนฉันได้สร้างโปรเจ็กต์หนึ่งสำหรับโมเดลของฉันอีกโปรเจ็กต์สำหรับตรรกะของฉันจากนั้นก็มีเว็บ

ตอนนี้ฉันกำลังเรียนรู้ asp.net mvc ฉันหวังว่าจะทำตามรูปแบบที่คล้ายกันและวางโมเดลและคอนโทรลเลอร์แต่ละตัวไว้ในโปรเจ็กต์แยกกันของตัวเองและปล่อยมุมมอง / สคริปต์ / css ไว้ในเว็บ ส่วนของโมเดลนั้นง่าย แต่สิ่งที่ฉันไม่เข้าใจคือการทำให้คอนโทรลเลอร์ของฉันในโปรเจ็กต์แยกเป็น "พบ" ได้อย่างไร นอกจากนี้ฉันต้องการทราบว่าสิ่งนี้แนะนำได้หรือไม่ ขอบคุณ!

คำตอบ:


92

ก่อนอื่นคุณควรใส่โมเดลของคุณไว้ในโครงการแยกต่างหาก อย่างที่คุณค้นพบนี่เป็นเรื่องเล็กน้อย

เกี่ยวกับตัวควบคุมและมุมมองฉันไม่เห็นข้อได้เปรียบที่ชัดเจนในการแยกพวกเขาสำหรับโครงการพื้นฐานส่วนใหญ่แม้ว่าคุณอาจมีความจำเป็นพิเศษในการทำเช่นนั้นในแอปพลิเคชันเฉพาะก็ตาม

หากคุณเลือกที่จะทำสิ่งนี้คุณจะต้องบอกกรอบวิธีการค้นหาคอนโทรลเลอร์ของคุณ วิธีพื้นฐานในการดำเนินการนี้คือการจัดหา ControllerFactory ของคุณเอง คุณสามารถดูซอร์สโค้ดสำหรับ DefaultControllerFactory เพื่อรับแนวคิดว่าจะทำอย่างไร การพิมพ์ย่อยคลาสนี้และการแทนที่เมธอด GetControllerType (string controllerName) อาจเพียงพอที่จะบรรลุสิ่งที่คุณต้องการ

เมื่อคุณสร้าง ControllerFactory ของคุณเองแล้วคุณจะเพิ่มบรรทัดต่อไปนี้ใน Application_Start ใน global.asax เพื่อบอกกรอบงานว่าจะหาได้ที่ไหน:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

อัปเดต:อ่านโพสต์นี้ และโพสต์ที่ลิงก์ไปยังข้อมูลเพิ่มเติม ดูความคิดเห็นของ Phil Haack ในโพสต์นั้นเกี่ยวกับ:

ControllerBuilder.Current.DefaultNamespaces.Add(
    "ExternalAssembly.Controllers");

... ซึ่งไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์ แต่อาจดีพอสำหรับกรณีธรรมดา ๆ


2
ขอบคุณเครก! นี่คือสิ่งที่ฉันกำลังมองหา ข้อมูลนี้มีอยู่บนเว็บหรือไม่ ฉันได้รับ googling มาโดยตลอดด้วยโชคไม่มากนัก StackOverflow มาอีกแล้ว!
Aaron Palmer

11
ฉันเห็นด้วยผู้ควบคุมจัดการการป้อนข้อมูลของผู้ใช้จัดการโมเดลจากนั้นส่งข้อมูลไปยังมุมมอง โดยทั่วไปแล้วจะมีความเฉพาะเจาะจงมากสำหรับแอปพลิเคชัน ตรรกะใด ๆ ที่ไม่เฉพาะเจาะจงสำหรับแอปอาจดีกว่าในไลบรารีหรือโมเดล แต่ตัวควบคุมโดยทั่วไปควรอยู่กับโครงการเว็บ
เลิก

2
ฉันมีตัวควบคุมข้อผิดพลาดและมุมมองที่เหมือนกันระหว่างสองแอพ มันสมเหตุสมผลสำหรับฉันที่จะมีแอสเซมบลีเดียวที่ทั้งสองแอพสามารถใช้ได้
Sailing Judo

3
การทดสอบคอนโทรลเลอร์และใช้ IoC ไม่ใช่เรื่องง่ายกว่าหรือไม่เมื่อคอนโทรลเลอร์อยู่ในโปรเจ็กต์แยกต่างหากนั่นอาจเป็นเหตุผลหลัก
Samuel Goldenbaum

1
@ เชฟฉันไม่คิดว่ามันจะสร้างความแตกต่างที่นั่น ความสามารถในการทดสอบของคอนโทรลเลอร์ของคุณมีส่วนเกี่ยวข้องกับวิธีที่คุณเขียนโค้ดมากกว่าไม่ใช่ว่าอยู่ที่ใด
Craig Stuntz

19

แม้ว่าจะมีเหตุผลที่จะสร้าง ControllerFactory ของคุณเอง แต่ฉันพบว่าสะดวกกว่าในการกำหนดคอนโทรลเลอร์ทั้งหมดของฉันในแต่ละโปรเจ็กต์ แต่ได้มาจากคอนโทรลเลอร์ในโปรเจ็กต์ที่แชร์ของฉัน:

namespace MyProject1.Controllers
{
   public class MyController : MySharedProject.Controllers.MyController
   {
      // nothing much to do here...
   }
}

namespace MySharedProject.Controllers
{
   public abstract class MyController : System.Web.Mvc.Controller
   {
      // all (or most) of my controller logic here...
   }
}

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

ฉันคิดว่ามันเป็นอย่างนั้น ฉันได้สร้างตรรกะการจัดการบัญชีทั่วไปที่ฉันต้องการแบ่งปันระหว่างโครงการที่มีตรรกะทางธุรกิจที่แตกต่างกันมาก ดังนั้นฉันจึงแชร์บัญชีและตัวควบคุมผู้ดูแลระบบของฉัน แต่ตัวควบคุมอื่น ๆ จะเฉพาะสำหรับโครงการของตน


1
สิ่งนี้ทำงานได้ดีมาก แต่ฉันต้องกำจัดรหัสซ้ำซ้อนเพื่อป้องกันข้อผิดพลาดในการกำหนดเส้นทาง
Ken Mc

สวัสดีฉันจะจัดการการกำหนดเส้นทางในโครงการประเภทนี้ได้อย่างไร ฉันต้องการใช้การกำหนดเส้นทางแอตทริบิวต์ ...
محمد

คุณสามารถใช้การกำหนดเส้นทางแอตทริบิวต์ได้เช่นเดียวกับปกติ
ThisGuy

2
ไม่แน่ใจว่าเหตุใดจึงไม่มีการโหวตเพิ่มขึ้น ... ฉันคิดว่าสง่างามกว่าคำตอบที่ได้รับการยอมรับมาก ขอบคุณ!
jleach

สิ่งนี้ไม่ได้ผลสำหรับฉัน คุณบอกได้ไหมว่านี่คือ. Net Core หรือ. Net Framework?
Homayoun Behzadian

4
  • เพิ่มไลบรารีคลาสสำหรับโครงการ mvc ของคุณ
  • ในชั้นเรียนให้เพิ่มรหัสต่อไปนี้ (สำหรับรหัสคอนโทรลเลอร์ของคุณ)

    namespace ContactController
    {
    public class ContactController : Controller
    {
        public ActionResult Call()
        {
            ViewBag.Title = "Inside MyFirst Controller.";
            return View();
        }
    }

    }

  • ในโฟลเดอร์มุมมองโครงการ mvc ให้เพิ่มโฟลเดอร์สำหรับผู้ติดต่อและสร้างไฟล์ Call.cshtml ดูโฟลเดอร์

  • เพิ่มการอ้างอิงโปรเจ็กต์ไลบรารีคลาสลงในโปรเจ็กต์ MVC หลักของคุณ

ข้อมูลอ้างอิง

  • ในที่สุดเพื่ออ้างอิงเนมสเปซผู้ควบคุมผู้ติดต่อในการกำหนดเส้นทาง

RouteConfig


3
โชคไม่ดีเล็กน้อยที่คุณมีเนมสเปซที่มีชื่อเดียวกับคอนโทรลเลอร์
Mariusz Jamro

3

ปัญหาของฉันได้รับการแก้ไขหลังจากฉันอัปเดตSystem.Web.Mvcข้อมูลอ้างอิง NuGet เพื่อให้ MvcWebsite และ Class Library ใช้System.Web.Mvcเวอร์ชันเดียวกัน

ไม่จำเป็นต้องเพิ่มเนมสเปซเริ่มต้น


ปัญหาคือ MvcWebsite ไม่ได้มีข้อยกเว้นในขณะที่แอสเซมบลี mvc ในปัจจุบันมีเวอร์ชันที่ต่ำกว่าแอสเซมบลี mvc อ้างอิงของไลบรารีคลาส
Homayoun Behzadian

1

รูปแบบการแยกที่ง่ายที่สุดที่ฉันใช้คือการคงมุมมอง "ตามที่เป็นอยู่" ไว้ในโปรเจ็กต์ MVC ดั้งเดิม แต่เอาตัวควบคุมออก จากนั้นในโครงการ ClassLibrary ใหม่ให้เพิ่มคลาส Controller และตรวจสอบให้แน่ใจว่าสืบทอดมาจาก Controller

กลไกการกำหนดเส้นทาง MVC จะกำหนดเส้นทางไปยังตัวควบคุมใน ClassLibrary โดยอัตโนมัติและตัวควบคุมจะสร้างมุมมองจากโครงการ MVC ดั้งเดิมโดยอัตโนมัติหากคุณมีการอ้างอิงและการใช้งานของคุณอย่างถูกต้อง

ฉันใช้สถาปัตยกรรมนี้เพื่อใช้โมดูลรายงาน Html ที่สามารถคอมไพล์และปรับใช้แยกต่างหากจากโซลูชันหลัก ในที่สุดฉันก็เป็นอิสระจาก SSRS!

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