ASP.NET MVC model binding and action parameters - asp.net

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.

Related

How can I transform posted XML to a POCO in an MVC action?

I have the following method signature for an action on an MVC controller:
public ActionResult DoSomething(int id, string anotherParameter, IEnumerable<StronglyTypedThing> data)
{
}
This method is called by an AJAX Request (in this instance I'm using ExtJS, but that should have little/no bearing on this I imagine!) which passes up, for example:
id: 1,
anotherParameter: 'cake',
data: '<stronglyTypedThings>
<stronglyTypedThing>
<id>1</id>
<anotherProperty>Smith, John></anotherProperty>
</stronglyTypedThing>
<stronglyTypedThing>
<id>2</id>
<anotherProperty>Doe, Jane></anotherProperty>
</stronglyTypedThing>
</stronglyTypedThings>'
Currently the method signature I've shown above is not what I have, instead the final parameter is defined as string data and I have what is effectively boilerplate code which transforms the XML string into an IEnumerable<StronglyTypedThing>.
Is there a way to have (either by virtue of something baked into MVC, or by extending it) MVC deal with the grunt-work for me so I don't have the boilerplate code present in my action method?
You can create a custom model binder.
This link will have an example of custom xml binder: http://lostechies.com/jimmybogard/2011/06/24/model-binding-xml-in-asp-net-mvc-3/
You might want to look into a custom ValueProviderFactory.
A custom XmlValueProviderFactory will parse the incoming xml string and construct an intermediate dictionary. (which MVC uses to model bind)
Based on your need, you could parse the whole XML/or a part of it, to construct the dictionary equivalent of your Model object. Once there, MVC will take care of creating the Model for you using Model Binding. Also, value providers have the additional benefit of input validation which custom model binders don't have.
Please see following help links to see a JSON & XML Value Provider factory.
i think the JSON Value provider is now in built, but not the XML one. not sure.
http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx/
http://www.nogginbox.co.uk/Media/files/XmlValueProviderFactory.txt

ASP.Net , data validation should be in the controller, not the model, contrary to this tutorial example?

I am following ASP.NET MVC Music Store Tutorial by Jon Galloway Microsoft from http://mvcmusicstore.codeplex.com
While setting up this fictitious music store , we have Album.cs as the model with these lines of code
public class Album
{
[Required(ErrorMessage = "An Album Title is required")]
[StringLength(160)]
public string Title { get; set; }
//.......More code follows
What I find confusing is, why is the validation being done here by the Required attribute in the model, instead of the controller? Isn't the controller supposed to do the validation? or is that standard practice to do the validation in the model...suppposedly the tutorial is from microsoft?
Thank you
What I find confusing is, why is the validation being done here by the
Required attribute in the model, instead of the controller
Actually that's the domain model and it should have domain validation on it in order to ensure that it will stay consistent. On the other hand you should have a view model being exposed to the views on which perform view specific validation. And if this domain model will never be reused outside of this application you could rely only on the view model validation.
For example you will see many wrong examples putting view specific data annotation attributes on the domain models such as [DisplayFormat] and [Display]. All those examples are an illustration of bad design in which the domain models are used as view models.
You are using DataAnnotations in the Model that states that the Title field must be filled in before being posted back to the server. In the controller you can also check if ModelState.IsValid however adding the DataAnnotations at the Model level is the correct way to implement data validation.
we generally use Microsoft enterprise library's validation block to validate in the controller. Which enable us to add or remove validations
easily by modifying config file.

In ASP.NET MVC, Data exchange between Model and View is possible?

Is there a option to pass data between Model and view in ASP.NET. If it can be accomplished how? This was asked in an interview !!!
Yes... well, the view is either typed, which means the object that represents the model is directly accessible, or the controller returns a ViewBag with data or anything else the view needs to render. That's the whole point of the model-view part of the pattern.
The whole point of MVC is that the data(Model) should be shown to user (View) by use of Controller. Even if the view is typed, your still need the model to bind to it. Even to create a ViewBag, you need the controller action to fill it...

asp.net mvc3 / razor view best practices

I am using in my views (asp mvc3/razor cshtml) references to the Request object (eg, #Request.Params["Name"]). Do you think this is a very bad practice? Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Best practice is to use a model class. An instance of the model class is created or updated in your controller. Then the controller displays a strongly-typed view.
So I'd avoid direct access to the request from the view as well as the use of the view bag.
Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Yes. You will avoid runtime errors if "Name" does not exist.
The IDE will not warn you of the NullReferenceException about to be thrown with the following code.
#Request.Params["Fake"].ToString()
Of course, you'll have to be careful about ViewBag.Fake being null as well.
I like to use the viewbag to store things not related to the model, for example if I have a dropdown containing locations. I like to store only the id of the selected location on the model and the locations in the viewbag, since is not needed to create a contact. I think that's the purpose of the viewbag.
For me the model is a bag or properties used in business operations, for example if I have a customer creation view using a NewCustomerModel, I don't wanna pollute my model with things like a IList<CustomerType> AND a SelectedCustomerTypeId property. I just want the second since is the one imma use to create the customer.

Asp.net mvc 2 model binders what's behind scene

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.

Resources