ASP.NET: Only catch certain errors at page level? - c#

Looking at:
https://learn.microsoft.com/en-us/aspnet/web-forms/overview/getting-started/getting-started-with-aspnet-45-web-forms/aspnet-error-handling
and specifically:
private void Page_Error(object sender, EventArgs e)
{
Exception exc = Server.GetLastError();
// Handle specific exception.
if (exc is HttpUnhandledException)
{
ErrorMsgTextBox.Text = "An error occurred on this page. Please verify your " +
"information to resolve the issue."
}
// Clear the error from the server.
Server.ClearError();
}
Is there a way to only handle asp.net file uploader file size too big (e.g. over 50MB) and let all other errors be handled at the application level?
BTW, here is code to catch files that are too big at the application level:
//Global.asax
private void Application_Error(object sender, EventArgs e)
{
var ex = Server.GetLastError();
var httpException = ex as HttpException ?? ex.InnerException as HttpException;
if(httpException == null) return;
if (((System.Web.HttpException)httpException.InnerException).WebEventCode == System.Web.Management.WebEventCodes.RuntimeErrorPostTooLarge)
{
//handle the error
Response.Write("Too big a file, dude"); //for example
}
}
So in other words, can we "throw" an application level error from a page level error method (e.g., when it's anything other than that file size exception that we want to handle on that specific page)?

Related

How to pass Exception from Global.asax to another controller

I am using Application_Error method to handle and log exceptions. I need to pass Exception from Global.asax to Error controller
I tried
this.Session["w"] = (Exception)exception;
but that's not working.
My code looks like this:
protected void Application_Error(Object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
if (exception != null)
{
this.Session["w"] = (Exception)exception;
Server.ClearError();
ExceptionManager.LogExceptionToTextFile(exception);
ExceptionManager.LogExceptionToEmail(exception);
if (!Response.IsRequestBeingRedirected)
Response.Redirect("~/Error/Index");
}
}
You can try something like this
Exception exception = Server.GetLastError();
string errorId = Guid.NewGuid().ToString();
if (exception != null)
{
this.Application.Lock();
this.Application[errorId] = exception;
this.Application.Unlock();
Server.ClearError();
ExceptionManager.LogExceptionToTextFile(exception);
ExceptionManager.LogExceptionToEmail(exception);
if (!Response.IsRequestBeingRedirected)
Response.Redirect("~/Error/Index?errorId="+errorId);
}
and in the error controller
var Exception = (Exception)Application[Request["errorId"]]
EDIT:
If you want to use sessions, You might also want to replace
Response.Redirect("~/Error/Index");
With
Response.Redirect("~/Error/Index", false);
Reason you loose your session, is due to thread cancellation.
You can read more about it at When Should I Use Response.Redirect(url, true)?:

Append To Text File Each Error

I am using this syntax to write errors to a text file for logging in my Global.axax - it overwrites each time and only logs the most recent error. While this is helpful, it is not as helpful as I need it to be. How can I log each error that is raised?
This is my current code that only logs the most recent:
void Application_Error(object sender, EventArgs e)
{
Exception CurrentException = Server.GetLastError();
Server.ClearError();
if (CurrentException != null)
{
try
{
using (StreamWriter sw = new StreamWriter(Server.MapPath("HereAreErrors.txt")))
{
sw.WriteLine(CurrentException.ToString());
sw.Close();
}
}
catch (Exception ex) { }
}
}
As others have stated you're better off using an existing log tool to handle your logging. They have a myriad of features and, best of all, are maintained by someone else!
With that said, and in the interest of answering the question as asked, here's how to resolve your problem. It has the added benefit of creating the file if it doesn't exist.
void Application_Error(object sender, EventArgs e)
{
Exception CurrentException = Server.GetLastError();
Server.ClearError();
if (CurrentException != null)
{
try
{
File.AppendAllText(Server.MapPath("HereAreErrors.txt"), CurrentException.ToString());
}
catch (Exception ex) { }
}
}

Custom Error using Global.asax asp.net

I made an error; the page directs users in case of error in any applications within the website. I made Global.asax rather than using Webconfig. My question is : Is it possible to redirect user from Global.asax for those statusCodes "401", "404" and "500" in case of error rather than using Webconfig ?
In other words, using Global.aspx rather than Webconfig !? I am just curious to know.
Thank you
protected void Application_Error(Object sender, EventArgs e)
{
Exception ex = this.Server.GetLastError();
if(ex is HttpException)
{
HttpException httpEx = (HttpException)ex;
if(httpEx.GetHttpCode() == 401)
{
Response.Redirect("YourPage.aspx");
}
}
}
Yes it is possible. Here is little code example. This should be added in Global.asax.cs.
Never set customErrors to Off in your Web.config file if you do not have an Application_Error handler in your Global.asax file. Potentially compromising information about your Web site can be exposed to anyone who can cause an error to occur on your site.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
// Get the exception object.
Exception exc = Server.GetLastError();
// Handle HTTP errors
if (exc.GetType() == typeof(HttpException))
{
// The Complete Error Handling Example generates
// some errors using URLs with "NoCatch" in them;
// ignore these here to simulate what would happen
// if a global.asax handler were not implemented.
if (exc.Message.Contains("NoCatch") || exc.Message.Contains("maxUrlLength"))
return;
//Redirect HTTP errors to HttpError page
Server.Transfer("HttpErrorPage.aspx");
}
// For other kinds of errors give the user some information
// but stay on the default page
Response.Write("<h2>Global Page Error</h2>\n");
Response.Write(
"<p>" + exc.Message + "</p>\n");
Response.Write("Return to the <a href='Default.aspx'>" +
"Default Page</a>\n");
// Log the exception and notify system operators
ExceptionUtility.LogException(exc, "DefaultPage");
ExceptionUtility.NotifySystemOps(exc);
// Clear the error from the server
Server.ClearError();
}
Also once can get error code like
exc.GetHttpCode() == 403 so that
if (exc!= null && httpEx.GetHttpCode() == 403)
{
Response.Redirect("/youraccount/error/forbidden", true);
}
else if (exc!= null && httpEx.GetHttpCode() == 404)
{
Response.Redirect("/youraccount/error/notfound", true);
}
else
{
Response.Redirect("/youraccount/error/application", true);
}
Also see Custom error in global.asax

Catch all exceptions in ASP.NET C# rather than each method in a `try{} catch{}` block

Is there a better way to catch all exceptions in one place without writing try{} catch{} for each method?
You can catch the exceptions in your application by overwriting Application_Error found in Global.asax. However, using this approach you cannot act on these exceptions like you could using a regular try catch block.
You can log it
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
// if there's an Inner Exception we'll most likely be more interested in that
if (ex .InnerException != null)
{
ex = ex .InnerException;
}
// filter exception using ex.GetType() ...
// log exception ...
// Clear all errors for the current HTTP request.
HttpContext.Current.ClearError();
}
And/or redirect
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
// process exception
// redirect
HttpContext.Current.ClearError();
Response.Redirect("~/Error.aspx", false);
return;
}
And this is about all your can do.
Thanks All. I got an answer from a site.Here is the code i have modified according to the exception and logging errors with a third party(Elmah) in the application. Hope, it will be helpful for others.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
//Get the exception object
Exception exceptionObject = Server.GetLastError();
try
{
if (exceptionObject != null)
{
if (exceptionObject.InnerException != null)
{
exceptionObject = exceptionObject.InnerException;
}
switch (exceptionObject.GetType().ToString())
{
case "System.Threading.ThreadAbortException":
HttpContext.Current.Server.ClearError();
break;
default:
// log exception ...
//Custom method to log error
Elmah.ErrorSignal.FromCurrentContext().Raise(exceptionObject);
break;
}
}
}
catch
{
//Avoiding further exception from exception handling
}
}

ASP.NET error handling problems

I'm new to ASP.NET and I have a very basic site that I just want to grab all Application Errors and email them to me, while giving the user a error page. I read a lot on the subject and seems to be a lot of information. Below is what I came up with but I'm having problems keeping the Exception in session so I can email it to me.
I keep getting a NullReferenceException was unhandled by user code on the ex.Message from the Error.aspx.cs file.
Any thoughts?
Global.asax.cs-
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
HttpContext.Current.Response.Redirect("~/Error.aspx");
}
Error.aspx.cs-
public partial class Error : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Exception ex = (Exception)Session["Exception"];
this.SendEmail(ex);
Session.Remove("Exception");
}
}
private void SendEmail(Exception ex)
{
string body = "An exception occured at "
+ DateTime.Now.ToLongTimeString()
+ " on " + DateTime.Now.ToLongDateString()
+ "<br />" + ex.Message; //ERROR HERE
MailMessage msg = new MailMessage("from#email.com", "to#email.com");
msg.Subject = "Exception in Portal Website";
msg.Body = body;
msg.IsBodyHtml = true;
SmtpClient client = new SmtpClient("localhost");
client.Send(msg);
}
}
Your problem is that you are never setting Session["Exception"], so on your Error.aspx, Exception ex is always going to be null... and then doing ex.Message will throw the NullReferenceException. Even if you fix that and appropriately set Session["Exception"], what you are doing isn't ideal.
You could just send the email from the Application_Error function.
Your Response.Redirect (MSDN Entry) is going to cause ANOTHER exception (ThreadAbortException)
You should look at implementing ELMAH. It is easy to implement and does everything you want to do.
But if all you want to do is fix your code, just move the send email logic to Application_Error and then you don't have to worry about Session.
What I did in a similar instance is to throw all exceptions and then in your global.asax uses the Application_Error method to perform any work you need to with the error message.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
string exception;
Exception ex = Server.GetLastError();
if (ex.InnerException != null)
{
Exception innerException = ex.InnerException;
exception = ex.InnerException.Message;
}
else
{
exception = ex.Message;
}
//Send email here
//redirect to error page
}
I don't see you pushing the exception object to session, why not move the SendEmail method to global.ascx and SendEmail then redirect user to Error page. There are third party plugins like ELMAH that can do all this easily for you with simple configurations.
I'm in a similar bind. I'm going to check out ELMAH, but my project has a huge restriction on Open Source Projects, yours may to. Sucks to be me!
In which case I'd suggest creating a logging function for the message that you can call directly from the Global.asax. Something like:
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
LogException(ex);
HttpContext.Current.Response.Redirect("~/Error.aspx");
}
//Somewhere Else
void LogException(Exception ex)
{
WriteExceptionToEndOfTextFile(ex);
SendEmail();
}
This way if someone decides they want to suppress our exceptions, they can still properly handle the exception.

Categories

Resources