Photo by Surface on Unsplash

Video/Audio call with Peerjs and SignalR including deployment into windows server

Have you ever noticed that sometimes there are topics which we as developers are so afraid to get involved into because we think if we do, we will fail BUT as soon as we overcome this fear we realize that the topic is much easier than we were thinking.

Couple of days ago I was wondering what should I do at home to use my time better and the only thing which came to my mind was, let’s try to do a base video call sample application then I did my research and I got insipired by a youtuber’s video which I’ve shared the link.

After I checked this video I said ok, now it is time to implement but had to do the backend with C# because I wanted to offer this project to our company.

We are going to write a backend in C# and a frontend with Vuejs together and we will deploy the whole thing on a windows server which btw for me was more challenge than the code itself.

What are we going to need?

Take whatever IDE you are comfortable with, install nodejs and dotnet sdk and we should be good to go.

Let’s make sense out of it first

First lets say why are we using signalR and what is Peerjs.

The only signalR’s responsibility here is to let our app know that a new user has joined/left a channel which obviously you can also do with WebAPIs but to be honest this way is much more fun.

Peerjs is responsible to bring us an easier and more understandable implementation of WebRTC. What is WebRTC you ask? WebRTC is short for web Real-Time Communication. It allows you to have a p2p(Peer-to-Peer) connection inside web browsers to transfer audio and video. In the section below you will find the browsers support for WebRTC.

WebRTC browsers support

The plan is that when the user enters a room we notify other users about the new user. The other users will call this new user then they will connect ans will send and receive the Video/Audio stream.

As simple as that.

Let’s begin

We are going to start with our backend.

Create a new C# webapi project and set the framework to dotnet core 3.1.

Add signalR 3.1.15 to your project. If you want you can add the version 5.x but since this project is using dotnet core 3.1.x, I used 3.1.15 version for signalR

dotnet add package Microsoft.AspNetCore.SignalR.Common --version 3.1.14

Well thats all for your setup.

Since we are going to have signalR hubs, add a “Hubs” folder like below to your project. I consider these hubs like http request controllers.

SignalR Hubs folder

Now it is time to register signalR. You can go on and do you for registering services but I normally add a Kernel.cs if I’m going to register a new service which brings new features and will manage the DependencyInjection code inside a static class.

I’m not registering services here because I’m planning to use the default settings but you can also register signalR here too.

Now in Startup.cs in ConfigureServices add the following.


And in Configure method add the following.

app.RegisterSignalR(); // This is the method inside the Kernel.cs

With SignalR you gonna need to configure CORS(Cross-Origin-Resource-Sharing) which also for this I normally add a folder like below and will configure it inside CORS.cs

CORS config

Here is a basic configuration to just allow the client’s origin in.

Ok now let’s get to the interesting stuff :-)

Create a ChatHub.cs inside the Hubs folder and add the following code and I will explain what each part will do.

Let’s describe the JoinRoom method.

This event is triggered as soon as a new user opens the url to a “VideoChat” room. The user will send it’s ID and the room which she has joined.

We receive this information on the ChatHub and will add the user to the passed RoomGroup and will notify all the other users about this new user with broadcasting user-connected event to everyone in this group.

What is the MiniDatabase object you ask? well since this project is just to run a VideoChat stream I did not care about having an actual database which the users can have an account in and so on. So I store a joned user in a static KeyValuePair so I can remove them later on disconnect.

Now Let’s describe the OnDisconnectedAsync override.

We don’t want to keep a frozen video element of a disconnected user on a room’s page for other users do we.

So as soon as we receive the “Disconnect” event we gonna look up the disconnected user in our “MiniDatabase” then when we find the user we will send it’s Id to all the other members of the room to let them know that this user is diconnected so they can remove the “HtmlVideoElement” from the page.

Well that is all for the backend now lets do the frontend.

Vuejs, Peerjs — Our video chat frontend

You are free to use preejs with anyother framework that you like. I chose Vuejs because well I praise it.

I would skip setting up a project with vue-router and so on since this is not an article about vuejs. For getting an understanding about vue-router please checkout my former post about vue-router and how to make it easier to use.

After initiating your vuejs project and added the Room route please add the following package to the project

npm i peerjs@1.2.0

I used version 1.2.0 like in the posted youtube video. I remember that I had some problems with the latest version but I don’t remember it at the moment 😅.

In your view for room you should be able to read the passed Id from the url as a vue property.

I will share the whole code for this view which is written carelessly in typescript with vue class component and I will descibe the important parts.

btw I’m using bootstrap for the grid system.

First lets’s check the constructure.

In the constructor which as soon as this component is created the connection signalR is configured.

Now let’s go to the mounted method.

Here, first you need to create a new instance for the peerjs if you leave the passed object empty and just code new Peer(undefined) it will connect to the peerjs host on the cloud hosted by peerjs itself.

The undefined parameter is to tell peerjs to create the joined user id automatically.

Next you have to inform other user’s about new user joining the room.

which happens by listening on peerjs open event. When the connection to peerjs server is open you will send the “JoinRoom” event with the userId which is generated by peerjs.

Now you will get the user’s camera/mic access permission and by that you can get the stream.

After a user joins, the first method which will be called is the ‘user-connected’ event on the other available users in the current room.

When the other users receive this event, they will try to call the just added user and will listen to a call by the joined user. When they call the user and the other user answered the old users will also accept the call and will send their stream back to the new user so they can see and hear each other.

But the main point of this article is to have this project on a windows server and hosing it on IIS.

Deploying to windows server

First you may need to use your own peerjs server.

On your windows server install nodejs and install pm2 for running a node application as a service from the link below.

Now create a node project for your peerjs server. You also can use the peer server which is already available by peerjs. You can have it by running the following command.

npm install peer -g

But for having your own server and being able to configure it after creating the node project, in your index.js add the following code.

ah and don’t forget to add peer@0.6.1 package to your node project.

Also add the nodemon package so you can run the node server with live monitoring.

And this is how your node package.json should look like

By this your peerjs server is ready to be deployed.

To run this on IIS, I had to use reverseProxy with IIS. Which means the peerjs will run on the server’s localhost env and when IIS receives a request it will check it with the localhost and will response.

First you need to run the peerjs as a service with pm2 . Run the following command to add it to pm2 . Run this command when your command line is pointing to the index.js’s directory.

pm2 start index.js

In index.js file we have already defined that the server should run on http://localhost:9000 .

Now it is time to have the reverseProxy configured in IIS.

For this to work you need to install URL Rewrite extension for IIS. You can get it from the link below.

Now create a website in IIS and point it to where ever you link that doesn’t really matter since IIS will not run the website, it is already running by pm2

Now it is time to use URL Rewrite extension.

Click on the website for peerjs server, click URL Rewrite extension and then select reverseProxy like in the picture below.

Then you will get the following popup.

ReverseProxy IIS setup

In the field at the top, you need to enter the address for peerjs which is running in localhost. In our case with the setup we had you need to enter


Now whenever IIS gets a HTTP or WS request it will check it with this address on localhost and will responde accordingly to the request.

The challenge was so far. Now that you have successfuly have your own peerjs server running you can deploy the C# project and the Vue project as a standard IIS website and enjoy your app being running on windows server.

Please note that this is a very basic way of how you can setup a chat application. After you figured out how the whole thing interact with each other you can get creative and create your own customize application with real database and real chat-rooms.

Happy coding!

Fullstack developer for around 10 years. Love to code for fun at free times if something interesting comes up and always ready to share the experience.