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

2

11

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?

Vyky answered 19/2, 2014 at 16:57 Comment(3)
I know this was not the question, but an alternative would be to handle this in the global.asax Application_Error method. msdn.microsoft.com/en-us/library/24395wz3(v=vs.100).aspxParlando
Thanks @EladLachmi. I believe that is what I am doing now. I was looking for a more elegant approach that is wrapped up in my Master Page.Vyky
We have a very large site with many master pages and the only consistent way we found of logging all exceptions / redirecting to error pages for all the different types of exceptions thrown in our application is this.Parlando
S
2

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

Sheehy answered 21/3, 2014 at 23:13 Comment(2)
Could you show an example of how jQuery would catch when someone tried to access a page that my website no longer contained, like this old file www.mywebsite.com/Bugs2012.aspx?Vyky
Sure, there are a few different ways you could do it. If you used $.get() then you would check the response status code in the .fail() callback, if it's 404 you would set your message accordingly. You could also use $.ajax() and use the statusCode property to add callbacks for each statusCode. I don't like that way as well because it has the potential to split error handling unnecessarily. I'll edit my answer to show an example using $.get().Sheehy
P
3

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.

Parlando answered 26/3, 2014 at 8:9 Comment(0)
S
2

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

Sheehy answered 21/3, 2014 at 23:13 Comment(2)
Could you show an example of how jQuery would catch when someone tried to access a page that my website no longer contained, like this old file www.mywebsite.com/Bugs2012.aspx?Vyky
Sure, there are a few different ways you could do it. If you used $.get() then you would check the response status code in the .fail() callback, if it's 404 you would set your message accordingly. You could also use $.ajax() and use the statusCode property to add callbacks for each statusCode. I don't like that way as well because it has the potential to split error handling unnecessarily. I'll edit my answer to show an example using $.get().Sheehy

© 2022 - 2024 — McMap. All rights reserved.