How does ASP.NET MVC3 gather data from GET/POST into a model? - data-binding

I've learned about custom editor templates for ASP.NET MVC3 and I see now how I can easily implement my own. However for an editor to work it must not only display that data in a textbox, but also somehow transfer the user-edited contents to the server for processing. So how does this binding work for complex models? How does MVC decide where each POST value goes? Are there some magic naming conventions? What about very complex models like dynamic lists or dictionaries or DataTables?

There is a naming convention. So for example if you have the following model:
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public string Baz { get; set; }
}
and the following action:
public ActionResult Index(Foo foo) { ... }
you could send the following request:
/home/index?Bar.Baz=somevalue
in order to set the Baz value. Of course this will automatically instantiate the Foo model and its Bar property. And obviously this convention also extends for lists and dictionaries.
Whether the values are sent in the query string (GET request), as form values (POST request) or as route values it doesn't really matter for the default model binder. It will look at all those places.
And you should never forget that if this default naming convention doesn't suit your particular requirements you should feel free to write a custom model binder.
Remark: there is also the case for uploading files.

Related

Entity Framework Class Manipulation

I'm using Entity Framework (DB First) on a new project and wanted to add some customisation to the classes generated. However, my changes are obviously lost every time that the edmx is refreshed. I was just wondering if there is a design pattern for handling this sort of thing?
As an example, suppose I have a class with a integer property; StatusID - and I'd like to extend the entity class so that the status value can also be accessed/set via the related enum and finally a property that gets a text representation of that Enum from the description attribute. This all works, but those customisations are lost when the model is refreshed. I appreciate that the property can be converted to an enum, so the latter property that gets the description of the enum is perhaps a better example for this question.
I think I know the answer but I just wanted to put this out there in case there were some magic tricks that would allow this to work and prevent those customisations from being lost.
public int StatusID { get; set; }
public Enumerations.ValidationStatus StatusEnum
{
get
{
return (Enumerations.ValidationStatus)StatusID;
}
set
{
StatusID = (int)value;
}
}
public string StatusText
{
get
{
return MyMethodThatGetsTheEnumDescription(StatusEnum);
}
}
Two Solutions to work around the problem:
User Data Transfer Object(DTO) nd put the enum there. then use Automapper or manually map between the DB Model and the DTO Model (best practice)
Instead of enum you can use extension functions on the model and define your getter, setters and any extra properties you want as extension functions to the class
(will add some complexity to your models)

How can I create more than one Model in a view? Preferably using Partial Views and a dynamic number of models

I have list of "skills" that I want a user to be able to go through, selecting appropriate levels from the list. So Skill looks something like this:
public class Skill
{
public String SkillName { get; set; }
public SkillLevel CurrentSkillLevel { get; set; }
public Boolean IsRequired { get; set; }
public Skill(String Name)
{
this.SkillName = Name;
this.IsRequired = true;
this.CurrentSkillLevel = SkillLevel.None;
}
}
There could be hundreds of skills - and the exact number is unknown at the moment, and certainly it needs to be dynamic, so I don't want to make the user go through the process of clicking on each skill, filling out the form, and submitting each time. I'd like to display all of the skills in the same page (one row each), allow the user to select all the values, then click submit once at the end.
Unfortunately, I've not had any experience with using MVC for anything other than singleton creation. I would normally use a separate ViewModel for several models bundled together, but I don't see how that would work with a dynamic list, and since they are all the same type ("Skill"), I guess the ViewModel would look exactly like a list of the model.
Does anyone have an appropriate solution?
Thanks
Building on DaveA's answer, you can use an editor template for Skill. You will need to add a folder named EditorTemplates to your Views\Controller folder. Now make a partial view in that folder named Skill.cshtml that looks something like this
#model Skill
#Html.TextBoxFor(s => s.SkillName)
#Html.TextBoxFor(s => s.Skills[i].Title)
// etc...
Now in your main view
using (Html.BeginForm("UpdateCart", "Orders"))
{
#Html.TextBoxFor(p=>p.Name)
#Html.TextBoxFor(p=>p.Title)
#Html.EditorFor(p => p.Skills)
}
Razor is smart enough that it will render each skill in Skills using the Skill.cshtml editor template.

Models, ViewModels, DTOs in MVC 3 application

I have a web solution (in VS2010) with two sub-projects:
Domain which holds the Model classes (mapped to database tables via Entity Framework) and Services which (besides other stuff) are responsible for CRUD operations
WebUI which references the Domain project
For the first pages I've created I have used the Model classes from the Domain project directly as Model in my strongly typed Views because the classes were small and I wanted to display and modify all properties.
Now I have a page which should only work with a small part of all properties of the corresponding Domain Model. I retrieve those properties by using a projection of the query result in my Service class. But I need to project into a type - and here come my questions about the solutions I can think of:
I introduce ViewModels which live in the WebUI project and expose IQueryables and the EF data context from the service to the WebUI project. Then I could directly project into those ViewModels.
If I don't want to expose IQueryables and the EF data context I put the ViewModel classes in the Domain project, then I can return the ViewModels directly as result of the queries and projections from the Service classes.
In addition to the ViewModels in the WebUI project I introduce Data transfer objects which move the data from the queries in the Service classes to the ViewModels.
Solution 1 and 2 look like the same amount of work and I am inclined to prefer solution 2 to keep all the database concerns in a separate project. But somehow it sounds wrong to have View-Models in the Domain project.
Solution 3 sounds like a lot more work since I have more classes to create and to care about the Model-DTO-ViewModel mapping. I also don't understand what would be the difference between the DTOs and the ViewModels. Aren't the ViewModels exactly the collection of the selected properties of my Model class which I want to display? Wouldn't they contain the same members as the DTOs? Why would I want to differentiate between ViewModels and DTO?
Which of these three solutions is preferable and what are the benefits and downsides? Are there other options?
Thank you for feedback in advance!
Edit (because I had perhaps a too long wall of text and have been asked for code)
Example: I have a Customer Entity ...
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public City { get; set; }
// ... and many more properties
}
... and want to create a View which only shows (and perhaps allows to edit) the Name of customers in a list. In a Service class I extract the data I need for the View via a projection:
public class CustomerService
{
public List<SomeClass1> GetCustomerNameList()
{
using (var dbContext = new MyDbContext())
{
return dbContext.Customers
.Select(c => new SomeClass1
{
ID = c.ID,
Name = c.Name
})
.ToList();
}
}
}
Then there is a CustomerController with an action method. How should this look like?
Either this way (a) ...
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
return View(list);
}
... or better this way (b):
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
List<SomeClass2> newList = CreateNewList(list);
return View(newList);
}
With respect to option 3 above I'd say: SomeClass1 (lives in Domain project) is a DTO and SomeClass2 (lives in WebUI project) is a ViewModel.
I am wondering if it ever makes sense to distinguish the two classes. Why wouldn't I always choose option (a) for the controller action (because it's easier)? Are there reasons to introduce the ViewModel (SomeClass2) in addition to the DTO (SomeClass1)?
I would solve your problem by using an auto-mapping tool (like AutoMapper) to do the mapping for you. In cases where the mapping is easy (for example if all properties from one class should be mapped to properties with the same name on another class) AutoMapper will be able to do all the hook-up work for you, and you'll have to give a couple of lines of code to note that there should be a map between the two at all.
That way, you can have your entities in Domain, and a couple of view model classes in your WebUI, and somewhere (preferrably in WebUI or a sub namespace of the same) define maps between them. Your view models will in effect be DTOs, but you won't have to worry much about the conversion process between the domain and your DTO classes.
Note: I would strongly recommend against giving your Domain entities straight to the views of your MVC web UI. You don't want EF to "stick around" all the way to the front-end layer, in case you later want to use something other than EF.
introduce ViewModels which live in the
WebUI project and expose IQueryables
and the EF data context from the
service to the WebUI project. Then I
could directly project into those
ViewModels.
The trouble with this is you soon run into problems using EF trying to 'flatten' models. I encountered something similar when I had a CommentViewModel class that looked like this:
public class CommentViewModel
{
public string Content { get; set; }
public string DateCreated { get; set; }
}
The following EF4 query projection to the CommentViewModel wouldn't work as the couldn't translate the ToString() method into SQL:
var comments = from c in DbSet where c.PostId == postId
select new CommentViewModel()
{
Content = c.Content,
DateCreated = c.DateCreated.ToShortTimeString()
};
Using something like Automapper is a good choice, especially if you have a lot of conversions to make. However, you can also create your own converters that basically convert your domain model to your view model. In my case I created my own extension methods to convert my Comment domain model to my CommentViewModel like this:
public static class ViewModelConverters
{
public static CommentViewModel ToCommentViewModel(this Comment comment)
{
return new CommentViewModel()
{
Content = comment.Content,
DateCreated = comment.DateCreated.ToShortDateString()
};
}
public static IEnumerable<CommentViewModel> ToCommentViewModelList(this IEnumerable<Comment> comments)
{
List<CommentViewModel> commentModels = new List<CommentViewModel>(comments.Count());
foreach (var c in comments)
{
commentModels.Add(c.ToCommentViewModel());
}
return commentModels;
}
}
Basically what I do is perform a standard EF query to bring back a domain model and then use the extension methods to convert the results to a view model. For example, the following methods illustrate the usage:
public Comment GetComment(int commentId)
{
return CommentRepository.GetById(commentId);
}
public CommentViewModel GetCommentViewModel(int commentId)
{
return CommentRepository.GetById(commentId).ToCommentViewModel();
}
public IEnumerable<Comment> GetCommentsForPost(int postId)
{
return CommentRepository.GetCommentsForPost(postId);
}
public IEnumerable<CommentViewModel> GetCommentViewModelsForPost(int postId)
{
return CommentRepository.GetCommentsForPost(postId).ToCommentViewModelList();
}
Talking about Models, ViewModels and DTOs is confusing, personally I don't like to use these terms. I prefer to talk about Domain Entities, Domain Services, Operation Input/Result (aka DTOs). All of these types live in the Domain layer. Operations is the behavior of Entities and Services. Unless you are building a pure CRUD application the presentation layer only deals with Input/Result types, not Entities. You don't need additional ViewModel types, these are the ViewModels (in other words, the Model of the View). The View is there to translate the Operation Results to HTML, but the same Result could be serialized as XML or JSON. What you use as ViewModel is part of the domain, not the presentation layer.

ASP.NET MVC 2 Using an interface to strongly type a partial

I'm experimenting with ASP.NET MVC2, in particular viewmodels and partials. My question is: Is it ‘valid’ or ‘right’ to have your partials strongly typed against an interface and the have your viewmodels implement that interface if the view uses the partial?
To illustrate, say I have a Product form partial (strongly typed against IProductFormViewModel) which is used in both the Edit and Create views. These views are strongly typed against ProductEditViewModel and ProductCreateViewModel which implement the IProductFormViewModel.
The benefit being that the corresponding POST actions for Create and Edit take ProductCreateViewModel & ProductEditViewModel objects respectively.
Edit:
If the partial has its own dedicated viewmodel (ProductFormViewModel) and each of the ProductEditViewModel & ProductCreateViewModel expose a property of type ProductFormViewModel which is passed to the partial, then when the form is submitted the model binding of ProductEditViewModel & ProductCreateViewModel doesn't work as the Edit and Create actions expect their respective object types...thats the reason for the approach.
You may have problems when your interfaces for your different partials expose the same property name e.g. name. You would then have to explicity implement the interface which would then cause problems with your model binding.
Otherwise it should work.
Yes, this seems a valid approach.
Interfaces are essentially contracts that need to be fulfilled by implementing classes. but in case of view engines i don't see any specific benefit of having you viewmodels implement an interface because at the end you have to instantiate the viewmodel in controller and pass it to the view and suppose you change implementation of ProductFormViewModel or EditProductViewModel, u still have to instantiate (populate) the object in controller and pass it to the view. so it does not achieve the same purpose as we do in repository pattern in conjunction with dependency injection. if you can tell what exactly u are trying to achieve by this approach, we might help.
Your approach is fine.
Or you could have a model specific to your partial and use composition instead, e.g.:
public class AddressModel
{
public string Address { get; set; }
public string Code { get; set; }
}
public class PersonModel
{
public string Name { get; set; }
public AddressModel Address { get; set; }
}
Then when redering your partial you pass it the correct model.
HTH

Problem organizing code in asp.net MVC 2

I'm new to MVC and I borrow a book from library yesterday on asp.net MVC 2.
I'm a bit confused about what kind of code should be included in Model, view and controller. I was working on user input validation from the book and if I understand correctly, it seems they declare variables in "Model", validating user input in "Controller" and display the web page in "View".
Model:
-Declaring variables
e.g:
class Contact:
public string Name { get; set; }
public string EmailAddress { get; set; }
Views:
-Contain HTML, HTML Helper code, displaying contents and use variables from "Model"
e.g:
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
Controller:
-"Playing"/"Manipulating" variables from Model + Call "View" to display web page at the end (return View()). (Validating user input for this example)
e.g:
if (String.IsNullOrEmpty(contact.Name))
ModelState.AddModelError("Name", "Please enter your name.");
I'm not sure but it seems to me that "Controller" is the "heavy coding" part to me. On the other hand, "View" is the good old HTML, markup that display the web site and "Model" is a place that store data (declaring variables for example.)
Please let me know whether I'm on the right direction.
Thanks :)
I'm not sure but it seems to me that "Controller" is the "heavy coding" part to me
You should avoid having fat controllers. In fact the controller might depend on a service layer which contains the business logic of you application. This service layer could itself depend on repositories performing the data access (simple CRUD operations) on the models. So the controller would simply invoke a business operation call on the service layer to fetch/update the model and then pass a view model to the view in order to display it.
I am also new to MVC and first thing i did when i started was to view most of the talks given by Scott Hanselman and Phill Haack. So you might try this one: [http://channel9.msdn.com/blogs/matthijs/aspnet-mvc-2-basics-introduction-by-scott-hanselman][1]
[1]: http://channel9.msdn.com/blogs/matthijs/aspnet-mvc-2-basics-introduction-by-scott-hanselman to get started. From what i got so for, Darin is right. Try to avoid fat controllers and work with a repository for your model. Also, I noticed that for simple validation (required, maximum string length and such) it is preferred to use DataAnnotion on the model... So your Contact model might look like this:
class Contact:
[Required]
public string Name { get; set; }
public string EmailAddress { get; set; }
This will make the Name property required on Edit/Create Views.

Resources