为Web API和SignalR控制器提供每个Web应用程序对象

时间:2015-06-08 23:02:04

标签: .net asp.net-web-api owin signalr-hub self-hosting

我有一个使用Redis协调服务器节点的Web应用程序。该应用程序具有集成测试,可以使用WebApp.Start启动服务器实例,并使用HttpClient和SignalR .NET客户端对其进行调用。

我希望增强集成测试,多次调用WebApp.Start来启动多个服务器实例,使用不同的端口号代替不同的主机地址。这应该很容易做到。我无法弄清楚的部分是如何从控制器访问每个实例对象。这些是诸如与Redis的连接和缓存字典之类的对象。传统上,它们是简单的静态字段。现在,我希望它们是使用Startup对象实例化的实例字段。

我的问题是我应该如何创建每个Web应用程序的这些对象,以及如何从Web API和SignalR控制器访问它们?

简化示例:

[TestMethod]
public void IntegrationTest()
{
    // Starts 3 server instances.
    for (int port = 9000; port < 9003; ++port)
       WebApp.Start("http://localhost:" + port);

    // Validates SignalR events on 9000.
    var hubConnection9000 = new HubConnection("http://localhost:9000");
    hubConnection9000.CreateHubProxy("MyHub").On<MyMessage>(name, m => Assert.IsTrue(...));
    hubConnection9000.Start().Wait();

    // Sends a SignalR command to 9001. Causes an event on 9000.
    var hubConnection9001 = new HubConnection("http://localhost:9001");
    hubConnection9001.CreateHubProxy("MyHub").Invoke("DoIt").Wait();

    // Sends a Web API request to 9002. Causes an event on 9000.
    var httpClient9002 = new HttpClient { BaseAddress = new Uri("http://localhost:9002") };
    httpClient9002.PostAsJsonAsync("api/My/NewRecord", "[]").Result.EnsureSuccessStatusCode();
}

// From Startup.Configuration(IAppBuilder app):
// Creates a per-web-application backplane object which communicates to other servers.
   object addresses;
   int customPort = app.Properties.TryGetValue("host.Addresses", out addresses) ? int.Parse((string)((List<IDictionary<string, object>>)addresses)[0]["port"], CultureInfo.InvariantCulture) : 0; // The custom port number if one was provided at startup; otherwise, 0.
   var backplane = new Backplane(customPort);
   new AppProperties(app.Properties).OnAppDisposing.Register(() => { backplane.Dispose(); });

public class MyController : ApiController
{
   [HttpPost]
   public void NewRecord(string[] items)
   {
       // I want to use Backplane. How do I get at it?
   }
}

public class MyHub : Hub<IMy>
{
   public void DoIt()
   {
       // I want to use Backplane. How do I get at it?
   }
}

internal class Backplane
{
   // A Redis object that is expensive to create and should be shared with the entire web application.
   readonly StackExchange.Redis.ConnectionMultiplexer redis =    StackExchange.Redis.ConnectionMultiplexer.Connect();
}

0 个答案:

没有答案