问题
I have little experience with Database First Models and how to approach these with MVC View Models.
It is clear I cannot change the original model but I would like to add some annotations to the model for validation purposes.
Therefore what I tried to do was create a ViewModel which inherits from the entity
My DB First generated model - do not amend
public partial class xmldata
{
public string ISBN { get; set; }
public string title { get; set; }
public string blurb { get; set; }
...
}
I then created a view model as follows which inherits from xmldata
public class XmlDataViewModel : xmldata
{
[AllowHtml]
[Display(Name = "Blurb")]
public string BlurbVm {
get { return blurb; }
set { blurb = value; }
}
...
}
The field shown above I needed to AllowHtml and my best solution so far but however in the controller actions I have still had to manually map the BlurbVm field back to blurb even though i would of thought the setter above would of handled that (im using Automapper for the rest of the fields) so I am confused as to why this didn't work.
Also at the moment I am doing Validations in the controller and may want to refactor this later to move them into the View Model so I can use the [Required] annotation and also [Display (Name="Title")] fields which are currently handled in the view.
Probably my overall question here is am I using the best strategy for dealing with Model Annotations and view models when using a Database First Model.
回答1:
I thought I might add some detailed explanation on why data model is different from view model
Difference between model and view model
You are mixing two different things, as @Stephen Muecke mentioned in comments. View model serves one purpose - take data from controller and transfer it to to view. In complicated cases data you want to show the user is completely different from what your database looks like. To represent your data structure in your code you use data model. It has exactly the same properties as you have in your database.
However view model shouldn't know about how your data is structured. You just simply assign its properties and pass those data to the view.
Consider following example. You have Customers
and Orders
tables in your database.
Customers:
ID | Firstname | Lastname
Orders:
ID | Amount | CustomerID
In order to map those data in your code you would have to create two classes
public class Customer
{
public int ID { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
public class Order
{
public int ID { get; set; }
public decimal Amount { get; set; }
public int CustomerID { get; set; }
}
But in your application you have some view, where you want to display customers first names and total amount they've spent in your shop. You could create view model, which will serve exactly this purpose.
public CustomersViewModel
{
public string Firstname { get; set; }
public decimal TotalAmount { get; set; }
}
See how different this view model is, compared to your data model? It doesn't know about ID
value nor about Lastname
.
This model is used only to display your data properly, so here you can use all DataAnnotation
s you want.
public CustomersViewModel
{
public string Firstname { get; set; }
[DisplayFormat(DataFormatString="{0:#.####}")]
public decimal TotalAmount { get; set; }
}
Why on MSDN they're annotating data models?
Because like @CodeCaster mentioned - it's bad practice, but it's not forbidden. If your application is really simple, you can skip view models altogether! Is it a bad idea? Yes - even in simple cases you should use dedicated view models, because it costs you nothing, but decouples your views from your data structure. I guess they didn't want to complicate those examples, so when reading this tutorials you should focus only on how to use DataAnnotation
s.
How to bind custom view model in your controller?
Usage of view models is not limited to returning them to views in order to simply display some data. You can use them, if you want to pass data for the user to modify it. It is absolutely acceptable to have view model, which have exactly the same properties as your data model. Considering previous example, we could have CustomerViewModel
which we can use in EditCustomer.cshtml
view.
In this view we could have our edit form looking like this
@model CustomerViewModel
// HTML markup
@Html.LabelFor(m => m.Firstname)
@Html.TextboxFor(m => m.Firstname)
// another properties similar
If our Edit
method in CustomerController
would look like this
public Edit(CustomerViewModel customer)
there is not much we have to do more. ASP.NET will automatically bind posted form with customer
of type CustomerViewModel
. Now we only have to pass data stored in customer
into appropriate data model and save it in database.
回答2:
You can add data annotation to your main domain model. While creating manual data annotation ensure that namespace are equal with generated class's namespace.
[MetadataType(typeof(XmlDataDataAnnotation))]
public partial class xmldata{ }
public class XmlDataDataAnnotation
{
[AllowHtml]
[Display(Name = "Blurb")]
public string blurb { get; set; }
}
Then you can create complex property in your view model.
public class XmlDataViewModel
{
public xmldata XmlData {get;set;}
}
Also please see below link for clarification:
Add data annotations to a class generated by entity framework
Data Annotations with Entity Framework 5.0 (database first)
来源:https://stackoverflow.com/questions/39995841/database-first-and-view-models