I have a request map which returns list from database in json. Is it possible if visitor enters the exact url in browser, the page will be empty?
#RequestMapping(value = "/pics/{profileId}", method = RequestMethod.GET, headers = "Accept=application/json")
#ResponseBody
public List<ProfilePic> getProfilePics(#PathVariable("profileId") BigInteger profileId) {
return practiceServices.getProfilePics(profileId);
}
if visitor enters the url http://localhost:8080/practiceProject/pics/10, the page will show the list, but I don't want visitors to see it. I want the browser to show an empty page. Is it possible?
If you just want a quick solution check a header that will be sent within your AJAX requests. If this is not available just return null or whatever. You can also return a ResponseEntity<List<ProfilePic>> and in case the header is not present respond with a different HTTP status or just with an empty body or 204 (no content) using the ResponseEntity static methods / builder.
For example you can check if the header X-Requested-With is available with the value XMLHttpRequest. That is one of the default headers that will be sent when AJAX is used (but not always; I don't know exactly when it is sent and when not - maybe it depends on the used javascript library).
But keep in mind: This is nothing secure, someone can fake those headers and access the page anyway.
If you want such a behaviour for your complete API try it within a filter which checks this header and if available proceed with doFilter, otherwise stop and respond nothing.
You are returning the list on body of request, if you don't like to do it you should create a ModelAndView object and add the object list to it.
Example:
`#RequestMapping(value = "/pics/{profileId}", method = RequestMethod.GET, headers = "Accept=application/json")
public ModelAndView getProfilePics(#PathVariable("profileId") BigInteger profileId) {
ModelAndView view = new ModelAndView("html_to_be_returned");
view.addObject("list", practiceServices.getProfilePics(profileId));
return view
}'
PS: I have not test this code so it can have same issue.`
Related
I'm trying to implement ajax pagination using Umbraco.
On the server side, I have the following:
[System.Web.Http.HttpGet]
public JsonResult pagination(int? page)
{
IEnumerable<IPublishedContent> newsPosts = Umbraco.AssignedContentItem.DescendantOrSelf("news").Children.Where(x => x.IsVisible() && x.DocumentTypeAlias == "newsPost").OrderByDescending(x => x.UpdateDate).Take(5);
//from here on we will be returning the json within which information required for displaying post entries in carousel is included.
string json = "[some random string]"; //just random string for now.
return Json(json, JsonRequestBehavior.AllowGet);
}
As you can see, I'm trying to get necessary data from IPublishedContents, but I'm having trouble instantiating this series of IPublishedContents.
And this is the error I'm getting when I access:
locahost:{port}/umbraco/surface/{controller}/pagination on Chrome.
Cannot return the IPublishedContent because the UmbracoHelper was constructed with an UmbracoContext and the current request is not a front-end request.
Details: System.InvalidOperationException: Cannot return the IPublishedContent because the UmbracoHelper was constructed with an UmbracoContext and the current request is not a front-end request.
As I said, I'm making this request from Chrome, which is I think means this request is from the front end, so I'm not sure why I'm getting this error.
In the course of searching I found these
1) our.umbraco.com forum
2) stackoverflow post
is deserted with no answer, and as for 2, it strikes me that the answer is not quite relevant to my case. I want to instantiate IPublishedContent in the first place.
Mine is Umbraco 7.
and could it be possible to tell me why requests from the front-end are not desirable?
Any hint would be highly appreciated.
Thanks,
Try getting your node this way.
var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
var yourNode = umbracoHelper.TypedContentAtXPath("umbracoPathtoYourNode");
Perhaps easier to use web api
Create a controller which inherits from UmbracoApiController
public class PagedItemsController : UmbracoApiController
{
[HttpGet]
[ActionName("list")] //Optional see note below
public IHttpActionResult GetItems([FromUri] int pageNo = 1)
{
// Next you need some way of getting the items you need.
// I would not return the whole IPublishedContent items. Rather query those and then use linq Select to transform into a more relevant smaller class (not doing this here)
// I've just included this for brevity
var items = _itemService.GetPagedItems(pageNo);
// Now return the results
return Ok(items);
}
}
Calls to endpoints in Umbraco follow the format
/umbraco/api/{controller}/{endpoint}
With the [ActionName("list")] above the call to the GetItems method will be
http://example.com/umbraco/api/PagedItems/list?pageNo=3
Without the ActionName attribute the call would be
http://exampe.com/umbraco/api/PagedItems/GetItems?pageNo=3
With a standard jquery ajax call this will return json without needing to serialise.
#JsonView
how can use like parameter from request:
#JsonView(header="range")
when response value,read request header range to exclude/include some field
JsonView provides "static" view mapping. so for your dynamic behaviour you can do like this:
// actual request handling is happened here
private ResponseEntity<SomeObject> processRequest();
// request handling with view limit in result
#JsonView(YourDefinedView.class)
#RequestMapping(value = "/request", headers={"range=include"})
public ResponseEntity<SomeObject> processWithView() {
return processRequest();
}
// request handling without view (no headers specified)
#RequestMapping(value = "/request")
public ResponseEntity<SomeObject> processWithoutView() {
return processRequest();
}
this will map your client to same request url, but depending on header it will provide view or not. Than you can create a set of methods, that will be using different #JsonView depending on headers information.
But with this you will limit only the data transfered to client, and the whole data load will happen on server. For example with database and JPA, if you would like not to fetch from database all that data you will end with javax.persistence.NamedEntityGraphs, which will change the general logic of your application - and will at the end of the day produce 2 different methods.
And if you would like to expose custom header with list of fields, to be serialized - custom DTO object, or Map<String, Object> (ugly-ugly-ugly) or custom HandlerMethodReturnValueHandler comes to your help.
I am pretty new in Spring MVC and I have some problem trying to redirect to a controller method after that another controller method terminate its execution.
So I have the following situation. Into a controller class I have this method that correctly handle POST request toward the validaProgetti resource:
#RequestMapping(value = "validaProgetti", method=RequestMethod.POST)
public #ResponseBody String validaProgetti(#RequestBody List<Integer> checkedRowList) {
System.out.println("ID progetti da aggiornare: " + checkedRowList);
List<Twp1007Progetto> progettiDaValidare = new ArrayList<Twp1007Progetto>();
for (int i=0; i<checkedRowList.size(); i++) {
System.out.println("ID PROGETTO: " + checkedRowList.get(i));
progettiDaValidare.add(progettoService.getProgetto(checkedRowList.get(i)));
}
progettoService.validaProgetti(progettiDaValidare);
return "redirect:ricercaValidazione";
}
So this method is correctly mapped and when the validaProgetti resource is called it is executed.
At the end of this method I don't return a view name that render a JSP page but I have to redirect to another method (that do something and render a JSP page). So, instead to return a view name, I redirect toward another resource:
return "redirect:ricercaValidazione";
Then in the same controller class I have declared this method that handle request toward this ricercaValidazione resource:
#RequestMapping(value = "ricercaValidazione", method=RequestMethod.POST)
public String ricercaValidazione(#ModelAttribute ConsultazioneFilter consultazioneFilter, Model model, HttpServletRequest request) {
RicercaConsultazioneViewObject filtro = null;
try {
filtro = new ObjectMapper().readValue(request.getParameter("filtro"), RicercaConsultazioneViewObject.class);
filtro.setSelStatoProgetto(3); // Progetti da validare
} catch (IOException e) {
logger.error(e);
}
consultazioneFilter = new ConsultazioneFilter(filtro);
model.addAttribute("consultazioneFilter", consultazioneFilter);
model.addAttribute("listaProgetti", new ListViewObject<Twp1007Progetto>(progettoService.getListaProgettiConsultazione(consultazioneFilter)) );
return "validazione/tabellaRisultati";
}
The problem is that it can't work and after the redirection can't enter into the ricercaValidazione() method.
I think that maybe the problem is that this ricercaValidazione() method handle POST request toward the ricercaValidazione resource and the return "redirect:ricercaValidazione"; maybe generate a GET request.
But I am not sure about it.
Why? What am I missing? How can I solve this issue?
Tnx
the redirect and fordward prefix are for resolving views; you are tring to redirect from one controller to another one. This can be done but redirect works in the following way
A response is sent to the browser with the redirect http status code and and url
The browser loads via GET the request URL
Your Spring controller (and the corresponding ammping method) is invocated if it matches the annotation params
From what you write I'm not sure this is what you really want; as you already noted there is a mismatch between HTTP methods (GET vs POST).
Your second method ricercaValidazione expects a filtro param in order to filter some data, but in the validaProgetti there is nothing similar, so it seems that the two controllers are not directly chainable. If what you want is to display a page after validaProgetti that shows a form and the the user can submit it you must add a method annotated with a method GET and url ricercaValidazione; the new method must return the view containing the form; which points via POST to url of validaProgetti. In this way you can redirect from ricercaValidazione to validaProgetti
Give mapping name of your controller with redirect like
redirect:/controll-mapping_name/ricercaValidazione
have a look on this question
Unable to redirect from one controller to another controller-Spring MVC
So, say I have an existing, working page Display Cashier, which displays information about a cashier in a shop. Now, I add a button to this page that looks like:
Manager
The request-mapping for this URL maps it (successfully) to a controller: HandleGetManager
the HandleGetManager controller looks like this:
#Controller
public class HandleGetManager{
private employeeBO employeeBO; //BO handles all business logic
//spring hooks
public HandleGetManager(){}
public void setemployeeBo(employeeBO employeeBO){
this.employeeBO = employeeBO;
}
//get controller
#RequestMapping(method=RequestMethod.GET)
public String getManager(#RequestParam String cashierId){
Long managerId = employeeBO.getManagerByCashierId(cashierId);
String redirectUrl = "/displayManager.ctl?managerId=" + managerId.toString();
return redirectUrl;
}
}
Here's what happens when I try it:
I hit the new button on the Display Cashier page, I expect the following to happen:
The browser sends a get request to the indicated URL
The spring request-mapping ensures that the flow of control is passed to this class.
the #RequestMapping(method=RequestMethod.GET) piece ensures that this method is evoked
The #RequestParam String cashierId instructs Spring to parse the URL and pass the cashierId value into this method as a parameter.
The EmployeeBo has been injected into the controller via spring.
The Business logic takes place, envoking the BO and the managerId var is populated with the correct value.
The method returns the name of a different view, with a new managerId URL arg appended
Now, up until this point, everything goes to plan. What I expect to happen next is:
the browsers is directed to that URL
whereupon it will send a get request to that url,
the whole process will start again in another controller, with a different URL and a different URL arg.
instead what happens is:
this controller returns the name of a different view
The browser is redirected to a half-right, half wrong URL: handleGetManager.ctl?managerId=12345
The URL argument changes, but the name of the controller does not, despite my explicitly returning it
I get an error
What am I doing wrong? Have I missed something?
Assuming you have a UrlBasedViewResolver in your MVC configuration, the String value you return is a View name. The ViewResolver will take that name and try to resolve a View for it.
What you seem to want to do is to have a 301 response with a redirect. With view names, you do that by specifying a redirect: prefix in your view name. It's described in the documentation, here.
Here's a question/answer explaining all the (default) ways you can perform a redirect:
How can I prevent Spring MVC from doing a redirect?
My existing code is like:
String myController(#PathVariable someId, ModelMap map){
....
return "myViewName";
}
Now I want to set a cookie in some cases, so I need to get hold of a HttpServletResponse obj. Can I just add such a response obj to the list of params and operate on it in the controller?
If so, I wonder how my own response is kind of reconciled with the response generated by the JSP that resolves the "myViewName".
Yes.
#RequestMapping
public String myController(#PathVariable someId, ModelMap map, HttpServletResponse response) {
// Do what you need to do on the response, like set a cookie
return "myViewName";
}
Regarding your other question : "how my own response is kind of reconciled with the response generated by the JSP that resolves the "myViewName"."
When you return a view say "myViewName", it will be resolved to a particular resource (JSP View or JSON View or any other view). Once that view resource is obtained depending on what you return, that view does the rendering on to the response. This response object is the same that was passed to the controller function (myController). So say if you set some cookie/headers on the response in the controller function, the response that is being used by the view to do the rendering will also have the same properties.
In case you want to handle the actual rendering/response yourself, you can always get the outputstream of the response and write to it and close the stream. Then the view that you return is just ignored as the dispatcher will check that the response is already handled and will just do post handle stuff.
Hope that clears up for anyone looking for the dispatcher logic behind it.