Access-Control-Allow-Origin header completely ignored by FireFox - asp.net

I set up my website (running IIS8.5) to send the response header for CORS to a subdomain off my main domain and the header response is getting to Firefox just fine. All plug-ins, ad-blockers, etc, are disabled and I can see the header in the DOM inspector.
I've tried:
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: https://services.mywebsite.com
Access-Control-Allow-Origin: http://services.mywebsite.com
Access-Control-Allow-Origin: null
Access-Control-Allow-Origin: "null"
I've verified the SSL Certificate is working just fine (it's a wildcard cert for *.mywebsite.com from Sectigo and I've verified that the entire certification path is working properly)
There are no other response headers except for: X-Frame-Options: SAMEORIGIN ,however, I removed it with the same result.
The site predates CORS by years (ASP.NET Webforms) and there are no other settings I can find that would prevent Firefox from acknowledging this response header.
I've read dozens of posts here (usually someone had a self-signed cert or forgot something) but am at a loss on what is wrong?
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://services.mywebsite.com/api/geodata/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
It's absolutely NOT MISSING! WTF Firefox?
Pulling hair out here. Anyone?
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
Expires: -1
Server: Microsoft-IIS/8.5
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: https://services.mywebsite.com
X-Frame-Options: SAMEORIGIN
Date: Wed, 27 May 2020 08:28:05 GMT
Someone else suggested adding a CORS module to IIS. I did, then added to my web.config file the following (in system.webserver section):
<cors enabled="true">
<add origin="*" allowed="true" >
<allowHeaders allowAllRequestedHeaders="true" />
</add>
</cors>
No Joy! Same message from Firefox (and Chrome) - both browsers completely ignore this directive. Could this be a bug in Mozilla?
-------------------- more info ---------------------------------
I think the problem is with the following jquery script with my CHAT (which is doing the calling to the api). It's worked for 12 years (and still works on old versions), so I'm looking to see what's been deprecated. I suspect that SignalR may be the issue and confusing the browser(s) - since SignalR is making the request (not sure, though -just guessing now). Sorry for not mentioning this sooner.
$.connection.hub.start()
.done(function () {
var existingChatId = getExistingChatId(chatKey);
$.get("https://services.mywebsite.com/api/geodata/", function (response) {
myHub.server.logVisit(document.location.href, document.referrer, response.city_name, response.region_name, response.country_name, existingChatId);
}, "json");
})
.fail(function () { chatRefreshState(false); });
------------------- after using wildcards for CORS headers --------------
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
Expires: -1
Server: Microsoft-IIS/10.0
X-Content-Type-Options: nosniff
X-SourceFiles: =?UTF-8?B?RDpcU2l0ZXNcaWNhcnBldGlsZXMyXFdlYlxzaWduYWxyXHN0YXJ0?=
X-Powered-By: ASP.NET
X-Frame-Options: SAMEORIGIN
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: *
Date: Sun, 07 Jun 2020 10:31:35 GMT
Still no joy - Headers are there. Must be a bug in ASP.NET webforms, IIS, SignalR (please note this is NOT MVC). Time to upgrade this site for this client. No one supports webforms anymore, anyway - it's dead.

It's not possible to do cross domain requests with SignalR and be CORS compatible. There is no way around this problem.
Just move your service to your www.yourwebsite.com and save your hair!

You can install cors dependency:
"Microsoft.AspNet.Cors": "6.0.0-rc1-final"
Add the CORS services in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
And enable it for specific domain:
public void Configure(IApplicationBuilder app)
{
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
}
Another option is enable cors for a specific method:
public class HomeController : Controller
{
[EnableCors("AllowSpecificOrigin")]
public IActionResult Index()
{
return View();
}
}
Or enable it for an specific controller:
[EnableCors("AllowSpecificOrigin")]
public class HomeController : Controller
{
}
If you're using MVC 3, and you have the file Global.asax you can use the method:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", allowedOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET,POST");
}
If you're using WebApi, you might use:
Install-Package Microsoft.AspNet.WebApi.Cors
And register the cors using:
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
}
And:
[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]
public class TestController : ApiController
{
// My methods...
}
Or enable it for whole the project:
public static void Register(HttpConfiguration config)
{
var corsAttr = new EnableCorsAttribute("http://example.com", "*", "*");
config.EnableCors(corsAttr);
}
ASP.Net web forms
Response.AppendHeader("Access-Control-Allow-Origin", "*");
Also try:
Response.AppendHeader("Access-Control-Allow-Methods","*");
Try adding directly in web config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Methods" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>

Do you have app.UseCors() in your middleware pipeline, before app.MapSignalR()?
You can start with app.UseCors(CorsOptions.AllowAll) to check if it'll work and then add your own domain.
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();

Related

.Net Core Cross Site Cookie Not Being Set by Chrome or Firefox

I am trying to use a cookie sent from an Asp.Net Core web api site in a cross-site configuratioun. I can see the cookie arrive in the Response, but from what I can tell, it's not being set by either Firefox or Chrome. Either way, it's not being sent back on subsequent requests to the API. When I use Postman, everything works great.
I've tried using .Net Core middleware for authentication cookies with server and app configuration in Startup.cs. But I get the same result if I use the direct approach of appending the cookie to the HTTP response in my controller (shown in the sample code below).
My web site is running out of VS Code from a minimal create-react-app, npm start, localhost port 3000.
My API is running of out Visual Studio 2019, .Net Core 3.1, web api site, port 44302. I've also tried deploying to an Azure app service so that my localhost web site could call a non-localhost API. Cookie still not set or sent.
Question is, how do I get the browser to set and then send the cookie back to the API when developing in localhost (or deployed anywhere, for that matter!)? I've spent hours combing Stack Overflow and other docs for the answer. Nothing has worked. Thanks much for any help!
From Startup.cs. Define CORS policy. Note the allow credentials that pairs with the web site's xhr withCredentials:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder
.SetIsOriginAllowed(host => true)
.AllowCredentials()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
...
}
From my controller endpoint simulating login:
[HttpPost]
public IActionResult FauxLogin(string Email, string Pwd)
{
Response.Cookies.Append("LoginCookie", "123456", new CookieOptions
{
//Domain = ".app.localhost", // some suggest specifying, some suggest leaving empty for default.
Path = "/",
Secure = true,
HttpOnly = false,
SameSite = SameSiteMode.None
});
return Ok(new { success = true });
}
Javascript function calling back to the API:
function callApi() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://localhost:44302/api/account/echo', true);
xhr.withCredentials = true;
xhr.send(null);
}
Response header from dev tools for faux login call. Set Cookie present:
content-type: application/json; charset=utf-8
server: Microsoft-IIS/10.0
set-cookie: LoginCookie=123456; path=/; secure; samesite=none
access-control-allow-origin: http://localhost:3000
access-control-allow-credentials: true
x-powered-by: ASP.NET
date: Sun, 31 Oct 2021 23:27:22 GMT
X-Firefox-Spdy: h2
Request header calling back to API. No cookie.
GET /api/account/echo HTTP/2
Host: localhost:44302
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: http://localhost:3000
Connection: keep-alive
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site

ASP.NET 4.5 Rest API's work in Unity Android/iOS build but fails with "Unknown error" in Unity WebGL build

I have scoured every possible forum for this and somehow have not gotten my WebGL to consume my ASP.NET 4.5 REST API's.
From what I can tell it is possibly related to WebGL requiring CORS, but even enabling this I cannot get the game to communicate with my API's
So either there's something wrong with the way I have implemented global CORS settings in ASP.NET or something else is breaking.
To be clear these API's are running perfectly well on Android/iOS/Windows builds and even in the editor.
What I have done so far:
Installed the Microsoft CORS build as recommended by Microsoft's documentation relating to it, then added the following code to the WebAPIConfig class in Visual Studio:
public static void Register(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
////new code
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
This is also in my web.config:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
I need these settings global so I used the "*" as indicated by the documentation to include all domains, method types, and headers because I use ASP.NET token authentication for my API.
Here is a code snippet that gets the token in the Unity project (just to be clear, this works on other platforms, only throws an error in a WebGL build)
public IEnumerator login()
{
string url = API.ROUTEPATH + API.TOKEN;
WWWForm form = new WWWForm();
form.AddField("grant_type", "password");
form.AddField("username", API.APIUSERNAME);
form.AddField("password", API.APIPASSWORD);
UnityWebRequest uwr = UnityWebRequest.Post(url, form);
uwr.SetRequestHeader("Content-Type", "application/json");
yield return uwr.SendWebRequest();
try
{
if (uwr.isNetworkError)
{
Debug.Log(uwr.error);
}
else
{
APIAuthToken returnauth = JsonUtility.FromJson<APIAuthToken>(uwr.downloadHandler.text);
if (!string.IsNullOrEmpty(returnauth.access_token))
{
API.hasAuth = true;
API.token = returnauth.access_token;
Debug.Log(returnauth.access_token);
}
}
}
catch
{
}
}
uwr.error produces the following, very helpful error: Unknown Error So I'm not even sure if it is CORS related, it's just my best guess based on the research I have done, but even with multiple different implementations of it I still sit with the same error. So if it's not a problem with the API's and with my Unity code please just ignore the ASP.NET code snippet.
cURL - A simple curl -I <endpoint> or curl -X OPTIONS -v <endpoint> can reveal a ton of information about what is happening related to CORS. It can allow you to set different origins, check preflight responses, and more.
"Let's say you have a backend API that uses cookies for session management. Your game works great when testing on your own domain, but breaks horribly once you host the files on Kongregate due to the fact that your API requests are now cross-domain and subject to strict CORS rules."
Is this your problem?
Problably on both sides if things are not set up properly will refuse to send cookies, but its good, its mean you have the control to allow what domains your sessions cookies will be sent to.
So probably you need first to configure the server to allow multiplies origins but make sure to validate the value against a whitelist so that you aren't just enabling your session cookies to be sent to any origin domain.
Example on a Node Express with CORS middleware(game ID 12345) and an origin whitelist below:
express = require('express')
var cors = require('cors')
var app = express()
var whitelist = ['https://game12345.konggames.com'];
var corsOptions = {
credentials: true,
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
};
app.use(cors(corsOptions));
app.options('*', cors(corsOptions)); // Enable options for preflight
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(8080, () => console.log(`Example app listening on port 8080!`))
cURL command to check the headers for an OPTIONS preflight request from an origin in the whitelist array:
curl -X OPTIONS -H"Origin: https://game12345.konggames.com" -v http://localhost:8080/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> OPTIONS / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Origin: https://game12345.konggames.com
>
< HTTP/1.1 204 No Content
< X-Powered-By: Express
< Access-Control-Allow-Origin: https://game12345.konggames.com
< Vary: Origin, Access-Control-Request-Headers
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
< Content-Length: 0
< Date: Tue, 24 Sep 2019 22:04:08 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
instruct the client to include cookies when it makes a cross-domain request,If the preflight response did not include Access-Control-Allow-Credentials: true, or if your Access-Control-Allow-Access is set to a wildcard (*) then the cookies will not be sent and you are likely to see errors in your browser's Javascript console:
Access to XMLHttpRequest at 'https://api.mygamebackend.com' from origin 'https://game54321.konggames.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Unity's UnityWebRequest and the older WWW classes use XMLHttpRequest under the hood to fetch data from remote servers. Since there is no option to set the withCredentials flag to true, we have to perform a pretty dirty hack when initializing our application in order to turn that on for the appropriate requests.
In your WebGL template or generated index.html:
<script>
XMLHttpRequest.prototype.originalOpen = XMLHttpRequest.prototype.open;
var newOpen = function(_, url) {
var original = this.originalOpen.apply(this, arguments);
if (url.indexOf('https://api.mygamebackend.com') === 0) {
this.withCredentials = true;
}
return original;
}
XMLHttpRequest.prototype.open = newOpen;
</script>
This snippet of code overrides the open method of XMLHttpRequest so that we can conditionally set withCredentials equal to true when desired. Once this is in place, cross-origin cookies should begin working between the Kongregate-hosted iframe domain and the game's backend servers!
info taken from here
also looks nice for this

How to set Response.Cache.SetCacheability in ASP.net WebForms?

How do i call Response.Cache.SetCacheability in WebForms?
If you look at MSDN's How to: Set a Page's Cacheability Programmatically:
To set a page's cacheability programmatically
In the page's code, call the SetCacheability method on the Cache property of the Response object.
The following code sets the Cache-Control HTTP header to Public.
Response.Cache.SetCacheability(HttpCacheability.Public);
Fine. Excellent. Good. Except how do i do it?
In try adding it to the Page_Init event handler:
protected void Page_Init(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.Public); //Public, while we test this
}
But the response from the server does is not public (and in fact is private):
HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Fri, 11 Jul 2014 14:11:06 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 9382
Connection: Close
So i want to confirm that my code is working, so i add some dummy headers:
protected void Page_Init(object sender, EventArgs e)
{
//Response.Headers.Add("X-Hello-Before", "WhyArentYouWorking");
Response.AddHeader("X-Hello-Before", "WhyArentYouWorking");
Response.Cache.SetCacheability(HttpCacheability.Public); //Client is allowed to cache
//Response.Headers.Add("X-Hello-After", "MyGodYouSuck");
Response.AddHeader("X-Hello-After", "MyGodYouSuck");
}
and the items appear in the response header:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Fri, 11 Jul 2014 14:16:47 GMT
X-AspNet-Version: 4.0.30319
X-Hello-Before: WhyArentYouWorking
X-Hello-After: MyGodYouSuck
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 9382
Connection: Close
The question is:
How do i make ASP.net do what i tell it to do?
I don't know where the bug is. It could be in ASP.net. It could be in WebForms. It could be in .NET Framework 4.0. It could be in Cassini.
Do you have a proxy in between, maybe that is not letting you change it? Otherwise you can try to set it IIS as well:
Open your IIS Manager, go to your application in the tree.
Select your application and in the right hand section Double click "HTTP Respond Headers" option.
Click "Add…" on the Actions Panel
Fill in the pop-up window:
Name: Cache-Control
Value: public
and see if that works.

OutputCache is sending wrong Vary header when the call hits the cache

I have an action method that I want to cache:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="index")]
public ActionResult Index()
{
return View();
}
With this approach:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
context.Response.Cache.SetOmitVaryStar(true);
context.Response.Cache.VaryByHeaders["Cookie"] = true;
if (User.Identity.IsAuthenticated)
{
Debug.Print("Authenticated");
context.Response.Cache.SetNoServerCaching();
context.Response.Cache.SetCacheability(HttpCacheability.Private);
return null;
}
else
{
Debug.Print("Non authenticated");
return custom;
}
}
The idea was to keep a cached version of the page for non-authenticated users, but avoid caching for authenticated ones.
I thought it will always return a Vary:Cookie HTTP header, but it is not.
Doing a test with Fiddler and issuing twice the same request, in the first HTTP call it goes good:
HTTP/1.1 200 OK
Cache-Control: public, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: Cookie
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:37 GMT
Content-Length: 441
But in the second one, it overwrites the header:
HTTP/1.1 200 OK
Cache-Control: public, max-age=297
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:39 GMT
Content-Length: 441
So, as far as I know, browsers won't cache the request even if it is public, since Vary:* means that the request has been generated with parameters that are not in the URL nor in the HTTP headers. Is there a way to fix this?
Regards.
UPDATE:
In a similar way, when I send two identical authenticated requests, the first call gets the private modifier, but not the Vary header:
HTTP/1.1 200 OK
Cache-Control: private, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:43:14 GMT
Last-Modified: Thu, 09 Feb 2012 12:38:14 GMT
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:38:14 GMT
Content-Length: 443
But the second one gets the same response that a non-authenticated request:
HTTP/1.1 200 OK
Cache-Control: public, max-age=298
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:44:32 GMT
Last-Modified: Thu, 09 Feb 2012 12:39:32 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:39:33 GMT
Content-Length: 443
I have uploaded a test project showing the issue so may be you want to give it a try.
Please be aware that there is an IHttpModule that sets a request as authenticated or not depending on if the request has a cookie or not, this is not a "real life" approach, it is just for testing purposes.
The project contains only a web page with a link to itself, a link that logs you in, and another link that logs you out:
LogIn : Sends a cookie in a HTTP 302 redirection to the home page again.
LogOut: Sends a expired cookie in a HTTP 302 recirection to the home page again.
The expected/ideal behaviour would be:
User access Index, and get the page from the server. The page show date "A".
User access Index again, and the browser shows the cached version.The page show date "A".
Clean browser cache.
User access Index again, and the browser shows the server cached version. The page show date "A".
User clicks login, and the broswer gets a new page, that show date "B".
User clicks logout, and the browser gets the server cached page. The page show date "A" again.
But this is the behaviour so far:
User access Index, and get the page from the server. The page show date "A".
User access Index again, and the browser shows the cached version.The page show date "A".
Clean browser cache.
User access Index again, and the browser shows the server cached version. The page show date "A".
User clicks login, and the broswer gets a new page, that show date "B".
User clicks logout, and the browser should get the server cached page, but it does not. The page show date "B" again from the browser cache. This is because the lack of the Vary header in the authenticated response.
I don't know if I get something wrong about caching, just missing some detail or the OutputCache does not work very well, but I would appreciate any guidance.
Cheers.
UPDATE 2:
My intention is to use the HTTP cache semantics to:
Allow browsers and proxys to cache the "public" version of the page.
Allow browsers to cache the "authenticated" version of the page for its user.
If I change the OutputCache declaration to do the caching only on the server and prevent the downstream and client caching:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Server, VaryByCustom="index")]
it behaves as expected, but the downstream and client cache is prevented, and that is not what I want.
I don't think the [OutputCache] attribute is what you want, the VaryByCustom method is basically saying that I want to cache different versions based on these parameters, it doesn't really have an option for Do Not Cache and the majority of the code in the attribute is built around server based caching.
That being said the documentation on MSDN for custom caching seems to indicate you need to return a string to vary on based on the authentication state:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if(custom == "user") return "User:" + context.Request.User.Identity.Name;
return base.GetVaryByCustomString(context, custom);
}
And then use the user literal in the VaryByCustom:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="user")]
public ActionResult Index()
{
return View();
}
So basically this would result in a cache being built for anonymous (assuming the anonymous identity is empty string or something) and every user on the server, and a Vary: * sent to the client I believe. Obviously not ideal what you are looking for.
If you really just want to cache the unauthenticated version using HTTP caching I would recommend not using the OutputCacheAttribute and using something more custom.
You could easily just write in your own custom attribute something like what you have for your GetVaryByCustomString implementation (this is just some pseudo code, would need more than this):
public class HttpCacheUnauthenticatedAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if(!filterContext.HttpContext.Request.IsAuthenticated) {
//TODO: set unauthenticated caching values and vary here
}
}
}
And then tag your action method with it:
[HttpCacheUnauthenticated]
public ActionResult Index()
{
return View();
}
Sort of wrestling with something similar myself. Have you tried in the web.config to the setting omitVaryStar=true
https://msdn.microsoft.com/en-us/library/ms228124(v=vs.100).aspx
I am using a custom cache provider and in this case there is a simple solution for this.
On the BeginRequest, based on the user authentication status, we set a context information to not run cache:
HttpContext.Current.Items["NoCache"] = "1";
And then on our GetVaryBy method we return null if this information is set:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (HttpContext.Current.Items["NoCache"] != null)
return null;
// remaining code here
}
And then on the cache methods, we can test the same. For instance:
public override object Add(string key, object entry, DateTime utcExpiry)
{
if (HttpContext.Current.Items["NoCache"] != null)
return null;
// remaining code here
}

IIS7 overwriting defined HTTP header values

I am attempting to set the content-type of an asp.net .ashx file to text/plain.
When I run this through the ASP.NET Development Server, the content-type is properly set. When I serve it through IIS7, however, the content-type (and any other header values I set) don't come through (it came through as text/html).
The only value set in the HTTP Response Headers section of IIS Manager is the X-Powered-By attribute. I tried setting the content-type here, but that didn't work. But if I removed the X-Powered-By attribute, it was removed from the header.
Any ideas?
Code in .ashx file
public class Queries1 : IHttpHandler, System.Web.SessionState.IReadOnlySessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("hello");
}
public bool IsReusable
{
get { return false; }
}
}
HTTP Header from IIS7 (pulled through python script):
[('content-length', '58'),
('x-powered-by', 'ASP.NET'),
('server', 'Microsoft-IIS/7.0'),
('date', 'Thu, 21 Oct 2010 15:51:28 GMT'),
('content-type', 'text/html'),
('www-authenticate', 'Negotiate, NTLM')]
To add HTTP Headers you need to use:
context.Response.Headers.Add("MyHeader", "Hello World!");
Based on Coding Gorilla's clarification, are you sure you're browsing to the correct url? If I try the exact same code as you've written I see the following in Fiddler:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Thu, 21 Oct 2010 20:11:44 GMT
Content-Length: 5
hello

Resources