Сервис Fabri c ServiceReplicaListener no HttpContext.Current внутри моего контроллера - PullRequest
0 голосов
/ 07 января 2020

У меня есть базовая c служба с отслеживанием состояния, такая как

 internal sealed class MyServiceService : StatefulService
{
    protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
    {
        return new ServiceReplicaListener[]
        {
            new ServiceReplicaListener(serviceContext => new OwinCommunicationListener(Startup.ConfigureApp, serviceContext, MyServiceEventSource.Current, "WbsServiceEndpoint"))
        };
    }
}

Мой OwinCommunicationListener является экземпляром ICommunicationListener, который запускает веб-сервер.

 public class OwinCommunicationListener : ICommunicationListener
{
    private readonly ServiceEventSource eventSource;
    private readonly Action<IAppBuilder> startup;
    private readonly ServiceContext serviceContext;
    private readonly string endpointName;
    private readonly string appRoot;

    private IDisposable webApp;
    private string publishAddress;
    private string listeningAddress;

    public OwinCommunicationListener(Action<IAppBuilder> startup, ServiceContext serviceContext, ServiceEventSource eventSource, string endpointName)
        : this(startup, serviceContext, eventSource, endpointName, null)
    {
    }

    public OwinCommunicationListener(Action<IAppBuilder> startup, ServiceContext serviceContext, ServiceEventSource eventSource, string endpointName, string appRoot)
    {
        if (startup == null)
        {
            throw new ArgumentNullException(nameof(startup));
        }

        if (serviceContext == null)
        {
            throw new ArgumentNullException(nameof(serviceContext));
        }

        if (endpointName == null)
        {
            throw new ArgumentNullException(nameof(endpointName));
        }

        if (eventSource == null)
        {
            throw new ArgumentNullException(nameof(eventSource));
        }

        this.startup = startup;
        this.serviceContext = serviceContext;
        this.endpointName = endpointName;
        this.eventSource = eventSource;
        this.appRoot = appRoot;
    }

    public bool ListenOnSecondary { get; set; }

    public Task<string> OpenAsync(CancellationToken cancellationToken)
    {
        var serviceEndpoint = this.serviceContext.CodePackageActivationContext.GetEndpoint(this.endpointName);
        int port = serviceEndpoint.Port;

        if (this.serviceContext is StatefulServiceContext)
        {
            StatefulServiceContext statefulServiceContext = this.serviceContext as StatefulServiceContext;

            this.listeningAddress = string.Format(
                CultureInfo.InvariantCulture,
                "http://+:{0}/{1}{2}/{3}/{4}",
                port,
                string.IsNullOrWhiteSpace(this.appRoot)
                    ? string.Empty
                    : this.appRoot.TrimEnd('/') + '/',
                statefulServiceContext.PartitionId,
                statefulServiceContext.ReplicaId,
                Guid.NewGuid());
        }
        else if (this.serviceContext is StatelessServiceContext)
        {
            this.listeningAddress = string.Format(
                CultureInfo.InvariantCulture,
                "http://+:{0}/{1}",
                port,
                string.IsNullOrWhiteSpace(this.appRoot)
                    ? string.Empty
                    : this.appRoot.TrimEnd('/') + '/');
        }
        else
        {
            throw new InvalidOperationException();
        }

        this.publishAddress = this.listeningAddress.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);

        try
        {
            this.eventSource.ServiceMessage(this.serviceContext, "Starting web server on " + this.listeningAddress);

            this.webApp = WebApp.Start(this.listeningAddress, appBuilder => this.startup.Invoke(appBuilder));

            this.eventSource.ServiceMessage(this.serviceContext, "Listening on " + this.publishAddress);

            return Task.FromResult(this.publishAddress);
        }
        catch (Exception ex)
        {
            this.eventSource.ServiceMessage(this.serviceContext, "Web server failed to open. " + ex.ToString());

            this.StopWebServer();

            //throw; JRH
            return Task.FromResult(string.Empty);
        }
    }

    public Task CloseAsync(CancellationToken cancellationToken)
    {
        this.eventSource.ServiceMessage(this.serviceContext, "Closing web server");

        this.StopWebServer();

        return Task.FromResult(true);
    }

    public void Abort()
    {
        this.eventSource.ServiceMessage(this.serviceContext, "Aborting web server");

        this.StopWebServer();
    }

    private void StopWebServer()
    {
        if (this.webApp != null)
        {
            try
            {
                this.webApp.Dispose();
            }
            catch (ObjectDisposedException)
            {
                // no-op
            }
        }
    }
}

У меня возникла проблема что код, который я пытаюсь переместить в эту службу с состоянием, зависит от HttpContext.Current, но когда я пытаюсь получить доступ к HttpContext.Current внутри моего контроллера, он становится пустым.

Есть ли способ получить HttpContext.Current в этом сценарии?

Я пытался рефакторинг своего кода для использования CallContext, но любые данные, которые я установил в CallContext в моем конвейере Owin теряется, когда я нажимаю на контроллер webapi. Я могу получить доступ к своему HttpActionContext в фильтре webapi, но не могу найти какой-либо способ доступа к нему с контроллера или за его пределами. В конечном счете мне нужен контекст, который остается в живых с начала конвейера owin до самого конца запроса, к которому можно получить доступ из любого уровня в моей кодовой базе. HttpContext был хорош для этого до сих пор, но не уверен, что делать сейчас, когда он недоступен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...