2011-11-16 147 views
2

我只是在學習MVC,我有幾個關於設計/問題應該如何工作的問題。我正在使用MVC 3和Razor,實體框架類(例如位置),我要創建一個帶有驗證註釋的好友類。在我的視圖中,我有一個局部視圖,用於呈現DevExpress TreeView(使用位置列表)和表單來創建/編輯樹中的位置。我有一個LocationController,一個LocationManagementView,一個LocationManagementPartialView(包含樹視圖的代碼)和一個LocationModel。 LocationModel將保存好友類並獲取獲取子項的方法(只有在展開節點後才能獲取子項)。我有一個服務包裝器(用於我的服務客戶端),它將使用StructureMap注入。ASP.NET MVC 3 - 模型驗證

我應該將服務包裝器注入Controller的構造函數還是注入Model的構造函數?

此外,我的模型已經獲得使用服務包裝器從數據庫中獲取數據的方法(這些方法屬於模型中的這些方法嗎?):例如,樹視圖的GetChildren。

另外,在模型中存儲Location Buddy類是否正確?

我想確保我設計好這個應用程序,因爲它是一個更大的項目的一部分。任何設計指針都非常感謝。我一直在閱讀ScottGu的博客MVC的東西。

編號:http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

+0

你需要花一些時間閱讀你的問題。用段落格式化它。只列出那些相關的類。 – jgauffin

回答

3

這裏有一對夫婦爲你的 「框架」 的建議。

實體框架

對於每個模型返回從EF回來,提取EF模型的接口,並使用接口作爲數據源,而不是實現EF類。原因在於,如果您決定爲任何一個或多個模型(或整個實體框架)使用其他數據源,則可以簡單地確保您的新數據層返回相同的接口,而無需更改整個Web碼。缺點是確保您的界面在更改模型時保持最新。

這還允許您的視圖模型實現EF模型的界面(使用您選擇的其他邏輯)。如果您對數據層的插入/更新的所有調用都接受返回的相同接口模型,則這是有利的。這允許您創建具有不同需求的多個模型,這些模型都適合數據層需要插入/更新的內容。缺點是在你的數據層中,你必須[創建一個新的EF模型]/[獲取模型更新]並將界面中的字段映射到模型。

視圖模型

我強烈建議每個視圖模型是不是需要顯示的實際模型(一個或多個),但包含模型(一個或多個)類。示例:

public class Car //Not what I recommend passing to a view 
{ 
    public string Make { get; set; } 
    public string Model { get; set; } 
} 

//Pass this to the view, i'll explain why... 
public class CarViewModel : IPartialViewCar  { 
    public Car Car { get; set; } 
    public ColorCollection { get; set; } 
} 

通過傳遞示例「CarViewModel」,可以將部分視圖與視圖分離。以下是如何(使用以上型號):

public interface IPartialViewCar 
{ 
    public Car { get; } 
} 

[BuildCar.cshtml] 
@Model MyNameSpace.Models.Car 

@Html.EditorFor(model) 

[PartialViewCar.cshtml] 
@Model MyNameSpace.Models.IPartialViewCar 

@Html.EditorFor(model) //something like that.. 

現在,只要你想使用的PartialViewCar你只需要做出一個實現IPartialViewCar界面模型,基本上去耦從視圖中partialview。

驗證

我建議創建接口(類,如果你真的想,但是是不是真的有必要)有大家驗證邏輯。假設我們要求匿名用戶輸入品牌和型號,但註冊用戶只需輸入一個品牌。怎麼可以這樣很容易做到,方法如下:(擴展更多的以前的代碼)

public interface IAnonymouseCarValidation 
{ 
    [required] 
    public string Make { get; set; } 
    [required] 
    public string Model { get; set; } 
} 

public interface IRegisteredCarValidation 
{ 
    [required] 
    public string Make { get; set; } 
} 

public interface ICar 
{ 
    public string Make { get; set;} 
    public string Model { get; set; } 
} 

[updating the Car model to abstract and use an interface now] 
public abstract class Car : ICar 
{ 
    //maybe some constructor logic for all car stuff 

    public string Make { get; set;} 
    public string Model { get; set; } 

    //maybe some methods for all car stuff 
} 

//MetadataType tells MVC to use the dataannotations on the 
//typeof class/interface for validation! 
[MetadataType(typeof(AnonymouseCarValidation))] 
public class AnonymousCar : Car 
{ 
} 


[MetadataType(typeof(AnonymouseCarValidation))] 
public class RegisteredCar : Car 
{ 
} 

[Now update the ViewModel] 
public class CarViewModel : IPartialViewCar  
{ 
    public ICar Car { get; set; } //this is now ICar 
    public ColorCollection { get; set; } 
} 

現在,您可以創建一個AnonymouseCarRegisteredCar,它傳遞到CarViewModel,讓MVC採取驗證照顧。當您需要更新驗證時,您需要更新單個界面。這個缺點是感覺相當複雜。

注射&數據請求

我的選擇是儘量保持控制器操作儘可能簡單和不包含的代碼有檢索數據。我選擇不這樣做的原因是我不喜歡重複代碼。例如:

public class AccountControllers 
{ 
    DataServer _Service; 

    public AccountControllers(DataServer Service) 
    { 
     this._Service = Service; 
    } 

    public ActionResult ShowProfiles() 
    { 
     ProfileViewModel model = new ProfileViewModel(); 
     model.Profiles = this._Service.Profiles(); 
     return View(model); 
    } 

    public ActionResult UpdateProfile(ProfileViewModel updatedModel) 
    { 
     service.UpdateProfile(updatedModel); 

     ProfileViewModel model = new ProfileViewModel(); 
     model.Profiles = this._Service.Profiles(); 
     return View(model); 
    } 
} 

相反,我會做這樣的事情:(不完全)

public ActionResult ShowProfile(Guid ID) 
    { 
     ProfileViewModel model = new ProfileViewModel(this._service); 
     return View(model); 
    } 

    public ActionResult UpdateProfile(ProfileViewModel updatedModel) 
    { 
     // pass in the service, or use a property or have SetService method 
     updatedModel.Update(this._service) 

     ProfileViewModel model = new ProfileViewModel(this._service); 
     return View(model); 
    } 

public class ProfileViewModel() 
{ 
    DataServer _Service; 
    Profile _Profile 
    public ProfileViewModel() 
    { 
    } 

    public ProfileViewModel(DataServer Service) 
    { 
     this._Service = Service; 
    } 


    public Profile Profiles() 
    { 
     get 
     { 
      if (this._service == null) 
      { 
       throw new InvalidOperationException("Service was not set."); 
      } 
      return = Service.Profiles(ID); 
    } 

這意味着,型材枚舉ONLY時,它的要求,我沒有來填充它自己。如果我使用代碼來獲得優勢,那麼往往會減少錯誤,而不是要求我或其他程序員手動填充模型。