There is a HttpModule that change Server field in Response Headers. But it does not work in ASP.NET/IIS7 classic mode. what is the solution for remove or change Server field in reponse header?
public class CloakHttpHeaderModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders);
}
public void Dispose()
{
}
private void context_PreSendRequestHeaders(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
context.Response.Headers.Set("Server", "Apache 2.0");
//HttpContext.Current.Response.Headers.Set("Server", "WSGIServer/0.1 Python/2.6.1");
}
}
You can't do this unless you're running at least IIS7, Integrated Pipeline Mode and .NET 3.0. The documentation states this:
HttpResponse.Headers Property
The Headers property is only supported with the IIS 7.0 integrated
pipeline mode and at least the .NET Framework 3.0. When you try to
access the Headers property and either of these two conditions is not
met, a PlatformNotSupportedException is thrown.
Related
I have a website with files which are static like Jquery library, images and other JS files.
So, I wish to set expiry time for those resources specifically so that those can be easily retrieved from users cache and without caching other static resources
can anybody suggest a way to do that in asp.net 3.5?
Thank You
You should separate this static files in folder and configure it directly on IIS
Here's a example for IIS6:
http://www.websiteoptimization.com/secrets/advanced/9-7-content-expiration-IIS.html
Or via code you can implement an IHttpModule
public class CacheExpiresModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
string url = context.Request.Url.ToString();
if (url.Contains("/Static/"))
{
context.Response.Cache.SetExpires(DateTime.Now.AddYears(30));
context.Response.Cache.SetMaxAge(TimeSpan.FromDays(365));
}
}
}
and configure it on your web.config
You can leverage browser caching setting an expiration data through http headers. There is a brief explanation of this process from Google Developers / Page Speed Insight:
https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
I've recently installed VS 2012 and .net Framework 4.5, and everything is mostly ok, except that I occasionally get the error:
This operation requires IIS integrated pipeline mode.
I of course have Managed pipeline mode: Integrated in IIS.
protected override void OnLoad(EventArgs e)
{
var st = new StackTrace(true);
string message = String.Format("Redirect to url: {0}, Stack Trace:\r\n{1}", url, st);
Trace.TraceInformation(message);
}
protected void Application_Start(Object sender, EventArgs e)
{
Trace.Listeners.Add(new OurAspTraceListener(Context));
}
And the Custom Trace listener is pretty simple.
private class OurAspTraceListener : TraceListener
{
private readonly HttpContext _context;
public OurAspTraceListener(HttpContext context)
{
_context = context;
_context.Trace.IsEnabled = true;
}
public override void Write(string message)
{
_context.Trace.Write(message); // it's throwing here.
}
public override void WriteLine(string message)
{
_context.Trace.Write(message);
}
}
It's really weird because if I just hit refresh it continues without any problem.
Any help would is appreciated,
Thanks.
Which version of IIS do you have ?
If you use IIS 7, make sure you have the application pool type set to integrated and not classic. The integrated pipeline mode is IIS 7 specific.
I have created an HttpModule so that Whenever I type "localhost/blabla.html" in the browser, it will redirect me to www.google.com (this is just an example, it's really to redirect requests coming from mobile phones)
My Questions are :
1) How do I tell IIS(7.0) to redirect each request to the "HttpModule" so that it is independent of the website. I can change the web.config but that's it.
2) Do I need to add the .dll to the GAC? If so, How can I do that?
3) The HttpModule code uses 'log4net' . do I need to add 'log4net' to the GAC as well?
Thanks
P.S. the site is using .net 2.0.
You can use request object in BeginRequest event
public class MyHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.context_BeginRequest);
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
//check here context.Request for using request object
if(context.Request.FilePath.Contains("blahblah.html"))
{
context.Response.Redirect("http://www.google.com");
}
}
}
There is a new app setting in asp.net 4.5
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
code like this can run in asp.net 4.0
protected void Button1_Click(object sender, EventArgs e)
{
CallAysnc();
}
public void CallAysnc()
{
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(Guid.NewGuid().ToString());
WebClient client = new WebClient();
client.DownloadStringCompleted += (object sender, DownloadStringCompletedEventArgs e) =>
{
asyncOp.PostOperationCompleted(CallCompleted, e.Result);
};
client.DownloadStringAsync(new Uri("http://www.google.com"));
}
private void CallCompleted(object args)
{
Response.Write(args.ToString());
}
But it doesn't work in asp.net 4.5,and when I remove the new appsetting,it works again!
So what's the meaning of "UseTaskFriendlySynchronizationContext" ?
Regarding UseTaskFriendlySynchronizationContext, from Microsoft Forums:
That tells ASP.NET to use an entirely new asynchronous pipeline which
follows CLR conventions for kicking off asynchronous operations,
including returning threads to the ThreadPool when necessary. ASP.NET
4.0 and below followed its own conventions which went against CLR guidelines, and if the switch is not enabled it is
very easy for asynchronous methods to run synchronously, deadlock the request, or otherwise not behave as expected.
Also, I think AsyncOperationManager is intended for desktop applications. For ASP.NET apps you should be using RegisterAsyncTask and setting <%# Page Async="true", see here for more details.
So using the new c# keywords your example would be:
protected void Button1_Click(object sender, EventArgs e)
{
RegisterAsyncTask(new PageAsyncTask(CallAysnc));
}
private async Task CallAysnc()
{
var res = await new WebClient().DownloadStringTaskAsync("http://www.google.com");
Response.Write(res);
}
The aim is to support the following by release but is not currently supported in the beta:
protected async void Button1_Click(object sender, EventArgs e)
{
var res = await new WebClient().DownloadStringTaskAsync("http://www.google.com");
Response.Write(res);
}
More details, quoted from ASP.NET 4.5.1 documentation for appSettings on MSDN:
aspnet:UseTaskFriendlySynchronizationContext
Specifies how asynchronous code paths in ASP.NET 4.5 behave.
...
If this key value is set to false [default], asynchronous code paths in ASP.NET 4.5 behave as they did in ASP.NET 4.0. If this key
value is set to true, ASP.NET 4.5 uses code paths that are optimized
for Task-returning APIs. Setting this compatibility switch is
mandatory for WebSockets-enabled applications, for using Task-based
asynchrony in Web Forms pages, and for certain other asynchronous
behaviors.
For an ASP.NET 4.0 / IIS7 web app, I would like to support compressed HTTP requests. Basically, I would like to support clients that would add Content-Encoding: gzip in the request headers, and compress the body accordingly.
Does anyone known how I achieve such a behavior?
Ps: concerning, I have multiple endpoints REST and SOAP, and it feels a better solution to support compression at the HTTP level rather than custom encoders for each endpoint.
For those who might be interested, the implementation is rather straightforward with an IHttpModule that simply filters incoming requests.
public class GZipDecompressModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += BeginRequest;
}
void BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if ("gzip" == app.Request.Headers["Content-Encoding"])
{
app.Request.Filter = new GZipStream(
app.Request.Filter, CompressionMode.Decompress);
}
}
public void Dispose()
{
}
}
Update: It appears that this approach trigger a problem in WCF, as WCF relies on the original Content-Length and not the value obtained after decompressing.
Try Wiktor's answer to my similar question here:
How do I enable GZIP compression for POST (upload) requests to a SOAP WebService on IIS 7?
...but please note his implementation on his blog contained a couple of bugs / compatibility issues, so please try my patched version of the HttpCompressionModule class posted on the same page.
Although hacky, you can get around WCF using the original Content-Length even after the request has been decompressed by setting the private _contentLength field in the HttpRequest class using reflection. Using Joannes Vermorel's code:
void BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if ("gzip" == app.Request.Headers["Content-Encoding"])
{
app.Request.Filter = new GZipStream(
app.Request.Filter, CompressionMode.Decompress);
// set private _contentLength field with new content length after the request has been decompressed
var contentLengthProperty = typeof(HttpRequest).GetField("_contentLength", BindingFlags.NonPublic | BindingFlags.Instance);
contentLengthProperty.SetValue(app.Request, (Int32)app.Request.InputStream.Length);
}
}