I am passing an object to an action method and that action method displays the view but it has all the proerties in the querystring and I do not want that (I have a long json string that cannot pass in url). How can I pass in a model object and not have it in the querystring? Also when you have a strong type view, Where does the object values for the Model store? Thanks for any help.
//This works fine when I am calling /controller/uploader
public ActionResult Uploader(Model model)
{
//logic
return View(model);
}
//But when I am on another method and want to call uploader it does pass the object but puts //all the data in a querystring
public void DoSomething(string val, string anotherval){
Model model = new Model();
Uploader(model);//This passes the object but when uploader page shows it has all the //model object properties in querystring and I do not want that.
return RedirectToAction("Uploader",model);//or this does the same thing
}
Try using the POST method on the html form:
<form action="/uploader" method="POST">
<!-- maybe some input elements? -->
<input type="submit" />
</form>
This will transfer the data as Form Encoded within the request body and keep the data out of the query string.
Related
I have a drop down box in my jsp with a search button. On the click of search button on the same jsp below this drop down and search button i am displaying a data table which took the selected value from the drop down and displays all the results matching the key.
Jsp:
<form:form action="/search" modelAttribute="myModel" method="post">
<form:select path="categorySearched">
<form:option option="0" label="--Select--">
<form:options items="${myModel.categoryList}" itemLabel="name" itemValue="id"/>
</form:select>
<button type="submit">Search</button>
</form:form>
<form:form action="/edit" modelAttribute="myModel" method="post">
<c:forEach var=""... -------------------------->>>>> data table displayed properly
</form:form>
Controller:
#RequestMapping(value = "/showSearchPage", method = RequestMethod.GET)
public String showSearch(#ModelAttribute("myModel") MyModel myModel){
//call from db to get list of category type objects
myModel.setCategoryList(categories);
return "SearchPage";
}
#RequestMapping(value = "/search", method = RequestMethod.POST)
public String searchGoals(#ModelAttribute("myModel") MyModel myModel) throws Exception {
System.out.println(goalModel.getCategoryList());------------>> null; want this to have all objects in the list
..................
return "SearchPage";
}
MyModel:
private List<Category> categoryList;
private String categorySearched;
Catgory:
private String id;
private String name;
As you can see on search i am returning "SearchPage" and displaying same page.
i want to re-populate drop down on Search without calling the db again. It is because i can change the search criteria again from different selection in drop down.
Please help me bind the category objects from drop down to the model. Everything else is working as expected. only when i click on search button and page reloads the drop down is not getting populated.
When you are processing a /search request, the list of all categories is nowhere : you do not want to fetch it from the db and it did not come from the request parameters. Because when you write :
#RequestMapping(value = "/search", method = RequestMethod.POST)
public String searchGoals(#ModelAttribute("myModel") MyModel myModel)
Spring creates a new MyModel and populates it with request parameters.
If the request is simple enough, the more straightforward solution would be to cache the getCategories(xxx) method at service level. That way, you can call it as many times you want without reloading it from db. EhCache for example integrates nicely in Spring. Advantage : you just write in your code that you want the date and the framework deals with the caching
An alternative is to use a #SessionAttribute. If you add
#SessionAttributes("myModel")
above you controller class declaration, you ask Spring to store the model attribute myModel in session and take it from there instead of re-creating a new one on each request. It should meet your requirement but has drawbacks : there is no simple and reliable way to purge the attribute from the request when it is no longer needed. It is up to you to decide whether you can waste some session memory for that or not, depending on the number of expected simultaneous sessions, the server memory, ...
I am new to spring-mvc and have a basic question.
I have a controller that reads the parameters that are sent in from a jsp and adds an object called userInfo to the ModelAndView and passes on to another jsp. The second jsp displays the vaious properites of the userInfo.
How do I send back the userInfo object to the controller?
<td><input type="hidden" name="userInfo" value="${requestScope.userInfo}"/></td>
I try to read the userInfo in the controller as follows:
request.getAttribute("userInfo")
However, this is null.
What is the best way for me to do this?
Thanks
HTML <form> <input> elements are sent as url-encoded parameters. You need to access them with HttpServletRequest#getParameter(String)
request.getParameter("userInfo");
Or use the #RequestParam annotation on a handler method parameter
#RequestMapping(...)
public String myHandler(#RequestParam("userInfo") String userInfo) {
...
}
Note however, that this won't send back the object, it will send back a String which is the toString() value of the object because that is what is given with ${requestScope.userInfo}.
Consider using session or flash attributes to have access to the same object in future requests.
What I want to do is to sent data from a view to another (just a name)
I've tried using the ViewBag but it losts all the data in the postback.
Find useful this example but:
How to pass data from razor view to controller in mvc3?
The data that I'm trying to send is in the index of a list of Stores and I got a link that sends you to the View that contain the images /StoresImages.
I got in the Stores view and in StoreImages index the following inputs:
<input type="text" name="StoreName"/>
and in StoreImagesController:
public ActionResult SaveName(string StoreName, FormCollection Collection){}
This is exactly as is in the example above but I'm getting the following error: not all code paths return a value.
What I'm missing??
You should return something from ActionResult:
[HttpPost]
public ActionResult SaveName(string StoreName, FormCollection Collection)
{
ViewBag.StoreName = StoreName;
return View("viewName");
}
Then you can use ViewBag.StoreName in "viewName" view;
I have a controller with the following:
#ModelAttribute("searchCriteria")
public abstract SearchableCommand searchCriteria();
#ModelAttribute("searchList")
public PaginatedListAdapter searchList() {
return new PaginatedListAdapter(defaultSortColumn, searchableService);
}
#RequestMapping
public String doSearch(
#ModelAttribute("searchCriteria") SearchableCommand searchableCommand,
Errors errors,
#RequestParam(value="sort", required=false) String sort,
#RequestParam(value="pageSize", required=false) Integer pageSize,
#RequestParam(value="dir", required=false) String dir,
#RequestParam(value="page", required=false) Integer page,
#ModelAttribute("searchList") PaginatedListAdapter searchList) {
//some logic here
};
And in my JSP I have the following for test purpose:
<form:form id="searchForm" commandName="searchCriteria">
<form:input path="searchCriteria[0].searchOperand"/>
<input id="submitButton" type="submit"/>
</form:form>
When submitting the form, I trace through my code and searchableCommand.getSearchCriteria[0] .setSearchOperand(...) is called correctly. However once this is done I recieve the exception:
org.springframework.beans.NullValueInNestedPathException: Invalid property 'searchCriteria[0]' of bean class [com.domain.web.command.PaginatedListAdapter]: Cannot access indexed value of property referenced in indexed property path 'searchCriteria[0]': returned null
This because it is also trying to call PaginatedListAdapter.getSearchCriteria[0] .setSearchOperand(...). Co-incidentally this class also has a method called getSearchCriteria, but regardless it makes no sense to me as to why spring is trying the bind the form post parameters to both #ModelAttribute arguments, when my form explicitly states commandName="searchCriteria for which only one #ModelAttribute has that name.
I'm writing an application with Spring framework and I have a question how to do a form validation with extra fields.
I'm new to this but as far as I understand to fill the form with form:form tag I set attribute with
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String register(Model model) {
model.addAttribute("tenant", new Tenant());
return "register";
}
Then create validator class and use it on POST request:
#RequestMapping(value = "/register", method = RequestMethod.POST)
public String registerPost(#ModelAttribute("tenant") Tenant tenant,
Model model,
BindingResult result) {
TenantValidator validator = new TenantValidator();
validator.validate(tenant, result);
if (result.hasErrors()) {
return "register";
}
tenantService.save(tenant);
return "redirect:accountOverview";
}
It works very well and I'm fascinated by how convenient this is!
The only problem is what do I do with extra fields?
For example I have "repeat password" field.
If I create extra fields without using tags and by using and validate them directly I would not be able to use:
<form:errors path="repeatPassword>
tag as 'repeatPassword' is not a member of form object.
The first solution that comes to mind is to create special form object TenantDTO that would hold those extra fields and on save just transfer the data to 'Tenant' (entity bean).
Is this a good approach? What are the best practices in this situation?
Thanks!
Leonty
You can still have these values in the form object. I guess you don't want to save these to the database. You can avoid that by using the annotation Transient (http://docs.oracle.com/javaee/5/api/javax/persistence/Transient.html). This will give a leverage for you to do the path mapping, having in the form object and do all the validation but still dont save in the database. hope it helps.