Most of browsers have window.onerror event which fired when JavaScript error occur. You can bind your function to this event which receives three parameters: message, URL and line number where error raised.

Let’s create function which will be graceful handling of JavaScript errors, send in poor JavaScript AJAX request all information about error and then we can log it with Log4Net and send email notice.

Step 1: Create JavaScript Handler

/// JSErrorHandler.js
// JS error handler
window.onerror = function(msg, url, line) {
    if (encodeURIComponent) {
        return loadXMLDoc("/Error/JSErrorHandler", "msg=" + encodeURIComponent(msg) + '&url=' + encodeURIComponent(url) + "&line=" + line);
    };
    return false;
};
// Ajax request
function loadXMLDoc(url, params) {
    var req;
    if (window.XMLHttpRequest) {
        try {
            req = new XMLHttpRequest();
        } catch (e) {
            req = false;
        }
    } else
        if (window.ActiveXObject) {
        try {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                req = false;
            }
        }
    }

    if (req) {
        req.open("POST", url, true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.send(params);
        return true;
    }
    return false;
}

Step 2: Handle request with information in Error Controller

/// ErrorController.cs
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

[HttpPost]
public EmptyResult JSErrorHandler()
{
    // Init Log4Net library
    log4net.Config.XmlConfigurator.Configure();

    if (!string.IsNullOrEmpty(Request["msg"]) && !string.IsNullOrEmpty(Request["url"]) && !string.IsNullOrEmpty(Request["line"]))
    {
        try
        {
            System.Text.StringBuilder bodystr = new System.Text.StringBuilder();
            bodystr.Append("<html><head>");

            bodystr.Append("<style>");
            bodystr.Append(" body {font-family:\"Verdana\";font-weight:normal;font-size: .7em;color:black;} ");
            bodystr.Append(" p {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}");
            bodystr.Append(" b {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}");
            bodystr.Append(" H1 { font-family:\"Verdana\";font-weight:normal;font-size:16pt;color:red }");
            bodystr.Append(" H2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }");
            bodystr.Append(" H4 { font-family:\"Verdana\";font-weight:bold;font-size:11pt;}");
            bodystr.Append(" pre {font-family:\"Lucida Console\";font-size: .9em}");
            bodystr.Append(" .marker {font-weight: bold; color: black;text-decoration: none;}");
            bodystr.Append(" .version {color: gray;}");
            bodystr.Append(" .error {margin-bottom: 10px;}");
            bodystr.Append(" .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }");
            bodystr.Append("</style>");
            bodystr.Append("</head><body bgcolor=\"white\">");

            bodystr.Append(String.Format("<b>Date:</b> {0}<br>", DateTime.Now));
            bodystr.Append(String.Format("<b>Page:</b> <a href=\"{0}\">{0}</a><br>", Request.ServerVariables["HTTP_REFERER"].ToString()));
            bodystr.Append(String.Format("<b>JS File: </b><a href=\"{0}\">{0}</a><br>", HttpUtility.HtmlEncode(Request["url"])));
            bodystr.Append(String.Format("<b>Error Message: </b>{0}<br>", HttpUtility.HtmlEncode(Request["msg"])));
            bodystr.Append(String.Format("<b>Line:</b>{0}<br><br>", HttpUtility.HtmlEncode(Request["line"])));

            int i = 0;
            bodystr.Append("<h4>Server Variables:</h4>");
            for (i = 0; i <= Request.ServerVariables.Count - 1; i++)
            {
                bodystr.Append(String.Format("<b>{0}:</b> {1}<br>", Request.ServerVariables.Keys[i], Request.ServerVariables[i]));
            }

            // Add Session Values in email
            bodystr.Append("<h4>Session Variables:</h4>");

            if ((Session != null))
            {
                if (Session.Count > 0)
                {
                    foreach (string item in Session.Keys)
                    {
                        bodystr.Append(String.Format("<b>{0}:</b> {1}<br>", item, (Session[item] == null ? "" : Session[item].ToString())));
                    }
                }
                else
                {
                    bodystr.Append("<b>No Session values: 0</b> <br>");
                }
            }
            else
            {
                bodystr.Append("<b> No Session values: nothing</b> <br>");
            }
            bodystr.Append("</body></html>");

            AlternateView bodyHtmlView = AlternateView.CreateAlternateViewFromString(bodystr.ToString(), new System.Net.Mime.ContentType("text/html"));

            MailMessage message = new MailMessage { From = new MailAddress("support@kitsula.com") };
            message.To.Add(new MailAddress("support@kitsula.com"));
            message.Bcc.Add(new MailAddress("IgorKitsula@gmail.com"));
            message.Subject = String.Format("JS Error on the site - {0}", Request["msg"]);
            message.AlternateViews.Add(bodyHtmlView);
            using (SmtpClient client = new SmtpClient())
            {
                client.Send(message);
            }
            // Save error to database using Log4Net
            log.Error(bodystr.ToString());
        }
        catch (Exception ex)
        {
            // If sending email failed - save error to DB using Log4Net
            log.Fatal("Error", ex);
        }
    }
    return null;
}

Here we are saving error to DB with Log4Net library and send email with error.

Step 3: Register action in routing rules table:

/// Global.asax.cs
routes.MapRoute(
    "JSError", // Route name
    "Error/JSErrorHandler",
    new { controller = "Error", action = "JSErrorHandler"},
    new string[] { "Kitsula.Controllers" }
);

And put reference to created JavaScript errors handler. I suggest to put it in the header of materpage:

<!-- Site.Master -->
<head runat="server">
  ...
  <script type="text/javascript" src="/Scripts/JSErrorHandler.js"></script>
  ...
</head>

That’s it. Let’s create simple test anywhere on the page:

<script type="text/javascript">
   $().ready(function () {
       alert(generateError);
   });
</script>

And we should receive an error message:
Date: 03/01/2011 2:23:28 AM
Page: http://localhost:12611/About
JS File: http://localhost:12611/About
Error Message: generateError is not defined
Line: 60