通过单独的程序集充分利用 ASP.NET MVC DataAnnotations
假设我有一个描述域模型的域程序集,并且它有一个名为产品的类:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
我还有另一个程序集,它是与此域模型一起运行的 Web 应用程序。现在我想创建一个表单来创建新产品并对属性进行一些验证。最简单的方法是在类上使用 DataAnnotations。然而,这导致域模型现在包含有关表单验证的元数据,这不是一个非常清晰的关注点分离。
类可以有 MetadataType
属性,但我认为这并没有更好。突然间,您的域模型类依赖于表单验证元数据类。
另一种方法是创建一个 CreateProductForm 类并在其中添加所需的属性,并在类之间进行映射。然而,这会产生一些开销,因为您需要单独维护这些类,并且其中一个类的更改可能会破坏另一个类。在某些情况下这样做可能是可取的,但在其他一些情况下,它可能只会产生额外的工作(例如,假设您有一个 Address 类)。
更新:有些人建议我为此使用 AutoMapper,我已经知道了。 AutoMapper 只是使映射变得更简单、更容易,实际上并没有解决必须维护两个几乎相同的独立类的问题。我的偏好是仅在有明确需要时才创建表单类。
是否可以直接在 Web 程序集中声明注释,而无需为域程序集创建不必要的依赖项?
Let's say that I have a Domain assembly that describes the domain model, and it has a class called product:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
I have also another assembly that is the web application running with this domain model. Now I want to create a form to create new products and have some validation on the attributes. The easiest way to do this is to use DataAnnotations on the class. However this results in that the domain model now contains metadata about form validation, which is not a very clear separation of concerns.
It is possible to have the MetadataType
attribute for the class but I see this as no better. Suddenly your domain model class has a dependency on the form validation metada class.
Another way is to create a CreateProductForm
class and add the required attributes there, and do mapping between the classes. However this creates some overhead as you need to maintain these classes seperately and changes in one might break the other. It might be desirable in some scenarios to do that, but in some others it might just create extra work (imagine that you have an Address class, for example).
UPDATE: some people have suggested that I use AutoMapper for this, which I'm already aware of. AutoMapper just makes mapping simpler and easier, does not actually solve the problem of having to maintain two separate classes which will be almost identical. My preference would be to only create the form classes when there is a distinct need for it.
Is there a straightforward to declare the annotations within the web assembly, without creating unnecessary dependencies for the domain assembly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您不想在域模型和视图之间引入耦合,则应该采用 CreateProductForm 类方式。
根据您的项目大小/要求,您迟早必须将视图模型与域分离。假设您正在使用 DisplayName 属性:您要标记您的域实体吗?
使用像 AutoMapper 这样的工具可以大大简化绘图过程。
If you don't want to introduce coupling between your domain model and your views, you should go for the CreateProductForm class way.
Depending on your project size/requirements, you're going to have to separate your view model from your domain sooner or later. Suppose you're using the DisplayName attribute : are you going to tag your domain entities ?
Using a tool like AutoMapper simplifies greatly the mapping process.
为什么你的域类上没有 DataAnnotations。如果有一些东西是必需的,那么我认为在域中将其标记为必需是完全有效的。
其他 DataAnnotations,例如 StringLength、Range 等,对我来说都是完全有效的东西来装饰你的域实体。
恕我直言,实现 IValidableObject 对于域对象来说也是完全可以接受的事情。
我不会在它们上面添加 UI 内容,例如 UIHint 或描述属性格式的注释。那会很糟糕。
通常我会避免在用户界面上显示域类,而是使用 ViewModel 类和 AutoMapper 等映射工具来从一个类映射到另一个类。 ViewModel 类具有域类的注释,可能还有其他特定于 UI 的注释。
Why wouldn't you have DataAnnotations on your domain classes. If there is something that is Required, then I think it's perfectly valid to mark it as required in the domain.
Other DataAnnotations such as StringLength, Range etc, all to me perfectly valid things to decorate your domain entities with.
Implementing IValidableObject is also a perfectly acceptable thing for domain object to do IMHO.
I wouldn't go putting UI stuff on them such as UIHint though or annoations describing the formatting of the property. That would be bad.
Normally I avoid displaying domain classes on the user interface, and use ViewModel classes with a mapping tool such as AutoMapper etc to map from one to the other. The ViewModel class has the annoations of the domain class with perhaps additional UI specific annotations.
正如 mathieu 和 XHalent 所说,您应该使用 CreateProductForm (或 CreateProductFormViewModel)以及 Automapper 并创建自动映射的属性模型到动作的视图模型。
这样,所有表单验证都在您的视图模型中进行,所有数据验证(与数据库相关)都在您的域模型中进行。
在 Silverlight 和 WPF 中,它被称为 MVVM 模式,很多人都这样认为谁有asp.net mvc推荐一下。
在我当前的项目中,我还将它与 Automapper 一起使用。我的所有视图都有一个关联的视图模型,它是特定于该视图的域模型的扁平化版本。
我认为 this 是我使用的示例(这是我仍然使用的示例)无论如何已经添加了书签,但是这个one 似乎更好。)
使用该属性意味着您从控制器中的操作返回域对象,并且 automap 属性自动将域对象映射到视图模型。
这样做应该会给你带来你想要的分离。
As mathieu and XHalent state you should use a CreateProductForm (or a CreateProductFormViewModel) along with Automapper and create attribues that automap the model to the viewmodel for the action.
That way all the form validation goes on your view model and all the data validation (related to the database) goes in your domain model.
In Silverlight and WPF it is called the MVVM pattern and a lot of people who do asp.net mvc recommend it.
In my current project I am also using it with Automapper. All my views have an associated view model that is a flattened version of the domain model specific to that view.
I think this was the example I used (It's the one I still have bookmarked anyway. but this one linked in the first one seems better.)
Using the attribute means that you return the domain object from your action in the controller and the automap attribute maps the domain object to your viewmodel automatically.
Doing this should give you the seperation you are looking for.