I'm creating a ASP.NET MVC 4 web app with a database and Entity Framework 5 for a web form to maintain Document (aka Contract) entries.
Below is a sample ERD (in the form of edmx diagram with navigational properties) I have created for a DB in SQL server. For MVC web app the Model is generated from the DB with .edmx file.
Based on the Model, I have setup a form which can create and edit a Document like so:
Document Create and Edit View
This view refers to Document model class. So all the input fields using html helper (Html.TextBoxFor...,etc) are referred from Document object and its related objects (Section 1 & Section 2). The checkbox hides and shows the subform for a section with JS/jQuery. For the Edit view I use same as Create view, except it contains additional hidden ID fields to identity the records to edit from the DB.
I have added a variable length list for section item addition by following this:
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
In the partial view for the items dynamic list I use Section1Item and Section2Item as model reference.
Document Controller's Create method
So on Create the document object posted in Create(...) method contains all the attributes from the Document including the section's attributes.
If the checkbox value for Section 1 & Section 2 are false then I set the Document's Section 1 & Section 2 to null like so:
if (section1_chkbox == false) {
document.Section1 = null;
}
I have to add each item from the dynamic list into the document object like so:
foreach(Section1Item item in itemsList) {
document.Section1.Section1Items.Add(item);
}
So finally the Create method in the DocumentController adds the document in a db context and saves changes. The document and its related entities are successfully added to database tables.
Document Controller's Edit method
But when I'm editing the document with the Edit method in DocumentController there are some inconsistencies with some section1 object's ID being null for some related objects in Section1Items. For example when Section1Items are present the posted Document object (for edit) does not contain reference to Section 1 object's ID.
So it is fiddly and messy to update an existing document record as I'm having to check the ID attributes of a object. There are always errors like inconsistent principal and dependent objects in the relationship when saving or setting the object's entry state to modified.
My Question
How can I setup the View and Controller to achieve a functioning Create and Edit of a document along with its related entities as in the form's interface able? I need a efficient and correct way to use Entity Framework for this. How can I use view models for this if that would make this easier?
From what you described here I understand that there is a problem with virtual reference to Section1 from Section1Items. So in other words the problem is that entity framework model doesn't suit you display needs. You would need to render duplicated entities to map entier Document in your view. Am I right?
If that's the case I see two solutions:
like you suggested use view models to solve the problem. If you confirm the issue I can try to write example view model.
serialzie/encrypt entier Document in your view and next merge edited result with encrypted Document. You can achive that by using Mvc3Futures feature.
Serialize and encrypt your document in view:
#Html.Serialize("Document", Model, SerializationMode.EncryptedAndSigned)
And to deserialzie and decrypt you can use:
public ActionResult Edit(string id,[Deserialize(SerializationMode.EncryptedAndSigned)]Document document)
Just a rookie in .NET MVC world and still learning
I created three EF models in framework, one is clients, one is order, and items, below is the relation:
Client Order Items
PK:ID PK Order.id PK Items.ID
... FK:Client.id ...
FK:Item.id
In this case I wanna display all the client information and the item details they've bought in one table, obviously I cannot use any DBcontext here. So what should I do to combine the three table's info and output that? Create a new model on those three?
Any ideas or article are very welcomed!
I would create a ViewModel with all of the Data that you want to display. This is the model that will get populated in the controller and then it would get passed to the View.
So in the View it would use the ViewModel and wouldn't need to know about the underlying Database Model.
And in the Controller you would get the data needed and populate the ViewModel and pass that model onto the View.
Here is a page with an examples. There are plenty more out there too. http://sampathloku.blogspot.com/2012/10/how-to-use-viewmodel-with-aspnet-mvc.html
I am relatively new to MVC. I am trying to just display the contents of a remote SQL Server table on a page. It is READ ONLY, and nearly everything I find online is utilizing the Entity Framework or something similar which is overkill for what I am after. I just need to print all the rows from a table out to a view.
So my questions are:
should I just hack the sqlconn and everything into the view that I want the data printing out to?
Or should I add the sql in that view's controller?
Create a model and somehow get that data back into the view?
I know step #3 is the 'correct' way to do it, however I am looking for something simple and quick. :)
Thanks everyone!
You say EF is overkill, but that's the easiest way to do this. Maybe use Linq to SQL, since that's more lightweight. This is all there is to it:
Generate the EF / L2S entity classes
Instantiate the database context in the controller, and get all records
Return the IEnumerable records to the view
In the view, use #Html.DisplayForModel()
Here's a simple example. Note that returning the database entity classes is considered bad practice, you should map / automap them to a View Model type class first.
Home Controller
public ActionResult Index()
{
MyEntityModel[] items = MyDatabaseContext.GetAllRows();
return View(items);
}
Home/Index View
#model IEnumerable<MyEntityModel>
#foreach (MyEntityModel item in Model)
{
#Html.DisplayFor(m => item)
}
Without EF / L2S it's almost as easy, but you'd have to create your own entity / wrapper class for the database records and populate them manually.
There are also scaffolding projects for MVC that will generate repository and controller classes, as well as Razor views. See for example MVC Scaffolding on NuGet.
Once you get used to forcing yourself to use Entity Framework for even your "small" applications then and only then will you truly understand that is it the simplest way.
Sure, if you come from a background of memorized ADO.NET dataset/datatable/datareaders etc.. then sure you have projects with "canned" operations that you port over and modify but it is truly just old and cost you more time in the long run.
Use EF
Use multiple projects in a solution
Use a repository pattern if you can, it pays off in dividends for reasons you will discover
Keep your controllers "skinny"
Dont' use a "ViewModel" just to use / do it.
The SOC of having View and Controller are critical, but the Models folders does not need to be used, you can wire things up without it if you want, just pay attention to where your "model" is and abiding by SOLID principle etc..
I am currently working on an ASP.NET MVC project.
Some developers on the team want to bind the auto-generated database entities directly to the Views.
Other developers want to create tailor-made ViewModel's and bind those to the Views.
Objectively, what are the pros and cons of both approaches?
(By "database entities" I am referring to the auto generated classes that an ORM framework generates, such as LINQ to SQL, Entity Framework or LLBLGen).
Definitely use view models in your views, and use something like AutoMapper to create view models from entities easily.
Cons:
Sometimes it feels like you are duplicating code, specifically, when the view model and the entity have the exact same properties
Pros:
You often need to represent an object in a simpler format (often called flattening), but you need full fidelity on the server side. This allows you to transition between the two without mucking up your domain model with presentation cruft.
Aggregate roots often have a lots of value objects and additional entities that are irrelevant to a specific view, and omitting them in a view model makes it easier to work with.
Your entities will have lots of two way references that are sensible in terms of an API, but create pure hell when serializing them for JSON, XML, etc. View models will eliminate these circular references.
You may often use the same entity but in different ways for different views. Trying to balance both needs on one type can create a huge mess.
The orthodoxy is that you should never use your raw database entities in your views. Like any rule, it is there to be broken if you know your entities well and you understand the consequences, but there are very good reasons not to break that rule, particularly when working in teams and with code that will be maintained in future by people who might not understand the rule or the entities as well as you do. The main reasons are:
ORM lazy loading. Imagine your Customer has a lazy loaded collection Orders. You pass Customer off to the View and it iterates over Orders. You get an N*1 select on the Orders table. But it also means that your database connection still needs to be open in the View. There is a pattern that people use 'Transaction per Action' which disposes of the database context in the Action_Executed event, which happens before your View is rendered. So you could be trying to access the database after it has been disposed. Even if you are not doing that now, someone in future might decide to implement that pattern because it is fashionable.
The concerns of the ViewModel are different to the db Model. For example, you typically decorate your ViewModel properties with validation attributes. These typically are different or only concern the UI not the db. If you bind to your database entities you will find all these UI concerns polluting you DB entities.
Related to 2 - the requirements of the ViewModel may demand computed or derived properties. For example, a Fullname constructed from First and Last names. These kind of things are best kept in the ViewModel.
You can unit-test your ViewModels in isolation from the database. ViewModels can end up containing quite a lot of logic which needs to be unit-tested. This is easier to test if it is not tied to your database (as with EF entities).
In general, creating and maintaining ViewModels (even without AutoMapper) is not an overhead and you will find it is a much better pattern of development overall. I would recommend it for everything but the simplest cases (lookup lists of static data, for example).
I believe using view models is the only way to go, so no pros for ORM entities:) View models not only provide data for view, but they also define how view should look (by defining templates) or how it should validate (by adding data annotations or implementing IDataErrorInfo).
Using view models:
Pros:
View models contain only properties required by view, nothing else.
View models may contain specific validation rules using data annotations or IDataErrorInfo.
View models can combine values from different database entities.
View models document themselves and are not tied to any framework.
View models protect you from forged POSTs, containing values, that were not provided in form, but were contained in ORM entities.
You can specify easily display templates for view models and reuse them in many places using DisplayFor or EditorFor helpers.
Using ORM entities:
Cons:
ORM entities already contain data annotations, that can mess up your validation. Example: Password field in user may be markes as Required, but it is not required when you change only basic user info.
ORM entities are strongly tied to Framework (Entity Framework) and may be not easy to implement rules in.
ORM entities can contain properties for more than one view, but it is hard to separate validation rules for different views.
Using ORM entities with lazy loading can lead you to executing SQL queries when views are rendered. It shouldn't happen.
Using ORM entities can lead to using huge SQL queries instead on small ones. When you want to display dropdown with first name and last name, you should only retrieve first name and last name from database, not whole entities.
Thanks for the answers so far - they have been a big help in understanding the pros/cons of both approaches. I have one thing to add that no one else has mentioned.
Over-posting attack
A worrying disadvantage with binding directly against DB entities is an "over-posting attack". This is where the attacker, using a tool no more advanced than FireBug, can insert form fields that are not intended to be editable by the user, but which do exist on the DB entity.
Consider an "Edit my profile" page. Your view might look like this:
#using(Html.BeginForm() {
<div>
#Html.LabelFor(x=> x.FirstName)
#Html.TextBoxFor(x=> x.FirstName)
</div>
<div>
#Html.LabelFor(x=> x.LastName)
#Html.TextBoxFor(x=> x.LastName)
</div>
<input type="Submit" value="Save" />
}
It would render the following HTML:
<form action="/profile/edit" method="post">
<div>
<label for="FirstName">FirstName</label>
<input type="text" name="FirstName" value="" />
</div>
<div>
<label for="LastName">LastName</label>
<input type="text" name="LastName" value="" />
</div>
<input type="Submit" value="Save" />
</form>
Using FireBug, an attacker merely needs to insert a chunk of HTML inside the form:
<input type="hidden" name="IsAdmin" value="true" />
...and suddenly users are able change data in very unexpected and harmful ways.
Here are some even scarier hidden form fields:
<input type="hidden" name="ShoppingCart.Items[0].Price" value="0.01" />
<input type="hidden" name="BankAccount.Balance" value="1000000" />
<input type="hidden" name="User.Administrator.Password" value="hackedPassword" />
Ouch!
Info taken from:
http://hendryluk.wordpress.com/tag/asp-net-mvc/
I once tried to develop an app which used NHibernate entities directly in ASP.NET views. I ran into many problems with Lazy loading and deferred SQL execution running directly from the views rather than in the business logic layer or even controllers. Moving to a viewmodels and using automapper seemed to solve all these problems and make the app easier to test, debug and maintain.
I also found that view models were helpful in holding all the associated data I needed on a page. Some developers like to use the dynamic ViewBag for this, but this is bad for testing and debugging.
In particular, view models made it easy when you wanted to pick associated entities from dropdown lists.
AutoMapper was a lifesaver on this project, as it saved having to write a ton of mapping code, all I had to do was create the view models and then the controllers automapped from entities to view models.
Do not expose backend-entities to the client.
Real world application have behaviour -not CRUD. It you databind your entities to the view it will just be a matter of time before you dig into muddy hack when behaviour is required on the clientside.
I was just about to add exactly the same sentiment as hackedbychinese. also i'd add, with fk's to lookup lists, you just HAVE to use viewmodels as the entity model merely will hold a pointer to a single id within that table. A viewmodel allows you to pass the required populated list into the view - voila.
Also, a viewmodel can contain discreet logic where required, this would definately NOT be the case with the entity model. Also, your validations may vary depending on the use of your view, therefore different validations can be applied per 'view' requirement.
The purpose of a ViewModel is mainly separation of concerns - decoupling the View from the implementation details of the Model.
Using DB entities in your views, especially your forms is a massive security issue. Take the following POCO object
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public bool IsAdmin { get; set; }
}
Now say you are presenting a view that allows a user to change their email. The MVC method for processing the form result when using Db Entities instead of view models would look like: (unless you don't use model binding, in which case you are making more work for yourself)
public class HomeController : Controller
{
[HttpPost]
public ActionResult ChangeEmail(User user)
{
//....
}
}
Model binding in Asp.net works by looking for GET or POST parameters matching the names of the properties in the model. Therefore, all the user has to do is add IsAdmin=true to the POSt parameters and viola, the model passed into the ChangeEmail function will have the IsAdmin property set to true, which could very easily be accidentally added into the database, giving users free access to change data they didn't have access to change.
This goes for user permissions, changing who owns an entity (make your question be associated with me instead of you), change original creation dates, etc...
I'm using NerdDinner as a guide for my first MVC/LINQ to SQL project. It discusses the use of the ViewModel pattern when a View needs data from multiple sources - in their example: Dinners and Countries (serves as the drop down list).
In my application, the problem is a bit different. It's not so much different data, rather data linked via a key constraint. I have a Story table that links to aspnet_users via the UserId key. I would like to have easy access to the UserName for each story.
Since I'm using the repository pattern and returning IQueryable in some cases for deferred execution, I'm struggling with the correct way to shape the data. So I'm using this VideModel pattern right now to make it work but not sure if it's the right way.
Instead of returing IQueryable Story (which wouldn't work since I need the UserName), I'm returning a new custom class UserStory, which has a Story property and a string Username property.
What are your thoughts?
It seems like your question has less to do with MVC as it is simply a question about how to access the story data based on the username string.
Would it be possible to create a view in your database with all the UserStory data, the username, along with userid in it? That way, you could select from the view based on the username you have.
To create the view, you would simply have to do a join between the user table and the userstory table based on the userid.
After that, you could still use the repository pattern with the IQueryable being returned.
If you are wanting to do updates, it would be simple to do since you still have the userid, and would be able to link back to the actual table which would need the update.
If you look at Kigg, you will see that they mess about with the initial model to create custom ViewModels. That's the thing that NerdDinner doesn't cover in any detail. You could create a StoriesWithUserName class that inherits from Stories, but adds a new property - UserName. Then you return that to your View which would inherit from IEnumerable<StoriesWithUserName>
[EDIT]
Oops. Didn't spot that you already did this :o)
Using the repository pattern and returning an IQueryable of Stories is fine. The relationship allows you to access the the username value something like this >>
Assuming you are returning the IQueryable in your model object:
foreach(Story story in Model.Stories)
{
// do something with the value
response.write(story.aspnet_user.UserName);
};
Your Repository method would look like this:
public List<Stories> GetStories(Guid UserId)
{
return datacontext.Stories.Where(u => u.UserId = UserId).ToList();
}
The relationship will automatically provide you with access to the UserName value in the foreach loop i first mentioned. nothing more is required.
I'm not sure why your pagination control failed on Count() though??
Hope this helps