2009-10-14 109 views
5

我有一個控制器是從一個基礎控制器繼承,我想知道如何利用基礎控制器的所有邏輯,但返回一個不同於基礎控制器使用的視圖。如何繼承ASP.NET MVC控制器並只更改視圖?

基本控制器填充一個模型對象並將該模型對象傳遞給它的視圖,但我不知道如何在子控制器中訪問該模型對象,以便我可以將它傳遞給子控制器的視圖。從我的應用程序

+1

您是否嘗試從基本控制器繼承並準備視圖? – LukLed 2009-10-14 15:31:08

回答

1

基於此線程給出的反饋,我實現了一個類似Antony Koch提出的解決方案。

取而代之的是使用抽象方法,我使用了一個具體的,虛擬的GetIndex方法,這樣我就可以爲它的基礎控制器放置邏輯。

public class SalesController : Controller 
{ 
    // Index view method and model 
    public virtual ActionResult GetIndex() 
    { 
     return View("Index", IndexModel); 
    } 
    protected TestModel IndexModel { get; set; } 

    public virtual ActionResult Index() 
    { 
     ViewData["test"] = "Set in base."; 

     IndexModel = new TestModel(); 
     IndexModel.Text = "123"; 

     return GetIndex(); 
    } 

    [AcceptVerbs(HttpVerbs.Post)] 
    public virtual ActionResult Index(TestModel data, FormCollection form) 
    { 
     TryUpdateModel(data, form.ToValueProvider()); 
     IndexModel = data; 

     return GetIndex(); 
    } 
} 

// This class will need to be in a different namespace or named differently than the 
// parent controller 
public class SalesController : MyApp.Controllers.BaseControllers.SalesController 
{ 
    // Index view method and model 
    public override ActionResult GetIndex() 
    { 
     return View("ClientIndex", IndexModel); 
    } 

    public override ActionResult Index() 
    { 
     return base.Index(); 
    } 

    [AcceptVerbs(HttpVerbs.Post)] 
    public override ActionResult Index(TestModel data, FormCollection form) 
    { 
     return base.Index(data, form); 
    } 
} 
+0

我面臨着同樣的問題,任何人都可以幫助我嗎? [我的問題](http://stackoverflow.com/questions/12720611/cant-add-controller-which-uses-class-which-is-inherited-from-other-class) – user1668543 2012-10-05 06:25:04

3

樣品:

基類:

public abstract class BaseTableController<T,TU> : BaseController where TU : IGenericService<T>,IModelWrapperService 
{ 
    protected readonly TU _service; 

    public BaseTableController(TU service) 
    { 
     _service = service; 
     _service.ModelWrapper = new ControllerModelStateWrapper(ModelState); 
    } 


    public ActionResult Index() 
    { 
     return View(_service.List()); 
    } 

繼承:

public class SeverityController : BaseTableController<Severity, ISeverityService> 
{ 
    public SeverityController(ISeverityService service) 
     : base(service) 
    { 
    } 

    //NO CODE INSIDE 
} 

SeverityController.Index()導致查看/嚴重性/的Index.aspx 。只需準備視圖。嚴重性是我的錯誤跟蹤應用程序中的一個詞典。每個字典都有類似的邏輯,所以我可以分享一些代碼。

0

我最終只是在基礎控制器 - viewName上添加了一個額外的參數。

似乎工作得很好。

我錯過了任何主要的缺點?

public class SalesController : Controller 
{ 
    public virtual ActionResult Index(string viewName) 
    { 
     ViewData["test"] = "Set in base."; 

     TestModel model = new TestModel(); 
     model.Text = "123"; 

     return String.IsNullOrEmpty(viewName) ? View(model) : View(viewName, model); 
    } 

    [AcceptVerbs(HttpVerbs.Post)] 
    public virtual ActionResult Index(TestModel data, FormCollection form, string viewName) 
    { 
     TryUpdateModel(data, form.ToValueProvider()); 
     return String.IsNullOrEmpty(viewName) ? View(data) : View(viewName, data); 
    } 
} 

public class SalesController : MyApp.Controllers.BaseControllers.SalesController 
{ 
    public override ActionResult Index(string viewName) 
    { 
     return base.Index("ClientIndex"); 
    } 

    [AcceptVerbs(HttpVerbs.Post)] 
    public override ActionResult Index(TestModel data, FormCollection form, string viewName) 
    { 
     return base.Index(data, form, "ClientIndex"); 
    } 
} 
+1

我擔心的是用戶可以通過http將參數發送到控制器中的ActionResult。如果用戶能夠在不覆蓋「索引」的控制器上調用索引,從而能夠傳遞具有意外結果的視圖名稱,就會冒風險。不太可能,但仍然有可能。 – 2009-10-14 16:00:35

+1

我不喜歡這個解決方案。您不必指定視圖名稱。想象一下你有一個BaseController和兩個繼承 - ChildOneController和ChildTwoController。如果您調用〜/ ChildOne/Index,它會從〜/ ChildOne/Index/Index.aspx中查看。如果您調用/ ChildTwo/Index,它會從〜/ ChildTwo/Index/Index.aspx中查看。視圖名稱相同,但是來自不同的地方。 – LukLed 2009-10-14 16:09:00

+0

我面臨着同樣的問題,任何人都可以幫助我嗎? [我的問題](http://stackoverflow.com/questions/12720611/cant-add-controller-which-uses-class-which-is-inherited-from-other-class) – user1668543 2012-10-05 07:13:05

0
public class BaseController : Controller { 
protected BaseController() {} 

public ActionResult Index() 
{ 
    return GetIndex(); 
} 

public abstract ActionResult GetIndex(); } 

public class MyController : BaseController { 
public MyController() {} 

public override GetIndex() 
{ 
    return RedirectToAction("Cakes","Pies"); 
} 

}

只需使用抽象給你打電話從子類需要的位。

+0

我做了類似的事情。看到我的新答案。我希望避免爲每個控制器操作創建輔助方法,但我想這是最好的方法。 – 2009-10-14 17:30:17

7

有幾點。如果您知道這就是您要返回的所有內容,則可以將您的返回值輸入爲ViewResult。然後你可以從重寫的實現中詢問這個值。更重要的是,根據MVC v1源代碼,調用View(object)只需在控制器上設置ViewData.Model,然後構造一個ViewResult。

Controller.cs:440

protected internal ViewResult View(object model) { 
    return View(null /* viewName */, null /* masterName */, model); 
} 

Controller.cs:456

protected internal virtual ViewResult View(string viewName, string masterName, object model) { 
    if (model != null) { 
     ViewData.Model = model; 
    } 

    return new ViewResult { 
     ViewName = viewName, 
     MasterName = masterName, 
     ViewData = ViewData, 
     TempData = TempData 
    }; 
} 

因此,所有你需要做的是調用基方法,並調用視圖(串)。

namespace BaseControllers 
{ 
    public class CoolController 
    { 
     public virtual ViewResult Get() 
     { 
      var awesomeModel = new object(); 
      return View(awesomeModel); 
     } 
    } 
} 

public class CoolController : BaseControllers.CoolController 
{ 
    public override ViewResult Get() 
    { 
     var ignoredResult = base.Get(); 
     // ViewData.Model now refers to awesomeModel 
     return View("NotGet"); 
    } 
} 

當然,你浪費CPU週期來構造你忽略的ViewResult。因此,你可以這樣做:

public class CoolController : BaseControllers.CoolController 
{ 
    public override ViewResult Get() 
    { 
     var baseResult = base.Get(); 
     baseResult.ViewName = "NotGet"; 
     return baseResult; 
    } 
} 

如果你的基本控制器返回的ActionResult,你就必須改變之前VIEWNAME把它轉換爲的ViewResult。