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.
Related
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'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.
Normally, when receiving form data in a controller, I'd use:
public ActionResult Edit(int id, FormCollection formValues)
I have a view which is bound to a model but also includes some items not attached to the model which I thought I'd be able to access via FormCollection as
public ActionResult Edit(int id, MyModel objModel, FormCollection formValues)
I wondered if this is the best way to achieve this or if there's another to code this.
If this is a post, you will need to tag the method with the HttpPost attribute.
[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{
var objModel = new MyModel();
// updates model here
TryUpdateModel(objModel);
}
In your view, you would have something like:
#model MyModel
... some html here
<fieldset>
<legend>MyModel Information</legend>
#Html.EditorForModel()
</fieldset>
So you can edit the model fields using the EditorForModel and retrieve those values using TryUpdateModel. Noting that you still have access to your FormCollection object.
This isn't the way to work. You shouldn't use your database model directly into your View.
You should pass a ViewModel. This way you can pass your model and extra properties.
public class MyViewModel
{
// All the properties for your model.
// All other properties needed and not attached to your model
}
In the Post action in your controller you can receive the MyViewModel and just make your model with the properties inside the ViewModel.
Check out this post for more information:
http://blogs.msdn.com/b/simonince/archive/2010/01/26/view-models-in-asp-net-mvc.aspx
Before you get any further, read about difference between a domain model and a view model. Quite often, in a simple application you can get away with using a domain model. As the system grows, you are likely to encounter problems where simple features will be difficult to implement. Eventually you'll see a need to refactor code and this is when you are likely to see a need for a view model.
Your question is regarding parameters that are passed to controller actions. You have a controller to edit something.
There is an Edit GET where you do something like this:
Read data from database
Wrap it into the object
Pass this object to a view which will display the object
There is an Edit POST want to recieve data and write changes to the database. So what do you need to make that happen? You need id and a combination of fields that you wish to update. Passing FormCollection and something else means that you have to map values from FormCollection to your domain model. This is time consuming and a repetative task.
You don't want to do this, so you want submit back a single object, doesn't matter whether it's a view model or a domain model, but it should be an object that contains all the data that you need for an update.
Data binding feature of the MVC 3 framework will automatically map fields from the form to your model using clever reflection.
What you are doing is kind of works and it's a great way to learn. So don't give up. Refactor, see whether you can pass a single object and work with that.
Good luck
A simple controller action that is posted to which takes a model used by the view's form isn't being bound to the form fields when running under Mono 2.10.1. Under MS.NET the same code executes as expected with the model populated with the corresponding form values.
The controller action is defined as:
[HttpPost]
public ActionResult Login(LoginModel login, string returnUrl)
{
The first parameter login is null when the form is submitted on Mono, and fully populated with the login form fields under MS.NET.
The form fields are accessible via the Request.Form collection (ie Request.Form["UserName"]) under Mono, so it seems to just be the binding that isn't working.
This used to be an MVC2 app - anyone experienced something similar?
I tracked this down to a custom data annotations model validation provider that we register to handle our own way of localizing error messages such as Required and Display Name on model properties.
Commenting out the following line:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(LocalizedRequiredAttribute), typeof(RequiredAttributeAdapter));
From global asax fixes the issue, and the custom model validator still works - looks like it was a hang over from MVC2 days.
Let's say I have a controller action defined as:
public ActionResult(MyModel model, string someParameter)
{
// do stuff
}
I have a custom model binder for the MyModel type, and there is a form field called "SomeParameter" in the view that is not bound to the model. How does ASP.NET MVC know to pass the value of Request.Form["SomeParameter"] as the value for the "someParameter" argument to the action?
ASP.NET uses reflection to determine the correct method to invoke and to built up the parameters to pass. It does so based on the FormCollection array. Basically it will see model.* Keysin there and a FormCollection["someParameter"] it will first try Action(model,someParameter) then Action(model) and then Action(). Since it finds an Action with a model and someParameter arguments it will then try to convert them into the arguments types.
However by default it does so blindly which introduces some security risks, this blog post goes into greater detail on this.
If anyone can post up a link which in greater detail describes how ModelBinding is done under the hood that would be great.
Because the default model binder will be used for someParameter unless you specify otherwise. And the default model binder does exactly what you describe.
Phil Haack has a post on How a Method becomes an Action which explains just how this resolution happens.
Sounds like you need a model binder. These allow you to define how form data is bound to a model parameter. You can read more about them at the following:
ASP.NET MVC Preview 5 and Form Posting Scenarios
How to use the ASP.NET MVC Modelbinder
One of the easiest way is having Html items on the page with same name as the input parameters in the action method.
EX) In the View we have:
<input name="refNo" type="text">
Then in the Action method:
public ActionResult getOrders(string refNo)
So, it simply bind the value of "refNo" to the input parameter of the "getOrders" action.