I added an outputcache directive to my asp.net page (asp.net 4.0) as such:
<%# OutputCache Duration="3600" Location="Client" VaryByParam="None" %>
However, this does not appear to be working. When I check the http header information I see this:
HTTP/1.1 200 OK =>
Cache-Control => no-cache, no-store
Pragma => no-cache
Content-Type => text/html; charset=utf-8
Expires => -1
Server => Microsoft-IIS/7.0
X-AspNet-Version => 4.0.30319
Set-Cookie => ASP.NET_SessionId=0txhgxrykz5atrc3a42lurn1; path=/; HttpOnly
X-Powered-By => ASP.NET
Date => Tue, 15 Nov 2011 20:47:28 GMT
Connection => close
Content-Length => 17428
The above shows that the OutputCache directive was not applied. I even tried this from codebehind:
this.Response.Cache.SetExpires(DateTime.Now.AddHours(1.0));
TimeSpan ds = new TimeSpan(0, 1, 0, 0);
this.Response.Cache.SetMaxAge(ds);
The above code should have the same results as the OutputCache directive, but when I check the http header information, I can see it's still not being applied.
Basically, the purpose here is to make sure that when a user clicks the back button and lands on my page, the page will not be retrieved from the server. I want to avoid getting the browser popup that asks the user to 'resend.' I want the browser to just use the copy of the page it has in it's cache.
Thanks in advace for any help.
From your question:
I want to avoid getting the browser popup that asks the user to
'resend.' I want the browser to just use the copy of the page it has
in it's cache.
If browser asks you to resend data, it means that content was response to POST request.
According to RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1:
Some HTTP methods MUST cause a cache to invalidate an entity. This is
either the entity referred to by the Request-URI, or by the Location
or Content-Location headers (if present). These methods are:
PUT
DELETE
POST
So, to make cache work, you need to convert your POST to GET.
Related
I have a requirement where i need to invoke a SOAP Webservice operation for login and get the cookie from the SOAP response and use the cookie to invoke another SOAP operation to retrieve some data. The Login operation response has a cookie(Set-Cookie) which looks like ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb; path=/; HttpOnly; SameSite=Lax
Now how do i map this cookie to the retrieve operation. Do i map ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb; path=/; HttpOnly; SameSite=Lax fully or just ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb or just vqjucdxcxrgg5swr0f3z0peb. I tried all three options and i am getting java.lang.IllegalArgumentException: Port may not be negative error when i invoke the retrieve operation. Please let me know if i am doing anything wrong. I am using Tibco BW to invoke the SOAP operations.
Found the answer to my question in the link https://en.wikipedia.org/wiki/HTTP_cookie .Please read below
Setting a cookie
Cookies are set using the Set-Cookie HTTP header, sent in an HTTP response from the web server. This header instructs the web browser to store the cookie and send it back in future requests to the server (the browser will ignore this header if it does not support cookies or has disabled cookies).
As an example, the browser sends its first request for the homepage of the www.example.org website:
GET /index.html HTTP/1.1
Host: www.example.org
...
The server responds with two Set-Cookie headers:
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: theme=light
Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
...
The server's HTTP response contains the contents of the website's homepage. But it also instructs the browser to set two cookies. The first, "theme", is considered to be a session cookie since it does not have an Expires or Max-Age attribute. Session cookies are intended to be deleted by the browser when the browser closes. The second, "sessionToken", is considered to be a persistent cookie since it contains an Expires attribute, which instructs the browser to delete the cookie at a specific date and time.
Next, the browser sends another request to visit the spec.html page on the website. This request contains a Cookie HTTP header, which contains the two cookies that the server instructed the browser to set:
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
…
This way, the server knows that this request is related to the previous one. The server would answer by sending the requested page, possibly including more Set-Cookie headers in the response in order to add new cookies, modify existing cookies, or delete cookies.
The value of a cookie can be modified by the server by including a Set-Cookie header in response to a page request. The browser then replaces the old value with the new value.
Cookie attributes
In addition to a name and value, cookies can also have one or more attributes. Browsers do not include cookie attributes in requests to the server—they only send the cookie's name and value. Cookie attributes are used by browsers to determine when to delete a cookie, block a cookie or whether to send a cookie to the server.
Why does all responses from ASP.NET contain Cache-Control: private? Even a 404 response? Is there something in IIS that sets this default value, and is there a way to configure it? Or is there something in ASP.NET that sets this?
For dynamic content (that is, all MVC results) I would not like it to be cached by the browser, since it is dynamic and can change at any time. Static content is hosted on a CDN, so is not served by IIS.
Edit:
To clarify, I understand very well what Cache-Control: private is, the difference between private, public, no-store, etc and how/when to use them. The question I have is why Cache-Control: private is added by default by IIS/ASP.NET and how to prevent it from being added by default. I understand that it can be useful to cache dynamic pages, but in my application I don't want to cache dynamic pages/responses. For example, I don't want XHR JSON responses to be cached, since they contain dynamic content. Unfortunately the server adds Cache-Control: private to all responses automatically, so I have to manually override it everywhere.
How to reproduce: Open visual studio and create a new ASP.NET Framework (yes, framework, no not Core. We are not able to migrate our system to core yet) solution with an MVC project. Now start the project in IIS Express (just press the play button), and use F12 devtools in the browser to look at the http response. You will see that it contains Cache-Control: private. My question is, what adds this header, and how can I prevent it from being added by default?
Adding my bit to the great answers, given by community;
1. http caching header attrubute Cache-Control: private is added by default by IIS/ASP.NET ?
Cache request directives
Standard Cache-Control directives that can be used by the client in an HTTP request.
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: only-if-cached
Cache response directives
Standard Cache-Control directives that can be used by the server in an HTTP response.
Cache-Control: must-revalidate
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: public
Cache-Control: private
Cache-Control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-Control: s-maxage=<seconds>
IIS uses the secure and more obvious/useful one for default, which happens to be private
2. how to prevent it from being added by default?
IIS/asp.net allows this to be configured from the day it was introduced like this, ref1, ref2, ref3, ref4 and
System.Web Namespace
The System.Web namespace supplies classes and interfaces that enable browser-server communication. This namespace includes the System.Web.HttpRequest class, which provides extensive information about the current HTTP request; the System.Web.HttpResponse class, which manages HTTP output to the client; and the System.Web.HttpServerUtility class, which provides access to server-side utilities and processes. System.Web also includes classes for cookie manipulation, file transfer, exception information, and output cache control.
protected void Application_BeginRequest()
{
Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
TL; DR
Caching is not used by default for dynamic ASP.NET pages. You need to make an efforts to enable caching in ASP.NET.
Presence of 'Cache-Control: private' header does not mean at all that cached version of the page will be used on repeated requests.
--
There is a very simple test to validate above statements. Create an action that returns current time:
public ActionResult Index()
{
ViewBag.CurrTime = DateTime.Now.ToString("T");
return View();
}
View:
#{
ViewBag.Title = "Home Page";
}
<h1>#ViewBag.CurrTime</h1>
If you refresh such page in abrowser, you'll see fresh time on every request:
There is a possibility to use caching with ASP.NET MVC but you should make some efforts to enable it. See this article for details.
If in spite of this you still for some reason want to exclude any possibility of the caching, you could do it by setting specific HTTP headers. There is a great SO answer that lists which headers should be set:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
You could use action filter to set those headers in every ASP.NET response:
public class CachingHeadersFilterAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var response = filterContext.HttpContext.Response;
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.Cache.AppendCacheExtension("no-store, must-revalidate");
response.AppendHeader("Pragma", "no-cache");
response.AppendHeader("Expires", "0");
base.OnResultExecuted(filterContext);
}
}
In FilterConfig.cs (crated automatically in ASP.NET MVC template):
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new CachingHeadersFilterAttribute());
}
}
Here are result headers from the response:
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRHJvcGJveFxwcm9nXFN0YWNrT3ZlcmZsb3dcUTQ3MjI0NTYxQ2FjaGVcUTQ3MjI0NTYxQ2FjaGU=?=
X-Powered-By: ASP.NET
Date: Mon, 13 Nov 2017 17:44:33 GMT
Content-Length: 837
As you see there is no 'Cache-Control: private' header.
But again, I don't see a reason why you should add such filter to your application.
what adds this header?
The IIS 7 and later (included in the default installation) sends it to Web clients as one of the cache-related HTTP headers.
and how can I prevent it from being added by default?
I describe two ways of disabling cache mechanism (server-side approach and client-side approach) with a focus on server-side based on your question:
Server-Side Approach
Follow this steps Inside the Internet Information Services (IIS) Manager to change Cache-Control value (while I think this works for static contents):
In the Connections pane, go to the site, application, or
directory for which you want to disable caching.
In the Home pane, double-click HTTP Response Headers.
Click Set Common Headers ... in the Actions pane.
Check the box to expire Web content, select the option to expire after a specific interval or at a specific time,
and then click OK.
One way is to annotate your controller as follows which is quite powerful and the response headers contain a Cache-Control: public, max-age=0 header.:
[OutputCache(Duration = 0)]
public class SomeController : Controller {
}
You can also Define a cache profile in your application's Web.config file and in the profile, include duration and varyByParam settings:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="nocache" duration="0"
varyByParam="none" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
Then use it by the [OutputCache CacheProfile="nocache"] before the action/controller.
Note that there is a configuration in web.config file (following) which won’t prevent caching. Instead it just indicates that no kind of caching mechanism should be applied. By just disabling the output cache we get the default cache headers used by ASP.net MVC which falls back to Cache-Control: private, thus again opening the browser the possibility to cache requests.
<caching>
<outputCache enableOutputCache="false" />
</caching>
Client-Side Approach
Using cache: false inside your js request like:
$.ajax({
type: 'GET',
cache: false,
url: '/nation',
...
});
For additional information, visit:
Client Cache <clientCache>
How to: Set the Cacheability of an ASP.NET Page Declaratively
output-caching-in-aspnet-mvc
An answer from RickNZ, copied from https://forums.asp.net
Cache-Control private says that it's OK for the client to cache the page, subject to its expiration date. The expiration can either be provided with Cache-Control: max-age, or with an Expires HTTP header. In the default case, the page is set to expire immediately, which means that it won't be cached.
One of the purposes of Cache-Control: private is really to tell intermediate proxies that they should not cache the page.
BTW, just because a page is dynamic doesn't mean that it should never be cached. There are many cases where caching a dynamic page is appropriate. You can cache not only at the client, but also in proxies and in the server's output cache.
More info:
IIS 7.0 - IIS adding "private" to cache-control, where is that coming from
Private vs Public in Cache-Control
https://msdn.microsoft.com/en-us/library/ms524721(v=vs.90).aspx
https://msdn.microsoft.com/en-us/library/system.web.httpcacheability(VS.71).aspx
https://forums.asp.net/t/1443346.aspx?Cache+control+private+
https://forums.asp.net/t/2052325.aspx?Remove+the+private+value+from+the+Cache+Control+in+the+Response+Header
The Cache-Control: private header is added to the response by the framework by default.
https://learn.microsoft.com/en-us/dotnet/api/system.web.configuration.httpruntimesection.sendcachecontrolheader?view=netframework-4.8
Definition
Gets or sets a value indicating whether the cache-control:private header is sent by the output cache module by default.
...
Remarks
The HttpResponse class checks both the HttpRuntimeSection.SendCacheControlHeader property and the OutputCacheSection.SendCacheControlHeader property to determine whether to send the cache-control:private header in the HTTP response. If either property is set to false, the header will not be sent. When the cache-control header is set to private, then the client will not cache the response in a shared cache.
Support for the SendCacheControlHeader property in the HttpRuntimeSection class is provided for compatibility with legacy applications; this property is obsolete in the .NET Framework version 2.0. For more information, see the OutputCacheSection class.
To prevent the Cache-Control: private header from being added, simply disable the OutputCacheSection.SendCacheControlHeader property, which defaults to true.
https://learn.microsoft.com/en-us/dotnet/api/system.web.configuration.outputcachesection.sendcachecontrolheader?view=netframework-4.8#system-web-configuration-outputcachesection-sendcachecontrolheader
Property Value
true if the sending of cache-control:private header is enabled; otherwise, false. The default is true.
Example web.config
<configuration>
<system.web>
<caching>
<outputCache sendCacheControlHeader="false" />
</caching>
</system.web>
</configuration>
The default is specified in System.Web.HttpResponse.CacheControl:
/// <devdoc>
/// <para>
/// Provided for ASP compatiblility. Use the <see cref='System.Web.HttpResponse.Cache'/>
/// property instead.
/// </para>
/// </devdoc>
public string CacheControl {
get {
if (_cacheControl == null) {
// the default
return "private";
}
return _cacheControl;
}
While you can override the header through (global) filters, this doesn't work for error pages caused by authentication/authorization. Luckily there's a nice entry point for each request, allowing you to override this default:
// In Global.asax.cs:
protected void Application_BeginRequest()
{
Context.Response.CacheControl = "no-cache";
}
Furthermore when there's an error and the YSOD (yellow error page) is rendered through ReportRuntimeError, the framework will call ClearHeaders and your custom cache-control setting will be overridden. I haven't found a solution for this.
Addressing the question:
You will see that it contains Cache-Control: private. My question is,
what adds this header, and how can I prevent it from being added by
default?
The Short answer is: as others have noted, this is a default setting by IIS(7+).
To answer more fully: If you are looking to control or modify the default setting Cache-Control: private for caching HTTP requests, server side.
This will depend on your the which specific version of IIS you are running, and how specific you want to be with your modification. Generally speaking however you can do this using your HTTP Response Headers interface (in IIS Manager => Features view - IIS)
If you want to simply disable caching for a Web site or Application:
go to IIS Manager
Select Site/Application desired
in Features View select HTTP Response Headers:
In actions pane click: Set Common Headers
check Expire Web Content
Set to: Immediately
OK
alternatively, from your command line:
appcmd.exe set config "Default Web Site" -section:system.webServer/staticContent /clientCache.cacheControlMode:"DisableCache"
For Detailed Information and specifics please check:
https://learn.microsoft.com/en-us/iis/configuration/system.webserver/staticcontent/clientcache
Hope this is what your were looking for, cheers.
I've been trying to refresh my understanding of HTTP/1.1 caching - something I find I have to do every once in a while, as there seems to be too many possible combinations for my brain to remember reliably.
I took it as a given that the Expires or max-age cache control directives were used by browsers as hints, not ironclad laws: if a cache entry is stale (older than its max age), the browser MAY validate it.
A colleague and I had a bit of a row about this and he forced me to read the RFC, which I felt was a bit harsh but proved him entirely right: if I understand it correctly, clients are not allowed to use a cache entry that they know to be stale.
In other words: if a document specifies a max-age cache header, and no other directives such as must-validate affect caching behaviour, and that document's cache entry becomes stale, the browser will always re-validate it.
This is entirely clear and logical, and to put that argument to rest, I set out to confirm it empirically by having a server serve a test JavaScript file with the following headers:
< HTTP/1.1 200 OK
< Content-Type: application/x-javascript; charset=UTF-8
< Cache-Control: public, max-age=30
< Date: Thu, 30 Jan 2014 22:11:28 GMT
< Accept-Ranges: bytes
< Server: testServer/1.0
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
This JavaScript file is included by an HTML page hosted on the same server through a <script> element in the document's <head>. The HTML page is served with the following cache control header:
Cache-Control: no-cache, must-revalidate, no-store, max-age=0
After loading the HTML page, I clicked through to a different page, waited 5 minutes for good measure and clicked on a link back to the original page, monitoring all HTTP requests - and the test file was never requested. This was reproduced consistently with both Firefox and Safari at their latest versions.
This got a bit long-winded, but the gist of my question is: my tests seem to show that mainstream browsers do not respect the RFC and will not revalidate stale cache entries. Did I misinterpret the RFC? Just as likely, did I botch my tests, and can someone prove them wrong? Or do browsers really not respect the max-age cache directive?
After much digging and help from #CodeCaster, the canonical answer to this question is that browsers do appear to respect the RFC: stale cache entries are always re-validated, except in the very specific case that they were accessed, directly or indirectly, through the browser's history. In this case, section 13.3 of the RFC applies:
History mechanisms and caches are different. In particular history mechanisms SHOULD NOT try to show a semantically transparent view of the current state of a resource. Rather, a history mechanism is meant to show exactly what the user saw at the time when the resource was retrieved.
I cannot reproduce your issue. I have tried to, using ASP.NET MVC, with the following code:
public ActionResult Index()
{
Response.AddHeader("Cache-Control",
"no-cache, must-revalidate, no-store, max-age=0");
return View();
}
public ActionResult JavaScript()
{
Response.AddHeader("Cache-Control", "public, max-age=30");
return View();
}
public ActionResult Page2()
{
return View();
}
The first action returns the Index page (relevant headers only):
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Pragma: no-cache
Expires: -1
Vary: Accept-Encoding
Content-Length: 182
<html>
<head>
<script src="/Home/JavaScript" type="text/javascript"></script>
</head>
<body>
Page 2
</body>
</html>
The JavaScript is returned like this:
HTTP/1.1 200 OK
Cache-Control: public, max-age=30
Vary: Accept-Encoding
Content-Length: 24
document.write('Foo');
And Page2 merely contains a link back to Home.
Now when I, using Internet Explorer 11, Chrome 32 or Firefox 26, I see the following behavior:
Upon the first request to /, the Index document is requested as well as the JavaScript file, and they are returned like shown above as verified with Fiddler.
When I click the "Page 2" link, only Page 2 is requested, because it doesn't contain anything but a link back to Page 1.
Now when I click the "Home" link from Page 2 within 30 seconds, the JS file is not requested again in any browser.
When I wait a while (> 30 seconds) on Page 2 and then click the "Home" link, the JS file is requested in all three browsers.
However, when I click the Back button from Page 2 in any browser after any period of time (either greater or less than 30 seconds), the Index file is always, but the JS file is never requested again in any browser.
It requires a refresh (F5) or navigating away and back by clicking "Page 2" followed by "Home" again to make the browser perform a new request for the JS file after it became stale.
I'm trying to make a POC of which is possible to have a website that uses http and https. So i have a control in my master page that needs info if the user is authenticated or not. For this I want to use HttpContext.Current.User.Identity.IsAuthenticated. If is authenticated shows info for authenticated users, if not appear the login control.
To authenticate the control make an AJAX POST request to the Login action that has the [RequireHttps] attribute. The URL used in the AJAX request is:
$.ajax({
type: 'POST',
url: '#Url.Action("ModalLogIn", "Authentication", null, "https", Request.Url.Host + ":44300")',
By the way I'm using VS2013 IIS express with SSL enabled.
As you can see in my AJAX request i'm using the HTTPS in action url.
The request is made to the server using SSL and the response is made with success.
The problem is that in the subsequent requests the ASPXAUTH cookie is not passed in the request header. So the server does not get the user authentication info. The subsequent requests are made with no SSL, are simple HTTP requests.
I know that in security terms the authentication is still insecure because i'm expecting to pass the ASPXAUTH through HTTP, but like I said is a POC and I want to see if it is possible to make a simple authentication request using HTTPS and all the others using HTTP.
As requested this is the Response Headers:
Access-Control-Allow-Orig... *
Cache-Control private
Content-Length 15
Content-Type application/json; charset=utf-8
Date Sat, 26 Oct 2013 18:57:55 GMT
Server Microsoft-IIS/8.0
Set-Cookie ASP.NET_SessionId=j2a53htev0fjp1qq4bnoeo0l; path=/; HttpOnly
ASP.NET_SessionId=j2a53htev0fjp1qq4bnoeo0l; path=/; HttpOnly
IAC.CurrentLanguage=en; expires=Sun, 26-Oct-2014 19:57:55 GMT; path=/
.ASPXAUTH=730DEDBFD2DF873A5F2BD581AA0E25B685CAD12C26AEA63AD82484C932E26B617687A05BB403216CC5EFCF799970810059F9CA2CF829F953580AF81FF48102003C0129AB04424F0D011A733CAAF1DE00688E5A4C93DEA97338DD2B5E7EE752F3761A470D52449BEBCA74098912DE37AA8C1E293B1C5D44EB1F9E9384DAAEF289; path=/; HttpOnly
X-AspNet-Version 4.0.30319
X-AspNetMvc-Version 3.0
X-Powered-By ASP.NET
X-SourceFiles =?UTF-8?B?QzpcTXkgRGF0YVxCaXRidWNrZXRcaWFjLXdlYnNpdGVcaW1wbGVtZW50YXRpb25cZG90bmV0XElBQy5XZWJcQXV0aGVudGljYXRpb25cTW9kYWxMb2dJbg==?=
It might be that when you set the auth cookie, it is marked as "Secure".
Using the Chrome Developer Tools, click on 'Resources', then cookies. Under the 'Secure' column check if the cookie is marked. If it is, then this means that the browser will not send the auth cookie using a non-secure connection.
Just a shot in the dark, but try setting the ASPXAUTH cookie with an expiration date.
It's possible that the browser, upon receiving a session cookie, will only present the session cookie on connections using the same protocol (https) as when it was set. I know for sure that persistent cookies do not have this limitation.
Also, investigate whether port could be the issue. If your AJAX goes over 44300 and your web goes over 80 or 443, it's possible the cookie is lost because the browser considers secure cookies to be port-specific. The W3C spec doesn't say whether cookies are private with respect to port; browsers vary.
All things work perfect like that ajax request in HTTPS manner by JS. Related respond works correctly too. But it seems that you have not prepared Login page in SSL too! My meaning is :
[RequireHttps]
public ActionResult Login()
{
return View();
}
Then Send request to HttpPost enabled Action. I believe that will work correctly. Unless you had some lack of requirements like MicrosoftMvcAjax.js and MicrosoftAjax.js in situations that you are using formal Microsoft ajax form by your ViewEngine (Perhaps by Razor). I think studying this Article can help you more.
Good Luck.
I am using ASP.NET. I either add or set a cookie (depending on whether the HttpRequest contains a cookie with specified key), and immediately afterward call Response.Redirect. The cookie is not set. Is this correct behavior? Is there something mutually exclusive about setting a cookie during an http response with a 302 status code?
Here's the source:
if (context.HttpContext.Request.Browser.Cookies)
{
var cookies = context.HttpContext.Request.Cookies;
var stateCookie = new HttpCookie(SR.session, clientState.SessionId.ToString());
if (cookies.AllKeys.Contains(SR.session))
{
context.HttpContext.Response.Cookies.Set(stateCookie);
}
else
{
context.HttpContext.Response.Cookies.Add(stateCookie);
}
}
Here are the Response headers
X-AspNetMvc-Version - 2.0
Connection - Close
Cache-Control - private
Content-Type - text/html
Date - Sun, 20 Mar 2011 03:48:04 GMT
Location - http://localhost:3599/Home/Redirected
Server - ASP.NET Development Server/9.0.0.0
X-AspNet-Version - 2.0.50727
After googling a bit it seems that yes, there can be problems with setting the cookie in the redirect response as it may be ignored by a few browsers. (It may make some sense, as the response is really telling the client to ignore the resource and get some other resource instead).
This has been discussed here already: Sending browser cookies during a 302 redirect
So I would change the architecture in a way that allows the page being redirected to to set the cookie.