Why does the TypeFormatter web API not start in the same Call Context as the request request?

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, .

+4

Source: https://habr.com/ru/post/1542294/


All Articles