I have an application in which most requests are submitted via AJAX, though some are submitted via "regular" HTTP requests. If a request is submitted and the user's session has timed out, the following JSON is returned:
{"authentication":"required"}
The JavaScript function which submits all AJAX requests handles this response by showing a popup message and redirecting the user back to the login page.
However, when a non-AJAX request receives this response the JSON is simply shown in the browser because the response is processed directly by the browser (i.e. the aforementioned JavaScript function is bypassed). Obviously this is not ideal and I would like the non-AJAX requests that receive this response to behave the same as the AJAX requests. In order to achieve this, I can think of 2 options:
Go through the application and convert all the requests to AJAX requests. This would work, but could also take a long time!
The JSON shown above is generated by a very simple JSP. I'm wondering if it might be possible to add a JavaScript event handler to this JSP which is run just before the content is displayed in the browser - I'm assuming this would never be called for AJAX requests? This handler could call the other JavaScript code that displays the popup and performs the redirection.
If anyone knows how exactly I can implement the handler I've outlined in (2), or has any other potential solutions, I'd be very grateful if they'd pass them on.
Cheers,
Don
3) Change your AJAX code to add a variable to the GET or POST: outputJson=1
You cannot add a handler to the JSP that way. Anything you add to it will make it a non-JSON producing page.
There are two options that I can see:
Add a parameter to the page by appending a URL parameter to the screen that modifies the output.
URL: http://domain/page.jsp?ajaxRequest=true
would output json only
URL: http://domain/page.jsp
would display a jsp page that could forward to another page.
OR
change the response to have the forwarding code in the JSP that will get executed by the web browser if it is hit directly. Then have your calling AJAX to strip the forwarding code out, and then process what is left.
4) Read up on the 'Accept' request HTTP header.
Then, on the server side tailor the output:
e.g.
if(Accept contains application/json...) { // client asking for json, likely to be XHR
return {"foo":"bar"}
} else { // other
return "Location: /login-please";
}
Start with a smarter error message, like this:
{"error":"authentication required"}
Wrap the JSON output in a callback:
errorHandler({"error":"authentication required"});
Have a handler waiting in your script:
function errorHandler(r) {
alert(r.error);
}
And don't forget to send it down as text/javascript and not application/x-json.
Related
on server side, for example, I use flask to handle these post requests, the same code can handle the two type requests, but on client side, ajax request will not let the browser to refresh the whole page, but the form does.
So what is the difference in deep, is some header field not same?? or something else??
Thanks!
There is no difference, only that AJAX is, as the acronym suggests, asynchronous, which means it does not block anything else from running. Both the form and an AJAX request send a POST request the only difference is that the browser uses the response from the forms POST request to load the new page where as the AJAX requests response is passed to a callback in JavaScript.
Submitting an HTML form constructs an HTTP request formatted according to the rules defined for HTML forms and causes the browser to navigate to the response it gets.
Making a request with JavaScript allows the programmer to construct a much wider variety of requests — including adding custom headers, formatting data in different ways (such as JSON), and identically to how an HTML form would construct the request — and causes the response to be processed with JavaScript.
In general, when writing server-side code, you shouldn't need to care if the request came from JavaScript or an HTML form. There are situations where you do, but usually only as an XY Problem.
For example, you might wish to respond to a regular form submission with an HTML document (because the browser is navigating to it) but to an Ajax request with JSON (because you want to process it easily). In this case the JavaScript should set an Accept request header to tell the server that it would prefer a JSON response. Then the server-side code you write should look at that to determine if HTML or JSON is preferred (and not worry why HTML or JSON is preferred).
Ajax request is an xhr request sent in the background asynchronously and handled by your javascript code whereas form request is a normal request and browser page will be reloaded as well as the response rendered by the browser
Form and Ajax requests send to the back in the same way. For Flask, you capture the POST request and it would be identical if the Ajax contained all the same information from the form.
What submits the form (And causes the fresh of the page) is a "onsubmit" event the form fires to the DOM. This can actually be overridden if you desire. This is often done with the "PreventDefault" function. This i believe has been covered several times on the site. You may have just been missing the concept of the "onsubmit" event from the form.
I just get started in Ajax and httpRequest. While I was playing around with the code, I noticed that $.get works fine but $.post doesn't work. Here's my code:
$(document).ready(function() {
$.post('hello.txt', function(data) {
alert(data);
}).fail(function() {
alert('fail');
});
});
It always gives me a fail, and I cannot figure it out.
Thanks
Barmar is correct in the comments, but for an answer, let's go over what it is these functions are doing.
When you're using the jQuery AJAX methods, they are performing HTTP requests to the resource you're providing in the url parameter for the function. As long as the value is something sitting on your server (an endpoint) the function will hit it.
$.get() performs an HTTP GET action which is how we'd fetch data over HTTP. In your example, you specify hello.txt as the url, which as long as that is a file sitting on your server, the application will make a GET request to that resource. If it is found, the contents of that resource are returned. This can be done with a text file, a JSON payload, HTML web pages, etc. As long as the resource has returnable content, it will return that content.
$.post(), on the other hand, performs an HTTP POST action which sends data up to a resource to be processed. A POST action is not intended to fetch a resource's data, but to push data into it. Canonically, you would use a POST to create something with the data you push to the resource (as opposed to PUT for modifying and DELETE for removal, but that's beyond this answer).
So, the GET works because the action is intended to fetch data and the resource you provided has data to return. The POST fails because it is intended to give data to the resource to process, which your text file is not equipped to handle.
Hope this sheds a bit of light on the problem.
What would be the "best" approach to dealing with forms which have to work without and with JavaScript enabled?
Would it be better to create different routes for each, like
AJAX request: route "API/contact" and return res.send("message")
without JavaScript: route "contact"and return a redirect with a query param of "message"
Or in one route and detect xhr and render it depending on this?
Or is there a better way of dealing with the problem of taking the user to the res.send("") when the JavaScript isn't enabled to give the user feedback on the submit?
To clarify:
I have a site which is working with AJAX requests for its forms to avoid full page loads. It lacks the fallback when JavaScript is not enabled and thus when a user clicks submit on a form, he receives the data from the post back with res.send and it replaces the whole page, instead of the desired effect which would be to just update a label with the "success/fail" message. The question then remains as above which would be the neat way of dealing with this?
Probably the best thing to do would be to check the X-Requested-With header and check that it contains XMLHttpRequest (but this might get deprecated as the new fetch API will slowly come into browser.
Based on that value, you might want to return a JSON payload, or eventually trigger a server side rendering, therefore returning an HTML page ready-to-be-consumed.
As an alternative, you can return a redirect response with a particular query string value; once the page is loaded, you will check for that value (using qs for example, or deparam in jquery and manipulate the client side accordingly.
Your server routes have nothing to do with client-side javascript. You don't need javascript to receive a "res.send" message.
I noticed that when a link on the page has JS onclick function and also a MVC action method, the JS function fires before the action.
Wondering is this always the case?
Why/how browsers deside to run JS and the the backend method?
Can I run backend method first, but still want to fire the JS function?
Regards
Wondering is this always the case?
Why/how browsers deside to run JS and the the backend method?
Client-side JavaScript runs on the client, inside a page. Server-side .NET code runs on the server and generates an HTML document (or other resource).
To run server side code, the browser has to make an HTTP request.
The easiest way to make an HTTP request is to leave the current page and load a new one from the server (by following a link or submitting a form).
Since client-side JavaScript runs in a page, it can't run after the browser has left the page it runs in.
Can I run backend method first, but still want to fire the JS function?
You can make an HTTP request from JavaScript (before doing other JS actions) instead of leaving the current page. This is usually done with the XMLHttpRequest object and is known as Ajax.
Why/how browsers deside to run JS and the the backend method?
server side code will need a request to return the response. HTTP works on Request and Response architecture. basically client make requests in order to get the response (i.e results or desired data)
wheenever you do postback or return true to the server, it will execute server side methods.
ClickHereToSee
here return value which is returned by the function, if you return the true value it will go to the server method, if you returned the false it will prevent the default action.
Can I run backend method first, but still want to fire the JS function?
You can. use Ajax. basically Ajax requests are XMLHTTPRequest. which used to update the paritial portions.
Can I run backend method first, but still want to fire the JS function?
First two answers are already well answered. For third one you can try Jquery Ajax-
function SomeFunction(){
$.ajax({
type: 'POST',
url: "#Url.Content("Controller/ActionResult")",
data : {
*yourparameter:value* //data
},
dataType: 'json',
success:function(result)
{
//javascript stuff
}
});
}
ClickHereToSee
How do I design a Django/Javascript application to provide for conditional Ajax responses to conventional HTTP requests?
On the server, I have a custom-built Form object. When the browser POSTS the form's data, the server checks the submitted data against existing data and rules (eg, if the form adds some entity to a database, does that entity already exist in the database?). If the data passes, the server saves, generates an ID number and adds it to the form's data, and passes the form and data back to the browser.
if request.method == 'POST':
formClass = form_code.getCustomForm()
thisForm = formClass(data=request.POST)
if thisForm.isvalid():
saveCheck = thisForm.saveData()
t = loader.get_template("CustomerForm.html")
c = Context({ 'expectedFormObj': thisForm })
(Note that my custom logic checking is in saveData() and is separate from the html validation done by isvalid().)
So far, standard Django (I hope). But if the data doesn't pass, I want to send a message to the browser. I suppose saveData() could put the message in an attribute of the form, and the template could check for that attribute, embed its data as javascript variable and include a javascript function to display the message. But passing all that form html back, just to add one message, seems inelegant (as does the standard Django form submission process, but never mind). In that case I'd like to just pass back the message.
Now I suppose I could tie a Javascript function to the html form's onsubmit event, and have that issue an XMLHttpRequest, and have the server respond to that based on the output of the saveData() call. But then the browser has two requests to the server outstanding (POST and XHR). Maybe a successful saveData() would rewrite the whole page and erase any potential for conflict. But I'd also have to get the server to sequence its response to the XHR to follow the response to the POST, and figure out how to communicate the saveData outcome to the response to the XHR. I suppose that is doable, even without the thread programming I don't know, but it seems messy.
I speculate that I might use javascript to make the browser's response conditional to something in the response to the POST request (either rewrite the whole page, or just display a message). But I suspect that the page's javascript hands control over the browser with the POST request, and that any response to the POST would just rewrite the page.
So can I design a process to pass back the whole form only if the server-side saveData() works, and a message that is displayed without rewriting the entire form if saveData() doesn't? If so, how?
Although you can arrange for your views to examine the request data to decide if the response should be an AJAXish or plain HTML, I don't really recommend it. Put AJAX request handlers in a separate URL structure, for instance all your regular html views have urls like /foo/bar and a corresponding api call for the same info would be /ajax/foo/bar.
Since most views will examine the request data, then do some processing, then create a python dictionary and pass that to the template engine, you can factor out the common parts to make this a little easier. the first few steps could be a generic sort of function that just returns the python dictionary, and then actual responses are composed by wrapping the handler functions in a template renderer or json encoder.
My usual workflow is to initially assume that the client has no javascript, (which is still a valid assumption; many mobile browsers have no JS) and implement the app as static GET and POST handlers. From there I start looking for the places where my app can benefit from a little client side scripting. For instance I'll usually redesign the forms to submit via AJAX type calls without reloading a page. These will not send their requests to the same URL/django view as the plain html form version would, since the response needs to be a simple success message in plain text or html fragment.
Similarly, getting data from the server is also redesigned to respond with a concise JSoN document to be processed into the page on the client. This also would be a separate URL/django view as the corresponding plain html for that resource.
When dealing with AJAX, I use this:
from django.utils import simplejson
...
status = simplejson.dumps({'status': "success"})
return HttpResponse(status, mimetype="application/json")
Then, AJAX (jQuery) can do what it wants based on the return value of 'status'.
I'm not sure exactly what you want with regards to forms. If you want an easier, and better form experience, I suggest checking out uni-form. Pinax has a good implementation of this in their voting app.
FYI, this isn't an answer...but it might help you think about it a different way
Here's the problem I'm running into...Google App Engine + jQuery Ajax = 405 Method Not Allowed.
So basically I get the thing to work using the outlined code, then I can't make the AJAX request :(.