У меня есть базовая 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 был хорош для этого до сих пор, но не уверен, что делать сейчас, когда он недоступен.