I have a queryparameter named "from" (a from date)
and also a input which binds to a property named From
In my ViewModel contructor i set the From property to a date...
This works if the query parameter name and the property name are different, but if they are same MVC3 with some magic takes whatever value there are in the query param and binds against that, it does not care what value are in the From property.. Why? this atuomagic is so wrong on so many levels! How do I disable it?
edit: It doesnt matter what value the Property gets, if a querystring exists with the same id as the input MVC automatic takes that value and assign it to the input element
You need to call
ModelState.Clear();
Before returning from your controller action.
The issue is that the ModelState has the value from the query string, and that takes precedence over the value in your model when binding occurs.
Whether this is a bug or a feature depends on your point of view... http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx
MVC works by convention, and binds values to the model by names. To understand what is happening, I suggest you read this blog article from Phil Haack: What’s the Difference Between a Value Provider and Model Binder?
It is bad practice to have two unrelated elements with identical names in the same request, as a name collision is very likely to cause unexpected problems. Best practice is to rename one of these elements so that you eliminate the name collision.
Related
Im using Magnolia RenderingModel in combination with Freemarker.
I have URLs like the following:
http://anyPath/context?productTypes=XXXXX&productTypes=YYYYY
my rendering model class looks like:
class MyModel extends RenderingModelImpl {
...
private String[] productTypes;
...
}
However the mentioned array contains only the first value, but not the second.
I checked the behaviour of template directives like ctx.getParameters(). This shows the same behaviour, I get only the first value returned. But if im using ctx.getParameterValues(paramName), it returns both values.
This leads me to following questions:
How would I go, if I want to lookup how the request parameters are mapped into the rendering model, or better:
How can i change the behaviour of that ?
Can anyone acknowledge, that this behaviour is wrong ?
It used to be mentioned in documentation and I believe it still is - if you use .getParameters() you get only first value for multivalue parameter. If you want to get all the values, you need to use .getParameterValues(String param).
From what I understand reasons for that were backward compatibility.
As for changing the behavior, you would need to write your own renderer (e.g. by extending default FreemarkerRenderer and override info.magnolia.rendering.renderer.AbstractRenderer.newModel(Class<T>, Node, RenderableDefinition, RenderingModel<?>) method which instantiates and populates the model class.
Alternatively you can provide fix for above set population method and submit it to Magnolia as a patch. While the .getParameters() behavior is iirc on purpose, the model param population might not be, so you have high chance of getting that changed.
would it be considered a valid implementation if I do not use the model for certain parameters? For example a webform posting values directly to the controller which then passes them to another class. Is it necessary to make sure that all the fields in the webform are also referenced/stored in the model?
I consider it a valid implementation, but suggest that you do this only if the parameters you want to exclude from the Model are absolutely NOT going to be used by the View (other than for confirmation of data entry in your webform), AND there is no need for the parameters to be referenced again once handled by the Controller.
Yes, it would work, strictly speaking.
However, you probably want to use the model. You don't want to create a new variable every time you run the view, which would happen if you use the controller.
I would consider it valid implementation if you decided not to use the model for certain parameters. I believe there are instances where certain fields may not relate directly to the model in question therefore giving valid reason to break those fields/parameters off from the model.
I am learning MVC, and in ASP.Net MVC 3, what is the ModelState class ? I have looked on Google and MSDN, but I can't seem to get a clear understanding of it's purpose. Can anyone help?
Take a look at http://www.gxclarke.org/2010/05/consumption-of-data-in-mvc2-views.html under the ViewData.ModelState section.
The ModelState property is a dictionary object that tracks HTTP values submitted to the server. In addition to storing the name and value of each field, it also tracks associated validation errors. Although its name may suggest otherwise, ModelState isn’t Model-aware. It doesn’t understand what a "Product" is. It simply contains a collection of items with names such as "ProductName" and "UnitPrice". It is the responsibility of other objects—ModelBinders, ViewResult, and the strongly-typed View—to map and interpret ModelState values as Model properties
The ModelState Class in MVC is a class which contains the collection that has the key and values of the data submitted to server in the Post method.When MVC comes across the post it takes all the parameters in the post request and puts them in the instance of a ModelStateDictionary. Whenever the ModelState is active in server,the properties of the model are validated according to the validation attributes that are associated with them. And if any of the property is invalid it will be added to the error list. And the property ModelState.IsValid will be set to false. You can use this later on your code to check if everything is correct.
Refer this link for further information.
I am trying to understand what BeanPropertyBindingResult does in the following code. Unfortunately, the javadoc is quite useless.
Please take a look at the following code:
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(item, "item");
validator.validate(item, errors);
My questions are:
As far as I can see, BeanPropertyBindingResult is basically some kind of a Map that can contain key/value pairs of (field name, error text). Is this correct, or is the truth more complicated?
When I create a new BeanPropertyBindingResult, why do I need to provide it (as the constructor's first parameter) with the object I am going to validate? As far as I can see, in the second line above, validator.validate(item, errors); the validator gets the object anyway.. so why doing it twice?
The javadoc says about the constructor's second parameter:
objectName - the name of the target object
yes, but why do I need that name? What am I supposed/able to do with it...?
1) Yes, that is my understanding too, even if it is technically a list. -- The most importent part is List<ObjectError> errors defined in the superclass AbstractBindingResult.
2) Because it is demanded by the BindingResult Interface. -- I know this is not a good answer, but If this interfaces requires that method, then ther is no otherway to implement it BTW: I think I have seen some example before where the Autor used null for that field, but I am not 100% if it works correct, but most of the code seams to be able to handle the null value.
3) If you use that binding result for example in a jsp to show the error messages for different input fields, then this must match the model attribute name.
Assume you have a command object with a field name. And a JSP page where the input filed is associated to myCommand.name. Then you need the name myCommand as some kind of prefix for the binding errors. -- It is hard to explain, I hope you understand what I mean
How do you get the object parameters, which action method was called with at run-time, to accomplish something to the effect of the following
public ActionResult Index(Int32? x, Int32? y, DateTime? z, NumberStyles n) {
this.RouteData.Values["x"] = x
this.RouteData.Values["y"] = y
this.RouteData.Values["z"] = z
this.RouteData.Values["n"] = n
return View();
}
It seems like it should be a possible to the names and values of each parameter without this kind of tedious code.
Sometimes you can get the parameters which the action method was called with, by looking in RouteData, but this isn't always the case, particularly if the action method was invoked with an ajax request, the parameters may not show up in the RouteData, and instead show up in the Request Params.
What I'm looking for, is a generic way to get each parameter that is defined in the action method signature at run-time, and gets the parameter's actual object, run-time value, not just a string. Further more, it should work no matter how the action method was invoked, whether it may be the result of ChildActionExtensions.Action or an ajax callback.
RouteData and Request Params don't seem to have what I'm looking for.
Your code sample is setting values back into the RouteData collection. Are you trying to pass parameters to your view using the RouteData collection? That's not what it exists for, you might consider using ViewBag instead.
Or, create a POCO which contains all your properties and let the data binder do all the work (so use #model YourType in your view and pass a single argument to your view. The default model binder will map the individual argument values for you).
As far as the input value collections are concerned, there's a good reason why the value is not to be found consistently in the collections you've mentioned.
Perhaps the trick here is to clarify what's going on prior to your action being invoked. The arguments to your action method can come from more than one source. For example, it may come from:
The URL Path
The URL query string (eg: in a GET, the parameters after the question mark ?)
POSTed form data
Explicit arguments from another action
In your code sample above, the RouteData collection will only contain the value of "x" if your route has a matching parameter name.
For example: "{controller}/{action}/{x}". (this is a custom route pulling "x" from the path)
Failing that, the values will be resolved using the default model binder and will be pulled from either the query string parameters or POST data as the case may be.
The route value will take precedence. So if the above custom route was applied, the following URL:
http://www.example.com/Something/Index/1?x=2
would invoke your action with x=1. The 1 would then be found in the RouteData as pulled from the URL path and the x=2 found in the Request.QueryString would be ignored.
If you are concerned with how x got its value, then you must take into account all of the above so you know where to look. There is also the question of which route is applied to the request, but that's another topic altogether.
All the input came across the wire as text.. it was the model binder that examined your action signature and converted to the types you specified (wherever that is possible).
So, I don't think what you are asking for exists even conceptually in this setting.