I am attempting to catch all errors except '404-File not found' error in global.asax file and writing in to a text file in server,But lot of errors gets missed ,like FormatException Error,Sessionout Error and "Yellow Page of Error" Appears !
How can I catch all errors here.
void Application_Error(object sender, EventArgs e)
{
CT.Bussiness.DevCommonFunctions devTools = new CT.Bussiness.DevCommonFunctions();
HttpContext ctx = HttpContext.Current;
//ctx.Response.
// Get page url
if (ctx != null)
{
string pageName = ctx.Request.Url.ToString();
Exception ex = Server.GetLastError().GetBaseException();
HttpException checkException = (HttpException)ex;
if (checkException.GetHttpCode() != 404)
{
string errorDate = DateTime.Now.ToString();
//string pageName =pageName;
string errorMessage = ex.Message;
string errorSource = ex.Source;
//string errorInnerException=ex.InnerException.ToString();
string errorData = ex.Data.ToString();
string errorTarget = ex.TargetSite.ToString();
string errorStack = ex.StackTrace.ToString();
devTools.WriteErrorsIntoErrorLog(errorDate, pageName, errorMessage, errorSource, "InnerException", errorData, errorTarget, errorStack);
//devTools.SendErrorMail("developer3#devwebservices.net,developer4#devwebservices.net,developer5#devwebservices.net,hr#devwebservices.net", errorDate, pageName, errorMessage, errorSource, "InnerException", errorData, errorTarget, errorStack);
//Response.TrySkipIisCustomErrors = true;
Response.Redirect("~/Error.aspx");
//Response.Redirect("Error.aspx");
}
}
}
SOLVED
I Followed Like this as KPL Adviced below:
Implemented Elmah
Excluded Global.asax and
Wrote redirection code in web.config.
Thus Solved !
Use:
1.) web.config "customErrors" tag to avoid "Yellow Page of Error":
<customErrors mode="On" defaultRedirect="~/Error.aspx">
<error statusCode="400" redirect="/error/400-bad-request/" />
<error statusCode="404" redirect="/error/404-file-not-found/" />
<error statusCode="500" redirect="/error/500-server-error/" />
</customErrors>
2.) Also try using Elmah to logging errors.
ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.
Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilities without changing a single line of your code:
Logging of nearly all unhandled exceptions.
A web page to remotely view the entire log of recoded exceptions.
A web page to remotely view the full details of any one logged exception, including colored stack traces.
In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
An e-mail notification of each error at the time it occurs.
An RSS feed of the last 15 errors from the log.
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'm trying to make a custom page in my asp.net project. I created a page for 404 not found errors. Here is a part in web config:
<customErrors mode="On" defaultRedirect="Errors.aspx">
<error statusCode="404" redirect="404.aspx"/>
</customErrors>
When I write to web browser like "(websitename)/asdfasdf.aspx", I can see to custom error page which I created, but when I write "(websitename)/asdfasdf", I see "Server Error / 404 - File or directory not found." page (Default Error page).
Do you know how can I redirect all page extensions to my custom error page?
In the Application_Error in global.asax file, find the server error code and redirect to corresponding page based on error code:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Response.Clear();
HttpException httpException = exception as HttpException;
if (httpException != null)
{
string redirectToPage;
switch (httpException.GetHttpCode())
{
// page not found
case 404:
redirectToPage = "(websitename)/PageNotFoundError.aspx";
break;
default:
redirectToPage = "(websitename)/GeneralError.aspx";
break;
}
Response.Redirect(redirectToPage);
}
}
I found the solution. I am using hosting to my website, so in hosting there was a setting to set 404 not found page. So, It solved.
In my global.asax file, I have the following code:
void Application_Error(object sender, EventArgs e)
{
Exception TheError = Server.GetLastError();
if (TheError is HttpException && ((HttpException)TheError).GetHttpCode() == 404)
{
Response.Redirect("~/404.aspx");
}
else
{
Response.Redirect("~/500.aspx");
}
}
When I navigate to an non-existing page, I get the generic error page. I don't want anything pertaining to custom error in the web.config because my plan is to add code to the global.asax file to log the exceptions. Is there a way to handle custom error with just the global.asax file?
EDIT:
The answer is not obvious, but this seems to explain it: http://www.asp.net/web-forms/tutorials/deployment/deploying-web-site-projects/displaying-a-custom-error-page-cs
If you scroll down a ways, you'll find this lovely tidbit:
Note: The custom error page is only displayed when a request is made
to a resource handled by the ASP.NET engine. As we discussed in the
Core Differences Between IIS and the ASP.NET Development Server
tutorial , the web server may handle certain requests itself. By
default, the IIS web server processes requests for static content like
images and HTML files without invoking the ASP.NET engine.
Consequently, if the user requests a non-existent image file they will
get back IIS's default 404 error message rather than ASP.NET's
configured error page.
I've emphasized the first line. I tested this out in the default template, and sure enough, this URL:
http://localhost:49320/fkljflkfjelk
gets you the default IIS page, whereas simply appending a .aspx makes the Application_Error kick in. So, it sounds like you need to enable customErrors/httpErrors if you want to have all errors handled.
For IIS <= 6, add to <system.web>:
<customErrors mode="On" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="/404.aspx"/>
<error statusCode="500" redirect="/500.aspx"/>
</customErrors>
For IIS7+, add to <system.webServer>:
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="/404.aspx" responseMode="ExecuteURL"/>
<remove statusCode="500"/>
<error statusCode="500" path="/500.aspx" responseMode="ExecuteURL"/>
</httpErrors>
I'll leave the original answer in case someone finds it useful.
I believe you need to clear the existing error code from the response, otherwise IIS ignores your redirect in favor of handling the error. There's also a Boolean flag, TrySkipIisCustomErrors, you can set for newer versions of IIS (7+).
So, something like this:
void Application_Error(object sender, EventArgs e)
{
Exception TheError = Server.GetLastError();
Server.ClearError();
// Avoid IIS7 getting in the middle
Response.TrySkipIisCustomErrors = true;
if (TheError is HttpException && ((HttpException)TheError).GetHttpCode() == 404)
{
Response.Redirect("~/404.aspx");
}
else
{
Response.Redirect("~/500.aspx");
}
}
Looks like IIS is looking for a page and did not find it.
Make sure:
404.aspx is created
customErrors tag from web.config is not present.
If you have custom errors set to RemoteOnly in web config - does this mean that MVC's application level error event in global.asax - Application_Error is not fired on error?
I have just noticed that when a certain error occurs in my application, and I am viewing the site remotely, no error is logged. However, when I am accessing the app on the server and the same error occurs, the error is logged.
this is the custom errors config setting:
<customErrors defaultRedirect="/Error/Application" mode="RemoteOnly">
<error statusCode="403" redirect="/error/forbidden"/>
<error statusCode="404" redirect="/error/notfound"/>
<error statusCode="500" redirect="/error/application"/>
</customErrors>
EDIT
Just out of interest for people - I ended up completely turning off custom errors and dealing with redirection in Application_Error like so:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
// ... log error here
var httpEx = exception as HttpException;
if (httpEx != null && httpEx.GetHttpCode() == 403)
{
Response.Redirect("/youraccount/error/forbidden", true);
}
else if (httpEx != null && httpEx.GetHttpCode() == 404)
{
Response.Redirect("/youraccount/error/notfound", true);
}
else
{
Response.Redirect("/youraccount/error/application", true);
}
}
If you do not call Server.ClearError or trap the error in the Page_Error or Application_Error event handler, the error is handled based on the settings in the section of the Web.config file.
See this SO question for more information
Coming from a desktop background I'm not sure exactly how to pass the exceptions I have caught to an Error page in order to avoid the standard exception screen being seen by my users.
My general question is how do I pass the exception from page X to my Error page in ASP.net?
I suggest using the customErrors section in the web.config:
<customErrors mode="RemoteOnly" defaultRedirect="/error.html">
<error statusCode="403" redirect="/accessdenied.html" />
<error statusCode="404" redirect="/pagenotfound.html" />
</customErrors>
And then using ELMAH to email and/or log the error.
The pattern I use is to log the error in a try/catch block (using log4net), then do a response.redirect to a simple error page. This assumes you don't need to show any error details.
If you need the exception details on a separate page, you might want to look at Server.GetLastError. I use that in global.asax (in the Application_Error event) to log unhandled exceptions and redirect to an error page.
We've had good luck capturing exceptions in the Global.asax Application_Error event, storing them in session, and redirecting to our error page. Alternately you could encode the error message and pass it to the error page in the querystring.
You can also get the exception from
Server.GetLastError();
Use the custom error pages in asp.net, you can find it in the customError section in the web.config
We capture the exception in the Global.asax file, store it in Session, the user is then redirected to the Error Page where we grab the exception for our Session variable and display the Message information to the user.
protected void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
this.Session[CacheProvider.ToCacheKey(CacheKeys.LastError)] = ex;
}
We do log the error message prior to displaying it the user.
I think you can use the global.asax -- Application_Exception handler to catch the exception and then store it for displaying in an error page.
But actually, your error page shouldn't contains code that might cause just another error. It should be simple "Oops! something went wrong" page.
If you want details on the error, use Windows' events viewer or ELMAH or employ some logging mechanism.