I am using Google Page Speed on my website in IIS7 and I was wondering how to set
Leverage browser caching - The following resources are missing a cache expiration
Leverage proxy caching - Consider adding a "Cache-Control: public" header to the following resources.
I am using doDynamicCompression in my web.config and little confused how to set these ? Hoping for some help
Note: Reference being used http://www.iis.net/ConfigReference/system.webServer/httpCompression
Under system.webServer in web.config set for example
<caching>
<profiles>
<add extension=".png" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange" location="Any" />
<add extension=".jpg" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange" location="Any" />
<add extension=".gif" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange" location="Any" />
</profiles>
</caching>
This can also be configured from IIS Manager under Output Caching but what the GUI doesn't do is set the 'location' attribute. Setting it to 'Any' will set Cache-Control:public.
You can read more about it here.
I imagine you already figured this out, but read up on setting content expiration in IIS here.
Note that this only applies to static content served by IIS. If you are looking to set caching headers for dynamic content (ASPX, PHP, ISAPI, whatever), you need to generate your own Expires and Cache-Control headers in your application. IIS will (quite correctly) not attempt to apply cache-control headers to dynamic pages that may include Set-Cookie headers or private data. ASP and ASP.net automatically set "Cache-Control: private" by default for all pages, but you can override that behavior on a per-response basis.
Related
We have a web service which is denys access to all except a single IP address. This is configured like so
<location path="ASMX/Service.asmx">
<system.webServer>
<security>
<ipSecurity allowUnlisted="false">
<clear />
<add ipAddress="[Our IP address]" allowed="true" />
</ipSecurity>
</security>
</system.webServer>
We recently installed a Web Application Firewall, so now all traffic now comes from a single source. The firewall however collects the origin IP and puts it into a request header called 'X-Origin-IP'.
Is it possible to use the web.config to read this new header and only allow where certain value exists, or is it better to drop into the code and perform the analysis there?
I realize that this question seems to come up frequently. I've gone through each one and tried many of the suggested solutions. One solution did seem to get me to a "working" state, but it does not seem like it addressed the actual underlying issue, but instead somehow worked around it. So, let me explain my scenario and what I've tried.
I'm writing an AspNet WebApi application that will be served up by IIS. My application is currently using convention based routing, as opposed to attribute routing. My application needs to handle CORS pre-flight requests (OPTIONS). I've installed the required Microsoft.AspNet.WebApi.Cors package, from Nuget. Below are the versions of the AspNet packages that I'm using:
<package id="Microsoft.AspNet.Cors" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Cors" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net461" />
Based on my reading, the Microsoft.AspNet.WebApi.Cors package is supposed to add support for handling CORS pre-flight requests. This means I won't have to add manual OPTIONS action methods, etc - the nuget package brings that for me. So, I've configured the package so that it enables CORS for all available controllers, based on a commonly referenced blog post. To my understanding, this should be all that is needed for my application to begin responding to OPTIONS requests. Below is my configuration for completeness sake - it shows that I also configure some other things:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var jsonMapping = new RequestHeaderMapping("Accept", "text/html", System.StringComparison.OrdinalIgnoreCase, true, "application/json");
var corsAttribute = new EnableCorsAttribute("*", "*", "*");
config.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);
config.Services.Replace(typeof(IFilterProvider), new UnityFilterProvider(UnityConfig.Container));
config.EnableCors(corsAttribute);
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Lastly, I've seen some reference to some items in the web.config regarding the OPTIONSVerbHandler. Mine is left at whatever the default value is, which is shown below ...
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Finally, with all of these items in place, it appears that my application still fails to handle OPTIONS requests. Using postman, I simply send an OPTIONS request to any of my endpoints and regardless of endpoint I receive the following 405 response ...
Allow →POST
Cache-Control →no-cache
Content-Length →76
Content-Type →application/json; charset=utf-8
Date →Wed, 14 Feb 2018 20:50:14 GMT
Expires →-1
Pragma →no-cache
Server →Microsoft-IIS/10.0
X-AspNet-Version →4.0.30319
X-Powered-By →ASP.NET
X-SourceFiles →=?UTF-8?B?QzpcVXNlcnNccmNvbGVcRG9jdW1lbnRzXFZpc3VhbCBTdHVkaW8gMjAxN1xQcm9qZWN0c1xQb3J0YWwuUkVTVFxQb3J0YWwuUkVTVFxhY2NvdW50XGF1dGhlbnRpY2F0ZQ==?=
{"Message":"The requested resource does not support http method 'OPTIONS'."}
Here's some of the things I've tried to fix this:
I tried removing the OPTIONSVerbHandler from web.config, which seemed to make no change.
I tried explicitly putting EnableCorsAttribute on individual action methods and controllers, which seemed to make no change.
I explicitly put HttpOptionsAttribute on an action method, which seemed to fix the issue. This seems like the incorrect approach, though, as that attribute is for saying that action method is for handling OPTIONS requests, which is not at all what I want. I thought Microsoft.AspNet.WebApi.Cors package brings its own OPTIONS handler.
I tried switching to attribute-based routing, as opposed to the original convention-based routing. Didn't seem to change anything.
Does anybody know what could be causing this issue? It doesn't seem like my Microsoft.AspNet.WebApi.Cors package is correctly wired up, or doing anything. The response has no CORS headers in it. It looks like AspNet doesn't think it has any OPTIONS handler in place, despite me enabling it in my configuration.
I've seen this question asked in several other locations. Most answers focus on web.config hacks, custom filter attributes, other custom code, etc, as the solution. I want to mark what ended up being the solution in my scenario, which I believe to be many of the other folks' scenarios ...
The Microsoft.AspNet.WebApi.Cors package does indeed work and handle OPTIONS pre-flight requests. It only kicks into action when the appropriate CORS headers are present, though.
So, in my scenario, I was testing this using a tool, such as Postman. I was testing by sending explicit OPTIONS requests. Well, many of these tools don't send CORS pre-flight requests, and even then, when sending manual OPTIONS requests they do not include the required CORS headers that trigger the Microsoft.AspNet.WebApi.Cors functionality.
So, in the end, for me, there was no technical issue or bug, it was a lack of knowledge about how the nuget package works. When I switched back over to my JavaScript project, and made the request across origin, using fetch, the requests worked. Chrome sends the pre-flight OPTIONS, with appropriate CORS headers.
So, make sure you're testing using appropriate CORS headers, if you're using a tool like Postman!
This isn't a CORS issue per se. It's your web server not allowing OPTIONS requests. I realize this isn't an answer, but it should help you get on the path to narrowing it down some more.
I had an ASP.NET MVC app running on port 8799 that posted JSON data via an XMLHttpRequest to an MVC controller handler. This pipeline was working perfectly fine.
I recently spun up a second app, this time an Express app running on port 8080, that again posts JSON in the same way (same exact code, using again an XMLHttpRequest), to the same MVC controller running on port 8799. This time, however, it appears as though while the request is received by the controller, there is no data on it.
I'm wondering if this is because I am making a cross-origin request between these two ports. Going off of this hypothesis, I added the following custom headers to my web.config file:
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost" />
<add name="Access-Control-Allow-Headers" value="X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
<add name="Access-Control-Max-Age" value="1000" />
</customHeaders>
This does not seem to solve the issue. How can I debug this problem, I don't seem to be throwing any particularly useful exceptions?
The issue did turn out to be CORS. For whatever reason the web.config file was not being used by my .NET application. Thus, I setup CORS setting in my Startup.cs file instead, using services.AddCors() in my Configure() call.
I want to access some things in local and session storage located on the same domain, but using a different protocol. The data is cached on HTTP and needs to be retrieved under HTTPS.
How can I configure ASP.Net to allow this without hard-coding the web site name in my web.config? This is what I have now
<add name="Access-Control-Allow-Origin" value="https://my-web-site" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
Do you also need Access-Control-All-Methods?
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE" />
I suggest you follow the methods suggest here:
http://brockallen.com/2012/06/28/cors-support-in-webapi-mvc-and-iis-with-thinktecture-identitymodel/
It seems that ASMX implicitly does not allow the OPTIONS verb. I'm posting this question because I'm using jQuery AJAX calls with POST which first queries the server for available OPTIONS before the POST verb** is issued.
By default Web.config maps all verbs to legacy ASMX, as shown in this partial configuration sample, so everything should be routed properly:
<system.webServer>
<requestFiltering>
<verbs>
<add verb="OPTIONS" allowed="true"/>
<add verb="GET" allowed="true"/>
<add verb="POST" allowed="true"/>
</verbs>
</requestFiltering>
<handlers>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
However the HTTP Response is always 405 for an OPTIONS request. For example, the following request is given:
OPTIONS http://localhost:35920/MarkupTransfomer.asmx HTTP/1.1
Host: localhost:35920
Access-Control-Request-Method: POST
and always results in:
HTTP/1.1 405 Method Not Allowed
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
The jQuery AJAX call looks like the following, a recommendation from a fairly recent Encosia blog post for working with ASMX:
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://localhost:35920/MarkupTransfomer.asmx",
data: "{'hi'}",
dataType: "json"
});
** Note: I don't want to switch the client to use GET instead of POST.
Summary question:
Can I configure ASP.NET to allow ASMX to handle OPTIONS
Requests inherently without error?
Other ideas I've considered
I can look for a way to tell jQuery.ajax(..) not issue the OPTIONS verb before POST?
If what I'm asking from legacy ASMX isn't possible, I've considered two other potential ideas:
implement a System.Web.IHttpHandler, stick it in the web.config handlers section to manage only the verbs=OPTIONS requests to path=*.asmx outside of the default ASMX behaviour. This would be a doable workaround.
I can switch over to using WCF. However I want to know if ASMX is too unwieldly first.
Before I take action, I want to query the community for things I might have overlooked, or for better options (no pun).
UPDATE #1
Yep, my web service is being hosted on a different domain. Apparently there are a plethora of issues to navigate with Same Original Policy. This update is definitely worthwhile information to the context of the question all things considered!
However I want to ensure this question stays at the ASMX server and HTTP levels. Although I might be facing related browser issues in the near future, those aren't of consequence to solving the HTTP protocol level of this question. Thanks.
Looks like maybe it doesn't apply because I don't see it in the question, but my answer to this was that In the web config I had to remove the instruction to <remove name="OPTIONSVerbHandler" />
Kudos to the person who posted it near the end of this SO question
I don't know that ASMX was ever able to handle OPTIONS, even for AJAX requests. What exactly do you want to return in the case of an OPTIONS verb? What does the client intend by using OPTIONS?
Also, I've looked into this from the point of view of ASP.NET dealing with the OPTIONS verb. In my case, it was prohibited at the level of the root web.config, not at the ASP.NET or ASMX level. The default mapping for that verb is
<add path="*" verb="*" type="System.Web.HttpMethodNotAllowedHandler" validate="True" />
This corresponds to the 405 error you received.