Use Signalr with SharePoint Webparts

Standard

Update 1: Download sample source code at https://1drv.ms/u/s!Ao7Q-78sQy60gcdrmHFyndmR_HWEMQ

Last month I got a task to make Signalr working on SharePoint environment. As all developers used to do on starting new tasks, I started my task with a search on Google to know how people made this task. I have found a lot of blogs speaks about that , however I didn’t get my answer as all people use SharePoint App-part in doing such scenario but no one made it on SharePoint web-part

It is totally different scenarios to use Signalr in app-part and web-part. App part simply is a separated ASP.NET and you can easily configure it away from SharePoint environment. To use Signalr in web-part or SharePoint user control you have to make extra configurations for Signalr and OWIN that are configured by default on ASP.NET web application. This made me deep dive into Signalr and OWIN architecture and make it work on SharePoint

To run Signalr at SharePoint web-part or user-control follow the following steps:

  1. Add Signalr NuGet package and follow the ordinary steps for Signalr to be runned on ASP.NET this includes defining hubs and OWIN startup class and write you client side code that consume the hub.

    You can check full signalr getting started tutorial at http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr 

  2. Remove startup attribute ( [assembly: OwinStartup(typeof(xxx))] ) from OWIN startup class. because this made conflict with point 4

  3. Add the following line of code on the OWIN startup class

    GlobalHost.DependencyResolver. 
    Register(typeof(Microsoft.AspNet.SignalR.Hubs.IAssemblyLocator),  
    () => new AssemblyLocator());
    

    Here is the complete code for OWIN startup class

    namespace Code
    {  
        public class OWINStartup
        {
            public void Configuration(IAppBuilder app)
            {
                app.MapSignalR();
                GlobalHost.DependencyResolver.Register(typeof(Microsoft.AspNet.SignalR.Hubs.IAssemblyLocator), () => new AssemblyLocator());
            }
        }
    }
    
  4. Add the following httphandler that responsible for startup OWIN application in section Configurations > System.WebServer > Handlers of web.config as following:

    <add name=”Owin” verb=”*” path=”/signalr” type=”Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />

  5. Add OWIN startup configuration app setting as following :

    <add key=”owin:appStartup” value=”MOFA.Notifications.Code.OWINStartup,MOFA.Notifications, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c7c61351043d379c” />

  6. Comment trust configuration on the web.config as following:

    <!–<trust level=”Full” originUrl=”” legacyCasModel=”true” />–>

    this because Signalr use dynamic expersions in .NET framework 4 and this made conflict with this trust configuration

  7. Add the following runtime configuration on web.config on Configuration > runtime  section as following:

    <assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″> <dependentAssembly> <assemblyIdentity name=”Microsoft.Owin” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” /> <bindingRedirect oldVersion=”0.0.0.0-3.0.0.0″ newVersion=”3.0.0.0″ /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name=”Microsoft.Owin.Security” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” /> <bindingRedirect oldVersion=”0.0.0.0-2.0.2.0″ newVersion=”2.0.2.0″ /> </dependentAssembly> </assemblyBinding>

27 thoughts on “Use Signalr with SharePoint Webparts

    • Hi,

      Actuly Signalr debug is not easy. However here is some helpful tips:

      1. Check your Hub proxy is generated successfuly at URL /Signalr/Hub . It would display javascript code contains your hub name else you have to redo the steps
      2. If you use NTLM or kerbores don’t use Websockets protocols it make a lot of issues. You can disable it in OWINStartup configuration as following:
                public void Configuration(IAppBuilder app)
                {
                    var transportManager = GlobalHost.DependencyResolver.Resolve() as TransportManager;
                    transportManager.Remove("webSockets");
                    app.MapSignalR();
                    GlobalHost.DependencyResolver.Register(typeof(Microsoft.AspNet.SignalR.Hubs.IAssemblyLocator), () => new AssemblyLocator());
                }
  1. Sorry for that, I forgot to post the Assembly Locator class code. Here is it

    public class AssemblyLocator : IAssemblyLocator
    {
    public IList GetAssemblies()
    {
    // list your hubclass assemblies here
    return new List(new[] { typeof(–Hub class name–).Assembly });
    }
    }

    Note: this class used because the hub class assembly will be located in GAC after sharepoint solution deployment

  2. shinichi

    Hi, I used this way to implement signalr in a webpart of sharepoint solution. But, at step 5( Add OWIN startup configuration app setting), I can not find app.settings file in solution or in C\inetpub\… direction.

    And when I deploy webpart to web app, I can’t excute javascript code as “var chatHub = $.connection.chatHub;” because $.connection hasn’t “chatHub” property. Other, I can’t debug in Startup.cs class when page is loaded.

    Can you please share how you solved your issue?

    • Did you used the class AssemblyLocator class as mentioned on the previous comment?

      public class AssemblyLocator : IAssemblyLocator
      {
      public IList GetAssemblies()
      {
      // list your hubclass assemblies here
      return new List(new[] { typeof(–Hub class name–).Assembly });
      }
      }

      Actually this is an important part because default behaviour expect that your hub is on the Bin folder. This not working with SharePoint as the hub is GAC

  3. srinivas

    this is my AssemblyLocator

    public class AssemblyLocator : IAssemblyLocator
    {
    public IList GetAssemblies()
    {
    // list your hubclass assemblies here
    return new List(new[] { typeof(SampleChatWebPart.ChatHub).Assembly });
    }
    }

    this is my startup class

    public class Startup
    {

    public void Configuration(IAppBuilder app)
    {
    var Tm = GlobalHost.DependencyResolver.Resolve() as TransportManager;
    Tm.Remove(“webSockets”);
    app.MapSignalR();
    GlobalHost.DependencyResolver.Register(typeof(Microsoft.AspNet.SignalR.Hubs.IAssemblyLocator), () => new AssemblyLocator());
    }
    }

    • Hi srinivas,

      Actually to determine exactly your problem I have to have your complete code.

      Actually I didn’t try this utility before, but I think you have to use the same Path /signalr/hubs/ as it is used by default if you didn’t define your path at app.MapSignalR()

      I recommend you use the generated file on that path and not to generate the proxy using a tool

  4. srinivas

    if i use default path what like “/signalr/hubs” i am getting “chathub” undefined error (Declare a proxy to reference the hub) that is the reason i am generating proxy . share your email id i can get back you

  5. Tony

    Hello –

    I tried all this suggestions, and still getting ERROR 404 file not found: signalr/hubs
    I have the progressbar signalr code from Microsoft, and want to convert it to sharepoint 2013 friendly code.

    Im running a sharepoint 2013 web part, and my app.config looks like this:


    thanks,
    Tony.

  6. Hello
    I am getting this error when I am trying this on my solution any idea’s

    http://vistrspdev2/signalr/hubs [HTTP/1.1 401 Unauthorized 28ms]

    Could not load file or assembly ‘Microsoft.Owin.Host.SystemWeb, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.

    [FileNotFoundException: Could not load file or assembly ‘Microsoft.Owin.Host.SystemWeb, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.]
    System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type) +0
    System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName) +106
    System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +62
    System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) +50
    System.Web.Compilation.BuildManager.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) +61
    System.Web.Configuration.HandlerFactoryCache.GetTypeWithAssert(String type) +48
    System.Web.Configuration.HandlerFactoryCache.GetHandlerType(String type) +17
    System.Web.Configuration.HandlerFactoryCache..ctor(String type) +25
    System.Web.HttpApplication.GetFactory(String type) +104
    System.Web.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +262
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137

  7. Mohamed Hamed

    Hi Mohamed,

    i am trying to use signalR with sharepoint 2013 webparts, your tutorial was very helpful for me “many Thanks :D”. but actually i have a little problem when i am trying to use SPContext.Current it always returning NULL to me, which preventing me to access My SPSite or SPWeb from inside the HUB!
    any suggestions?!

  8. Phillip

    Hi Mohamed,
    I never saw a comment saying, yay, I got it working! So I wanted to thank you for your post. It was the only one on the internet that actually had and example project which was sort of required, because it is very hard to just list out all the steps. You need an actual working example to understand the changes needed for SharePoint. So I really appreciate the effort you put in here.

  9. Soha

    Hello Mohamed,
    I have a weird thing happening in chrome, the authentication popup keeps appearing whenever signalr tries to connect. do you have any idea why?

    • Hi Soha,

      I faced that before when I was using windows authentication. In fact NTLM is not working correctly with websockets. The solution is to exclude the websockets from the connection protocols that are used by SignalR. So the SignalR will be able to use the other technologies such as long pooling which is based on HTTP and will work fine with NTLM

      In fact that is an old topic so I don’t have a sample to do this right now but sure it is doable

Leave a reply to srinivas Cancel reply