ASP.Net MVC3 模型与 ViewModel - 我不想写入数据库的属性
我目前正在玩 ASP.NET MVC3,并且有一个关于模型和视图模型的问题。
我有一个包含日期时间字段的数据库模型。当我在屏幕上显示此内容时,我想将日期和时间部分拆分到单独的输入框中。我想了几种方法来实现这一目标,并想知道最好的解决方案是什么。
1)创建具有两个属性的模型:
[DataType(DataType.Date)]
public DateTime DateOfIncident {get; set;}
[DataType(DataType.Time)]
public DateTime TimeOfIncident {get; set;}
当我生成它时,这会在我的视图上呈现两个字段。问题是,当将其写入数据库时,TimeOfIncident 仍然在 SQL Server 中呈现为日期时间,并且默认日期部分。为了解决这个问题,我可以将一些代码放入我的控制器中,例如在 HttpPost Create 中,我可以执行以下操作:
accident.TimeCreated = (accident.DateCreated.Value.Date + accident.TimeCreated.Value.TimeOfDay);
这有效(我得到带有正确日期部分的 TimeOfIncident ),但我现在有两个字段 - DateOfIncident 和TimeOfIncident,都是日期时间,实际上,我的直觉告诉我数据库中应该只有一个字段(因为它是日期时间)。
2)我可以在我的模型中创建一个属性 - DateOfIncident,将其注释为 DataType.Date 将一些自定义“未绑定”HTML 添加到我的视图中以捕获时间。然后在我的控制器中,我可以将该虚假元素强制到我的 DateOfIncident 的时间部分中。
3)仅使用 DateOfIncident 创建我的模型,然后创建一个 ViewModel,其看起来类似于:
public AccidentReport accidentReport {get; set;}
[DataType(DataType.Time)]
public DateTime TimeOfIncident {get; set;}
将该视图模型传递到我的视图中并从那里开始。
我没有太多 MVC 经验,所以我想知道我是否走在正确的轨道上,或者是否有更好/更简单的方法来连接这一切?
谢谢大家。
I'm currently toying with asp.net mvc3 and have a question with respect to models and viewmodels.
I have a database model that has a DateTime field. When I display this on screen I want to split the date and time portions into separate input boxes. I have thought of a few ways to accomplish this and was wondering what the best solution would be.
1) Create my model with two properties :
[DataType(DataType.Date)]
public DateTime DateOfIncident {get; set;}
[DataType(DataType.Time)]
public DateTime TimeOfIncident {get; set;}
this renders two fields on my View when I generate it. The trouble is, when this gets written to the DB, the TimeOfIncident is still rendered as a datetime in SQL Server and it defaults the date portion. To get around this, I can put some code into my controller, for example in the HttpPost Create, I can do something like:
accident.TimeCreated = (accident.DateCreated.Value.Date + accident.TimeCreated.Value.TimeOfDay);
which works (I get the TimeOfIncident with the correct date portion), but I now have two fields - DateOfIncident and TimeOfIncident, both being datetime and really, my gut says I should only have one field in the database (since it is a datetime).
2) I could create one property in my model - DateOfIncident, annotate it to be DataType.Date put add some custom "unbound" HTML into my view to capture the time. Then in my controller I could coerce that spurious element into the time portion of my DateOfIncident.
3) Create my model with only a DateOfIncident and then create a ViewModel which has looks something like:
public AccidentReport accidentReport {get; set;}
[DataType(DataType.Time)]
public DateTime TimeOfIncident {get; set;}
pass that viewmodel into my view and go from there.
I've not got much MVC experience so I'm wondering if I'm going down the right track here or if there is a better/simpler way to wire this all up?
Thanks everyone.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为你的数据库中应该只有一个字段。选项 2 和 3 效果很好,我在简单的场景中使用了这两种方法,效果都很好。
但我认为您会想看看编辑器模板。当场景变得复杂时,很好地使用它可以使事情变得更好:http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html如果您为此案例制作一个编辑器模板,您将能够在您的所有 Web 应用程序中重复使用它。
本教程适用于 ASP.NET MVC 2,但在 ASP MVC 3 中仍然有效。
希望它有所帮助。
I think you should have only one field in your database. Options 2 and 3 works well, and I used both with good results in simple sceneries.
But I think you will want to take a look to Editor Templates. Using it well can make things better when the scenary becomes complex: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html If you make an editor template for this case, you will be able to reuse it along all your web app.
The tutorial is for ASP.NET MVC 2, but It's still valid in ASP MVC 3.
Hope it helps.
我相信,一般来说,您永远不会遇到“ViewModel”与“Model”完美匹配的情况。总会有一个字段是您不希望写入数据库的。
我认为选项 3 正是我在这里所提倡的。
I believe that in general, you will never quite have a situation where your "ViewModel" matches your "Model" perfectly. There's always going to be one field here and there that you don't want written to the DB.
I think Option 3 is pretty much what I am advocating here.
这是我喜欢描述的一个例子。对于我的领域,我有一个客户模型。该模型将包括用户名、名字、姓氏、密码、电子邮件地址和邮政编码。
我可能对登录和注册有意见。我的登录视图将只关心用户名和密码。我的注册视图将涉及用户名、名字、姓氏、密码、确认密码、电子邮件地址和邮政编码。正如您所知,这些视图并不直接映射到域模型。例如,注册视图需要使用Password和ConfirmedPassword以及域模型中的其他属性,但这里的问题是客户域模型不包括ConfirmPassword。考虑到这一点,最好创建一个特定于视图所需数据的模型视图。因此,我将创建一个名为 CustomerRegistrationVM 和 CustomerLoginVM 的视图模型。
通常我的控制器调用服务来从存储库检索数据。存储库将每个域模型的数据返回到服务。该服务将域模型转换为正确的视图模型。
当需要更新或保存数据时,控制器将视图模型传递给服务来保存数据。服务的职责是将视图模型转换为域模型并调用存储库。在某些情况下,服务不需要将视图模型转换为域模型,而只需传递存储库所需的数据。
Here's an example I like to describe. For my domain, I have a model for customer. This model would include UserName, FirstName, LastName, Password, EmailAddress, and ZipCode.
I may have views for Login and Registration. My login view will only be concerned with UserName and Password. My Registration view will be concerned with UserName, FirstName, LastName, Password, ConfirmedPassword, EmailAddress and ZipCode. As you can tell, these views do not map directly to the domain model. For example, the registration view needs to work with Password and ConfirmedPassword and plus the other properties in the domain model, but the problem here is that customer domain model does not include ConfirmPassword. With this in mind, it would be preferred to create a model view that is specific to the data the view needs. So I would create a view model call CustomerRegistrationVM and CustomerLoginVM.
Usually my controllers call services to retrieve data from a repository. The repository returns data per the domain model to the service. The service translates the domain model to the correct view model.
When the data needs to be updated or saved, the controller passes the view model to a service to save the data. It's the responsibility of the service is to translate the view model to the domain model and call the repository. There are situations where the service does not need to translate the view model to the domain model, but just passes the data that is needed by the repository.
我认为您通常希望将任何内容如何持久保存到数据库中与其显示方式分开。仅仅因为您有两个数据输入组件来描述事件(时间和日期)并不意味着底层持久层应该模仿它 - 事实上,让视图和持久层关注通常不是一个好主意自己与他人所做的事情。这就是它们之间的层的用途。
因此,在您的情况下,我会在引擎盖下有一个 DateTime 对象,该对象存储该事件信息,然后将其分解为其组成部分以供显示/输入,在保留它之前重新组装它。
一般来说,我在编写第一个 ASP.NET MVC 3 应用程序时最初犯的一个大菜鸟错误是让实体框架吐出一些映射到数据库表的生成对象,然后将它们传递给视图。一旦我开始编写和使用视图模型将数据转换为可呈现的东西,然后让该层在视图模型/视图世界和底层模型/持久层世界之间进行转换,事情就变得容易多了。
I think you generally want to separate out how anything is persisted into the DB from how it is displayed. Just because you've got two data entry components to describe an event (time and date) doesn't mean the underlying persistence layer should mimic that - in fact, it generally isn't a good idea to let the view and persistence layer concern themselves with what the other does. That's what the layer between them is for.
So, in your situation I'd have a single DateTime object under the hood that stored off that incident information and then break it apart into its constituent pieces for display/entry, reassembling it before you persist it.
Generally speaking, the big rookie mistake I initially made when writing my first ASP.NET MVC 3 app was to let Entity Framework spit out some generated objects that mapped to DB tables and then pass those to the View. Once I started writing and using viewmodels to transform the data into something that was presentable and then just let that layer transform between the viewmodel/view world and the underlying model/persistence layer world, things were much easier.