Bind int? property to null if value is a non-numeric, non-empty string - asp.net-web-api

I have a viewmodel with a property of type int?.
If the send value is an integer or is empty it works fine. When the value is a string an exception is thrown 'Could not convert string to integer'
Would it be possible to change the behavior of the binding that instead of throwing a error it would bind the null value ?
I've created a modelbinder class for typeof(int?), but the ModeBind function doesn't get called. I guess the validation happening before the model binding.
Any ideas ?

When you say you have a view model are you referring to the parameter that is being passed to your action method? E.g.
public Foo Bar(MyViewModel vm)
If so then your modelbinder should be of type MyViewModel. You can additionally use a ValueProvider to extract an int from a random string to override the default value provider functionality.

Related

Springboot - validating enum

I have an enum that I am validating like this:
#EnumValueValidator(enumClass = MyEnum.class)
String value
It's a string field, but it is validated against a list of enums. However, once the validation is completed, and I know the field is valid, I want the getter to return the enum.
So I added a getter like this
public MyEnum getValue()
return MyEnum.valueOf(value)
The problem is if the value is not one of the valid enum types, the validation doesn't issue the proper error message, because it gets an exception calling the getter on the invalid type. I don't want the validation to use the getter. It should use the field directly. The getter() should only be used by explicit calls in the business logic. Is there a way to do this?

How does Spring bind form values into class variables?

If I use a form:form object in Spring, I can use the commandName in order to let Spring inject the class variable values.
However, I wonder, how does the controller catch this value?
#RequestMapping(method = RequestMethod.POST, value = "/form")
public String postForm(#ModelAttribute("item") Item item, ModelMap model)
{
return "result";
}
In the above code, the Item is injected. However, even changing the name of this variable (or removing the modelattribute), doesn't affect that this variable is injected with the form values.
Will spring just inject the values in the first model class found, from the form? How does Spring know that it has to inject the form into the Item item parameter?
At first I thought the variable in the controller (POST) should have the name of commandName of the form, but it does work with other names as well, strangely enough.
There is a dedicated section in the Spring Documentation describing the usage of #ModelAttribute on method arguments.
This process is known as Data Binding on submit and is following some conventions:
If #ModelAttribute is explicitely declared with a name on an argument (your case). In this case the submitted data of the form are copied over automatically under this name. You can check yourself that it is already there in your ModelMap model by invoking/inspecting model.get("item").
If there is no #ModelAttribute argument annotation at all, then the attribute name is assumed from the type essentially in your case type Item converts to attribute name item (camelCase notation) that is created for you holding a new Item with the form data-bind'ed fields. That is also there in the ModelMap (same check as above: model.get("item"))
Key point to realise is in all these cases DataBinding occurs before hitting your Post form RequestMapping.

MVC - Passing a Type as an action parameter

Can I pass a parameter of Type to the Action method in MVC via a HTML.ActionLink().
e.g.
public ActionResult Get(Type containerType, string name)
{
throw new NotImplementedException("vkag");
}
<%=Html.ActionLink(flow.Source.Name, "Get", new { containerType = typeof(Worksheet), name = flow.Source.Name})%>
For some reason the type is always null. I also can't pass back a base type to allow for subtypes to be passed in it's place.
I don't know whether this is a limitation of the HTML ActionLink Helper or MVC.
I can't pass an Interface, I specify a base type parameter and use sub type as an argument in the place of a base type parameter, and I can't seem to pass a Type back. I'm pretty stuck here.
Is there another HTML Helper that will help?
Can I do anything with model binding?
Can I modify the state of my model during an ActionLink invocation before control is passed to my action method?
Kind a stuck here. Any help would be gratefully appreciated.
Thanks
The types you can pass into Routes must be passable via a URL if you think about it.
You cannot pass a Type as it would have to be serialised. Why not pass the containerType as a string and convert it back to a Type in the action?

IValidatableObject and Nullable value types

I have a struct that implements IValidatableObject, which I use for properties on a view model. The validation works fine with non-nullable properties, but if add a property of type Nullable<MyStruct> the IValidatableObject.Validate method is never called for that property, even if it has a value.
Is there any way that I trigger the validation on my nullable properties too, or is IValidatableObject not intended to be used with value types?
Thanks
Additional information:
I wanted to be able to specify units when entering data in my form, e.g. 10m, 100km, 1cm etc. I also wanted to validate that the entered data was within range and of a correct format. My struct converts the string with potentially different units (100cm/100m/1km) into a decimal property which always has the same unit (1/100/1000) and vice-versa.
I used IValidatableObject for validation because the validation will always be the same for any instance of MyStruct - I didn't want to add an attribute each time it is used.
My model would look something like this:
public class MyModel
{
public MyStruct Ab {get; set;}
public MyStruct? Cd {get; set;}
}
My view is a strongly typed view using the model, which renders my struct as a text box using a display template. When the form is posted, I have a custom model binder to convert the entered string back to my struct.
My controller action looks like:
public ActionResult MyAction(MyModel model)
{
//do stuff
}
The model is bound ok for properties of type MyStruct and Nullable<MyStruct>.
It seems that this is not possible.
I dug into the MVC source. In System.Web.Mvc.DataAnnotationsModelValidatorProvider there is the following code:
// Produce a validator if the type supports IValidatableObject
if (typeof(IValidatableObject).IsAssignableFrom(metadata.ModelType)) {
//stuff
}
According to this rejected bug report, Nullable<T> cannot be assigned to an interface that T implements:
"In short, a "DateTime?" value can be unboxed to a DateTime or an IFormattable value. But it cannot be assigned to a DateTime or IFormattable location."
Thus no validators are returned.
Looks like I will have to do this another way.

MVC Ajax Int32 error

Hi when I try to do an Ajax post to my controller I keep getting this message:
The parameters dictionary contains a
null entry for parameter 'id' of
non-nullable type 'System.Int32' for
method 'System.Web.Mvc.JsonResult
GetContactsByDepartment(Int32)' in
'Intranet.Controllers.MyController'.
An optional parameter must be a
reference type, a nullable type, or be
declared as an optional parameter.
The method head looks like this: public JsonResult GetContactsByDepartment(int id)
What am I missing? I have ensured that the id is being passed through my Jquery ajax call.
Try to rename id to for example DepartmentID.
Probably an issue with your registered routes.

Resources