I am currently building a blog posting web application using MVC 4 in C# mostly for the purpose of honing my knowledge of application architecture.
Currently it is in a tiered structure as:
View > View Model > Controller > Data Access Layer > Data Store
There may be a Service Layer added between the Controller and Data Access Layer later but that is not the reason for this particular question.
What should the parameters and return types of Data Access Layer methods be?
My current understanding is the View Models exist to provide the View with data that may be more or less than the Domain Model's structure exposes.
In my application, a Post consists of the PostId, Description, Content & UserId. There is also a Users table that has a UserId and UserFullName.
The Post Model mirrors the Posts table in that it stores the UserId but not the UserFullName. As such, when I need to retrieve the Post details along with the UserFullName to pass to the View, what should be returned by the DAL method? I have created a new Domain Model which contains all the data required by the View, but this goes against the fact that the Domain Models be de-coupled from its implementation. I'm of the thinking that just an Object can be returned when I query the database for the Post data, plus whatever else is needed by the View.
Is a wholly generic data access layer required here or is it overkill?
In EF exists the method Include which let you to preload records from related tables.
public ActionResult Index()
{
var model = context.Posts.Include("Users");
return View(model);
}
In .cshtml:
#model IEnumerable<Post>
#foreach(var post in Model)
{
<p>#post.Description</p>
#Html.Raw(post.Content)
<p>By #post.Users.UserFullName</p>
}
See http://msdn.microsoft.com/en-us/data/jj574232.aspx for more details.
Related
I am new to MVC and am having a conceptual problem with state and object persistence and hope someone can put my thoughts in order.
I have a remote webservice which provides methods to manage orders. An order consists of a header and Lines as you would expect. Lines can have additional requirements.
I have my domain objects created (using xsd2code from the webservice schema), the webservice calls and object serialization all working fine. I've build the DAL/BLL layers and it's all working - tested using a WinForms testbed app front-end.
I have view model objects mapped from the domain objects using Automapper. As the order is returned from a single webservice method complete with lines etc I have an OrderViewModel as follows
public class OrderViewModel
{
public OrderHeaderViewModel OrderHeader { set; get; }
public List<OrderLineViewModel> OrderLines { set; get; }
public List<OrderLineAdditionalViewModel> OrderLineAdditional { set; get; }
public List<OrderJustificationViewModel> OrderJustifications { set; get; }
}
Firstly I'm wondering if I should dispense with the OrderViewModel as if I pass this as a model to a view I'm passing far more data than I need. Views only need OrderHeader or OrderLines etc - not the entire order.
Now my conceptual problem is in the controllers and the views and object persistence.
My Order controller has a Detail Action which performs the load of the order from the webservice and maps the Domain object to the OrderViewModel object.
public ActionResult Details(string orderNumber)
{
OrderViewModel viewModel = new OrderViewModel();
var order = WebServiceAccess.LoadOrderByOrderNumber(orderNumber,"OBOS_WS");
viewModel = AutoMapper.Mapper.Map<BusinessEntities.Order, ViewModels.OrderViewModel>(order);
return View(viewModel);
}
But the Order/Details.cshtml just has the page layout and a call to two partial pages for the header and the lines (I swap the Headerview for a HeaderEdit using Ajax, same for the LinesView)
#{ Html.RenderPartial("DetailsHeaderViewPartial", Model);}
#{ Html.RenderPartial("DetailsLinesViewPartial", Model);}
At the moment I'm passing the model into the main Details container page, then into the RenderPartials, However I don't think that the model should be passed to the main Detail page, as it doesn't need it - the model is only needed in the DetailsHeaderViewPartial, DetailsLinesViewPartial so I'd be better off using #RenderAction here instead and passing the model into the Header/Lines views instead.
However, The Order is retrieved from the webservice in the ActionResult Details() how can I make the retrieved OrderViewModel object available in the ActionResult HeaderDetails() / LineDetails() methods of the controller to pass as the model in return PartialView(...,model) ?
Should I use a User Session to store the Order ViewModel so it can be used across actions in the controller.
Moving on from this stage the user will be able to maintain the order (add/remove lines - edit the header etc). As the webservice call to save the order could take a few seconds to complete I'd rather only call the save method when the user has finished with the order. I therefore would like to persist the in-progress order locally somewhere whilst it's being worked on. User session ?
Many thanks for any advice. Once I've got my head around state management for the ViewModels I'll be able to stop reading a million Blog posts and actually write this thing !
You actually have a few questions here so I will try to address them all the best I can.
1) Dispensing with the view model : I would say no. The view model represents the data that you need in order to populate your view. It seems like you are using the view model as an identical container to the domain model object. So you are asking if you should dispense with it and just pass the domain model to the view while your original concern is that you are passing along more data then you really need as is?
Rather then dispensing with the view model, I would revisit your properties on your view model. Only use properties that you need and create the mapping logic (either with automapper or on your own) for taking the complex domain object and populating the properties on the view model.
summation: build the view model to be only things that the view needs and write mapping logic to populate that view model.
2) This is just a statement of best practice before I breakdown your specific scenario.
You describe your architecture as having a BLL and DAL. If that is the case then you should not be persisting any objects from your controller. The controller should not have any knowledge of the database even existing and the objects used in the controller should have no idea of how to persist themselves. The objects that are going between your controller and the web service should strictly be Data Transfer Objects (DTO's). If you are unfamiliar with what constitutes a DTO then I highly suggest that you do some research and try to build them into your solution. It will help you conceptually see the difference between view model objects, domain objects and data transfer objects.
3) I would not try to store an order object in the session. I would re-analyze how you are breaking up the partial views within the view so that you can call actions with the ordersviewmodel being the parameter in a way that you need. It sounds like you are needlessly breaking up views into partial views.
4) You should not be concerned with state management for the view model object. Your view (which can be comprised of many partial views) is filled based on properties provided by the view model. The user can make changes using the UI you have developed. Since you express the desire to only save once they are finished making all changes to optimize calls to the web service, you just need to repopulate the fields of the view model upon clicking submit. Now you have a "state" for orderviewmodel that represents the users changes. You can send this object to the web service after converting back to a DTO (if you do what I said above) or by mapping it to the domain object.
1 final note. You are using automapper to map your domain to the view model. I am assuming that your view model is too complex and includes things that you don't need because you built your view model to emulate the domain object so that automapper could map by naming convention. Automapper has an api for doing complex (custom) mappings that fall outside of standard same name properties. Don't let automapper constrain you to building your view models a certain way.
Hope this helps
I have An EntityModel that is named ECommerceEntities that contains several entities. If I want to use this model in a view in asp.net mvc, Can I pass ECommerceEntities instance to view or Sould I pass one entity in ECommerceEntities.
I mean :
//Can I use this?
public ActionResult Index()
{
ECommerceEntities entity = new ECommerceEntities();
return View(entity);
}
or
//Should I use this?
public ActionResult Index()
{
ECommerceEntities.OneEntity one_entity = new ECommerceEntities.OneEntity();
//filling one_entity here and then send to view
return View(one_entity );
}
Thanks.
If you are asking if it is possible, it is possible to do both. Yes, both options will work. However if you only need the sub entity in the view, I would just pass the sub entity into the view. No use in passing in more than needed right?
Do not forget that in MVC whatever object you pass in to your view,(EcommerceEntities for example) can have its properties set in the post by MVC's automatic model binding which maps data from the post into the object you pass into the view.
So, this means that someone can hijack the http post and can fill in EcommerceEntities and its sub entities with various bits of random data of their choosing if you are not careful and you may accidentally save this data to your db because you did not expect some of these properties to get set.
So, when working in MVC you have to protect properties that are not being used in your view but are passed into the view to ensure that nobody has injected them.
If you do decide to pass in EcommerceEntities, make sure that you use whitelisting or look at MVC's bind attribute to protect your data when your entity is posted back to your controller.
Because of the work involved in protecting that much extra data, I would say that the sub entity would be best if the screen will populate correctly just off of the sub entity object.
Hopefully this is helpful.
If you want to display a list of all entities (which the Index action is typically used for), you probably want to get all the entities from your database context:
public ActionResult Index()
{
// assumes dbContext is already initialized
ICollection<ECommerceEntities> entities = dbContext.ECommerceEntities
return View(entities);
}
I've read a few articles about MVC but there's one thing that isn't clear to me. What is the role of the model in practical term.
Does the model represent the business object?
Or is it just a class that help send information from the controller to the view?
Take for example two business class (data populated from the database)
Class Image
Property FileName As String
Property CreatedBy As User
End Class
Class User
Property UserName as String
End Class
Will "Image" be the model or should I create a new class?
In the model, should I create a UserName property that will fetch it's data from the User object?
Class ImageModel
Property FileName As String
Property CreatedBy As User
ReadOnly Property UserName As String
Get
Return User.UserName
End Get
End Property
End Class
There are many views on this, but in my experience, there are 2 major views of the Model:
ViewModel
This is a POCO that simply contains all the data necessary to display the View. The data is usually populated by the Controller.
Fat Model, Skinny Controller
The Model does the majority of the business-work. It contains and populates all the data that is needed by the View, and is used by the Controller to save data, etc.
The beauty of MVC
The beauty of MVC is that it's OPEN! You can choose any type of model you want ... you can put all your data into ViewState, into a Model, into a ViewModel that contains a bunch of Models, whatever. It's really up to you. The Model, View, and Controller are blank canvases that can be used however you like.
What I use
My team has done a lot of MVC work, and we have tried many of these different methods. We finally decided that our favorite was the Fat Model, Skinny Controller paradigm.
I believe that this pattern is the best at "keeping it simple" and "don't repeat yourself", and it definitely maintains the "separation of concerns".
Here's how our code is organized:
Controllers
Handles everything that pertains to HTTP requests - redirects, authentication, web safety, encoding, etc.
Gives all "input" to a Model, and gives the Model to the view. Does NOT access Business or Data layers.
Views
Handles all HTML and JSON generation
Only accesses data from the strongly-typed Model
Models
Responsible for making all updates, calling Business and Data layers, loading all data
Handles all validation and errors, and returns these to the Controller
Contains properties of all data that is required for the View, and populates itself
Even though this sounds like a generic principle of MVC, it quickly becomes obvious that MVC does not require these principles, which is why many projects use other principles.
Example
Here's an example Model. The Controller creates it, it populates itself, and the Controller passes it to the View.
public class UsersModel
{
protected UserBusiness userBusiness = new UserBusiness();
public UsersModel(string editUserName)
{
// Load all users:
this.Users = userBusiness.GetAllUsers();
// Load the user to be edited:
this.EditUser = (editUserName == null) ? null : userBusiness.GetUser(editUserName);
}
public List<User> Users { get; private set;}
public User EditUser { get; private set; }
}
All the "user business logic" in this case is in a different project (our "Business Layer"), because we have a large system. But smaller projects don't require this ... the Model can contain business logic, and even data-access code.
There are many models. It both can be business data (or domain) objects (Controller -> Datasource, and vice-versa), business rules (act on domain objects) or view models (Controller to View, and vice-versa).
You don't explicitly have to define the username again in ImageModel.
I'm begginer in asp.net mvc and i have some doubts.
P.S: I'm using DDD to learn
I have an ACtion in a Controller and it'll save an entity (from my model) by a repository (for a database).
My doubts is, How can I get the informations from the View and save it by a repository in my Controller ?
Is it correct to get an entity of my Model in Save method of controller, like this:
public ActionResult Save(Product product)
{
// validate object
// save data in repository
return View("Success");
}
Or Need I get an DTO (with a structure similar to my entity) and create an object passing property by property to an entity ?
I didnt' like of FormCollection and I'd like to know, What is recommended architecturally ?
Thanks a lot guys
Cheers
I you want to follow DDD practices as described by the Blue Book you should bind your views to DTO's which can be forwarded to a thin 'Application' layer where Domain objects are created or retrieved from database. This application layer can be a simple facade with methods or can leverage command pattern.
For a live demo, you can see my project -- DDDSample.NET
This kind of problem can be fixed by adding so called view model.
Basically - a view model is DTO that provides data for particular view. In similar fashion - view models are used to get data back from view via model binding. Then - controller just forwards necessary data to domain model.
Typically, in ASP.NET MVC your controller actions will receive strongly typed objects returned by the DefaultModelBinder when editing entity types. Using this pattern you can pass a "Product" to your GET view either by itself or as part of a DTO and then your "Save" method would receive a "Product" object in its parameter list.
So long as you are using either editor templates or fields with matching names (i.e. Html.TextBox("Name") corresponds to Product.Name) then the DefaultModelBinder should be able to correctly fill the typed entity object passed to the action method. You shouldn't have to mess with the FormCollection except in certain edge cases.
[HttpGet]
public ActionResult Create() {
return View("Create", new Product());
}
[HttpPost]
public ActionResult Create(Product product) { //or Save(Product)
...
}
As long as your form has fields which match the fields in Product, they should automatically be populated for you based on the values. How you save the entity depends on the data model, whether you're creating a new record or editing an existing one, etc.
I'm currently in the process of converting some small personal web sites from WebForms to MVC. With the existing sites, the database schema is solid but I had never really taken the time to build proper data/business models/layers. The aspx pages all talked to the database directly using a variety of Views and Stored Procedures that were created as needed for convenience. With MVC, I'm now trying to "do it right" as they say and use things like LINQ to SQL and/or the Entity Framework to build a proper data model or models for the application.
My question revolves around what goals I should have for building data models. I've read various pattern related articles and I realize that ultimately the answer is likely going to depend on the characteristics of my data. But generally should I attempt to build bigger models that encompass as much of the database as possible so that there's only one way to interact with a given set of tables? Or should I build smaller custom models for each MVC View that only contain the data and access that View will need?
Or should I build smaller custom models for each MVC View that only contain the data and access that View will need?
This would probably be better.
Do not forget, you can stick your models in hierarchies, so common properties, like ids, names, preferences can be present in each model.
Fat expanded models could be better for enterprise application, where framework automatically does lot of stuff based on preloaded user preferences, user roles, access rights etc. For a small personal project would probably be better to try to keep your models small and clean. It is also a protection. By not putting unnecessary data into a model you ensure your view will not by mistake display wrong entries or submitting a form would not by mistake overwrite some other data.
I would go for the model representing the actual data logic within your current system and have your controllers return the piece of the model which the view needs such as:
Controller:
public ActionResult index()
{
var ListOfObjects = DataHelper.GetAll();
ViewData.Add(ListOfObjects);
return View();
}
public ActionResult ViewObject(int id)
{
var Object= DataHelper.GetObject();
ViewData.Add(Object);
return View();
}
public ActionResult ViewObjectChild(int Objectid, int ChildId)
{
var Child= DataHelper.GetChildObject(Objectid, ChildId);
ViewData.Add(Child);
return View();
}
On the view
/
<% var myListOfObjects = ViewData.Get<IList<Object>>(); %>
/ViewObject/1/
<% var myobject= ViewData.Get<Object>(); %>
/ViewChild/1/1/
<% var myChild = ViewData.Get<Child>(); %>
Note I have used MVC Contrib typed functions I highly recommend these.
Generally, you would have one comprehensive domain model for the database. You can use (modify/add/remove/etc.) the domain model in your service layer or the controller if it is a small app.
However, for your views, you can use presentation objects to make the views easier to maintain. These are sometimes also called DTO or view model objects. Basically what you do is create an object that contains all the data from the model that is necessary for the view to be populated.
For example:
Your model may include:
public class Car()
{
public string Model;
}
public class Driver()
{
public string Name;
}
You want the view to output the name and model of the car and you would have to pass both the Car and Driver model objects the view.
Rather than sending the two model objects directly from the controller to the view, you can create an object which contains just the data you need:
public class CarAndDriverViewModel()
{
public string CarMake;
public string DriverName;
}
You would populate this object from the domain data and pass that to the view. And the view would be:
model.DriverName + ": " + model.CarMake
Now you don't have to worry about lazy loading issues or complicated view logic to deal with model peculiarities. It's more work to create these view model objects but they really help keep the view clean and provides an easy way to do formatting before sending data to the view.
There are projects and conventions you can use to help automate the creation of the view models, if you want to look into them. AutoMapper is an example.