15

http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-signalr-20-self-host

In my case, my hubs are in a project referenced from the project code that spins up the self-hosted application.

On the line connection.Start().Wait(); I get an exception. The following is the sequence of exceptions thrown at that line:

  1. The specified registry key does not exist System.IO.IOException
  2. 'MessageHub' Hub could not be resolved InvalidOperationException
  3. The remote server returned an error: (500) Internal Server Error WebException

The signature of the message hub class in the referenced project is public class MessageHub : Hub.

Update: To test the theory, I moved the hub class from the referenced project into my test project and updated the namespace. It worked. So I think the theory here is sound... default hub resolution does not find hubs in referenced project or in separate namespace.

How can I convince MapHubs to find the test hub in the referenced project?

4

1 回答 1

25

我想我已经找到了答案。

在对源代码进行了一些挖掘之后,SignalR 似乎使用以下方法来指定一个 IAssemblyLocator 来定位 Hub。

    internal static RouteBase MapHubs(this RouteCollection routes, string name, string path, HubConfiguration configuration, Action<IAppBuilder> build)
    {
        var locator = new Lazy<IAssemblyLocator>(() => new BuildManagerAssemblyLocator());
        configuration.Resolver.Register(typeof(IAssemblyLocator), () => locator.Value);

        InitializeProtectedData(configuration);

        return routes.MapOwinPath(name, path, map =>
        {
            build(map);
            map.MapHubs(String.Empty, configuration);
        });
    }

public class BuildManagerAssemblyLocator : DefaultAssemblyLocator
{
    public override IList<Assembly> GetAssemblies()
    {
        return BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList();
    }
}

public class DefaultAssemblyLocator : IAssemblyLocator
{
    public virtual IList<Assembly> GetAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies();
    }
}

这让我尝试简单地将我的外部程序集添加到当前域,因为虽然它被引用了,但它没有被加载。

因此,在调用 WebApp.Start 之前,我调用了以下行。

    static void Main(string[] args)
    {
        string url = "http://localhost:8080";

        // Add this line
        AppDomain.CurrentDomain.Load(typeof(Core.Chat).Assembly.FullName);

        using (WebApp.Start<Startup>(url))
        {
            Console.WriteLine("Server running on {0}", url);
            Console.ReadLine();
        }
    }

Core.Chat 只是我正在使用的 Hub 类。然后加载引用程序集中定义的集线器。

可能有更直接的方法来解决这个问题,但我在文档中找不到任何内容。

希望这可以帮助。

于 2013-07-07T23:48:46.873 回答