Unwanted comma-splitting when binding string (from inputText) to List<String> in Spring - spring

I'm working with Spring Web, my JSP has a inputText that I bind to List because I could set many inputText.
The problem is that if I have a inputText with something like "yyyyMMdd hh:mm:ss,SSS". I got a list with two elements: "yyyyMMdd hh:mm:ss" and "SSS", when I would like to get just one with all the text. Why?

This is the default behavior of how the binding in Spring works. if you have just one input, and have a value containing commas for that input, Spring will convert this into a list of values for that attribute.
Suppose you have:
<input type="hidden" name="fields" value="Hi, SO">
The mapping in the DTO for the attribute List<String> fields will be set to ["Hi", "SO"].
To overcome this, you can have an extra empty input for that field just before the ones containing the actual values.
<input type="hidden" name="fields" value="">
This will set the values in fields to ["", "Hi, SO"] and you can handle the empty string in your logic accordingly.

Related

How to bind List<String> values to <select> tag in jsp without comma separated values?

First things first-
My Class-
public class StakeHolder{
private String stakeHolderName;
private Date startDate;
private Date endDate;
}
My Controller Request Mapping-
#RequestMapping(value = { "/add" }, method = RequestMethod.GET)
public String addGet(Model model) {
StakeHolder stakeholderObj = new StakeHolder();
//To be selected in drop-down for 'stakeHolderName' attribute of StakeHolder
List<String> organizationList = stakeholderObjService
.getApplicantOrganizations();
model.addAttribute("orgList", organizationList);
model.addAttribute(STAKEHOLDER_OBJ_STRING, stakeholderObj);
return STAKEHOLDER_ADD_VIEW;
}
My JSP code for drop-down -
<form:select path="stakeHolderName" name="stakeHolderSelect"
id="stakeHolderSelect" style="width:220px;" items="${orgList}" >
When i submit the form with any value from drop down I have a server-side validator to verify all the values of attributes. When there is an error in date format it returns to the same page. When the data is correct and submitted again the dropdown value gets binded to my class's 'stakeHolderName' attribute in comma separated format which is not required.
its something like
StakeHolder [stakeHolderName=,TestOrg1,TestOrg1,TestOrg1, startDate=null, endDate=null]
The original values keeps getting appended to the name each and every time it get submitted with a preceding comma. How can I get the value "TestOrg1" just once without any comma?
Appreciate the help.
try to change your drop down code to this in JSP
<form:select path="stakeHolderName">
<form:options items="${orgList}" />
</form:select>
thank you
Sorry for posting the solution so late.
The problem was found elsewhere. It was actually on the jsp. The select option had a prior radio button selection to it and on its click event i had to show a pre-filled input text box with default value for the same path variable. So when i submitted the form, it binded the value to the input text as comma separated values.
I couldn't find a solution for it through spring path variable. So i used normal html input boxes with different names and binded those values through init binder.

How to change textboxfor's input name when we are using multiple model in MVC3?

I'm using multiple model hence textboxfor's input name is different because of multiple model so parameters are always null.
I explain what I mean as you can see at below:
#Html.TextBoxFor(model => model.managers.person_name)
I have two tables which are "manager" and "mayor_assistance" and I call these models with my class. Everything is fine at this point. But when I used these models with the TextBoxFor input name is set " manager.person_name" but my table which name is manager has a person_name column hence my parameters are always null as you can see html tag at the below
<input id="managers_person_name" name="managers.person_name" type="text" value="">
Then I have to changed tex box for input name with "new" tag, I get the same result
#Html.TextBoxFor(model => model.managers.person_name,new { #name="person_name" })
So how can I change TextBoxFor input name?
Finally I have found the answer.I want to share my solution who be faced with my problem.
TextBoxFor or something like EditBoxFor etc.. their names and ids are set by properties on the Model.Because of this you get parameter always Null!
The solution is very simple just use TextBox and put your column name as string
<div class="editor-field ">
#Html.TextBox("person_name")
#Html.ValidationMessage("person_position")
</div>

MVC matching ModelState keys to ViewModel collection

Is it possible to match a ViewModel property to the matching ModelState.Key value when the ViewModel is a (has a) collection?
Example: To edit a collection of viewmodel items, I am using the extension found here.
That adds a GUID to the id of the fields on the page.
example:
class Pets
{
string animal;
string name;
}
For a list of Pets, the generated html source is like this:
<input name="Pets.index" autocomplete="off" value="3905b306-a9..." type="hidden">
<input value="CAT" id="Pets_3905b306-a9...__animal" name="Pets[3905b306-a9...].animal" type="hidden">
<input value="MR. PEPPERS" id="Pets_3905b306-a9...__name" name="Pets[3905b306-a9...].name" type="hidden">
<input name="Pets.index" autocomplete="off" value="23342306-b4..." type="hidden">
<input value="DOG" id="Pets_23342306-b4...__animal" name="Pets[23342306-b4...].animal" type="hidden">
<input value="BRUTICUS" id="Pets_23342306-b4...__name" name="Pets[23342306-b4...].name" type="hidden">
So when this gets bound on post, the ModelState gets loaded with all the form fields.
In ModelSTate.Keys, there is:
Pets[23342306-b4...].name
Pets[23342306-b4...].animal
Pets[3905b306-a9...].name
Pets[3905b306-a9...].animal
Everything good so far, but I am doing some business logic validation, things like, cant add new animal if one exists with the same name. In that case, I want to be able to highlight the input field that is in error.
So if my create function fails, it will return an error/key value pair like this:
{ error = "Duplicate Name", key="name" }
So I at least will now what property caused the problem.
But since my repository functions don't know about the view field ids, how can I match the key "name" to the appropriate ModelState key (in this case, either Pets[23342306-b4...].name or Pets[3905b306-a9...].name)?
If you used the built in functionality of MVC for displaying collections (Html.DisplayFor(m => m.Pets) or Html.EditorFor(m => m.Pets)) with appropriate display/editor template, MVC would render something like this:
Pets[0].name
Pets[0].animal
Pets[1].name
Pets[1].animal
This maps to IEnumerable<Pets> and you know that first item has index of 0, second item 1 etc.
So if the second item has an error, you can set error for the ModelState key "Pets[1].name" for example.
If you are using the Html.BeginCollectionItem extension method, like I was, I was able to get around this by not using the GUID. I need the dynamic add and delete, but I was always looking up known items, persons that have an ID, which I had in my editor. So instead of using the GUID, I just assign the ID (uniqueId) in the code below. I could then find the key because I knew it was Person[234232]. Of course if you are adding new items and not displaying selected items, it might not work for you.
public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName, string uniqueId)
{
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : uniqueId;
// autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex)));
return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
}

Model binding on POST with query string AND form parameters

What is the defined behavior for form binding in ASP.NET/MVC if you POST a form and its action has query parameters and you have form data?
For example:
<form action="my/action?foo=1" method="post">
<input type="hidden" name="bar" value="2">
</form>
If such a form is submitted should the controller get both foo and bar or only one of them?
The controller will get both values. The default model binder will try to find matches for the parameters from both the URI (either query string or route parameters) or the body (and forms data is supported out-of-the-box).
Note, you can see this is supported by Html.BeginForm helper, you do so through routeValues:
#Html.BeginForm("ActionName", "ControllerName", new { foo = "1" })
It essentially generates the same html as your form tag, but wanted to post for those who find this question and want to know how to pass additional values that are not part of the form using the BeginForm helper.
I think it should be able to get both. In this case, I would create a ViewModel that contains two string or int properties, one named 'foo' and the other named' bar' and have your ActionResult accept the ViewModel. You should see both values come in.

Posting an array of Guid pairs to an Action

As you can see here, I'm allowing a user to dynamically create a table of data, and storing the ids of the table in a hidden field (in the example it's a text area so you can see it, and the final solution will be Guid rather than integers).
My question is simply this: What data type should I use on the server/MVC action to take the data held in the textarea/hidden field?
At the moment I have a string, and am contemplating doing a load of .split()'ing and whatnot, but it doesn't feel right!
Ultimately I need some sort of IEnumerable<Guid, Guid> thing?!?! so I can do a foreach and get each pair of Ids.
I'm sure the answer will be simple, but I can't think of what to do.
Any help appreciated.
If your UI has multiple, like-named form fields, they will be submitted to your action method and bound properly to an array. We could use string[] for this case.
<form action="">
<input type="text" name="guids"/>
<input type="text" name="guids"/>
<input type="text" name="guids"/>
<input type="text" name="guids"/>
<input type="submit" value="Submit"/>
</form>
Then your controller could handle them like so:
public ActionResult MyAction(string[] guids)
{
guids.Count == 4 // if all four fields were filled in.
}
Note that if there is just a single guids value sent by the form, the string[] guids will still work - it will contain just a single item.
Finally, note that if no values are entered, the array value will be null, not an empty array.
You can actually bind to a list from your model, take a look at this post
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Resources