I'm working on a MVC 5 project, very new to MVC. I noticed this line in the code:
#Html.DropDownListFor(model => model.ContractorId, Model.Contractors)
the directive on the top of the page is:
#model Project.Models.ContractViewModel
The ContractViewModel class does have a Contractors object in it.
public IEnumerable<SelectListItem> Contractors
I'm just a little confused on the capital M (Model.Contractors), does Model always refer to the object passed in the #model? Then what is the difference between using Model.Contractors and model.Contractors?
Model actually represents an instance of the class that is your model and model is an alias for lambda expression.
When you write #Model in your view you are using the object of ContractViewModel which is passed from Controller action, if it is not passed from View it can be null and accessing any property of Model can throw Null Reference Exception and writing Model.Contractors you basically mean ContractViewModel.Contractors
and when you write a html helper you need to write an alias for it, its not mandatory to write model you can write anything.
for example:
#Html.DropDownListFor(m=> m.ContractorId, Model.Contractors)
It is just an alias to access the model properties inside Html Helper.
When you write #model Project.Models.ContractViewModel at the top of View that is a different thing, in this case we are defining the model of view that it will take instance of Project.Models.ContractViewModel , actually our view is now strongly typed to instance of class Project.Models.ContractViewModel.
Related
I have created a Custom Model Binder that works perfectly.
All my ViewModels extend the BaseViewModel however when I register the Model Binder for BaseViewModel it just doesn't run.
If I register every ViewModel "by hand" like the following line it works perfectly
ModelBinders.Binders[typeof(ArticlesViewModel)] = new ContextDataBinder();
What I need to know if there is a way to do that kind of registration for all my viewModels without register all viewModels one by one.
As it was commented in my original post you can register all the model blinders by replacing the default binder
ModelBinders.Binders.DefaultBinder = new ContextDataBinder();
However that didn't worked for my specific case because the ViewModels that the framework creates automatically always return the previous ViewModel (in searches for example it doesn't return me filtered results but all the results).
I ended up creating a List of types containing the type of only the ViewModels that actually need to pass trough the ModelBinder and with a foreach e register them all one by one.
I'm new to ASP.NET MVC, so far I have read that I have if I have lets say two form in one view, the recommended thing to do, is to have a View model which will have the model associate for each form, this forms are not related in any way just are in the home page, one form is for searching a fly and the other is contact form so as you can see there is no relationship of any kind.
this my "HomePageViewModel"
public class HomePageViewModel
{
public SearchFlyViewModel SearchFly;
public ContactFormViewModel Contact;
}
, in my index file which is the homepage I have this at the top
#model Project.WebSite.Models.HomePageViewModel
now, I have a partial view inside my homepage, this partial view has the search fly form, I did it this way because I use the same form in a lot of places.
My partial view is _QuoteForm in which i have this at the top
#model Project.WebSite.Models.SearchFlyViewModel
when I tried to do this in my homepage
#Html.Partial("_QuoteForm", Model.SearchFly)
an error is showing up in runtime telling me this
The model item passed into the dictionary is of type 'Project.WebSite.Models.HomePageViewModel', but this dictionary requires a model item of type 'Project.WebSite.Models.SearchFlyViewModel'.
Which I don't understand why because I did not pass the HomePageViewModel to my partial view, I passed Model.SearchFly which is of the type SearchFlyViewModel
if someone can help figure it out what I'm missing.
thanks
The second parameter ( "The model" ) of the Html.Partial should not be null.
#Html.Partial("_QuoteForm", Model.SearchFly)
Verify
Model.SearchFly != null
I am new to asp.net mvc4 and there is something i don't understand well.
Why do I have to declare the Model using #model at top of the view, if I already pass an object to the View in the controller.
Taking an example :
Controller:
public ActionResult countryDetails(int id)
{
Country country = db.Country.Find(id);
return View(country);
}
View:
#model MvcApplication2.Models.Country
#{
ViewBag.Title = "countryDetails";
}
...
The controller returns a View with an object as parameter, so the model should be already known. I'm sorry if it is obvious, but I can't figure out why this is not a "double" declaration.
Thanks for you help !
The declaration at the top will do two things for you:
It will allow intellisence to know what type you are using when you type in #Model or use any of the Html helper extensions.
It will also check at runtime that model passed in can be cast to the type the view expects.
Its not necessarily a "double declaration" as it is analogous to specifying a type to a parameter on a method. Like so
Person Someone = new Person();
RenderView(Someone);
...
void RenderView(Person model) { }
By default your view inherits from System.Web.Mvc.WebViewPage<TModel>
You can optionally override this class, it's default ASP.NET inheritance mechanism:
#inherits System.Web.Mvc.WebViewPage<List<CompanyName.MyProduct.MyCategory>>
Or you can just simplify this since MVC3 like this:
#model List<CompanyName.MyProduct.MyCategory>
This sugar syntax was made to simplify code typing.
This declaration give you some things
View automatically cast object to the preferred type
You receive type-defined 'model' property which allows you to access
to your object methods and properties
Just believe that this is a method which accepts object and cast it to the specified type that you provide
The main reason is type-safety, it allows you to work with strongly typed views with the benefit of intellisense, compiler error hints, invalid casting etc.
Also, another reason is for readability - it acts as a reminder to what sort of model it is you are actually dealing with instead of having to keep referring back to the controller.
Using ASP.NET MVC 3 I would like to render different "templates" (i.e. partial views or whatever you want to call them) to my views based upon the type of the view model (or a property on the view model) supplied at runtime.
I understand the out-of-the-box ASP.NET MVC functionality enables the addition of a UIHint attribute to a property or field on the viewmodel supplied to the view, but as far as I can tell this doesn't meet my needs as I won't know the template required until runtime.
AFAICT ASP.NET doesn't support generic viewmodels of type T either, so my idea is to take the ASP.NET MVC3 source code and write my own DisplayFor method that accepts a viewmodel instance (specified by it's abstract base type in the view), which resolves the actual type at runtime and uses this to find the template name by convention.
Does this sound feasible/worthwhile?
The view would look thus (note specification of base type, a concrete instance would be supplied at runtime):
#model MyViewModelBase
#{ DisplayFor(Model); }
Viewmodel:
public class MyMagicalViewModel : MyViewModelBase {}
Invocation of this view would look thus:
...
return View("MyView", MyMagicalViewModel);
...
...and this would return html corresponding to the MyMagicalViewModelPartialView.cshtml
Have you looked into Html.EditorFor?
Im starting with MVC2 and i have a simple question:
If i have a typed view with a form inside, and this textbox created with lambda expressions:
<%: Html.TextBoxFor(e => e.Name)%>
When i submit this form the default model binder take the request form, takes the model typed to the view, serialize the data posted (as a this model) and pass it to an action of my controller.
To try to explain myself better, lets imagine that i have a url like localhost/edittestmodel/ID/1 and i have in my controller action the following code:
public ActionResult Edit(int id)
{
TestModel testmodel=new TestModel();
testmodel.Name="texttorenderintotextbox";
//whats the class that place the testmodel properties into the view?
return View(testmodel);
}
What's the responsable class for place the Name property of my testmodel object into the textbox
<%: Html.TextBoxFor(e => e.Name)%>
Thanks in advance.
Best Regards.
Jose.
It's the TextBoxFor helper method that's responsible for generating the input field from the lambda expression.
View's don't have anything to do in POST request and model binding
When you have strong type views, model type is barely used to have the simplicity of code intellisense in view's code (so you can use lambda expressions like in your example).
But when you POST data back, nothing gets checked against the view. It gets checked against controller action parameters though. And if there's a parameter with a certain custom model binder type, that particular model binder is used to process incoming data.
But to answer your question: TextBoxFor checks your strong type view's model and generates particular textbox with correct name attribute. So data from it will be posted back under the correct form field name.
To go even deeper. It's the view engine that parses view's ASPX code and runs all server side scripts including Html.TextBoxFor() call.