I had an url pattern like this:
http://xy.com/param1/value1/param2/value2/..../paramN/valueN
I would like to write a #RequestMapping in Spring colntroller, but I don't know how can I do if I don't know how many param and value will be.
Is there any way to get all params and values to collection?
Or can anybody helpme how to fix this?
Thanks
Why can't you use the standard way without #PathVariables at all? So url will be like
http://xy.com?param1=value1¶m2=value2&....¶mN=valueN
and your annotation as:
#RequestMapping("xyz1")
#ResponseBody
public String index(#RequestParam(required = false) String param1, #RequestParam(required = false) String param2,
#RequestParam(required = false) String paramN) {
return "Param1=" + param1 + ", Param2=" + param1 + ", ParamN=" + paramN;
}
#RequestMapping("xyz2")
#ResponseBody
public String index2(HttpServletRequest servletRequest) {
StringBuilder result = new StringBuilder();
for (Entry<String, String[]> entry : servletRequest.getParameterMap().entrySet()) {
result.append(entry.getKey());
result.append('=');
result.append(Arrays.toString(entry.getValue()));
result.append(", ");
}
return result.toString();
}
where #RequestParam is used when all the expected parameters are known and servletRequest.getParameterMap() is used if you really need to handle them dynamically.
Or you can go the hackish way with really optional #PathVariables that is described here.
I was use Spring ModelAttribute instead of
Related
I can find hundreds of examples of how to build an OData API, but i'm consuming an OData API.
At the moment we're doing something horrible like;
string filter = "FirstName eq '" + firstName + "' " +
"LastName eq '" + lastName + "'";
But i'm assuming there's a library I can use and do something like;
SomeType query = new SomeType();
query.AddFitler("FirstName", Comparison.Equals, firstName);
query.AddFilter("LastName", Comparison.Equals, lastName);
string filter = query.ToString();
Could you point me in the right direction please- thanks!
I think i've found the solution after half a day of searching Strong-typed Linq to construct OData query options
// url doesn't matter unless you will use data service to execute the call
var dsContext = new DataServiceContext(new Uri("http://stackoverflow"));
// need to pass in the controller into CreateQuery - could create an extension method to pluralize the type to not have to pass it in.
var query = dsContext.CreateQuery<Product>("/api/products").Where(p => p.Category == "Cars");
// ToString will output the url
var uri = new Uri(query.ToString());
// Grab just the path and query
var path = new Uri(uri.PathAndQuery, UriKind.RelativeOrAbsolute);
await client.GetAsync(path); // this will call the api not DataServiceContext
Just testing now!
EDIT this worked well- I ended up creating a little wrapper to DRY it up a bit;
public class SearchQueryBuilderService<T>
{
private DataServiceContext _context = new DataServiceContext(new Uri("https://tickett.net"));
public string Build(Expression<Func<T, bool>> predicate)
{
return _context.CreateQuery<T>("tel").Where(predicate).ToString().Replace("https://tickett.net/tel?$filter=", "");
}
}
So I can now call this from various "Api Repositories" like;
string searchString = new SearchQueryBuilderService<SomePoco>().Build(sp => sp.SomeProp == "SomeValue");
I'm trying to do something like this:
#GET("values")
Call<List<Values>> getResult(#Query("ids") List<String> ids);
My desired request is something like this:
server.com/values?ids=abc%2Cdef%2Cghi%2Cjkl
Actual request is this:
server.com/values?ids=abc&ids=def&ids=ghi&ids=jkl
How can I achieve the desired request?
Finally, figured this out. This was my approach to going this:
First, convert ArrayList into an encoded string:
String uriString = null;
try {
uriString = URLEncoder.encode(TextUtils.join(",", ids), "utf-8");
} catch (UnsupportedEncodingException e) {
// Catch the exception
}
And then do the following while making the retrofit call:
#GET("values")
Call<List<Values>> getResult(#Query(encode=true, value="ids") String ids);
Setting encode = true is extremely important, otherwise your % will be further encoded and you will never be able make the desired call.
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
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.
.Net's System.Web.HttpUtility class defines the following function to parse a query string into a NameValueCollection:
public static NameValueCollection ParseQueryString(string query);
Is there any function to do the reverse (i.e. to convert a NameValueCollection into a query string)?
System.Collections.Specialized.NameValueCollection does NOT support this, but a derived internal class System.Web.HttpValueCollection DOES (by overriding ToString()).
Unfortunately (being internal) you cannot instantiate this class directly, but one is returned by HttpUtility.ParseQueryString() (and you can call this with String.Empty, but not Null).
Once you have a HttpValueCollection, you can fill it from your original NameValueCollection by calling Add(), before finally calling ToString().
var nameValueCollection = new NameValueCollection {{"a","b"},{"c","d"}};
var httpValueCollection = System.Web.HttpUtility.ParseQueryString(String.Empty);
httpValueCollection.Add(nameValueCollection);
var qs = httpValueCollection.ToString();
nameValueCollection.ToString() = "System.Collections.Specialized.NameValueCollection"
httpValueCollection.ToString() = "a=b&c=d"
A NameValueCollection has an automatic ToString() method that will write all your elements out as a querystring automatically.
you don't need to write your own.
var querystringCollection = HttpUtility.ParseQueryString("test=value1&test=value2");
var output = querystringCollection.ToString();
output = "test=value1&test=value2"
I found that a combination of UriBuilder and HttpUtility classes meets my requirements to manipulate query parameters. The Uri class on its own is not enough, particularly as its Query property is read only.
var uriBuilder = new UriBuilder("http://example.com/something?param1=whatever");
var queryParameters = HttpUtility.ParseQueryString(uriBuilder.Query);
queryParameters.Add("param2", "whatever2");
queryParameters.Add("param3", "whatever2");
uriBuilder.Query = queryParameters.ToString();
var urlString = uriBuilder.Uri.ToString();
The above code results in the URL string: http://example.com/something?param1=whatever¶m2=whatever2¶m3=whatever2
Note that the ToString() goes via a Uri property, otherwise the output string would have an explicit port 80 in it.
It's nice to be able to do all this using framework classes and not have to write our own code.
I don't think there is a built in one, but here is an example of how to implement http://blog.leekelleher.com/2008/06/06/how-to-convert-namevaluecollection-to-a-query-string/
Here are 2 very useful functions that I use all the time:
private string GetQueryStringParameterValue(Uri url, string key)
{
return HttpUtility.ParseQueryString(url.Query.TrimStart('?'))[key];
}
private Uri SetQueryStringParameterValue(Uri url, string key, string value)
{
var parameters = HttpUtility.ParseQueryString(url.Query.TrimStart('?'));
parameters[key] = value;
var uriBuilder = new UriBuilder(url) { Query = parameters.ToString() };
return uriBuilder.Uri;
}