Spring MVC url parameters format - spring-mvc

In my web application, I am trying to make an URL accesible with this format:
http://host/admin/users/edit/{id}
http://host/admin/users/edit/20 -> 20 represents the id param
I am trying with #RequestMapping like this
#Override
#RequestMapping(path = { "/admin/users/edit/{id}" }, method = RequestMethod.GET, params = { "id" })
public ModelAndView editUserInfo(#RequestParam(value = "id", required = true) Long id) {
...
}
I don't want use the url?param=value format if it's possible without config friendly urls.
Thanks in advance.

In order to do what you want yo have to write the following:
#Override
#RequestMapping(path = { "/admin/users/edit/{id}" }, method = RequestMethod.GET)
public ModelAndView editUserInfo(#PathVariable("id") Long id) {
...
}
PathVariable is for parameter variables, RequestVariable is for request params
Angelo

Related

how to Share model object in #RequestMapping methods in spring mvc without using session?

I am using Spring to create and download Excel sheet I want to add some variable in model in requestiong mapping method so that I can use in other request maping method
#RequestMapping("/contentUploadDetails/{content_type}/{date}")
public ModelAndView contentUpload(
#PathVariable(value = "content_type") String content_type,
#PathVariable(value = "date") String date) {
List<CountAndValue> ls = contentCountImp
.getuploadedContentCountDatewise(content_type, date);
model.addObject("CountAndValue", ls);
return model;
}
As you can see in above
model.addObject("CountAndValue", ls);
I want to use this model value in my other requestMapping method
#RequestMapping(value = "/ContentUploadExport", method = RequestMethod.GET)
public ModelAndView getExcel() {
return new ModelAndView("CountAndValueExcel", "CountAndValue", CountAndValue);
}
how can I use CountAndValueExcel model object that is set by first method in second method with using session? Can I send model object(which contains list of class object) back from view to controller?
You can save an object into a session:
#RequestMapping("/contentUploadDetails/{content_type}/{date}")
public ModelAndView contentUpload(HttpServletRequest request,
#PathVariable(value = "content_type") String content_type,
#PathVariable(value = "date") String date) {
List<CountAndValue> ls = contentCountImp
.getuploadedContentCountDatewise(content_type, date);
model.addObject("CountAndValue", ls);
request.getSesion().setAttribute("CountAndValue", ls);
return model;
}
And then you retrieve it like this:
#RequestMapping(value = "/ContentUploadExport", method = RequestMethod.GET)
public ModelAndView getExcel(HttpServletRequest request) {
List<CountAndValue> CountAndValue = (List<CountAndValue>) request.getSession().getAttribute("CountAndValue");
return new ModelAndView("CountAndValueExcel", "CountAndValue", CountAndValue);
}
Wrote it from my head, not tested.

why redirect not work in springmvc

I want to redirect after a upload, and want to redirect "files" page. but after submit successfully, the url in browser doesn't redirect, I also use firebug to check if there is any redirect, but not happen.
I change the "redirect:/files" to "redirect:/files.jsp" also not help.
is there any mistake?
Here is my code:
#Controller
#RequestMapping({ "/files", "/files/" })
public class FileAdminController {
#RequestMapping(value = { "/upload/index", "/upload", "/upload/" }, method = RequestMethod.GET)
public String showUplaod() {
return "upload";
}
#RequestMapping(value = { "/index", "/index/", "/" }, method = RequestMethod.GET)
public String showFilePage() {
return "files";
}
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public #ResponseBody String handleFileUpload(
#RequestParam("jarName") String jarName,
#RequestParam("manifestName") String manifestName,
#RequestParam("files") MultipartFile file) {
try {
File file1 = new File("c:/uploads/");
file1.getParentFile().mkdirs();
file1.createNewFile();
BufferedOutputStream stream = new
BufferedOutputStream(
new FileOutputStream(file1));
stream.write(bytes);
stream.close();
return "redirect:/files";
} catch (Exception e) {
return "You failed to upload " + jarName + " => " + e.getMessage();
}
}
}
redirect: is a view name which gets resolved by the UrlBasedViewResolver. But with #ResponseBody you tell spring that this controller is not returning a view name. I.e. you will have to take care about the redirect by yourself, by injecting the HttpServletResponse.

redirect to another url list of objects

I've got this method in MVC controller
public String save(
#RequestParam("id") Long id,
#RequestParam(value = "book", required = false) List<Long> books,
#RequestParam(value = "bookNow", required = false) List<Long> booksNow) {
if (booksNow != null)
return "redirect:/saveNow.html?id=" + id + "&bookNow=" + booksNow;
But the problem is that I want to redirect to another method my list of objects booksNow if it is not null.
#RequestMapping(value = "/saveNow.html", method = RequestMethod.GET)
public String saveNow(
#RequestParam("id") Long id,
#RequestParam(value = "bookNow", required = true) List<Long> booksNow) {
But I've got an error
The request sent by the client was syntactically incorrect.
What is the proper way to redirect list of objects?
"&bookNow=" + booksNow does not make sense.
booksNow will just print some java object something like List#1e23
You need to loop through the list so that your URL looks like so:
"redirect:/saveNow.html?id=123&bookNow=234&bookNow=235&bookNow=236

How to get POST data in WebAPI?

I'm sending a request to server in the following form:
http://localhost:12345/api/controller/par1/par2
The request is correctly resolved to a method like:
[HttpPost]
public void object Post(string par1, string par2)
However, I pass additional data through the request content. How can I retrieve these data?
For the sake of example, let's say, that the request is sent from the form:
<form action="http://localhost:12345/api/controller/par1/par2" method="post">
<input type="hidden" name="data" value="value" />
<input type="submit" name="submit" value="Submit" />
</form>
From answer in this question:
How to get Json Post Values with asp.net webapi
Autoparse using parameter binding; note that the dynamic is made up of JToken, hence the .Value accessor.
public void Post([FromBody]dynamic value) {
var x = value.var1.Value; // JToken
}
Read just like Request.RequestUri.ParseQueryString()[key]
public async Task Post() {
dynamic obj = await Request.Content.ReadAsAsync<JObject>();
var y = obj.var1;
}
Same as #2, just not asynchronously (?) so you can use it in a helper method
private T GetPostParam<T>(string key) {
var p = Request.Content.ReadAsAsync<JObject>();
return (T)Convert.ChangeType(p.Result[key], typeof(T)); // example conversion, could be null...
}
Caveat -- expects media-type application/json in order to trigger JsonMediaTypeFormatter handling.
After spending a good bit of time today trying to wrap my brain around the (significant but powerful) paradigm shift between old ways of processing web form data and how it is done with WebAPI, I thought I'd add my 2 cents to this discussion.
What I wanted to do (which is pretty common for web form processing of a POST) is to be able to grab any of the form values I want, in any order. Say like you can do if you have your data in a System.Collections.Specialized.NameValueCollection. But turns out, in WebAPI, the data from a POST comes back at you as a stream. So you can't directly do that.
But there is a cool little class named FormDataCollection (in System.Net.Http.Formatting) and what it will let you do is iterate through your collection once.
So I wrote a simple utility method that will run through the FormDataCollection once and stick all the values into a NameValueCollection. Once this is done, you can jump all around the data to your hearts content.
So in my ApiController derived class, I have a post method like this:
public void Post(FormDataCollection formData)
{
NameValueCollection valueMap = WebAPIUtils.Convert(formData);
... my code that uses the data in the NameValueCollection
}
The Convert method in my static WebAPIUtils class looks like this:
/// <summary>
/// Copy the values contained in the given FormDataCollection into
/// a NameValueCollection instance.
/// </summary>
/// <param name="formDataCollection">The FormDataCollection instance. (required, but can be empty)</param>
/// <returns>The NameValueCollection. Never returned null, but may be empty.</returns>
public static NameValueCollection Convert(FormDataCollection formDataCollection)
{
Validate.IsNotNull("formDataCollection", formDataCollection);
IEnumerator<KeyValuePair<string, string>> pairs = formDataCollection.GetEnumerator();
NameValueCollection collection = new NameValueCollection();
while (pairs.MoveNext())
{
KeyValuePair<string, string> pair = pairs.Current;
collection.Add(pair.Key, pair.Value);
}
return collection;
}
Hope this helps!
I had a problem with sending a request with multiple parameters.
I've solved it by sending a class, with the old parameters as properties.
<form action="http://localhost:12345/api/controller/method" method="post">
<input type="hidden" name="name1" value="value1" />
<input type="hidden" name="name2" value="value2" />
<input type="submit" name="submit" value="Submit" />
</form>
Model class:
public class Model {
public string Name1 { get; set; }
public string Name2 { get; set; }
}
Controller:
public void method(Model m) {
string name = m.Name1;
}
It is hard to handle multiple parameters on the action directly. The better way to do it is to create a view model class. Then you have a single parameter but the parameter contains multiple data properties.
public class MyParameters
{
public string a { get; set; }
public string b { get; set; }
}
public MyController : ApiController
{
public HttpResponseMessage Get([FromUri] MyParameters parameters) { ... }
}
Then you go to:
http://localhost:12345/api/MyController?a=par1&b=par2
Reference: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
If you want to use "/par1/par2", you can register an asp routing rule. eg routeTemplate: "API/{controller}/{action}/{a}/{b}".
See http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
Try this.
public string Post(FormDataCollection form) {
string par1 = form.Get("par1");
// ...
}
It works for me with webapi 2
None of the answers here worked for me. Using FormDataCollection in the post method seems like the right answer but something about my post request was causing webapi to choke. eventually I made it work by including no parameters in the method call and just manually parsing out the form parameters like this.
public HttpResponseMessage FileUpload() {
System.Web.HttpRequest httpRequest = System.Web.HttpContext.Current.Request;
System.Collections.Specialized.NameValueCollection formData = httpRequest.Form;
int ID = Convert.ToInt32(formData["ID"]);
etc
I found for my use case this was much more useful, hopefully it helps someone else that spent time on this answer applying it
public IDictionary<string, object> GetBodyPropsList()
{
var contentType = Request.Content.Headers.ContentType.MediaType;
var requestParams = Request.Content.ReadAsStringAsync().Result;
if (contentType == "application/json")
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(requestParams);
}
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
Is there a way to handle form post data in a Web Api controller?
The normal approach in ASP.NET Web API is to represent the form as a model so the media type formatter deserializes it. Alternative is to define the actions's parameter as NameValueCollection:
public void Post(NameValueCollection formData)
{
var value = formData["key"];
}
ON WEB API.
[HttpGet]
[Route("api/Get_EXCUTA_PROCEDURE_IBESVNDACMVDD")]
public IHttpActionResult Get(int CodigoPuxada...)
{
string retornoErro = string.Empty;
try
{
//int codigoPuxada = entrada.CodigoPuxada;
SetKeyAtual(CodigoPuxada);
var repo = new ItemBroker_Dim_Canal_BookRepositorio(ConnectionString);
try
{
var dadosRetorno = repo.ExcuteProcedure_Busca_vbc_(CodigoPuxada,...); // method return object (dataset)
return Ok(dadosRetorno);
}
catch
{
throw;
}
}
catch (Exception ex)
{
retornoErro = ex.Message;
if (ex.InnerException != null)
retornoErro = ex.InnerException.ToString();
}
return Ok(retornoErro);
}
Other projet invoke web api...
(USING RESTSHARP DLL)
RestClient clientHttpPost1 = null;
string dadosVbc123 = string.empty;
clientHttpPost1 = new RestSharp.RestClient($"{urlWebApiAvante}Get_EXCUTA_PROCEDURE_IBESVNDACMVDD?CodigoPuxada=...");
RestSharp.RestRequest request2 = new RestSharp.RestRequest(RestSharp.Method.GET);
request2.RequestFormat = RestSharp.DataFormat.Json;
request2.AddHeader("Content-Type", "application/json;charset=utf-8");
string strAux1 = string.Empty;
request2.Timeout = 180000;
RestSharp.IRestResponse response = clientHttpPost1.Execute(request2);
if ((response != null) && response.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
var dataObjects = response.Content.ToString().Trim();
dadosVbc123 = dataObjects.ToString().Replace("\t", "");
if (dadosVbc123.Trim() == "{\"IBESVNDACMVDD\":[]}")
dadosVbc123 = string.Empty;
}
...
}
// converting JSON to dataset
string val1 = dadosVbc123.Replace("{\"IBESVNDACMVDD\":", "").Replace("}]}", "}]");
DataTable dtVBC123 = (DataTable)Newtonsoft.Json.JsonConvert.DeserializeObject(val1, (typeof(DataTable)));

optional POST parameter in spring MVC?

I have the following code:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView editItem(String name, String description)
However, sometime description is not passed in (this is a simplified example than the real one), and i would like to make description optional, perhaps by filling in a default value if none is passed in.
Anyone have any idea how to do that?
thanks a lot!
Jason
If you are using Spring MVC 3.0 or higher then just set defaultValue parameter of #RequestParam:
public ModelAndView editItem(#RequestParam(value = "description", defaultValue = "new value") String description)
In Spring MVC 2.5, I suggest to mark value as required = false and check their value against null manually:
public ModelAndView editItem(#RequestParam(value = "description", required = false) String description) {
if (description == null) {
description = "new value";
}
...
}
See also corresponding documentation about #RequestParam annotation.
UPDATE for JDK 8 & Spring 4.1+: now you could use java.util.Optional like this:
public ModelAndView editItem(#RequestParam("description") Optional<String> description) {
item.setDescription(description.getOrElse("default value"));
// or only if it's present:
description.ifPresent(value -> item.setDescription(description));
...
}
Instead of using #RequestParam for the optional parameters, take a parameter of type org.springframework.web.context.request.WebRequest. For example,
#RequestMapping(method = RequestMethod.POST)
public ModelAndView editItem(
#RequestParam("name")String name,
org.springframework.web.context.request.WebRequest webRequest)
{
String description = webRequest.getParameter("description");
if (description != null)
{
// optional parameter is present
}
else
{
// optional parameter is not there.
}
}
Note: See below (defaultValue and required) for a way to solve this without using a WebRequest parameter.

Resources