I have made a custom error page for my ASP.NET 4 application. I put the exception object in HttpContext.current.Session["CustomError"] but when the user is redirected to the error page HttpContext.current.Session["CustomError"] is null.
I do it in CustomError class constructor like this:
public CustomError(enExceptionType ExceptionType) : base(ExceptionMessage(ExceptionType)) {
HttpContext.Current.Session["CustomError"] = this;
}
when I step over the code Session["Error"] contains the error object.
any idea?
UPDATE:
I removed custom error page from web.config and added this to glabal.asax:
void Application_Error(object sender, EventArgs e)
{
if (Context.IsCustomErrorEnabled)
{
Response.Redirect("~/Error.aspx");
}
}
by stepping through this function I noticed that when an exception is thrown this function is called two time, the first time Session["CustiomError"] contains the error object but the second time its null.
Instead of using Response.redirect(URL) (which I assume you have in your code) use
Server.Transfer(URL)
or
Response.redirect(url, false)
Why Server.Transfer(url)?
Transferring to another page using
Server.Transfer conserves server
resources. Instead of telling the
browser to redirect, it simply changes
the "focus" on the Web server and
transfers the request. This means you
don't get quite as many HTTP requests
coming through, which therefore eases
the pressure on your Web server and
makes your applications run faster.
Source here.
Please let me know if one of these works for you.
UPDATE:
If you use a web config setting can you try adding ResponseWrite value to redirectmode var?
<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />
If this is still not working I suggest to implement this (I've done it in my application to log the errors in log files (for me as admin) and present a generic error to the user).
This solved the problem, but I would appreciate it if someone tells me why :)
void Application_Error(object sender, EventArgs e)
{
if (Context.IsCustomErrorEnabled)
{
Response.Redirect("~/Error.aspx");
**Server.ClearError();**
}
}
Related
In the site settings of our DotNetNuke installation, we set the Default Page for "500 Error Page" as you can see below.
After setting this, we were expecting to be redirected when an error occurs. Instead we're still redirected the the "Default.aspx?tabid=..." page.
Why isn't the correct page shown?
What do we need to change for it to work?
(We're using v9.02.00 366, .NET Framework 4.6)
EDIT: Here's how I force the error to occur using a custom module.
public partial class TriggerError500 : PortalModuleBase
{
protected void Page_Load(object sender, EventArgs e)
{
if(UserId == -1)
{
throw new NotImplementedException();
}
}
}
This module has been placed on a public page to test the error 500 page.
The 500 error page will most likely only be used when an exception is completely unhandled. For example, if an exception is handled by a developer, then a friendly message will be shown on the page with part of the exception in the URL. This may account for the URL thing you're seeing. It's the same page as the module in question, but in a different format.
When the exception is not handled, a visitor would ordinarily be shown the infamous "yellow screen of death" (YSOD) with error details. Depending on the settings in the web.config, the level of detail will be generic or detailed. I believe that this is the use case intended for the 500 error page. This is when you should see it.
If my memory serves me right, you may want to try this in your web.config:
<customErrors mode="On" defaultRedirect="500" />
A setting that will affect error handling at a platform level can be toggled in the security section
Screen Shot here
Due to the way that DNN handles the loading of modules, and pages, the code that you are writing does not actually trigger an HTTP 500 error, as the page itself is loaded properly. The module loading error is captured by the framework and the error is logged to the Admin Logs, but the page itself is rendered.
You typically get an HTTP 500 error when you cannot connect to the database or otherwise, in those cases the DNN will adhere to the rules.
It is possible, that you could set Response.StatusCode = 500; and then end the response and get the desired behavior, but i have NOT tested this.
I am using a generic error page using ASP.NET's <customErrors> directive.
<customErrors mode="On" defaultRedirect="500.html" redirectMode="ResponseRewrite">
</customErrors>
Problem - when an error occurs, this page does not return HTTP status "500". It comes as 200. So link checkers and spiders do not see that there is any problem.
How can I send the 500 HTTP status along with the static 500.html page?
Requirements:
I must use redirectMode="ResponseRewrite"
I can't use a dynamic page, only static .html.
The MSDN documentation for the customErrors element states that it is implemented by System.Web.Configuration.CustomErrorsSection. If we use Red Gate's .NET Reflector to analyze that class, we can see where that setting is used in the Framework.
It is used by System.Web.UI.Page.HandleError and System.Web.HttpResponse.ReportRuntimeError.
Both of these end up calling System.Web.HttpResponse.RedirectToErrorPage. (The name of this method is confusing: it is important to note that RedirectToErrorPage takes the redirectMode setting as a parameter, so it is called even if you are using ResponseRewrite and no redirection actually happens.)
The relevant part of the RedirectToErrorPage method is:
if (redirectMode == CustomErrorsRedirectMode.ResponseRewrite)
{
this.Context.Server.Execute(url);
}
There doesn't appear to be any way to set the response code in the error handling: at the end of the day it's just a plain Server.Execute. It therefore seems unavoidable that you would need to write code to achieve the HTTP response you want.
Can you re-examine why you want to use a plain .html file? This seems a sensible choice for error handling, because you don't want to go through all the overhead of a .aspx page when that might cause another error to occur.
But perhaps there is some middle ground which will be just as robust as a .html file?
For example, you could make a precompiled HttpHandler, register it to the URL /500.error, and then make 500.error your defaultRedirect page. (This would be similar to how ScriptResource.axd works.) If you precompile your module into a DLL (as opposed to on-the-fly compilation from a plain old .axd file), you may find it is just as robust in the face of error conditions. If you encounter an error where not even this will work, then a static .html file probably won't work either -- keep in mind that the customErrors directive still relies on .NET running under the hood, and still uses the StaticFileHandler to serve your .html file.
Alternatively you could consider a reverse proxy in front of your IIS application which would serve a friendly 500 page even in the face of catastrophic failure of the application pool. This would be more work to set up, but would be even more robust than customErrors, e.g. if your web.config becomes corrupted, even customErrors won't work.
In your gllobal.asax file add the following code
protected void Application_EndRequest(object sender, EventArgs e)
{
if (Request.Url.AbsolutePath.EndsWith("500.html"))
Response.StatusCode = 500;
}
OK, I have a solution, the only way I can get this to work is by bypassing the custom errors section in the web configuration file.
So, an example default.aspx
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
throw new Exception("boom");
}
}
Then in the global.asax file:
protected void Application_Error(object sender, EventArgs e)
{
// Clear the error to take control of process
Server.ClearError();
Response.WriteFile(Server.MapPath("500.html"));
Response.StatusCode = 500;
Response.StatusDescription = "Internal Server Error";
}
You can probably write a better handling mechanism for the 500.html part - I think this should do what you are trying to achieve.
Only tested with VS Cassini web server, however I see no reason why this shouldn't work in iis6.
Try configuring your custom errors section like this:
<customErrors mode="On" redirectMode="ResponseRewrite">
<error statusCode="500" redirect="500.aspx">
</customErrors>
In your 500.aspx file, change the response code in the page_load;
Response.StatusCode = 500;
Response.StatusDescription = "Internal Server Error";
This could be done with an isapi filter. It would have to be written in c, but it can modify the response status for the .html request so that the browser gets a 500 with you custom html page.
If you insist on changing the core HTTP signaling then you either have to give in on some demands or be prepared to write your own web server. Yes you have to run IIS7 integrated AppPool and you still may have to accept redirection to and active page since you are trying to fake that your server is down and server is not designed to fake suicide. So if it gives you one slim way to do it, your options are to either say thanks or develop your own, non-HTTP compliant server which will scramble response codes at will.
I handle my errors using Application_Error in global.asax.
How to check if the request is from the local client to display more information about the error or just show the yellow error page. Something like "remoteOnly" that ASP does when handling errors using web.config.
After I posted the question, I went back to my application and played around a little bit then I found this. Now I'm using it.
void Application_Error(object sender, EventArgs e)
{
if(!HttpContext.Current.Request.IsLocal)
HttpContext.Current.Server.ClearError();
// process error handling
}
I am developing an ASP.NET site with C# on IIS 7, but I hope for an answer that will apply to IIS 6 as well. Part of this site is the ability to upload up to 5 images at a time. I have a nice algorithm to resize the image that is uploaded to my optimal size and ratio.
So the only real size limitation I have is during the initial upload. I have modified my web.config to raise the packet limit from 4MB to 32MB. For the most part this takes care of my issues.
My question comes in the rare cases that a user tries to load more than my limit. I can raise the limit, but there is always a chance a user can find 5 files that are bigger. If a user selects files that are bigger, my try/catch block does not handle the error. The error is coming from IIS.
So how can I catch the error in C# code where I can make modifications to my ASP.NET interface to inform the user to select smaller files instead of them seeing a nasty error screen?
You can get access to the exception when the request length is exceeded. Use an HttpModule, and add a handler for the Error event.
The exception is of type: System.Web.HttpUnhandledException (with an InnerException of type: System.Web.HttpException).
To catch this exception, add this to your web.config:
<httpModules>
<add name="ErrorHttpModule" type="ErrorHttpModule"/>
</httpModules>
And add this class to your App_Code folder:
public class ErrorHttpModule : IHttpModule
{
private HttpApplication _context;
public ErrorHttpModule() {
}
private void ErrorHandler(Object sender, EventArgs e)
{
Exception ex = _context.Server.GetLastError();
//You can also call this to clear the error
//_context.Server.ClearError();
}
#region IHttpModule Members
public void Init(HttpApplication context)
{
_context = context;
_context.Error += new EventHandler(ErrorHandler);
}
public void Dispose()
{
}
#endregion
}
If you're using the traditional asp:FileUpload control, then there isn't a way to check the size of the files before. However, you can use a Flash or Silverlight approach. One option that has been suggested to me is Uploadify
I don't know for sure that this will work, but at least in IIS 7 you might try catching the Error event in an HttpModule that's configured to run for static files. From there, you could redirect to an appropriate error page.
You can catch these in Global (the global.asax.cs file). Add an Application_Error handler - you will get an HttpUnhandledException. Its InnerException will be an HttpException with the message "Maximum request length exceeded".
However, these errors are handled before your page code ever gets loaded or executed, so there is no way for your page to catch the exception or to know it ever happened. After catching this exception, you could stick a message in your Session for later display. You could also call response.Redirect from Global to display a new page, or redisplay the original with the error message from Session.
How to setup a common error page in ASP.NET website?
Also how to handel the error in Data Access Layer by common error page?
In my current project I'm sticking with Application_Error in the global.asax for showing the end-users a uniform error page in case of any unhandled errors. I added a sendmail call to mail certain exceptions to a mail address to get a better insight in what went wrong (you can't rely on customers/visitors to properly describe the problem).
After sending the mail and/or logging the problem I redirect users to a error.html with a generic errormessage.
In my DAL I try/catch most of the critical functions and show a warning/error accordingly (I return a status/message to show if for example a connection couldn't be made/timed out).
This is the pattern I tend to start with when starting a new app. Apologies this is in VB.NET ;)
In the global.asax Server.Transfer to your custom Error page.
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Server.Transfer("~/Error.aspx", False)
End Sub
Then in your custom error page.
Private Sub Page_Load
Response.Clear()
Dim err As Exception = Server.GetLastError
...
End Sub
Now you can test the Type of the exception. You'll need to recurse down through the inner exceptions as the parent exception will be probably be a general web exception. Get your DAL to throw a custom typed exception and you can test for that and handle differently.
here i am explaining the way to implement a custom error page feature.
Step by step implementation
Creating Error Page : Develop an error page (the page that has to be displayed when error occurs) in the root directory. Lets think that the name of the error page is ErrorPage.aspx
Configuring Web.Config : write the following code in Web.Config
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="~\ErrorPage.aspx"/>
</system.web>
</configuration>
Thats it!!! Now if any error occurs it will redirect to the error page. Now Sometimes we need to display the error. In that case we can write few lines of code in Global.asax
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException();
Session["LastException"] = ex.ToString();
}
As the exception has been captured and stored in the Session now we can show the message from the session. So we can write the following lines in ErrorPage.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
lblDisplayError.Text = Session["LastException"].ToString();
}
And we will be able to see the error on the label of ErrorPage.
Hope it will work fine.
Thanks
Pritom Nandy