The goal of our application was to use the same custom logging we created for our ASP.NET MVC applications. We implemented a solution that used some of the techniques in ElmahExceptionLogger:
WebApiApplication (Global.asax.cs)
protected void Application_Start()
{
var serializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver = (DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new CustomExceptionLogger());
GlobalConfiguration.Configuration.Filters.Add(new TokenAuthenticationAttribute());
}
CustomExceptionLogger
/// <summary>
/// Modified from ELMAH,
/// URL: https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/Elmah/Elmah.Server/ExceptionHandling/ElmahExceptionLogger.cs
/// </summary>
public class CustomExceptionLogger : ExceptionLogger
{
private const string HttpContextBaseKey = "MS_HttpContext";
public override void Log(ExceptionLoggerContext context)
{
HttpContext httpContext = GetHttpContext(context.Request); // Retrieve the current HttpContext instance for this request.
NameValueCollection serverVariables = new NameValueCollection();
LogException logException = new LogException();
try
{
if (httpContext != null && httpContext.Request != null && httpContext.Request.ServerVariables != null)
serverVariables = httpContext.Request.ServerVariables;
logException.Log(context.Exception, serverVariables);
}
catch (Exception e)
{
// swallow error because writing to log is failing
}
}
private static HttpContext GetHttpContext(HttpRequestMessage request)
{
HttpContextBase contextBase = GetHttpContextBase(request);
if (contextBase == null)
{
return null;
}
return ToHttpContext(contextBase);
}
private static HttpContextBase GetHttpContextBase(HttpRequestMessage request)
{
if (request == null)
{
return null;
}
object value;
if (!request.Properties.TryGetValue(HttpContextBaseKey, out value))
{
return null;
}
return value as HttpContextBase;
}
private static HttpContext ToHttpContext(HttpContextBase contextBase)
{
return contextBase.ApplicationInstance.Context;
}
}
LogException
public class LogException
{
public bool Log(Exception exception, NameValueCollection serverVariables)
{
var logService = new LogService();
int loop1, loop2;
StringBuilder serverVariableKeys = new StringBuilder();
bool logged = false;
if (HttpContext.Current != null)
{
// Get names of all keys into a string array
string[] allKeys = serverVariables.AllKeys;
for (loop1 = 0; loop1 < allKeys.Length; loop1++)
{
if (allKeys[loop1].ToUpper() != "ALL_HTTP" && allKeys[loop1].ToUpper() != "ALL_RAW")
{
serverVariableKeys.Append(allKeys[loop1] + " : ");
string[] values = serverVariables.GetValues(allKeys[loop1]);
for (loop2 = 0; loop2 < values.Length; loop2++)
{
serverVariableKeys.AppendLine("Value " + loop2 + ": " + values[loop2]);
}
}
}
}
if (exception != null)
{
exception.Data.Add("ServerVariables", serverVariableKeys.ToString());
logged = logService.LogException(exception, exception.TargetSite.Name);
}
return logged;
}
}
I haven't include LogService source because this is specific to where it gets logged to, which can be a database or text file.
Any suggestions for improvement?
CustomExceptionLogger
is derived fromExceptionLogger
rather than usingIExceptionLogger
? I feel that using the interface would give you more mileage overall. \$\endgroup\$