EF, MVC, Model binding, and Navigation properties - asp.net-mvc

I'm using EF5 Code First with :
public class Scenario
{
public int Id { get; set; }
public IList<Client> Clients { get; set; }
}
public class Client
{
public int Id { get; set; }
public string Name {get;set;}
public int VisibilityNumber{ get; set; }
}
I'm directly sending the scenario object to the view (MVC4, without using a viewmodel class - maybe a mistake ?, but a lot less plumbing code). In my view, I use HiddenFor for Scenario.Id, and a for loop to display an EditFor for each client VisibilityNumber.
This is the Controller :
[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{
if (ModelState.IsValid)
{
Scenario scen=GetScenarioFromDB(id);
TryUpdateModel(scen,formValues);
if (ModelState.IsValid)
SaveToDb(scen);
}
}
After the TryUpdateModel, for each Clients object (which were correctly loaded from DB) :
VisibilityNumber is correctly set
Id is set to 0, which of course is a bad thing
Name is set to null
After looking at the MVC Source code (DefaultModelBinder/UpdateCollection), I can see that when binding to collections, new items are always created.
If I can't fix that, I think I'm going to use a viewModel, and AutoMapper. I assume that the MVC team wanted to force us to use viewModel, rather than directly send EF object.

You should not get scenario from database in your update. Instead, you should take your bound model, attach it (if edited) or add it (if new) to context and then save changes. It's a common scenario called "disconnected entities" (which you, in fact, do have, because you have model that was disconnected when sent to client, and then got back also disconnected).

I "fixed" DefaultModelBinder/UpdateCollection so that it can work with my use case : when the binding is drilling down in the navigation properties, it uses the current object as model (it's easy, since I'm only doing modifications, no insert or delete) : I can take the DefaultModel source code, put my fix in it, and use it as a custom model binder. It's fun, but a bit dirty and over the top.
But I believe the best way is to use a specific ViewModel, using only the properties which are editable, and use AutoMap to map it to my EF hierarchy. BUT : it has the same problem of creating child objects collection.
In the end, I just did some manual mapping for between my View Model and my EF hierarchy : I'm nearly sure I can do something automatic, which could detect if a child item has been modified or inserted or deleted (since every item has a [key] property, but I just don't have the time budget to implement it.

Related

ASP.NET MVC Done Right: View Models

I read this q/a Real example of TryUpdateModel, ASP .NET MVC 3 and was really interested on #ben-foster response.
I started doing a comment on that answer but got quite long, so started a new Question.
Having ViewModels for everything approach (which i like a lot) get me into some 'weird scenarios' that i want advice in how should I do.
Imagine this structure :
public class ProductListEditableViewModel {
List<ProductEditViewModel> products {get;set;}
}
public class ProductEditViewModel {
List<PriceViewModel> prices {get;set;}
}
public class PriceViewModel {
CurrencyViewModel currency {get;set;}
}
and so on ... ? do you really make one view model for each inner class? how then you map all that to the Model Object?
Also, that covers the Edit, but I have an Add, a send via email, and potentially more Views so more ViewModels!! should i end like something :
AddCurrencyViewModel
QuickAddCurrencyViewModel
EditCurrencyViewModel
ListCurrencyViewModel
DeleteCurrencyViewModel
ShareCurrencyViewModel
all having the 'almost same' properties ?
Should all those be packed into one file ?
Also do i need all this all viewModels or a inheritance approach might be better?
If you can, I´ll appreciate elaborate on complex scenarios
Also, I use a DTO approach to expose some of the model objects into web service / apis, so I already have some form of mapping already in place where this DTO are not exactly my ViewModels, should I remove one of them? what´s the suggestion in this scenario ?
I´m using entity framework but i think the question is (or should be) ORM agnostic.
Not using UoW pattern (will this helps?) as looks it´s gets more complicated as the depth of the object increases.
Thanks a lot!
We typically have a view model per view so yes, if you have lots of views you will have lots of view models.
In typical CRUD applications we often have very similar views, for example Add and Update. In these cases, yes we use inheritance rather than writing duplicate code - usually Add subclasses Update.
public class AddFoo : UpdateFoo {
public AddFoo() {
// set up defaults for new Foo
}
}
public class UpdateFoo {
public string Name { get; set; }
// etc.
}
We attempted to "share" view models between views in the past and normally ended up in a world of pain.
With regard to your "weird scenario" - this does look weird indeed, but perhaps because I don't understand your application.
The goal of your view model is to provide the information to the view that is needed and ideally to flatten any complex objects so they are easier to work with. You shouldn't split your view models up like your example unless it makes sense to do so.
Let's say I wanted to a create a view where the customer could change their contact details. Taking the following domain object:
public class Customer {
public string FirstName { get; set; }
public string LastName { get;set; }
public Address Address { get; set; }
}
I'd probably flatten this to a view model like so:
public class UpdateAddressModel {
public string FirstName { get; set; }
public string LastName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressCity { get; set; }
// etc.
}
Of course there will be occasions where it doesn't make sense to do this, for example a dashboard view in an online store where you have a list of products going out of stock and a list of recent orders - these two things are unrelated but are required by your view:
public class DashboardModel {
public List<Product> ProductsGoingOutOfStock { get; set; }
public List<Order> NewOrders { get; set; }
}
how then you map all that to the Model Object?
I'm assuming by Model Object you mean your data/domain model. The key takeaway here is that the view model you use to render your view is unlikely to be the same as the "models" you POST to the server and if they are, you're probably over-POSTing or you have some crazy enter-everything data capture screen that will make your eyes bleed.
I find it helps to think of what you send to your server as Commands and what you use to render your views as view models.
So the answer to your question - how do you map your complex view model to your data model? - Quite simply, you don't. You should send commands to the server that perform a specific task e.g. updating an address.
There's no hard and fast rule in how you structure your view models but generally go with what makes sense and if it starts to feel too complicated you're probably trying to do too much with one view.
I hope this helps. You'll find lots of posts relating to this matter on my blog.
I realize this is an old-ish question but I did want to address one of the questions posed by the OP that was not answered.
Should all those [ViewModels] be packed into one file ?
Most of the examples I see put each ViewModel in a separate file, so the dominant convention seems to be one file per viewmodel, but I found in practice that this seems to be overkill. Instead I put all viewmodels for a particular controller in one file with multiple viewmodels in it. So for example if User is my Controller and I have several viewmodels associated with this controller such as UserAddViewModel, UserEditViewModel, UserDeleteViewModel I put all of the viewmodels for User in one file called UserViewModels.cs

Correct use of Model vs Controller in MVC / ASP.NET MVC

I have a Service class with a method called GetProducts(). That encapsulates business logic and calls the repository to get a list of products.
My MVC view wants to show that list of products as an MVC SelectList. Where is the correct place for that logic to go. I seem to have 3 options:
Model
The Model should expose a property called ProductSelectList. When the getter of this property is called by the View, the Model should call Service.GetProducts() and convert the result to a SelectList before passing it on.
Plausible argument: The Model should make calls to business logic and the repository. The View should merely render predetermined data. The Controller should not be involved, save for passing contextual data to the Model.
View
The View should contain code that calls Service.GetProducts() directly and converts the result to a SelectList inline.
Plausible argument: The View should call for this data directly as it is specifically for use on the View. There is no need to involve the Model or Controller, as we are calling an abstracted Service method anyway, so anything else just adds extra overhead.
Controller
The Controller should make the call to Service.GetProducts(), convert the results to a SelectList and pass it through to the Model, which should contain a simple ProductSelectList property. The View will access this property for rendering.
Plausible argument: The Controller knows which parameters to provide to the Service method, so it should make the call. The Model should be a simple placeholder for data, filled by the Controller. The View's job is to simply render the data from the Model.
I have a feeling that the correct answer is Model, but the other two make some reasonable points. Perhaps I've muddied the waters by already having a Service class that's separate to the Model?
Would anybody care to share their opinion? Is this just a matter of taste?
I personally subscribe to the logic of Number 3, allowing the controller to populate the Model (or View Model as is sometimes differentiated).
I have my views dumb and only displaying data.
I have my View Models store the information that the View will need, occasionally exposing 'get only' properties that format other properties into a nicer format. If my model needs access to my services, then I feel I'm doing something wrong.
The controllers arrange and gather all the information together (but do no actual work, that is left for the services.
In your example, I would have my controller action similar to:
public ActionResult Index()
{
IndexViewModel viewModel = new IndexViewModel();
viewModel.ProductSelectList = new SelectList(Service.GetProducts(), "Value", "Name");
return View(viewModel);
}
and my view model similar to:
public class IndexViewModel()
{
public SelectList ProductSelectList { get; set; }
public int ProductID { get; set; }
}
With the appropriate part of the view looking like:
#Html.DropDownListFor(x => x.ProductID, Model.ProductSelectList);
This way I'm content that I know where to look if there is an issue with anything and everything has a very specific place.
However, there is no correct way as seems always to be the case with these things. Stephen Walther has a good blog series on MVC tips. In one he talks about the View Model emphasis and although not a SelectList he populates, the SelectList is still data in much the same way his list of products is.
In a classic MVC architecture your Model shouldn't be much more than a container for your view data hence the reason it's often called a ViewModel. A ViewModel is different from the Entity Model(s) that your service layer manages.
Your controller is then responsible for populating your ViewModel from the entity model(s) returned by your service layer.
Due to convenience some developers will use their service layer entities directly in their ViewModels but long term that can lead to headaches. One way around that is to use a tool such as AutoMapper to automate the shuffling of data to and from your ViewModel and entity models.
Here's what a controller might look like. Notice that data such as the SSN does not get exposed to the view since there is a mapping from your Entity Models to your View Model.
public class Customer : IEntity
{
public string CustomerID { get; set; }
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class CustomerEditViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string PhoneNumber { get; set; }
}
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit ()
{
Customer customer = _customerService.GetCustomer (User.Identity.Name);
var model = new CustomerEditViewModel ()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Address1 = customer.Address.Address1,
Address2 = customer.Address.Address2,
Country = customer.Address.Country,
City = customer.Address.City,
State = customer.Address.State,
Zip = customer.Address.Zip,
PhoneNumber = customer.Address.PhoneNumber,
};
return View (model);
}
}
You're right that there are a number of ways to handle this, and that's even before considering variations like MVP, MVVM, et cetera. Since you're asking about ASP.Net MVC in particular, I will defer to Microsoft:
An MVC model contains all of your application logic that is not
contained in a view or a controller. The model should contain all of
your application business logic, validation logic, and database access
logic. For example, if you are using the Microsoft Entity Framework to
access your database, then you would create your Entity Framework
classes (your .edmx file) in the Models folder.
A view should contain only logic related to generating the user
interface. A controller should only contain the bare minimum of logic
required to return the right view or redirect the user to another
action (flow control). Everything else should be contained in the
model.
In general, you should strive for fat models and skinny controllers.
Your controller methods should contain only a few lines of code. If a
controller action gets too fat, then you should consider moving the
logic out to a new class in the Models folder.
Source
I would say your call belongs in the Model.
One thing to keep in mind is that the SelectList class is specific to MVC only. So in my opinion it shouldn't be included in any business logic, and model classes fall into that category. Therefore your select list should be a part of a view model class instead.
This is the way it works in my projects:
Controller method is called
Controller uses repository (business logic, in other words) to get model data
Controller converts the model data if necessary and creates a view model object
Controller passes the view model to the view
The view displays the data in the view model with limited logic to show or hide things, etc
I'd go with option 3. In general, I'll construct my MVC apps such that the controller makes a call to the service to return a model (or collection of models) which are then passed to the view.
I generally keep my models very thin. They are a flattened representation of the data with validation attributes and that's it. I use a service (or model builder) layer to construct the models and do business logic on them. Some folks embed that into the model, but I find that makes for a messy project.
You definitely don't want the view making any calls to your services.
Update...
I'm assuming that this SelectList is your model. If instead it's a part of your model, then you're right, you should put it in your model. I generally don't like to make it a method call, though. I'd have a property on my model:
public SelectList Products { get; set; }
And have my service or model builder class actually populate it. I don't usually have any data-oriented methods on my models.
I'm going with option 1.
Models are the place to make calls to business logic, et cetera.
View - Should display only what the ViewModel already has been populated with.
Controller - the job of the Controller is to direct the traffic coming in (from Web requests) to the Logic that is responsible for handling the request. Hence the term 'controller'.
There are always exceptions to these, but the best place (structurally) is the Model.
I had this problem when I started into MVC and came up with this solution.
The controller talks to a Service Layer. The service layer contains my Domain models and does all the processing for request from the Controllers. The service layer also returns ViewModels to satisfy requests from the controller.
The service layer calls a repository and gets the entities it will need to build the ViweModels. I often use Automapper to populate the ViewModel or collections within the view model.
So, my view models contain all that is needed by the View, and the Controller is doing nothing but handling request and forwarding them to the appropriate service handler.
I don't see a problem with having view specific items like SelectLists in the view Model either.
None of the above.
In my web layer I basically just have html and javascript views. The model shouldn't leak into the view and neither should the services.
I also have an Infrastructure layer which binds the services and model to the views. In this layer there are ViewModels, which are classes that represent what will be displayed on the screen, Mappers, which do the work getting data from services/model and mapping it to the view model, and Tasks, which perform tasks such as Saving, Updating and Deleting data.
It is possible to put a lot of this infrastructure in the Controllers, similar to the example Todd Smith has given above, but I find for anything other than trivial views the Controller becomes littered with code to load data and populate view models. I prefer a dedicated single responsibility mapper class for each view model. Then my controller will look something like
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit (int id)
{
return View (CustomerEditMapper.Map(id));
}
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Save(CustomerEditViewModel model)
{
var errors = CustomerEditUpdatorCommand.Execute(model);
ModelState.AddErrors(errors);
return View ();
}
}
I'm torn between option 1 and option 3. I've ruled option 2 out completely as to me that's polluting the view with procedure calls not just presentation layer work.
Personally I would do it in the model and the getter would call the Service layer but I also subscribe to the belief that the model should only contain the information the view needs to render the page, by not fully containing the data in the model at the time you pass it to the view you are breaking this.
Another option here though would be to avoid tightly coupling the view and model by putting a Dictionary of the Products into the view through a Service Call then using the view to transform the Dictionary to a SelectList but this also gives you the ability to just output the information as well.
I think this boils down to a preference as to where you are happy having your logic.

Asp.Net MVC2 TekPub Starter Site methodology question

Ok I've just ran into this and I was only supposed to be checking my emails however I've ended up watching this (and not far off subscribing to TekPub).
http://tekpub.com/production/starter
Now this app is a great starting point, but it raises one issue for me and the development process I've been shown to follow (rightly or wrongly). There is no conversion from the LinqToSql object when passing data to the view. Are there any negitives to this?
The main one I can see is with validation, does this cause issues when using MVC's built in validation as this is somthing we use extensivly. Because we are using the built in objects generated by LinqToSql how would one go about adding validation, like
[Required(ErrorMessage="Name is Required")]
public string Name {get;set;}
Interested to understand the benifits of this methodology and any negitives that, should we take it on, experiance through the development process.
Should this be taken as a guide and we should be using ViewModels? If so should we always use them even in simple cases? And how/where in the application logic does the Entity get converted to a ViewModel?
With entity objects, you could use buddy classes, whereby you create a second class which acts as a metadata provider for your entity. For instance, with a Customer entity generated by Linq-to-Sql, I could create a buddy class like so:
[MetadataType(typeof(CustomerMeta))]
partial class Customer {
}
public class CustomerMeta {
[DisplayName("Forename", Required(ErrorMessage = "Forename is required.")]
public string Forename { get; set;}
}
Entities are generated as partial classes so you can add your own code to them.
Alternatively, you could forego pushing your entity types to your views and create specific models based around the functionality required, for instance I would typically have a User entity, but when I need to create a User, I have something called a CreateUserSpec model:
public class CreateUserSpec
{
[DisplayName("Forename")]
public string Forename { get; set; }
}
Which has a subset of the properties of the User, only those required to create a User. This is the model I would pass to my view, and repopulate from the form data. For instance:
public class AccountController
{
public ActionResult Register() {
return View(new CreateUserSpec());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(CreateUserSpec spec) {
if (!ModelState.IsValid) {
return View(spec);
}
var user = UserFactory.CreateUser(spec);
// Redirect to authorisation page?
}
}

My custom ASP.NET MVC entity binding: is it a good solution?

Suppose I want to allow to select our entity (from a dropdown, etc) on a page, let's say Product. As a result I may receive this:
public ActionResult SelectedAction(Guid productId)
{
}
But, I want to use model binders power, so instead I write model binder to get my product from repository and instead use
public ActionResult SelectedAction(Product product)
{
if (ModelState.IsValid) {} else {}
}
My model binder will set model state to false if product is invalid.
Now, there're problems with this approach:
It's not always easy to use strongly-typed methods like Html.ActionLink(c => c.SelectedAction(id)) since we need to pass Product, not id.
It's not good to use entities as controller parameters, anyway.
If model state is invalid, and I want to redirect back and show error, I can't preserve selected product! Because bound product is not set and my id is not there. I'd like to do RedirectToAction(c => c.Redisplay(product)) but of course this is not possible.
Now, seems like I'm back to use "Guid productId" as parameter... However, there's one solution that I'd like to present and discuss.
public class EntityViewModel<T> where T : BaseEntity
{
public EntityViewModel(Guid id)
{
this.Id = id;
}
public static implicit operator EntityViewModel<T>(T entity)
{
return new EntityViewModel<T>(entity.Id);
}
public override string ToString()
{
return Id.ToString();
}
public Guid Id { get; set; }
public T Instance { get; set; }
}
Now, if I use
public ActionResult SelectedAction(EntityViewModel<Product> product)
{
if (ModelState.IsValid) {} else {}
}
all the problems are solved:
I can pass EntityViewModel with only Id set if I have only Id.
I don't use entity as parameter. Moreover, I
can use EntityViewModel as property inside another ViewModel.
I can pass EntityViewModel back to RedirectToController and it will keep its Id value, which will be
redisplayed to user along with the validation messages (thanks to MVCContrib and ModelStateToTempData / PassParametersDuringRedirect).
The model binder will get Instance from the repository and will set model state errors like "Not found in database" and so on. And I can use things like ActionLink(c => c.Action(Model.MyProductViewModelProperty)).
The question is, are there any drawbacks here? I can't see anything bad but I'm still new to MVC and may miss some important things. Maybe there're better and approved ways? Maybe this is why everybody uses entity IDs as input parameters and properties?
Overall that looks like a good appoach to me...
As an alternative, you could use POCO for your viewmodel then I think all 3 problems would be solved automatically. Have you seen the Automapper project that allows an Entity to DTO approach? This would give you more flexibility by separating you ViewModel from your EntityModel, but really depends on the complexity of you application you are building.
MVC's ViewDataExtensions might also be useful instead of creating custom containers to hold various viewmodel objects as you mention in number 2.
MVCContrib's ModelStateToTempData should work for any serializable object (must be serializable for any out of process sessionstate providers eg. SQL, Velocity etc.), so you could use that even without wrapping your entity classes couldn't you?

ASP.NET MVC / DDD architecture help

I am creating a Web application using ASP.NET MVC, and I'm trying to use domain-driven design. I have an architecture question.
I have a WebControl table to store keys and values for lists so they can be editable. I've incorporated this into my business model, but it is resulting in a lot of redundant code and I'm not sure it belongs there. For example, in my Request class I have a property called NeedType. Because this comes from a list, I created a NeedType class to provide the values for the radio buttons. I'm showing just one example here, but the form is going to have probably a dozen or so lists that need to come from the database.
[edit, to clarify question] What's a better way to do this? Are these list objects really part of my domain or do they exist only for the UI? If not part of the domain, then they don't belong in my Core project, so where do they go?
public class Request : DomainObject
{
public virtual int RequestId { get; set; }
public virtual DateTime SubmissionDate { get; set; }
public virtual string NeedType { get; set; }
public virtual string NeedDescription { get; set; }
// etc.
}
public class NeedType : DomainObject
{
public virtual int NeedTypeId { get; set; }
public virtual string NeedTypeCode { get; set; }
public virtual string NeedTypeName { get; set; }
public virtual int DisplayOrder { get; set; }
public virtual bool Active { get; set; }
}
public class RequestController : Controller
{
private readonly IRequestRepository repository;
public RequestController()
{
repository = new RequestRepository(new HybridSessionBuilder());
}
public RequestController(IRequestRepository repository)
{
this.repository = repository;
}
public ViewResult Index(RequestForm form)
{
ViewData.Add("NeedTypes", GetNeedTypes());
if (form == null)
{
form = new RequestForm();
form.BindTo(repository.GetById(125));
}
}
private NeedType[] GetNeedTypes()
{
INeedTypeRepository repo = new NeedTypeRepository(new HybridSessionBuilder());
return repo.GetAll();
}
}
Create a seperate viewmodel with the data you need in your view. The Model in the M of MVC is not the same as the domainmodel. MVC viewmodels are dumb DTO's without behaviour, properties only. A domain model has as much behaviour as possible. A domain model with get;set; properties only is considered an anti-pattern called "anemic domain model". There are 2 places where most people put the viewmodels: in the web layer, close to the views and controllers, or in a application service layer.
Edit:
When you only need to display a list of all needtypes in the database and one request in your view, I would indeed create one viewmodel with the request and the list of needtypes as properties. I don't think a call to multiple repositories in a controller is a smell, unless you have a larger application and you might want a seperate application service layer that returns the whole viewmodel with one method call.
I think it might also be a good idea to follow the advise of Todd Smith about value object.
When the needtypes can be added or edited by users at runtime, needtype should be an entity. When the needtypes are hardcoded and only changed with new releases of the project, needtype should be a value object and the list of needtypes could be populated by something like NeedType.GetAll() and stored in the database by adding a column to the request table instead of a seperate needtype table.
If it comes from a list, then I'm betting this is a foreign key. Don't think about your UI at all when designing your domain model. This is simply a case where NeedType is a foreign key. Replace the string NeedType with a reference to an actual NeedType object. In your database, this would be a reference to an id.
When you're building your list of NeedType choices, you simply need to pull every NeedType. Perhaps keeping it cached would be a good idea if it doesn't change much.
Your NeedType looks like a value object to me. If it's read-only data then it should be treated as a value object in a DDD architecture and are part of your domain.
A lot of people run into the "omg so much redundancy" issue when dealing with DDD since you're no longer using the old Database -> DataTable -> UI approach.

Resources