I am pretty new to ASP.NET MVC and I am trying to get my head around some of the design concepts at the moment. One thing I am currently stuck on is how (best) to handle a situation such as that described below.
Suppose I have a page that needs to render a number of "sections". For example, on the left hand side there is a list that is data driven and then the selected item in the list displays a further list in another section on the page. For better understanding lets suggest the left hand list is a list of movie categories and the other list displays a list of movies that are contained within that category, along with the various movie details.
Now, I have some form of ORM such as Entity Framework, LINQ to SQL or whatever that maps the tblCategory and tblMovie database tables into Category and Movie entities respectively. These entities live in the MyMVCApp.Data.Entities namespace. I then use a repository pattern located in the MyMVCApp.Data namespace to encapsulate the queries (via LINQ) against these entities to return our model entities.
This is where my first question lies. Should the repository be returning view model entities or domain entities which are then extended to produce view model entities? In my naive mind I see the entities returned from the ORM as simply containers for the data with domain entities containing the business logic. So surely there should be an abstration here?
Anyway, back to my scenario. Now lets assume I wish to present the two sections described at the beginning of this. I am assuming that what should be happening here is my domain entity model would contain a list of categories and their associated movies. So something like a List each of which contains a List.
This model would have been populated somewhere. This is my second question. Say my assumption above is correct and it is simply data entities are returned from the ORM. Now I have a namespace/project called MyMVCApp.Core.Model (or the like) with some domain entities such as the Movie and Category entities mentioned in the previous paragraph. Do these entities have methods on them to retrieve the data from the ORM and populate themselves? Or does the repository retrieve these populated entity models? And another question on this part, if I have a Movie and Customer entity in my ORM is it acceptable to be having domain entities named the same?
Finally, I assume the controller now has this populated list of Category and Movie objects and passes it back to the view. I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each? So, it may be the IndexController which retrieves the populated CategoryMovies entity, passing this to the Categories partial view and the Movies partial view. I would then need to somehow determine the selected Category (quesrystring?) and display the appropriate list of Movies in that category within the view.
OK, so if anyone has got to this point in my ramblings I will take a deep bow. I hope I have explained my mixed up thoughts and questions in sufficient detail for someone to provide some kind of enlightenment.
Thanks for listening! :-)
Since you didn't mention it, I will assume you are new to DDD concepts. DDD compliments the "M" in MVC by placing logic where it belongs. And, I think a good amount could be applied here.
In strict DDD form, I would use your Movie example as an Aggregate Root (a DDD concept). Within Movie, you would have business logic (methods) that obtain the categories and related entities directly related to Movie (i.e. Categories-this-movie-belongs-in). This assumes the "category" list you want to display is a list of categories this movie is in.
public class Movie
{
private IList<Category> _categories;
public IList<Category> FetchCategories()
{
// you can lazy-load here, use Linq-to-Sql, etc.
return _categories;
}
public void AddCategory(Category c)
{
_categories.Add(c);
}
}
Of course, you can treat Categories as a Value Object (VO, a DDD concept) here if you don't have an identity on them.
Now, what gets more interesting is if you do want to keep an identity on your Categories, treating them as Aggregate Roots with multiple entities and relations to other VOs and alike. In this case, you would want to utilize the DDD concept of Services to combine the two aggregates into your requested Model you want to pass to your Controller. This allows you to create business rules around loading the categories.
public class Movie
{...}
public class Category
{...}
public class MovieCategory : Movie
{
private IList<Category> _categories;
public IList<Category> Categories
{
get
{
return _categories;
}
internal set
{
_categories = value;
}
}
}
public class MovieCategoryService
{
public MovieCategory FetchMovieCategoryByMovieId(int id)
{
MovieCategory mc = _movieRepository.FetchMovie(id);
// do some logic here, some checks, etc
// to obtain your Categories list. Maybe querystring?
IList<Category> cats = ...;
mc.Categories = cats;
return mc;
}
}
The concept is that you now have logic in the domain layer, in this MovieCategoryService, to handle the complex creation of these relationships, or using Factories to create complex types as well.
This gives you a model you can pass around to different View and PartialViews.
The final step in your original post is how to get this into the View. I've been playing with the ViewModel approach to this issue. Creating ViewModels either dynamically, or as a class, and hanging all of the entities on this ViewModel. A recent StackOverflow question hits on this concept. ViewModel Best Practices
I've passed the Model directly into Views, and I am now trying this approach. It does clean things up, as your DOmain Model really should be disconnected from the "logic" on your page. I find myself thinking, "Dang it. I need to get this partialview populated based on this ID. Guess that means another method on the entity." Going the ViewModel approach removes the logic/thinking from the Domain Model, and puts it where it belong - in the Application/UI layer of where you are fine-tuning your view/partialview.
First of all, I think you should just get started with a simple project and try the various scenarios out you pictured in your long question :). There is nothing written in stone, you can use whatever architecture with datalayers and services or whatever, you like !
Or does the repository retrieve these populated entity models?
I would say yes. Your controller graps these from the service and gets them, populated and all and just moves them to the view in order to be displayed.
I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each?
And again i think you're on the right track ;).
It is a nice idea to give a view model entity to the view instead of the whole domain entity itself thereby providing the view only the required stuffs to work on
First of all return a List of Categories from your Domain, then construct a Movie view which takes the category name as a parameter something like this
- <Host>/Movies/Comedy
- <Host>/Movies/Horror
which would in turn display the movies which belongs to that particular category
Related
What's the most preferred way to work with Entity Framework and DTOs?
Let's say that after mapping I have objects like:
Author
int id
sting name
List<Book> books
Book
int id
string name
Author author
int authorID
My DTOs
AuthorDTO
int id
sting name
BookDTO
int id
string name
int authorID
Since author can have a lot of books I don't want to retrieve all of them, when for example I'm only interested in authors.
But sometimes I might want to get few authors and filtered books or all books.
I could go with multiple queries AuthorDTO GetAuthor(int id) List<BookDTO> GetBooks(int authorID). But that means several accesses to database.
The ways I see it:
If I had in AuthorDTO field List<BookDTO> books the job could be done. But sometimes I would keep this list empty, if for example I listed only authors. And that means some unconsistency, mess and a lot of details to remember.
Return Tuple<AuthorDTO, List<BookDTO>> it might be a bit confusing.
Define new DTO.
AuthorAndBooksDTO
AuthorDTO author
List<BookDTO> books
The problem with sticking to a sinlge AuthorDTO and selectively filling the List is that you are now forced to keep track of where that DTO came from. Is the list of Books not hydrated, or does this Author simply have no books? Do I have to go back to my controller and call a different method to get a different state of the same DTO? This lacks clarity from the consumer's standpoint.
In my experience, I've leaned the way of more DTOs instead of trying to re-use a set of basic DTOs to represent multiple different sets of data. It requires a bit more "boilerplate", having to set up a whole bunch of similar DTOs and mappings between DTO and Entity, but in the end the specificity and clarity makes the codebase easier to read and manage.
I think some clarification of the issues involved will actually solve your confusion here.
First and most importantly, your entity classes are DTOs. In fact, that's all they are. They're classes that represent a table structure in your database so that data from queries Entity Framework makes can be mapped on to them. In other words, they are literally objects that transfer data. The failing of Microsoft and subsequently far too many MVC developers is to conflate them with big-M Models described by the MVC pattern.
As a result, it makes absolutely zero sense to use Entity Framework to return one or more instances of an entity and then map that to yet another DTO class before finally utilizing it in your code. All you're doing is creating a pointless level of abstraction that adds nothing to your application but yet another thing to maintain.
As far as relationships go, that's where Entity Framework's lazy/eager loading comes in. In order to take advantage of it, though, the property representing the relationship must follow a very specific convention:
public virtual ICollection<Book> Books { get; set; }
If you type it as something like List<Book>, Entity Framework will not touch the relationship at all. It will not ever load the related entities and it will not persist changes made to that property when saving the entity back to the database. The virtual keyword allows Entity Framework to dynamically subclass your entity and override the collection property to add the logic for lazy-loading. Without that, the related entities will only ever be loaded if you explicitly use Load from the EF API.
Assuming your property is defined in that way, then you gain a whole world of abilities. If you want all books belonging to the author you can just interact with author.Books directly (iterate, query, whatever). No queries are made until you do something that requires evaluation of the queryset. EF issues just-in-time queries depending on the information you're requesting from the database. If you do want to load all the related books at the same time you retrieve the author, you can just use Include with your query:
var author = db.Authors.Include(m => m.Books).SingleOrDefault(m => m.Id == id);
My first question would be to ask why you are creating DTO's in the first place? Is there a consumer on the other end that is using this data? Is it a screen? Are you building DTO's just to build DTO's?
Since you tagged the question as MVC i'm going to assume you are sending data to a view. You probably want a ViewModel. This ViewModel should contain all the data that is shown on the View that uses it. Then use entity framework to populate the view model. This may be done with a single query using projections or something complex.
So after all that blathering. I would say you want option 3.
Just like the others said, for clarity reasons, you should avoid creating "generic" DTO's for specific cases.
When you want to sometimes have authors and some of their books then model a DTO for that.
When you need only the authors then create another DTO that is more suited for that.
Or maybe you don't need DTOs, maybe a List containing their names is enough. Or maybe you could in fact use an anonymous type, like new { AuthorId = author.Id, AuthorName = author.Name }. It depends on the situation.
If you're using ASP.NET MVC the DTO you'll want is in fact a ViewModel that best represents your page.
Based on what you've described, you're view model could be something like this
public class BookViewModel{
public int Id {get;set;}
public string Name {get;set;}
}
public class AuthorViewModel{
public int Id {get;set;}
public string Name {get;set;}
public List<BookViewModel> Books {get;set;} = new List<BookViewModel>();
}
public class AuthorsViewModel
{
public List<AuthorViewModel> Authors {get;set;} = new List<AuthorViewModel>();
//add in this class other properties, like the filters used on the page...
public void Load(){
//here you can retrieve the data from your database.
//you could do like this:
//step 1: retrieve data from DB via EF
//step 2: fill in the Authors view models from the data at step 1
}
}
//and in your controller you're calling the Load method to fill you're viewmodel with data from db.
public class AuthorsController{
public ActionResult Index(){
AuthorsViewModel model = new AuthorsViewModel();
model.Load();
return View(model);
}
}
I've split my project into (as of this time) 4 layers:
Application (ASP.NET MVC project)
Domain/Model (contains only models with no logic in them at all)
BusinessLogic (right now only "wraps" the repositories)
DAL (Entity Framework, but should be interchangeable)
The MVC Controllers use the business logic "services" to talk to the database through whatever lies beneath the business logic layer, and the controller should not need to tell anyone that "I want this Student, and I also want all his Courses" - this implies that lazy loading should be used.
The thing is, if I just "call through" and return the result to whoever calls the controller action, I can't really control what gets loaded unless I explicitly access the properties on the model to trigger the loading of the graph.
I'd like to use AutoMapper to map from my model to a Dto (one for each model, which defines what gets returned).
Say I have a model like this:
public class Student
{
public string Name {get;set;}
public int Age {get;set;}
public ICollection<Course> Courses {get;set;}
}
And a dto like this:
public class StudentDto
{
public string Name {get;set;}
public ICollection<Course> Courses {get;set;}
}
When AutoMapper does the mapping, it doesen't appear to map the Courses, which is my problem.
Should I be eager-loading at the repository layer instead?
As you have in the Student and StudentDto Automapper should map object graph correctly to the dto. This will work only if lazy loading enabled otherwise you may need to use eager loading.
I think the best way to choose what method to use is to test the performance of both method which will depend on several factors like your data model in the db and the delay between the sql server and your application etc.. .
Edit.. How to choose the best method
How to choose the best method
You need to consider three things,
How many connections that you are going to make with the database. If you are using lazy loading there will be a database call for all the reference points of a navigation properties if referred navigation property is not in the context.
How much data that you are going to retrieve from databaseIf you choose to load all the data in initial query with differed loading it will be too slow when you have huge amount of data to retrieve.
Complexity of the query . When you are using lazy loading the queries will be simple because all the data is not loaded in the initial query. If you use immediate loading it will make quires will be more complex with query paths
read more here
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
In an ASP.NET MVC project we are using AutoMapper to map from domain model to viewmodel - and sometimes also flattening a hierarchy while doing so. This works like a charm and makes the rendering logic of our views very lean and simple.
The confusion starts when we want to go the other way from viewmodel (or postmodel or editmodel) to domain model, especially when updating objects. We can't use automated/two-way mapping because:
we would have to unflat the flattened hierarchy
all properties on the domain model would have to be mutable/have public setters
the changes coming from the view isn't always just flat properties being mapped back to the domain, but sometimes need to call methods like "ChangeManagerForEmployee()" or similar.
This is also described in Jimmy Bogards article: The case for two-way
mapping in AutoMapper, but the solution to this isn't described in detail, only that they go:
From EditModel to CommandMessages – going from the loosely-typed
EditModel to strongly-typed, broken out messages. A single EditModel
might generate a half-dozen messages.
In a similar SO question there is an answer by Mark Seeman where he mentions that
We use abstract mappers and services to map a PostModel to a Domain Object
but the details - the conceptual and technical implementation - is left out.
Our idea right now is to:
Recieve a FormCollection in the controller's action method
Get the original domain model and flatten it to viewModelOriginal and viewModelUpdated
Merging the FormCollection into viewModelUpdated using UpdateModel()
Use some generic helper method to compare viewModelOriginal with viewModelUpdated
Either A) Generate CommandMessages a la Jimmy Bogard or B) Mutate the differences directly into the domain model through properties and methods (maybe mapping the 1-1 properties directly through AutoMapper)
Can someone provide some examples of how they come from FormCollection through editmodel/postmodel to domain model? "CommandMessages" or "abstract mappers and services"?
I use the following pattern:
[HttpPost]
public ActionResult Update(UpdateProductViewModel viewModel)
{
// fetch the domain model that we want to update
Product product = repository.Get(viewModel.Id);
// Use AutoMapper to update only the properties of this domain model
// that are also part of the view model and leave the other properties unchanged
AutoMapper.Map<UpdateProductViewModel, Product>(viewModel, product);
// Pass the domain model with updated properties to the DAL
repository.Update(product);
return RedirectToAction("Success");
}
You might want to consider CQRS(Command Query Responsibility Segregation - I think this might be the concept you were missing), possibly even with Event Sourcing.
It is basically a practice of separating the logic of reading from a data source and writing to a data source, might even mean having different data models for reading and writing.
This might be a good place to start: http://abdullin.com/cqrs/
Option C: Put it all in the controller action. Next, if that gets hairy, decompose into services (abstract mappers) or messages-as-methods (the command message way).
Command message way:
public ActionResult Save(FooSaveModel model) {
MessageBroker.Process(model);
return RedirectToAction("List");
}
And the processor:
public class FooSaveModelProcessor : IMessageHandler<FooSaveModel> {
public void Process(FooSaveModel message) {
// Message handling logic here
}
}
This is really just about moving the "processing" of the form out of the controller action and into individual, specialized handlers.
But, I'd only really go this route if controller actions get hairy. Otherwise, just take the form and do the appropriate updates against the domain models as necessary.
There are some similarities here with what I've been doing. My hierarchy of view models is only somewhat flattened from its domain object equivalents, but I do have to deal with calling explicit service methods on save to do things like adding to child collections, changing important values etc, rather than simply reverse mapping. I also have to compare before and after snapshots.
My save is Ajax posted as JSON to an MVC action and enters that action magically bound back to a view model structure by MVC. I then use AutoMapper to transform the top level view model and its descendants back into its equivalent domain structure. I have defined a number of custom AutoMapper ITypeConverters for those cases where a new child item has been added on the client (I'm using Knockout.js) and I need to call an explicit service method. Something like:
foreach (ChildViewModel childVM in viewModel.Children)
{
ChildDomainObject childDO = domainObject.Children.Where(cdo => cdo.ID.Equals(childVM.ID))).SingleOrDefault();
if (childDO != null)
{
Mapper.Map<ChildViewModel, ChildDomainObject>(childVM, childDO);
}
else
{
MyService.CreateChildDO(someData, domainObject); // Supplying parent
}
}
I do a similar thing for deletes and this process cascades quite nicely down through the whole structure. I guess a flattened structure could be either easier to work with or harder - I have an AbstractDomainViewModel with an ID with which I do the above matching, which helps.
I need to do comparisons before and after updating because my service layer calls trigger validation which can affect other parts of the object graph, and this dictates what JSON I need to return as the Ajax response. I only care about changes which are relevant to the UI, so I transform the saved domain object back to a new view model and then have a helper method to compare the 2 view models, using a combination of manual upfront checks and reflection.
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.