ASP.NET MVC 3 - 模型验证 [英] ASP.NET MVC 3 - Model Validation

查看:18
本文介绍了ASP.NET MVC 3 - 模型验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚学习 MVC,我有一些关于设计/事情应该如何工作的问题.

I'm just learning MVC and I have a few questions about the design/how things are supposed to work.

我正在使用 MVC 3 和 Razor,以及实体框架类(例如位置),我将创建一个带有验证注释的伙伴类.在我的视图中,我有一个局部视图,它呈现一个 DevExpress TreeView(使用位置列表)和一个用于在树中创建/编辑位置的表单.我有一个 LocationController、一个 LocationManagementView、一个 LocationManagementPartialView(包含树视图的代码)和一个 LocationModel.LocationModel 将保存伙伴类并获取获取子节点的方法(子节点仅在节点展开后才被获取).我有一个将使用 StructureMap 注入的服务包装器(用于我的服务客户端).

I'm using MVC 3 and Razor, with Entity Framework classes (e.g. Location) and I'm going to create a buddy class with Validation annotations. In my View, I have a Partial View that renders a DevExpress TreeView (using a list of Locations) and a Form for creating/editing the Locations in the Tree. I have a LocationController, a LocationManagementView, a LocationManagementPartialView (contains the code for tree view), and a LocationModel. The LocationModel will hold the buddy class and get methods for getting children (the children are only fetched after a node is expanded). I have a service wrapper (for my service client) that will be injected using StructureMap.

我应该将服务包装器注入控制器的构造函数还是模型的构造函数?

Should I inject the service wrapper into the Controller's constructor or into the Model's constructor?

此外,我的模型具有使用服务包装器从数据库中获取数据的 get 方法(这些方法是否属于模型中的此处?):例如,用于树视图的 GetChildren.

Also, my Model has get methods that use the service wrapper to fetch data from the database (do those methods belong here in the Model?): for example, GetChildren for the tree view.

另外,在 Model 中存储 Location buddy 类是否正确?

Also, is it correct to store the Location buddy class in the Model?

我想确保我能很好地设计这个应用程序,因为它是一个更大项目的一部分.任何设计指针都非常感谢.我一直在阅读 ScottGu 的关于 MVC 内容的博客.

I want to make sure I design this application well, as it's part of a much bigger project. Any design pointers are much appreciated. I've been reading ScottGu's blog for the MVC stuff.

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

推荐答案

这里有一些针对您的框架"的建议.

Here are a couple of recommendations for your "framework".

实体框架

对于从 EF 返回的每个模型,提取 EF 模型的接口并将该接口用作数据源,而不是实现的 EF 类.这样做的原因是,如果您决定为任何一个或多个模型(或整个实体框架)使用另一个数据源,您只需确保您的新数据层返回相同的接口,而无需更改您的整个 Web代码.缺点是确保您的界面在您进行模型更改时是最新的.

For each of your Models returned back from EF, Extract an Interface of the EF Model and use the interface as the source of data, not the implemented EF Class. The reason for this is that if you decide to use another data source for any one more or more models (or the entire Entity Framework) you can simply make sure your new Data Tier returns the same interfaces, without the need to change your entire web code. The downside is making sure your interfaces are up to date when you make model changes.

这还允许您的视图模型实现 EF 模型的接口(带有您选择的附加逻辑).如果您对数据层的所有插入/更新调用都接受返回的相同接口模型,这将是有利的.这允许您创建具有不同要求的多个模型,这些模型都适合数据层插入/更新所需的内容.缺点是在您的数据层中,您必须[创建一个新的 EF 模型]/[获取要更新的模型] 并将字段从接口映射到模型.

This also allows your view models to implement the interface of an EF model (with additional logic of your choice). This is advantageous if all your calls for inserts/updates to the Data Tier accept the same interface models returned. This allows you to create multiple models with different requirements that all fit what the Data Tier needs to insert/update. The downside is that in your Data Tier you'll have to [create a new EF model]/[Get the model to update] and map the fields from the interface to the model.

查看模型

我强烈建议每个视图模型不是需要显示的实际模型,而是包含模型的类.示例:

I highly recommend that each view model is not the actual model(s) that need to be displayed, but an class that contains the model(s). Examples:

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",您可以将部分视图与视图分离.方法如下(使用上述模型):

By passing the example "CarViewModel", you can decouple partial views from views. Here's how (using the models above):

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 接口的模型,基本上将局部视图从视图中分离出来.

Now anytime you want to use the PartialViewCar you simply need to make a Model that implements the IPartialViewCar Interface, basically decoupling the partialview from the view.

验证

我建议创建具有所有验证逻辑的接口(如果您真的需要,则为类,但实际上没有必要).

I would recommend creating interfaces (classes if you really want, but there really isn't a need) that have all of you validation logic.

假设我们希望匿名用户同时输入品牌和型号,但注册用户只需输入品牌.如何轻松完成此操作,方法如下:(在前面的代码上进行更多扩展)

Lets say we want to require anonymous users to type both a make and a model, but registered users only have to type a Make. How can this be done easily, here's how: (extending more on the previous code)

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 负责验证.当您需要更新验证时,您只需更新一个界面.这样做的缺点是感觉相当复杂.

Now you can create either an AnonymouseCar or RegisteredCar, pass it into the CarViewModel, and let MVC take care of the validation. When you need to update the validation, you update a single interface. The downside to this is it feels fairly complex.

注射 &数据请求

我的偏好是尽量保持控制器操作尽可能简单,而不是在其中包含用于检索数据的代码.我选择不这样做的原因是我不喜欢重复代码.例如:

My preference is to try to keep the Controller Actions as simple as possible and not to include code there to retrieve data. The reason I choose not to do this is that I don't like to repeat code. For example:

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

相反,我会这样做:(不完全)

Instead I would do something like: (not completely)

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

这意味着配置文件在被请求时被枚举,我不必自己填充它.如果我将代码用于我的优势,而不是要求我或其他程序员手动填充模型,那么错误往往会更少.

This means that profiles is Enumerated ONLY when it's requested, I don't have to populate it myself. Tends to be less bugs if I use the code to my advantage, instead of requiring me or other programmers to manually populate models.

这篇关于ASP.NET MVC 3 - 模型验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆