.NET Retrieving Error StackTrace in Custom Error Page - c#

I am running .NET 3.5 and IIS7.
I was trying to use customErrors to redirect to a custom error page that could still display the exception details, stack trace, etc. I had a hard time getting it to work, trying about 20 different approaches I found online (mostly on stackoverflow), some of which were slight variations of others. I preferred to have the redirect to happen in Web.config because I wanted the custom error page to be easily found/edited outside the code.
Here's what I finally got to work. I'm posting because I tried so many of the more complex approaches I found here and they didn't work for me, and just wanted to post the simple one that ultimately did.
Web.config:
<customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx" redirectMode="ResponseRewrite" />
Without the redirectMode="ResponseRewrite", I could not access the exception details from my custom error page.
Error.aspx
protected void Page_Load(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.GetBaseException() != null) ex = ex.GetBaseException();
litErrorMessage.Text = String.Format("<div class=\"error\">{0}</div>", ex.Message);
litErrorStackTrace.Text = String.Format("<b>Source:</b>\n{0}\n<b>Stack Trace:</b>\n{1}\n", ex.Source, ex.StackTrace);
}
else
{
litErrorStackTrace.Text = "No Exception information available.";
}
}
I also tried using
HttpException ex = (HttpException)HttpContext.Current.Server.GetLastError();, as seen in some examples, but that did not work.
I also tried all kinds of code in Global.asax -> Application_Error, but it turns out it was not necessary. After trying all kinds of code there, including storing session variables, Application_Error is now empty.

Related

How to fix the issue of Invalid viewstate

I have developed one web application in ASP.NET(Framework 4) with C# and deployed on one external server. As I checked server's log, the Invalid ViewState exception logged periodically. To resolve this issue, I have tried many solutions but non of that worked for me. I don't want to set enableviewstatemac property to false in web.config for security reason. (May be setting this to false will resolve the issue.)
Getting this error even for the pages that contains very small amounts of controls.
Error Description/Stacktrace:
Application_Error | Invalid viewstate.
Client IP: [IP]
Port: 26824
Referer: [URL with parameter]
Path: /page.aspx
User-Agent: Mozilla/5.0 (Linux; Android 8.1.0; SAMSUNG SM-G610F Build/M1AJQ) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/7.4 Chrome/59.0.3071.125 Mobile Safari/537.36
ViewState: /wEPDwUKMTU0MjgwMzYxMg8WAh4HTWVzc2FnZQULbWFsaS1icmlkZXMWAmYPZBYCAgMPZBYCAgEPZBYEAgEPDxYCHgRUZXh0BQZCcmlkZXNkZAIDDxQrAAIPFgQeC18hRGF0YUJvdW5kZx4LXyFJdGVtQ291bnQClQFkZBYCZg9kFioCAQ9kFgICAQ9kFgICAQ9kFg5mD2QWBGYPZBYEZg8VAQ9QaG90b3MvTUc4MC5qcGdkAgEPZBYCAgEPZBYCZg8VAQRNRzgwZAICD2QWAmYPFQEKMTk5Ni0xMC0wMmQCAQ9kFgICAQ9kFgJmDxUBBzVmdCAzaW5kAgIPZBYCAgEPZBYCZg8VAQdEaXBsb21hZAIDD2QWAgIBD2QWAmYPFQEiRGlwbG9tYShDaXZpbCksICBBdXRvIENhZCwgM0RTIE1heGQCBA9kFgICAQ9kFgJmDxUBDE5vdCBFbXBsb3llZGQCBQ9kFgICAQ9kFgJmDxUBDE5vdCBFbXBsb3llZGQCBg9kFgJmD2QWAgIBDw8WAh4LUG9zdEJhY2tVcmwFJX4vcHJvZmlsZS1kZXRhaWxzLmFzcHg/cHJvZmlsZWlkPU1HODBkZAICD2QWAgIBD2QWAgIBD2QWDmYPZBYEZg9kFgRmDxUBD1Bob3Rvcy9NRzc5LmpwZ2QCAQ9k...at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString, Purpose purpose)
Try 1: Used Machine key(key for .Net 4.0) generated by one online tool in config file.
Code:
<machineKey
validationKey='2EEA416CEFC6D6BE856ED57B97FB9CA7DFACE17C073125949A1D682C80A44BB2A
D887DDDC13DBFB0954F1000FEE5757E99693F222F8E28CAA2E6DAB8C4F99E0C'
decryptionKey='877478B2F33A74226ABEF55FDCC1A76E43F1BBEA6241A592'
validation='SHA1' />
<pages enableViewStateMac='true'/>
</system.web>
Try 2: Compressing the ViewState
As code is long, I have added link of the code here that I have tried.Compressing the ViewState
Try 3: MaxPageStateFieldLength property of page in web.config.
In this way, in web.config file, it showing warning as MaxPageStateFieldLength attribute is not allowed.
Code:
<system.web>
<pages MaxPageStateFieldLength="20"/>
</system.web>
Try 4: Place hidden fields for Encrypted Viewstate and Event validation on the top of the form
In this way, I have override the Render event of Page and write the code taken from this link: Link
None of the above solutions worked for me. Please correct me if I have did any thing wrong in above ways. Please ask for any other inputs if more clarification is needed.
Currently I have provided one workaround. I have catched this specific exception in application's error event and redirect to same page that causing this issue. But I am not satisfied with this workaround as issue is still exist.
Workaround:
void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
if (exception != null)
{
if (exception is System.Web.HttpException && exception.InnerException is System.Web.UI.ViewStateException)
{
Response.Redirect(Request.Url.AbsoluteUri);
WriteLog("Application_Error", "Invalid viewstate | Redirect to: " + Request.Url.AbsoluteUri);
}
else
{
WriteLog("Application_Error", exception.InnerException.Message + "|" + exception.StackTrace + "|" + Request.RawUrl);
}
}
// Clear the error from the server
Server.ClearError();
}

validating my mvc error handling

I have this in place in global.asax, and I was hoping some folks could tell me if I'm making any glaring mistakes. This my first MVC application.
protected void Application_Error(object sender, EventArgs e)
{
if (HttpContext.Current.IsDebuggingEnabled)
{
throw Server.GetLastError();
}
Exception exception = Server.GetLastError();
Response.Clear();
//here I email (exception.ToString()) to a helpdesk system.
Server.ClearError();
Response.Redirect("/Error/");
}
Basically I wanted something that would:
a) Let me get the raw thrown exception when in debug.
b) In production, send the exception to a logging service / helpdesk app.
c) In production, hide the exception from the user and present a simple error page.
So far it seems to work just fine but was just curious if there's anything wrong with my approach.
Please refer custome error configuration in web config

ASP.NET Custom Error Page for Web App that uses a Master Page

Reference KB306355: How to create custom error reporting pages in ASP.NET by using Visual C# .NET
I understand how to create a Custom Errors page. There are many examples of how to do it, like in the link above.
None of the examples I have found shows how to do what I am after.
I have a Web Application that uses a Master Page.
In my Master Page, I have a Label control used for errors that all pages will see:
<h4 id="bannerError"><asp:Label ID="lblError" runat="server" /></h4>
In the code behind on that Master Page, I have this:
public void Page_Error(object sender, EventArgs e) {
var err = Server.GetLastError().GetBaseException();
ErrorMessage = String.Format("URL {0}: {1} Error: {2}", Request.Url, err.GetType(), err.Message);
Server.ClearError();
}
public string ErrorMessage {
get { return lblError.Text; }
set {
LogError(value);
lblError.Text = value;
}
}
The ErrorMessage is a property. My other pages can easily access it, and I was easily able to edit out the part about writing the error to our server's database.
The Web.config page configuration (snippet):
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<customErrors defaultRedirect="Default.aspx" mode="On">
<error statusCode="403" redirect="Default.aspx" />
<error statusCode="404" redirect="Default.aspx" />
</customErrors>
</system.web>
</configuration>
How would I edit my files so that any errors that occur on any of my pages in my application (that derive from Master Page), simply show this basic information through the Master Page instead of redirecting the page to another URL?
I know the question was about how to get the MasterPage solution to work, but I think that using the application level Error event is the best way to make a catch-all error handler to forward to an error page.
You basclly need to handle the Application_Error in the Global.asax file. Here you can not only handle all page-level errors, but also application-level errors and HTTP errors of some types (if they can reach your application pipeline).
I think this is a better and more cetralized method. Adding MasterPage-level or BasePage-level error event handlers is also possible, but as a second layer.
Look here for a good example of doing this.
You won't be able to use controls to set the error message for unhandled Page level errors because no controls will be created (see this MS article). You could catch errors on the Page level and set the Master Page content like this:
protected override void OnError(EventArgs e) {
var err = Server.GetLastError().GetBaseException();
var errorMessage = String.Format("URL {0}: {1} Error: {2}", Request.Url, err.GetType(), err.Message);
((MyMasterPageClass)Master).ShowError(errorMessage);
Server.ClearError();
}
And then in the Master Page set the content directly:
public void ShowError(string message) {
Response.Write(string.Format("<h4 id=\"bannerError\">{0}</h4>", message));
}
But again, your Master Page wouldn't be rendering anyway, so it sort of defeats the purpose. If you really want to avoid the redirecting to an error page, you could load the content with ajax using something like jQuery.get(), and then display the results/errors as needed:
var request = $.get("www.mywebsite.com/Bugs2012.aspx");
request.done(function (data) {
$("#childContent").html(data);
});
request.fail(function (xhr, status, msg) {
var displayMsg = "Request could not be completed. ";
if (status === "error") {
switch (xhr.status) {
case 404:
displayMsg += "The content could not be found.";
break;
}
}
$("#bannerError").text(displayMsg);
});
I tried to create a jsfiddle, but it's a bit contrived because of the cross-domain ajax issues: js fiddle

Showing Detailed Error Messages

I have a little Try Catch block that will tell the user more detailed information when invalid data is passed to my application:
try
{
//do something that throws an exception because of invalid data
}
catch (Exception ex)
{
throw new Exception("You have invalid data");
//throw ex;
}
When I run the application locally with invalid data it throws the Exception as expected:
You have invalid data
However when I publish it to the server it will only throw Exceptions like this for the same exact error:
There was an error processing the request.
I can still run the code with valid data, so I know everything else is working correctly.
Is there something else I have to add to my web.config?
Here's what I have now:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpErrors errorMode="Detailed" />
<asp scriptErrorSentToBrowser="true"/>
</system.webServer>
You shouldn't really be showing your site visitors exceptions in this way.
If you are validating user data, then do it with form validation at the user interface level.
Exceptions are for dealing with exceptional circumstances. If you have invalid data that hasn't come from your user but has caused some exceptional circumstances then your user probably doesn't need to know the details. It's common in this situation to show a page with some kind of generic "Technical Error" message that apologises for the problem and assures them someone is looking into it.
If you want to see the details of exceptions on your server during development then you should set custom errors to off in the web.config
<system.web>
<customErrors mode="Off">
</customErrors>
</system.web>

exception catching in Global.ascx app_error

I have web application in asp.net and C#
I am trying to handle exceptions if they occur anywhere within this application.
like suppose the behaviour should be if and exception like this occurs
//generate your fictional exception
int x = 1;
int y = 0;
int z = x / y;
it should catch it in the app_error of the global.ascx file and redirect it to the Default.aspx page. i got the logging part but the redirect is not working as i still get the
Server Error in '/' Application.
page. or may be it is redirecting and getting killed in the middle..
this is what is there in global.ascx
protected void Application_Error(object sender, EventArgs e)
{
logger.Fatal(this.Server.GetLastError().GetBaseException());
logger.Info("FatalLogger Passed");
//get reference to the source of the exception chain
Exception ex = Server.GetLastError().GetBaseException();
Response.Redirect("~/Default.aspx?error=MessageHere");
}
this in the code in web.config
<authentication mode="Forms">
<forms loginUrl="Login.aspx" defaultUrl="~/Default.aspx" name="GUI" slidingExpiration="true" timeout="30" path="/">
</forms>
</authentication>
any ideas.. ill; be happy to provide more information.
Thanks
ok i want this approach for a reason because whenever there is an error the user get logged out and i dont want that to happen instead go to the default page
Have you tried calling Server.ClearError() before the redirect in Application_Error? It's been a while since I played with this, but I believe that if you don't call ClearError then the framework still thinks the error is unhandled.
Configure custom error pages
BTW, I recommend ELMAH for the logging part...
Try using Server.Transfer(page)
Also be wary of passing the error message via the Query String as it can open you up to XSS problems. Pass an error code and then display the message dependent on the code (using a switch statement)

Categories