I have created the handler to process .html pages in my asp.net c# web application.
I also use url rewriting concepts.
Handler works fine when any html requrest come to server/website.
Coding details are as follows:
web.config Handler Code:
<add verb="*" path="*.html," validate="false" type="MyProject.ContentHandler,MyProject" />
ContentHandler.cs Code:
public void ProcessRequest(HttpContext context)
{
string strMapPage = string.Empty;
if (context.Request.Url.ToString().Contains("category"))
{
strMapPage = "/Links.aspx?ID=" + ProducID;
}
else
{
strMapPage = context.Request.Url.ToString();
}
context.Server.Transfer(strMapPage);
}
This method works fine for any .html request like for this page http://localhost:9111/user-category-1.html
But when i try to open the page like '/JS/TinyMCE/imagemanager/index.html'
It throws the error "Error executing child request for /JS/TinyMCE/imagemanager/index.html"
How to solve this problem?
From microsoft:
Microsoft Internet Information Services (IIS) dispatches the Server.Transfer or the Server.Execute request to the appropriate Internet Server Application Programming Interface (ISAPI) extension based on the extension of the requesting file. For example, a request for an .aspx page is dispatched to the Aspnet_isapi.dll ISAPI extension.
After the request is dispatched to appropriate ISAPI extension, the ISAPI extension cannot call another ISAPI extension. You receive the error message "Error executing child request for PageName.asp" because the Aspnet_isapi.dll file, which handles requests to ASP.NET pages, cannot forward the request to the Asp.dll file, which handles requests to ASP pages.
Your haldler is creating problem,
try this:
This is caused by a custom HTTP Handler being added by another application that is most likely being run in the root of your web site. To resolve the problem, modify the web.config file. After add:
<httpHandlers>
<clear />
<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory" />
</httpHandlers>
I have added the handler in web.config and it resolved the issue.
<add name="tinyMceIndexHandler" verb="*" path="/js/tiny_mce/plugins/imagemanager/pages/im/index.html" type="System.Web.StaticFileHandler" />
Related
I've currently got httpErrors setup to deal with 500's here:-
<httpErrors errorMode="Custom" existingResponse="Replace">
......
<remove statusCode="500"/>
<error statusCode="500" path="/server-error" responseMode="ExecuteURL"/>
</httpErrors>
This works fine, but in the case where iis receives the error I still get the yellow screen of death. An example is when entity framework can not connect to the database and I receive:-
Cannot open database "Test-DB" requested by the login. The login failed. Login failed for user 'sa'.
I've setup customErrors to deal with this:-
<customErrors mode="On" defaultRedirect="error.html" redirectMode="ResponseRedirect">
<error statusCode="500" redirect="error.html" />
</customErrors>
which works as expected as long as there is no modules without preCondition="managedHandler".
I have a few modules which deal with images and css files and are in the same project.
<modules runAllManagedModulesForAllRequests="false">
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
<add name="ImageHandler" type="foo.bar.ProductImageHandlerHttpModule" />
<add name="CustomCssHandler" type="foo.bar.CustomCssHttpModule" />
<add name="Glimpse" type="Glimpse.AspNet.HttpModule, Glimpse.AspNet" preCondition="integratedMode" />
</modules>
Comment these out and I get the error.html, keep them in and I get
Runtime Error Description: An exception occurred while processing your
request. Additionally, another exception occurred while executing the
custom error page for the first exception. The request has been
terminated.
showing that a module from the project is also erroring when trying to show the error.html.
Does anyone know a fix/workaround?
Its a tough situation - your error comes from HttpModule, which is run for every single request - including request to error.html page. One way is to route static files (such as error.html) just via your server - and ignore them on .NET level; this may not be always possible (sometimes handling static files on .NET level is handy). The only other way I can think off is hook in global.asax to error event and handle it yourself (which will ignore the customErrors)
Something like:
public class Global : System.Web.HttpApplication
{
protected void Application_Error(object sender, EventArgs e)
{
// is there an error ?
var error = Server.GetLastError();
if (error != null)
{
// mark the error as - "i'll handle it myself"
Server.ClearError();
// load error.html manually & dump it to response
var content = File.ReadAllText(Server.MapPath("~/error.html"));
Context.Response.Write(content);
// set correct error code
Context.Response.StatusCode = 500;
}
}
}
Note: this can be ironed out, but you see the general principle ...
As #Ondrej said, another error occurred when handling the custom error page comes from unhandled exception on HttpModule, thus it is necessary to either skip or bypassing customErrors section on web.config file.
This code also includes how to skip custom errors generated from IIS, besides generating custom HTML error page:
protected void Application_Error(Object sender, EventArgs e)
{
// Get last error occurred
var exception = Server.GetLastError();
// catch unhandled exceptions
if (exception is HttpUnhandledException)
{
// handle the error by ASP .NET itself
Server.ClearError();
// write status code handling
HttpContext.Current.Response.WriteFile(Server.MapPath("~/error.html"));
HttpContext.Current.Response.StatusCode = 500;
HttpContext.Current.Response.StatusDescription = "Internal Server Error";
// set ASP .NET handlers instead of using IIS handlers
HttpContext.Current.Response.TrySkipIisCustomErrors = true;
}
}
Additionally, to get rid of YSOD pages generated by IIS you may set existingResponse attribute to pass error handling into ASP .NET Application_Error method as this:
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="PassThrough">
<remove statusCode="500" />
<error statusCode="500" responseMode="File" path="/error.html" />
</httpErrors>
</system.webServer>
The reason behind those settings based from Kanwaljeet Singla's explanation (source here):
existingResponse
Value of this section level property tells custom error module what to
do when response text is not blank. If a module call
IHttpResponse::SetStatus to set an error code and also sets up
response text, existingResponse property tells if custom error module
should replace current response text with its own error text or should
it let the current response text pass through. Asp.Net and WCF are
example of modules which sets error response text. This property can
be set to following three values.
Replace – This value make custom error module to always replace the error information with text generated by custom error module. If
existingResponse is set to “Replace”, errors/exceptions generated by
Asp.Net/WCF are replaced by IIS7 errors.
PassThrough – If existingResponse is seen as “PassThrough”, custom error module will always pass through responses from modules.
This setting will make custom error module return blank response if
modules don’t set any text.
Auto – This is the default value and tells custom error module to do the right thing. Actual error text seen by clients will be
affected depending on value of fTrySkipCustomErrors returned in
IHttpResponse::GetStatus call. When TrySkipCustomErrors is set to
true, custom error module will let the response pass through but if it
is set to false, custom errors module replaces text with its own text.
Asp.Net/WCF call IHttpResponse::SetStatus with TrySkipCustomErrors
true so that IIS doesn’t override their errors with its own. When
effective errorMode is “Detailed” and response is non-empty, this
value of existingResponse will act as “PassThrough” regardless of
value of TrySkipCustomErrors.
Hopefully this may figure out the essential things when setting custom error page for unhandled exception responses.
MSDN References:
https://msdn.microsoft.com/en-us/library/ms690576(v=vs.90).aspx
https://msdn.microsoft.com/en-us/library/system.web.httpresponse.tryskipiiscustomerrors(v=vs.110).aspx
SO References:
IIS7 Overrides customErrors when setting Response.StatusCode?
How to send status code "500" for generic error page in IIS?
Getting IIS7 'one liner' error when using custom error settings in web.config
It seems if your iis is set with Integrated Mode then Modules will still be run for static files. If you set it to Classic mode it will ignore the managed modules for static files.
Please refer this thread for more infomration see the answer of João Angelo Requests for static files are hitting the managed code in ASP.NET MVC3
The fix is either you changed your handler to not throw exception or you change iis to classic mode so if any handler or other part throws exception and iis redirects to error.html then none of manage module should hit.
I am developing an ASP.NET MVC application which needs to be loaded inside an iframe in another website. But the login page just won't appear inside the iframe because an Header is being sent in the response X-Frame-Options which is set to SAMEORIGIN. Browser is not displaying the page in iframe because of this. I already Googled and tried multiple things but nothing worked.
I am using ASP.NET forms authentication. May be in this case IIS adds this header in login page for added security. But I need to get rid of this in my use case.
I tried adding a custom header
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="ALLOW" />
</customHeaders>
</httpProtocol>
But the SAMEORGIN is still being added in the header with comma.
I also tried adding Header value from C# using Response.Headers["X-Frame-Options"] = "ALLOW". It cause two headers with the same name.
I also tried this in web.config
<customHeaders>
<remove name="X-Frame-Options" />
</customHeaders>
It also didn't worked.
MVC 5 automatically adds an X-Frame-Options Header, so go to your Global.asax file and add this to the Application_Start() method:
System.Web.Helpers.AntiForgeryConfig.SuppressXFrameOptionsHeader = true;
Please note that especially for a login page it is bad practice to remove this header, because it opens up your site for login credentials phishing attacks. So if this site of yours is publicly accessable I strongly recommend to keep this header.
Old question, but for other people searching for similar question, you can remove the X-Frame-Options in specific actions using the following solution:
First, add this code to method Application_Start in Global.asax.cs (as #Florian Haider said):
System.Web.Helpers.AntiForgeryConfig.SuppressXFrameOptionsHeader = true;
This will suppress the header in all actions. Add a new file named NoIframeAttribute.cs containing the following code:
using System.Web.Mvc;
namespace MyApplication
{
public class NoIframeAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Headers.Set("X-Frame-Options", "SAMEORIGIN");
}
}
}
Add the following line to RegisterGlobalFilters method in FilterConfig.cs:
filters.Add(new NoIframeAttribute());
Now, we have the header added to all actions again. But now we can remove it when needed. Just add the following line wherever needed:
Response.Headers.Remove("X-Frame-Options");
Well, I know it's IIS which is supposed to invoke it. Anyway; I have a Sharepoint solution which is supposed to return a special string when files with particular extensions are clicked on document libraries.
In the corresponding web.config file I have following to run this HTTP Handler:
<system.webServer>
<handlers>
...
<add name="MyFileHandler" path="*.bar" verb="*" type="Foo.Example.MyHandler, Foo.Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3b53a24010893ac2" resourceType="File" />
...
</handlers>
</system.webServer>
And the HttpHandler class is something like this:
namespace Foo.Example
{
public class MyHandler : IHttpHandler
{
public MyHandler(){} //For breakpoint
public void ProcessRequest(HttpContext context)
{
//Do stuff and write to response.
}
public bool IsReusable
{
get { return false; }
}
}
}
When I try to open a file with '.bar' extension on Sharepoint, it returns 404. What I do in ProcessRequest is not relevant because when I debug the handler, I can see that the handler's constructor is invoked but not the 'ProcessRequest'. Besides the debugger I have also put debug lines(File.AppendAll), again only the constructor gets invoked according to the debug output.
IIS 7.5.7600
Sharepoint 2010 Foundation
Turns out
resourceType="File"
on handler tag in web.config was the problem. Either remove it or set it as "Unspecified".
That is already mentioned here which, unfortunately, I failed to spot before.
The only thing I can think of is to try moving your handler to be really the first one.
Otherwise it could be better to actually integrate with SharePoint instead of trying to override its behavior. In this case you probably should post separate question for what you want to achieve.
I am hosting a wcf service in IIS 7. I was curious if it would be possible to create my own .svc HttpHandler mapping and class to handle service requests.
For example, if I was to intercept any requests to files that ended with an extension of ".foo" I could add this to my web.config
<handlers>
<add name="*.foo_**" path="*.foo" verb="*" type="MyServer.FooHttpHandler" />
</handlers>
And I could have a class in my default root that did the following
public class FooHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// do stuff, validate?
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("filename={0}", url));
HttpContext.Current.Response.AddHeader("Content-Type", "fooMimeType");
HttpContext.Current.Response.WriteFile(url);
HttpContext.Current.Response.End();
}
public bool IsReusable
{
get { return false; }
}
}
Is it possible to do something like this with wcf .svc requests? I'm not sure if it'd be the exact same thing or not, since I'm not necessary serving a file to respond with, I want to intercept and proxy the response.
Or is a better way to implement a service behavior that does my required pre-service logic?
What are you trying to achieve? Not sure if you can replace the existing *.svc http handler - but what you can do much more easily is create your own custom ServiceHostFactory for the WCF service. You basically add one attribute your *.svc file:
<%# ServiceHost Language="C#" Debug="true"
Service="YourNamespace.YourService"
Factory="YourNamespace2.YourServiceHostFactory" %>
Using this, IIS will now instantiate your own YourServiceHostFactory and ask you to create an instance of the YourService class. Maybe you can hook into the flow here and do what you need to do?
You could use ASP.NET Routing and an IRouteHandler that returns your own IHttpHandler implementation as well if you really want to as well
http://msdn.microsoft.com/en-us/library/system.web.routing.iroutehandler.gethttphandler.aspx
http://msdn.microsoft.com/en-us/library/cc668201.aspx
I've done this in the past when setting up WCF Data Services and I don't see why it can't work here as well.
I am trying to enable output caching on all ashx files in my site. I'm trying to keep the server from generating the file on each request - NOT trying to tell the browser to cache the file.
I've distilled my ashx file down to this simple code:
public class DefaultStyles : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/css";
StringBuilder styleSheet = new StringBuilder();
styleSheet.AppendLine(string.Format("/* Generated: {0}, {1} */", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));
context.Response.Write(styleSheet.ToString());
}
}
And in my web.config file, i have this:
<system.webserver>
<caching enabled="true">
<profiles>
<add extension=".ashx" policy="CacheForTimePeriod" duration="00:01:00" />
</profiles>
</caching>
</system.webserver>
Still, every request i make to the ashx file generates a new version with the current date and time in it.
What am i doing wrong?
Thanks.
Maybe this will help?
http://objectmix.com/dotnet/393333-output-caching-custom-http-handler.html
It would seem to suggest that since you're not using the normal page handler, the output caching module isn't invoked.
Simon
I was actually doing everything right, just not testing in the right environment. Once i deployed the simple example above on our IIS 7 server, it worked as expected with the code above. It should be noted that this DID NOT work on our IIS 6 server. I had not realized that this was a new feature only available in IIS 7