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:
-
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
-
Remove startup attribute ( [assembly: OwinStartup(typeof(xxx))] ) from OWIN startup class. because this made conflict with point 4
-
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()); } } }
-
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″ />
-
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” />
-
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
-
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>
Hello,
I used your solution for my environment. But finally i am getting /signalr/negotiate 500 Internal server error. any idea?
Hi,
Actuly Signalr debug is not easy. However here is some helpful tips:
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
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?
Sorry I wasn’t clear at that point
I meant you have to add the OWIN app setting at web.config of the web application
“NetworkError: 500 Internal Server Error – http://sharepoint2013:50000/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&_=1443181532149” any idea getting this error i am creating proxy js using signalr tools utility
i removed “/signalr/hubs/” with generated proxy file how to fixed this
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
yes i have used that class what you told in blog but still i am getting same error i have fallowed the each step what you explained in the blog , i have generated proxy js files from asp.net signalr utils tool script what i am using is below link
http://www.codeproject.com/Articles/562023/Asp-Net-SignalR-Chat-Room
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
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
any updates?
I am working on a sample to be uploaded soon
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.
Hi Tony,
I am currently working on a sample to be uploaded very soon.
Have you uploaded the sample
Hi Syed,
Yes you can find it at https://1drv.ms/u/s!Ao7Q-78sQy60gcdrmHFyndmR_HWEMQ
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
Found the solution All I have to do was to put all the dll in this folder and it worked I don’t know how
C:\inetpub\wwwroot\wss\VirtualDirectories\80\bin
Microsoft.AspNet.SignalR.Core.dll
Microsoft.AspNet.SignalR.SystemWeb.dll
Microsoft.Owin.dll
Microsoft.Owin.Host.SystemWeb.dll
Microsoft.Owin.Security.dll
Newtonsoft.Json.dll
Owin.dll
I also commented these lines
In short I followed your blog and this blog to fix my problem
https://sharepointpros.wordpress.com/2015/01/26/using-signalr-2-2-in-a-sharepoint-2013-farm-solution-3/
Thank you
Hi Syed,
Your solution is totally correct. However there is an easy way to reduce the deployment steps which I already made on the sample project. I added all the assemblies to be deployed to the GAC using the SharePoint project’s package
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?!
Hi Mohamed,
Actually you can’t get the SPContext inside the hub because the hub is running on the top of OWIN server. A workaround you can pass javascript window.location to your hub method and use it to open you current SPSite.
Hope it helps
Thanks alot.
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.
Thank you Phillips for your comment
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