ASP .NET Core MVC: What happens to a request on RedirectToAction - asp.net-core-mvc

I was trying to pass data around between controllers all day long, but now I'm at the point where I think I haven't quite understood the basics.
Throughout the documentation of ASP .NET core, they use the word "request". I was under the assumption that this is the HttpRequest that is made by the client of the WebServer.
There are also different things that are supposed to be bound to the lifetime of a request:
The HttpContext and its HttpContext.Items dictionary.
Services added with AddScoped via dependency injection.
The TempData dictionary? (not so sure about that)
But when trying to pass data around, I made the observation that when I do return RedirectToAction(...); the HttpContext changes (HttpContext.GetHashCode() has a different value), TempData changes and services added via AddScoped are also new objects.
That would suggest that on RedirectToAction a new request is made, going through all the steps of the request pipeline again. My expectation though was that a RedirectToAction only continues the current request pipeline with a different controller action.
I also thought that the browser or whatever client only made one request and got one response during that entire process.
So what is actually happening when calling RedirectToAction in a controller action and returning the result?
UPDATE:
Using TempData works, but a TempDataProvider has to be configured first. For example add services.AddSingleton<ITempDataProvider,SessionStateTempDataProvider>(); to Startup.cs. Thanks #RonC.

As mentioned, RedirecToAction will cause the browser to make a new request, and when that new request comes in, it will create a totally new HttpContext. As mentioned, To pass data between the two requests, you can use the query string, session or cookies. But there is another option to consider.
TempData
Data can be passed from one request to another via the TempData collection which is accessible in the controller action method. The TempData collection was specifically designed for passing data from one request to another. The beauty of TempData is that the lifetime of an object placed in TempData is exactly one additional request. So anything placed in TempData in request 1 will be there for request 2 but then be automatically removed from TempData at the conclusion of request 2. This makes TempData perfect for passing data from one request to another without having to disclose that information in a query string or possibly forgetting it in session and bloating the session object.

It's impossible to save state of current request, because... HTTP is stateless. Every RedirectToAction really tells browser to make another HTTP request. As documentation says.
Returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action.
If you would like to pass some data between HTTP requests, you have to use cookies or session mechanism.

Related

What is the difference between method handlers such .get, .post and actions such as .list, .create

I am learning Django Rest Framework and one of the things I have noticed is that Viewsets provide actions such as .list, .post instead of method handlers such as .get, .post which in turn are provided by Views. The documentation says that actions are more flexible than method handlers but I can't seem to find any reason for this. Could you please share some information on why does Viewsets use actions and not the method handlers?​
request handlers like .get() and .post() are based on http request methods, while actions like .create() or .list() are from a functionality point of view. Suppose you have a view class that can return a single user's info by user id or return all users in sorted order. These two requests are all GET requests from the client side, but with different parameters and purposes. If you just want to use .get() handler in this case you will need to define two view functions and register the two urls in url config. Or you can use ViewSet class or generic view with mixins that has action functions .list() and .retrieve() to handle these requests, then using router class to set the url configs that follows the REST url standards.
GET and POST are the only HTTP methods to use when dealing with forms.
Django’s login form is returned using the POST method, in which the browser bundles up the form data, encodes it for transmission, sends it to the server, and then receives back its response.
GET, by contrast, bundles the submitted data into a string, and uses this to compose a URL. The URL contains the address where the data must be sent, as well as the data keys and values. You can see this in action if you do a search in the Django documentation, which will produce a URL of the form https://docs.djangoproject.com/search/?q=forms&release=1.
GET and POST are typically used for different purposes.
Any request that could be used to change the state of the system - for example, a request that makes changes in the database - should use POST. GET should be used only for requests that do not affect the state of the system.
GET would also be unsuitable for a password form, because the password would appear in the URL, and thus, also in browser history and server logs, all in plain text. Neither would it be suitable for large quantities of data, or for binary data, such as an image. A Web application that uses GET requests for admin forms is a security risk: it can be easy for an attacker to mimic a form’s request to gain access to sensitive parts of the system. POST, coupled with other protections like Django’s CSRF protection offers more control over access.
On the other hand, GET is suitable for things like a web search form, because the URLs that represent a GET request can easily be bookmarked, shared, or resubmitted.

Writing cookies on Rails besides the controller, possible?

I'm working on an application stack that has a rather particular architecture. The forms component is loaded on a view, and when the action is submitted, an async call using sidekiq is performed. This calls an endpoint that validates the form data, but none of this is returned back to the server and after this process is fired, there is a redirect to another page.
We want to add cookies to write the status of this call sidekiq did. This is not possible to do on the controller as the controller when it is rendering the destination page has no knowledge of this event that occurred. The possibility of writing this cookie on the async callback is tempting but this is not done on the controller (The controller loads a class that contains a module with this functionality)
Question: Is it possible to write cookies in places not in the controller, such as classes or models? I'm assuming no, but I figured it might be an interesting question.
It's not possible. Writing a cookie is a part of HTTP response, so you need to be in the request-response cycle, i.e. in the controller.
What you could do (and I did that more than once) is to have some kind of record in the database, storing a status of a background job, and from the page you redirected to periodically poll some endpoint with AJAX (or establish a Websocket connection) to check if the job has finished and with what status. Then you'll be able to set the cookie.

Scraping a website made with ICEfaces (session expired on consecutive ajax POST requests)

I'm trying to scrape a website created with the ICEfaces web framework via a node.js script. I've managed to handle the login just fine, and then get some data from the main page (namely ice.session and ice.view, along with the JSESSIONID cookie returned by the login response).
The problem I've run into is when I try to do an AJAX POST request to the /block/ URLs. If I do the request by itself, it returns some data (just not the data I need), but if I do it after any other request, I get <session-expired/> as a result. It doesn't even matter which of the ICEfaces /block/ URLs I send the request to (I've tried with /send-receive-updates, /dispose-views, and even /ping). I've even tried the same request twice in a row just for kicks, and I always get a <session-expired/> response in return on the second one. I've monitored the requests when I browse the page with Chrome, and as far as I know I'm sending all the correct form data (as well as the correct headers). The page works just fine when I load it in the browser, so there must be something I'm not doing right.
Apparently, the order in which you do the requests matters in ICEfaces (i.e. it's not stateless, which kind of makes sense I guess). I just moved the requests around and finally got the response I desired.
IceWindow, IceView and ViewState
Need to be passed as a parameter whenever you do an ajax submit.
Managed bean takes the previous instance of the current view view using ViewState value.

does post-redirect-get need to happen for an ajax request?

is there any reason to use the post-redirect-get (prg) for a request that you know will only happen via an ajax request?
in this scenario, you might have a request that is sent (either via ajax or direct), and we're assuming on the back-end we can distinguish which is which. In the case where the direct request is handled using prg, is there any reason to also handle the ajax request with a prg too?
or can an ajax post just be responded to directly?
For something that only uses AJAX, I can't see a reason to use prg. Since it is not a user controlled action with the possibility of duplication, the only way the AJAX call would be duplicated is if the original page was refreshed before the action finished, and since prg has that same one flaw, you may as well use the direct approach.

Do I understand Ajax correctly?

I'm been reading up on Ajax and would like to see from the stackoverflow community if I'm understanding everything correctly.
So the normal client server interaction is a user pulls up a web browser types in a url and a HTTP request is sent to the server requesting the page and resources( css, pics ) from the web server. The web server responds to the client via HTTP the page/resources requested and the browser renders the html/JavaScript for the user to view the page.
1) So would it be safe to say that XMLHttpRequest( XHR ) object is doing the same process as the browser except your not requesting html from the server, your requesting text in some type of format?
2) Is it true that a XHR object is much like a regular object that can be manipulated by the program creating the object( like a normal object ), but also sends and receives data with another program( web server ) via HTTP?
3) So in my mind when a XHR is created it is loaded into memory and we setup some of the objects arguments when we do the request.open(“GET”, url, true). Once we do a request.send(null) the object basically attempts to “GET” the url via HTTP and once we get the data back from the server it is put in the responseText argument. Am I understanding this correctly?
4) Also synchronous vs asynchronous. When I think of synchronous I think of steps having to be followed in order. For example, I push a button, data gets sent to server, and I have to wait for data to come back before I can do anything else. With asynchronous connections I would push button, data gets sent to server, I do what ever I want while data gets sent back. Is this a good analogy?
1) Nope. The XMLHttpRequest object does exactly what its name implies -- it initiates an HTTP request. This request can be in XML, or HTML, or PHP. At the end of the day, the browser doesn't care, because in an AJAX request, it doesn't parse the request -- you have to do it yourself. So it doesn't automatically render the HTML from an AJAX request.
2) I'm not sure about manipulation (the XHR object may be immutable) but possibly. Would you ever need to extend it or manipulate it?
Yes, you can change properties of the object and so on. I apologize. I didn't understand you at first :)
3) Yep.
4) That's a great analogy. It's exactly what happens. Another analogy is a 4 lane highway is to asynchronous as a one-way street is to synchronous. If one car breaks down on the 4 lane highway, the rest can keep moving at their normal speed -- but if one breaks down on the one-way road, everything freezes. :)
Here I leave you a good graphic to see clearly the behavior differences between the synchronous and asynchronous application models:
(source: adaptivepath.com)
It would appear that you have a job grasp of how AJAX works. I can't see much to disagree with in your summary of the plumbing of an AJAX application.
I would say however that with the XMLHttpRequest object you aren't restricted to GET. You can also use POST and other HTTP verbs.
With async calls you register a callback function, the XMLHttpRequest object calls your method when the async request completes.
Seems ok to me.
Your first point though is not entirely correct, you can request html from the server using ajax is doesn't have to text, json or xml like most examples show.

Resources