I am trying to learn mvc - I apologize in advance for all the silly questions. What I've done is created an mvc proejct based on an exsiting database, and then i've been disecting it to try to understand what's been created for me, and how to create my own stuff. Unfortunately, because I'm a new stackoverflow user, i can't post a picture of my project structure.
i have a parent controller and a child controller created using the wizard based on 2 separate tables i have in my model. I want to display both of them in one view - ultimately in a webgrid and be able to change data for any parent item, or child item. You can ignore the CombinedController for now. I've been doing some reading and i've learned that i should be creating a viewmodel that combines both the parent and child at the model level, and then go from there.
so i created this class:
Imports System.Data.Objects.DataClasses
Public Class ParentAndChild
Public Property myChildren As IEnumerable(Of Child)
Public Property myParent as Parent
End Class
I have a few questions:
Question 1
Do i have to add this ParentAndChild entity into the .edmx file in order to create a controller and view for it? I guess what I'm really asking is do i have to create a view in the sql database first, have the entity show up in the .edmx and then create a controller? Or can I just combine the two entities in a class? That's what i've done so far. I don't have a sql View in my database combining these two tables. The reason why I ask is because when i create my controller, if i want to get all the CRUD for free, i have to create using the Entity Framework. But I don't know what to specify for the data context.
Question 2
If i want a webgrid to somehow show all my parents and all their children, will the new ParentAndChild class work? I think that will only show the details for One parent and its children. I think i need to create a list of parents.. and then in the parentlist for each parent, add a collection of modules. But i don't know how to do this..
Question 3
How does the entityframework know which modules to return when i'm using my new class? I don't define the relationship anywhere... Is it because in the .edmx file, the system knows the relationships between the tables?
If you simply need to access the information of a parent entity and its child entity's you should be able to send your view the parent entity. A ViewModel is not absolutely necessary for this if Entity Framework knows about the relationship between the two entity's. If the relationship between the 2 tables exists at the database level then Entity Framework should have modeled it automatically.
An example of a controller would be:
public ActionResult Parent(int id)
{
var parent = context.Foo.Single(x => x.Id == id);
return View(parent);
}
If you need to create a table of all the child entity's you could do something like this:
#foreach(var item in Model.Children)
{
<td>#item.Property</td>
<td>#item.Property2</td>
}
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'm learning as I go, so I'm not familiar with all of the concepts behind EF and MVC3. I have an app where my EF Models === MVC3 Models, but I also have some aggregate ViewModels. I call things like Person dude = Person.Get(id); in Controllers, where Person is an EF model generated from a database, which I extend with my custom methods, such as dude.GetSiblings();
What I want to do now (if you don't tell me that this is a bad idea) is to move the EF code into another assembly, create yet another assembly with new simpler non-entity models that I can feed to my views and somehow (if possible) serialize and move around as JSON.
The problem is I don't know how. If I move my EF models to a different project (like a separate DAL), how would I create second models that map to Ef models? Wouldn't that cause a lot of repetition if I had code like int id {get;set;} string name {get;set} on both the EF model and the MVC3 model? In my ViewModels I simply use the entities directly like class ViewModelX { Person person; List<Post> posts; int something; } - but that is simply a packaged set of entities rather than a model, isn't it?
What about methods like GetSiblings? var list = dude.GetSiblings() in Controller and public List<Person> GetSiblings() { return this.EFPerson.GetSiblings(); } in MVC3 model? I'm getting very confused as to what goes where. When googling around, I really only found advanced and very beginner tutorials - or maybe I just don't know what to look for so I kindly ask for your assistance!
If I move my EF models to a different project (like a separate DAL),
how would I create second models that map to Ef models?
The view models reside inside the ASP.NET MVC application.
Wouldn't that cause a lot of repetition if I had code like int id
{get;set;} string name {get;set} on both the EF model and the MVC3
model?
Yes, it will cause. That's what View Models are intended to do. To contain the data that the view needs to work with. Where does this data come from doesn't really matter. You could use tools such as AutoMapper to automate the mapping between your domain models and view models.
What about methods like GetSiblings? var list = dude.GetSiblings() in
Controller and public List GetSiblings() { return
this.EFPerson.GetSiblings(); } in MVC3 model?
Here's how a typical controller action might look like:
public ActionResult SomeAction(int id)
{
// fetch an instance of the domain model:
var domainModel = DomainLayer.GetSiblings(id);
// map the domain model to a view model (using AutoMapper):
var viewModel = Mapper.Map<DomainModel, ViewModel>(domainModel);
// pass the view model back to the view
return View(viewModel);
}
want to get rid of ViewBag in my views so i've made a little research about viewmodels.
i like the idea of using it for presentation, no questions here.
but i don't realise what is the best way to use viewmodels for update.
first of all, why shouldn't i use my EF entities with [MetadataType(typeof(User_Validation))]?
public ActionResult Edit(User user)
{
...
}
where User is EntityObject.
then, if i however use viewmodels for it there is another question: here people believe that nested viewmodels should be used, but here is another opinion ("They are not wrappers around domain models", he says). Who is right?
also, what is the best way to update an object in action after POST (without using tryupdatemodel, because here and not only, people are against this approach). i've tried to use ApplyCurrentValues but if there is some complicated logic of update with many-to-many relations, for example, i get some huge EF errors. that's why i need to manually set fields of my EntityObject that i get from DB with values that come to action. Smth like this:
public ActionResult Edit(User user)
{
if (ModelState.IsValid)
{
var userToUpdate = usersRepository.Get(user.UserId);
userToUpdate.Field1 = user.Field1;
...
// save
}
...
}
where User is EntityObject with validation class.
so, if i use flat viewmodels to get values from form and AutoMapper to set values to my entityobject will it be the most right way to deal with updates or it can be automatized even more?
You answered yourself in the last paragraph. I am using the exactly same approach in my MVC3 EF Code First project.
Here is the practice I follow:
All entity classes are clubbed under one folder "Entity". You can also opt for a separate library project.
Every entity has a corresponding ViewModel class with a postfix of Model (e.g. for Profile entity there is ProfileModel class).
For nested entities there are corresponding nested ViewModel classes.
AutoMapper is used for Model to Entity and vice versa conversions. Here automapper takes care of the nested entities. In case of complex updates, rather than relying on AutoMapper, I take the matter in my own hands in controller.
Works flawlessly with healthy separation between my domain objects and view models.
I am working on a fairly large MVC 3 application, and I'm running into an issue that doesn't smell quite right to me. This question takes a little set up to understand, so here are the premises that I'm currently operating on:
Views should be strongly typed (ViewBag/ViewData should be avoided)
Because the views are strongly typed, view model objects should be created that encapsulate all the data the view needs to display
When we have a need for drop down menus we should have two properties:
A property in the model that stores the selected value of the drop down
A SelectList property in the view model that represents the items in the drop down
The view itself always uses the #Html.DropDownListFor() helper method
We are using Entity Framework 4, and letting it generate entity classes from our already designed database
To avoid duplication and take advantage of LINQ, we are not creating our own separate business/model classes but adding to the partial classes generated by the entity framework
These partial classes that we write are located in the business layer to make everything compile correctly
Most model classes have a shared editor template that can be used in multiple views
Here's where the trouble comes in. The shared editor template's model type is set to the model class. This means that the partial view that makes up the editor template does not have access to the containing view model object where the list of drop down items is stored.
I was able to "solve" this by adding a SelectList property directly to the model class in the business layer instead of keeping it in the view model. But the SelectList class is specific to MVC, which in turn means that my business layer has a dependcy on MVC. That doesn't seem right to me because the BL should be agnostic to the UI.
Has anyone else run into this issue? How should I solve this? It's also possible that one of my premises are wrong.
Everything seems very nice and good design up until this point (which is not surprising as it is that point that is causing you headaches :-)):
Most model classes have a shared editor template that can be used in multiple views
It's view models that should have editor templates and not EF models. And because view models are specific to the requirements of the view you are free to put whatever information you need into them, like in this case the SelectList. So don't simply define a root view model that has your EF models as properties (that's not a view model). Define a view model that is designed to meet the requirements of the particular view. Don't put a single EF class in your view model hierarchy and you will see how much simpler your life will be :-)
And don't worry if you have duplicate properties in your view models. That's what those classes are designed for. Also AutoMapper could greatly simplify the mapping between your models and view models.
You have 2 main solution IMHO:
1. Generate DTOs / Models for your business logic entities
You can use AutoMapper to minimize the copying code.
You will achieve a nice separation between your view and business logic.
This however may be time-consuming for your large application.
2. Use extension methods
Instead of declaring a SelectList property in EF entity partial class and polluting your business logic with view-related code create an extention methods for your EF entites in Web project. You can than move your view-related code to web project from BL and keep type-safety.
Example:
Business Logic assembly
// This is EF entity
public partial class FooTable
{
public long Id { get; set; }
public string Name { get; set; }
}
Web assembly
public static class FooTableExtensions
{
public static SelectList GetSelectList(this IEnumerable<FooTable> fooTables)
{
return new SelectList(); // Create your select list from FooTables here.
}
}
Well, we ended up taking the simple way out. In the business layer we just changed the type to plain old Object. I figured that, regardless of the presentation layer, it will need some sort of list to contain the options available.
I know this isn't super clean as per #Darin and #Jakub, but I don't see our end result being any different this way except that we've avoided having to write and/or set up a whole bunch of mappings between objects.
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