I am not an experienced MVC3 developer but I'm trying to be. I am familiar with POCO classes and also ViewModels, as the former describes each classes of the database and the latter is used for strong type views in mvc3. My question is not that complicated for the experienced developers but I am a little confused about that.
The matter is that, I have a solution containing three projects;
The Model class library in which I have wrote my POCO classes. Here is an example:
.
public class Service
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int ServiceID { get; set; }
//------------------------------------------------------------//
[Required, MaxLength(30)]
[LocalizedAttribute("Name")]
public string Name { get; set; }
//------------------------------------------------------------//
[MaxLength(100)]
[LocalizedAttribute("Description")]
public string Description { get; set; }
//------------------------------------------------------------//
[Required]
public long ModifiedByUserID { get; set; }
[ForeignKey("ModifiedByUserID")]
public virtual User OperatorUser { get; set; }
//------------------------------------------------------------//
[Required, MaxLength(10)]
public int ModifiedDate { get; set; }
}
The repository and UnitOf Work class Library
The MVC application
Now, Did I correctly address the POCO classes? (I am using EF Code First to generate the database of course) If So, are they inferred as ViewModels too? I have used them to generate Strongly-Type View.
What is the best and actually standard way to define POCO classes and ViewModels?
I would appreciate any kind guidance,
To be honest, it depends on the size of your project.
If you look at most of the Microsoft examples, they use their POCOs as Models simply because their examples are small projects.
If however you are developing anything near an enterprise level application you really shouldn't be using your POCO's as models. There should be clear separation of concerns. Strictly speaking your Web project shouldn't even know about your POCO objects in those scenarios, a typical implementation is a common interface that both the POCO and the View Model can implement and see. That way saves you exposing your POCO objects to your Web layer.
ViewModel is a middle layer between data(Poco) and View, which usually contains additional logic to control UI.
If ViewModel doesn't have any specific data, I don't see the reasons not to use Poco as ViewModel.
In other case, to keep data as Poco, you can create ViewModel with the same fields as your Poco class and use Automapper to Poco->ViewModel, ViewModel->Poco transformation.
I agree with mt_serg. In my application, I use POCO classes directly if it is a straightforward case.
However if in my view I also need to display for example drop-down lists that are populated from the db, then I create a ViewModel that includes the POCO classes with the additional lists and use the VM in the view passed in from the controller. I don't however redo my work and create the VM with the same fields as the POCO + additional fields. I find this method works for me, since I do not have to take care of transformations myself and I let the MVC framework sort that out for me. Hope this helps
Related
I'm using code-first with entity framework for modeling and creating my db.
I'm just wondering - when I return objects to the user - I don't want to return data sensitive fields like id.
Should I add an atttibute like [DoNotReturn] combined with a filter to remove this fields when returning to the user, or should I just make a whole new class which doesn't contain these fields?
Example:
public class UserAccount
{
//Option 1 - Hide fields
[DoNotReturn]
public int Id { get; set; }
[Index(IsUnique = true)]
[MaxLength(50)]
public string Username { get; set; }
public decimal Cash { get; set; }
[DoNotReturn]
public Account Account { get; set; } //Contains Email / Password
//Option 2 - return a `safe` version
public User UserAccountToFriendly() {
return new FriendlyUser(this.Username, this.Cash);
}
}
Keep your database model separate from your view model that's the approach I have taken and doing it for a long time. it will give you a good separation. Once you start dealing with ViewModel then you can use a library like Automapper or custom mapping classes to convert ViewModel to database model or vice-versa. I hope it helps
Never use your database models as result for end-users and keep it separate from Presentation/Application layer.
There are so many problems that you will encounter:
disclosure of sensitive data (you've mentioned about);
performance issues and waste of RAM and CPU (for instance, you have Order entity with dozens of properties, it would be better to load only those properties that is required instead all);
problems with serialization (with enabled lazy-loading, for instance MVC could try to serialize whole object with navigation properties... );
etc...
I'd like to recommend the following:
return original database entity from Repository layer if necessary, but don't forget to cast it on Presentation layer to another completely brand new xxxModel, xxxViewModel, xxxResponse, etc;
return xxxView from Repository layer if you want to achieve best optimizations, but don't forget to cast it on Presentation layer to brand new object. (any changes on one layer shouldn't affect others, especially end-users);
This question already has answers here:
Should Entities in Domain Driven Design and Entity Framework be the same?
(4 answers)
Closed 5 years ago.
I have a three tier app with a class library as the Infrastructure Layer, which contains an Entity Framework data model (database first).
Entity Framework creates entities under the Model.tt folder. These classes are populated with data from the database.
In the past I would map the classes created by Entity Framework (in the data project) to classes in the Domain project e.g. Infrastructure.dbApplication was mapped to Domain.Application.
My reading is telling me that I should be using the classes contained in .tt as the domain classes i.e. add domain methods to the classes generated by Entity Framework. However, this would mean that the domain classes would be contained in the Infrastructure project, wouldn't it? Is is possible to relocate the classes generated by Entity framework to the Domain project? Am I missing something fundamental here?
I think in the true sense it is a Data Model - not a Domain Model. Although people talk about having the Entity Framework Model as a domain concept, I don't see how you can easily retro fit Value objects such as say amount which would be represented in the true domain sense as such:
public class CustomerTransaction
{
public int Id { get; set; }
public string TransactionNumber { get; set; }
public Amount Amount { get; set; }
}
public class Amount
{
public decimal Value { get; }
public Currency Currency { get; }
}
As opposed to a more incorrect data model approach:
public class CustomerTransaction
{
public int Id { get; set; }
public string TransactionNumber { get; set; }
public int CurrencyType { get; set; }
public decimal Amount { get; set; }
}
Yes, the example is anaemic, but only interested in properties for clarity sake - not behaviour. You will need to change visibility of properties, whether you need default constructor on the "business/data object" for starters.
So in the domain sense, Amount is a value object on a Customer Transaction - which I am assuming as an entity in the example.
So how would this translate to database mappings via Entity Framework. There might be away to hold the above in a single CustomerTransaction table as the flat structure in the data model, but my way would to be add an additional repository around it and map out to the data structures.
Udi Dahan has some good information on DDD and ORM in the true sense. I thought somewhere he talked about DDD and ORM having the Data Model instance as a private field in the domain object but I might be wrong.
Also, that data model suffers from Primitive Obsession (I think Fowler coined it in his Refactoring book - although it Is in his book) Jimmy Bogard talks about that here.
Check out Udi Dahan stuff.
You should move your model to a different project. That is good practice. I don't quite get it what you meant by "moving to to Domain project" Normally entity framework generated classes are used as a domain model. No need for creating "different" domain model from this. This model should be use only near to database operations, whereas web(window) application should use only DTO (Domain transfer objects)
I don't know if you use it or not - but this is a nice tool allowing for recreating model from the database :
https://marketplace.visualstudio.com/items?itemName=SimonHughes.EntityFrameworkReversePOCOGenerator
This allows to store model in classes (instead of EDMX) Someone refers to it as "code first" but there is a misunderstanding. One can use this tool to create model and still be on "database first" This is done simply to omit using EDMX as a model definition.
You can relocate the entity classes by creating a new item in your Domain project: DbContext EF 6.x Generator (not sure of the name and you might have to install a plugin to get this item in the list, also exists for EF 5.x).
Once you have created this new item, you have to edit it to set the path of your EDMX at the very begining of the file. In my project for example it is:
const string inputFile = #"..\..\DAL.Impl\GlobalSales\Mapping\GlobalSalesContext.edmx";
You will also need to edit the DbContext.tt file to add the right using on top of the generated class. At each change you've done on the EDMX, you also will have to right click the generator and click: "Run custom tool" to generate the new classes.
That being said, is it a good practice? As you can see that's what I have done in my project. As long as you do not have EF specific annotations or stuff like that in the generated entity classes, I would said that it is acceptable.
If you need to change your ORM, you can just keep the generated classes and remove all the EF stuff (.tt files, etc) and the rest of your application will work the same. But that's opinion based.
I am trying to design business entities in .NET like below which will be exposed via Web API/oData.
Business Entity 1 : "Vehicle" with the properties as below:
VehicleId string
ModelId string
Business Entity 2 : "Model" with the properties as below:
ModelId string
ModelDescription string
Now if someone uses my Web API to fetch Vehicle information only and wants to display Model description also then they need to make 2 HTTP calls which will result in degradation of performance specifically in slow networks. In this scenario I would like to know what is the best way to load & model nested business entities which will provide optimum performance via Web API?
Shall I model my Vehicle class as below and is it really a good practise for a REST/Web API design? For the below approach the entity seems to become too heavy also due to contained entities also. Please advise.
Business Entity 1 : "Vehicle" with the properties as below:
VehicleId string
ModelId Model
It all depends on what's consuming your API and how it recognizes and persists one-to-many relationships. Write your API so that your first consumer can call it in a performant fashion, then worry later about tweaking it.
For example, in an Ember.js app using Ember Data, you have a choice of returning child IDs, or you can embed the entire child as a property on the parent as well and it will be deserialized and tracked on the client as an individual model. Whether you want to do it one way or the other depends entirely on your application flow. I recognize that Ember Data is not OData, but the concept is the same.
I don't think there's a good "this is the way to do it" answer without considering both the client and server.
I would probably create Vehicle and Model as
public class Vehicle
{
public string Id { get; set; }
public string ModelId { get; set; }
public Model Model { get; set; }
}
public class Model
{
public string Id { get; set; }
public string Description { get; set; }
}
When your API client requests a vehicle, I would populate Model property if needed and would leave it as null if this information is not necessary.
This way you have a flexibility of not loading model information if you just need vehicle data while having while having to do only 1 API call in case you need both vehicle and model. This will also work well with a database with foreign keys and any ORM framework,
I plan to create a Asp.Net MVC app which contains edit/create pages for a large model with many-to-many relationship with other models. I found the Saving Many to Many relationship data on MVC Create view and plan to use it.
In the example, the create page uses the following ViewModel.
public class UserProfileViewModel
{
public int UserProfileID { get; set; }
public string Name { get; set; }
public virtual ICollection<AssignedCourseData> Courses { get; set; }
}
And the UserProfile model has only two properties so the ViewModel just duplicates all the properties.
public class UserProfile
{
public UserProfile()
{
Courses = new List<Course>();
}
public int UserProfileID { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
However, in my case, there will be a lot of properties (with data annotations), say 50 properties. Should the ViewModel duplicate all these properties (with data annotations too)? (looks ugly?) Or is there a better way?
Update
Is it a good practice to define ViewModel as
public class UserProfileViewModel
{
public UserProfile UserProfile { get; set; }
.... // Other properties needed by the view.
}
One shortcoming of this way is it expose all the properties in the Model even it's not needed in the view.
The thing with View Models is very simple: the View Model should consist only from data needed by the View. That is, the view model design is driven by the (static) view. Static because you can updates parts of the view via ajax in the browser so it makes no sense for your model to contain that info (except if it's required as init values for the JavaScript).
How the data is stored or how it's used by the business layer (if any) is not the view model concern.
Updated
The cleanest and safest way is to define the view models with the properties you need (you can copy paste them from the other model it's ok in this scenario) then use AutoMapper to map the business object to the view model. This way you can evolve both models differently. Personally, very rarely my view model is identical to a business model, they resembles a lot but there those tiny differences that complicate the things.
From a Separation of Concerns point of view, the busines model is for business usages, persistence model is for persistence usage while view model is for the view usage. Don't mix them or you'll have one model serving too many masters, which leads to complications down the road.
Taken from: This excellent explanation of ViewBag, ViewData and TempData
The type of data that suits ViewModels well is as follows:
Master-detail data
Larger sets of data
Complex relational data
Reporting and aggregate data
Dashboards
Data from disparate sources
So in summary, yes the ViewModel is what to use when the view requires a lot of complexity, it suits your needs. As for using and populating every property that should be determined by what the particular view requires. ViewModels are not necessarily one to one representations of a model / entity. That should be dictated by your view requirements, e.g. UserCourseViewModel could aggregate the UserProfile and Course entities, but not necessarily all of both of their properties, unless of course all properties are required by the view.
Rachels summary:
The ViewData and ViewBag objects give you ways to access those extra pieces of data that go alongside your model, however for more complex data, you can move up to the ViewModel. TempData, on the other hand, is geared specifically for working with data on HTTP redirects, so remember to be cautious when using TempData.
Is the following OK to do? I know Domain Models should never be used in views but is it ok to use Domain Models in your View Models? For some very small models it doesn't seem worth it to be creating and managing a View Model for them.
For Example
public class LoginDomainModel
{
public string Email { get; set; }
public string Password { get; set; }
public string DisplayName { get; set; }
public long UserTypeID { get; set; }
public virtual UserType UserType { get; set; }
}
public class UserTypeDomainModel
{
public UserType()
{
this.Logins = new List<Login>();
}
public long UserTypeID { get; set; }
public string UserType { get; set; }
public string Description { get; set; }
public virtual ICollection<Login> Logins { get; set; }
}
public class LoginViewModel
{
public string Email { get; set; }
public long UserTypeID {get; set;}
//Right here
public List<UserTypeDomainModel> UserTypesSelectList {get; set;}
}
Personally I use domain models in the view if they would naturally be an exact fit. That is likely to happen only on trivial projects that are CRUD in nature (editing the domain entities in a straightforward way). I find it a waste of time to create an exact copy of a domain entity for the sake of purity.
I will never modify a domain model in the slightest to account for needs of the view. In 95%+ of my projects, this is the circumstance I find myself in. The moment you pollute the domain for the sake of the view, you introduce maintainability headaches.
It depends on what you mean by "Domain model". Do you mean EF entities? Or do you mean business layer objects?
It's never a good idea to pass EF entities to the view, particularly if you're using default model binding. This can create security issues if you are not careful. Although the same issues can occur if you're not careful with business objects passed to the view.
One of the huge advantages of view models is that you have much finer control over mapping of data, so you can validate more easily that only the correct maps occur.
It all comes down to your app though. If it's a simple app, then it may not be worth the trouble of doing more complex mappings. If it's a complex app, that must live for a long time, and will likely to be updated a lot.. then you should definitely invest the effort.
I struggled for a long time with the perceived duplication caused by separate view models and domain models. I would assert that since they are intended for different purposes it's not really duplication, but it still feels "wrong" to declare so many similar properties.
In very small projects (especially ones with a highly trusted group of authenticated users) I may just bind directly to the domain models and be done with it. Or I may mix and match if the view model requires a different structure (as #Eric J. describes).
However: The ModelBinder will attempt to match values in the request to properties on your model. This means that any property on your domain model can potentially be populated by a (rogue) request. There are ways to prevent this, but for me the peace of mind outweighs a little extra effort creating separate view models.
I don't see an absolute need to create a separate view model for readonly, unbound values (possibly the list of user types in your case, though public virtual ICollection<Login> Logins may negate this).
Alternatively, you may wish to project the domain model to a UI-oriented abstraction (e.g. IEnumerable<SelectListItem>). You can use SelectListItems for a variety of input mechanisms, so you aren't tying yourself to a particular UI behavior.
Even with abstraction, you may still need to validate that the request doesn't contain an illegal value. For example, perhaps only super admins can assign certain UserTypeDomainModel IDs. Regardless of abstraction, you still need to validate this.
TLDR: abstract domain models as much as is practical, find appropriate abstractions (a new view model isn't always the correct answer), and be (slightly paranoid) about input validation.