2011-11-16 224 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时,它的要求,我没有来填充它自己。如果我使用代码来获得优势,那么往往会减少错误,而不是要求我或其他程序员手动填充模型。