问题
We are implementing a global exception handler for our WebAPI (like in this link)
http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling
We are also using log4net's LogicalThreadContext to pass around context information (like a call context id or a correlation id). For those of you not familiar, this uses CallContext.LogicalSetData and LogicalGetData.
My problem is that I can't seem to access the data once I get into our custom ExceptionLogger and ExceptionHandler classes. below is a very stripped down / pseduo code of what I mean.
Ideas of why this is happening?
public MyResponse Get(string someId)
{
CallContext.LogicalSetData("mytest", "555");
LogicalThreadContext.Properties["anotherprop"] = "999";
string contextValue = CallContext.LogicalGetData("mytest") as string;
string contextValue2 = LogicalThreadContext.Properties["anotherprop"] as string;
throw new Exception("Fake exception that I am logging");
}
public class HttpExceptionLogger : ExceptionLogger
{
public override void LogCore(ExceptionLoggerContext context)
{
// PROBLEM: this is null
string contextValue = CallContext.LogicalGetData("mytest") as string;
// this is okay, returns '999'
string contextValue2 = LogicalThreadContext.Properties["anotherprop"] as string;
// do some logging, etc.
}
public class HttpExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
// PROBLEM: this is null
string contextValue = CallContext.LogicalGetData("mytest") as string;
// PROBLEM: this is also null
string contextValue2 = LogicalThreadContext.Properties["anotherprop"] as string;
// return a message to the user, e.g.
string message = string.Format("unexpected exception, ref Id={0}, ref Id2={1}", contextValue, contextValue2);
context.Result = new TextPlainExceptionResult
{
Request = context.ExceptionContext.Request,
Content = message
};
}
回答1:
The problem is not that it is somehow being cleared. Rather, the problem is that CallContext isn't compatible with the "thread agility" model of ASP.NET. At unpredictable intervals, ASP.NET reserves the right to switch threads (leaving CallContext behind).
To compensate, ASP.NET has its own thread-scheduler with its own notion of CallContext, all conveniently wrapped up inside of:
HttpContext.Current.Items[]
If you use that, your values will not "disappear" or act like they were cleared. Furthermore, ASP.NET will automatically release / free the values you put there when the request is complete.
To clarify, when I say "release / free" I mean that the ASP.NET equivalent of CallContext, embodied by HttpContext.Current.Items[], is cleaned up automatically. I do not mean that IDisposable() is called on resources you have placed into HttpContext.Current.Items[]. It is still your duty to handle IDisposables that you allocated.
来源:https://stackoverflow.com/questions/23703464/when-does-callcontext-logicalsetdata-get-cleared-issues-with-webapi-global-exce