When processing a request, the Web API allows you to perform a complete operation in one Context for a stream with asynchronous code , we write to the Web API. However, somehow, when creating a custom MediaTypeFormatter Web API, it does not use the same context when performing type formatting.
My question is: why is this and how can we get around this?
Take a look at the following code:
public static class CallContextHelper
{
private static readonly string key = Guid.NewGuid().ToString();
public static void Append(string text) {
var appendedText = (string)CallContext.LogicalGetData(key) + " -> " + text;
CallContext.LogicalSetData(key, appendedText);
Debug.WriteLine(appendedText);
}
}
public sealed class TestDependencyResolver : IDependencyResolver
{
void IDisposable.Dispose() { }
IDependencyScope IDependencyResolver.BeginScope() {
CallContextHelper.Append("IDependencyResolver.BeginScope");
return this;
}
object IDependencyScope.GetService(Type serviceType) => null;
IEnumerable<object> IDependencyScope.GetServices(Type serviceType) =>
Enumerable.Empty<object>();
}
public class ValuesController : ApiController
{
public ValuesController() {
CallContextHelper.Append("ValuesController.ctor");
}
public IEnumerable<string> Get() {
CallContextHelper.Append("ValuesController.Get");
return new string[] { "value1", "value2" };
}
}
With the following media type format format:
public class MyCustomTypeFormatter : XmlMediaTypeFormatter
{
public MyCustomTypeFormatter()
{
SupportedMediaTypes.Add(
new MediaTypeHeaderValue("application/vnd.mywebapplication+json"));
}
public override bool CanReadType(Type type) => false;
public override bool CanWriteType(Type type) => true;
public override Task WriteToStreamAsync(Type type, object value, Stream ws,
HttpContent content, System.Net.TransportContext tc)
{
CallContextHelper.Append("WriteToStreamAsync (begin)");
return base.WriteToStreamAsync(type, value, ws, content, tc)
.ContinueWith(continuation =>
{
CallContextHelper.Append("WriteToStreamAsync (continu)");
});
}
}
Loader:
GlobalConfiguration.Configuration.DependencyResolver = new TestDependencyResolver();
GlobalConfiguration.Configuration.Formatters.Insert(0, new MyCustomTypeFormatter());
If we launch the application and call the ValueController, we see the following output:
-> IDependencyResolver.BeginScope
-> IDependencyResolver.BeginScope -> ValuesController.ctor
-> IDependencyResolver.BeginScope -> ValuesController.ctor -> ValuesController.Get
-> WriteToStreamAsync (begin)
-> WriteToStreamAsync (begin) -> WriteToStreamAsync (continuewith)
, , IDependencyResolver.BeginScope, ValuesConstructor ValuesController.Get , TypeFormatter .
, , - , . HttpRequestMessage, TypeFormatter, .