You can subclass HandleErrorAttribute
and override its OnException
member (no need to copy) so that it logs the exception with ELMAH and only if the base implementation handles it. The minimal amount of code you need is as follows:
using System.Web.Mvc;
using Elmah;
public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
base.OnException(context);
if (!context.ExceptionHandled)
return;
var httpContext = context.HttpContext.ApplicationInstance.Context;
var signal = ErrorSignal.FromContext(httpContext);
signal.Raise(context.Exception, httpContext);
}
}
The base implementation is invoked first, giving it a chance to mark the exception as being handled. Only then is the exception signaled. The above code is simple and may cause issues if used in an environment where the HttpContext
may not be available, such as testing. As a result, you will want code that is that is more defensive (at the cost of being slightly longer):
using System.Web;
using System.Web.Mvc;
using Elmah;
public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
base.OnException(context);
if (!context.ExceptionHandled // if unhandled, will be logged anyhow
|| TryRaiseErrorSignal(context) // prefer signaling, if possible
|| IsFiltered(context)) // filtered?
return;
LogException(context);
}
private static bool TryRaiseErrorSignal(ExceptionContext context)
{
var httpContext = GetHttpContextImpl(context.HttpContext);
if (httpContext == null)
return false;
var signal = ErrorSignal.FromContext(httpContext);
if (signal == null)
return false;
signal.Raise(context.Exception, httpContext);
return true;
}
private static bool IsFiltered(ExceptionContext context)
{
var config = context.HttpContext.GetSection("elmah/errorFilter")
as ErrorFilterConfiguration;
if (config == null)
return false;
var testContext = new ErrorFilterModule.AssertionHelperContext(
context.Exception,
GetHttpContextImpl(context.HttpContext));
return config.Assertion.Test(testContext);
}
private static void LogException(ExceptionContext context)
{
var httpContext = GetHttpContextImpl(context.HttpContext);
var error = new Error(context.Exception, httpContext);
ErrorLog.GetDefault(httpContext).Log(error);
}
private static HttpContext GetHttpContextImpl(HttpContextBase context)
{
return context.ApplicationInstance.Context;
}
}
This second version will try to use error signaling from ELMAH first, which involves the fully configured pipeline like logging, mailing, filtering and what have you. Failing that, it attempts to see whether the error should be filtered. If not, the error is simply logged. This implementation does not handle mail notifications. If the exception can be signaled then a mail will be sent if configured to do so.
You may also have to take care that if multiple HandleErrorAttribute
instances are in effect then duplicate logging does not occur, but the above two examples should get your started.
Microsoft recommends using singular for Enum
s unless the Enum
represents bit fields (use the FlagsAttribute
as well). See Enumeration Type Naming Conventions (a subset of Microsoft's Naming Guidelines).
To respond to your clarification, I see nothing wrong with either of the following:
public enum OrderStatus { Pending, Fulfilled, Error };
public class SomeClass {
public OrderStatus OrderStatus { get; set; }
}
or
public enum OrderStatus { Pending, Fulfilled, Error };
public class SomeClass {
public OrderStatus Status { get; set; }
}
Best Answer
I'm going to have to disagree with the previous answers of using either plural or singular and being consistent. Each controller should use a different convention based on whether they interact with single or multiple entities. Especially since the controller name is used by default in the URL.
While the project templates use singular (HomeController, AccountController), there is only one Home and the Account actions only operate on the single account for the session. I would not expect the URLs of /homes to access the homepage, nor would I expect to go to /accounts to manage my account settings.
The plural HomesController would work for a real estate website that had methods related to listing and searching multiple homes: /homes/new-listings.