.net, Asp.net, C#

Real time server side push notifications using Microsoft SignalR

It’s been a few years since I wrote anything, but this one deserves a post.

SignalR

Ever wanted to have a real time communication with your connected clients on your web application? Well, Microsoft SignalR helps you achieve exactly that and more. SignalR is amazing. It’s so simple to get started with, you will wonder why you haven’t used it yet. There are a few gotchas, but once you get around them, you will know how easy it is to implement real time two-way communication in your own apps.

There are many articles online about SignalR and almost all of them demo a live chat application. What I would like to show is another use case where you just need to send notifications from the server to your connected clients.

For the sake of this demo, we will create a ASP.NET MVC application. All that is required is the free Visual Studio Community Edition 2015 to get started.

Setup

Create a new Web Application project. Right click on the MVC project and click Manage Nuget packages. Search for SignalR and click install on the Microsoft.AspNet.SignalR package. You can also run the following command from the package manager console.

Install-Package Microsoft.AspNet.SignalR

This will install SignalR and all it’s dependencies. Once installed, a readme file should open up. Do take the time to read through it.

Configuration

The next step is to enable SignalR in your application. First, check if there is a Startup.cs file in your application. If there is no Startup.cs file in your project, then right click your project, click on Add New Item and select OWIN Startup class. Leave the file name as Startup.cs. If the OWIN Startup class template is missing, you can just add a regular class and copy the code below into it.

Open the Startup class, and include the app.MapSignalR() call to the Startup.Configuration method:

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SignalRDemo.Startup))]

namespace SignalRDemo
{
	public partial class Startup
	{
		public void Configuration(IAppBuilder app)
		{
			//Existing code if any goes here
			app.MapSignalR();
		}
	}
}

At this point, we just need to make sure that SignalR is working, so hit F5 to compile and view the app in the browser. Navigate to

http://<yourprojecturl>/signalr/hubs

This should open up the JavaScript proxy that SignalR has generated automatically for us. If the proxy script is visible, then SignalR is working as it should. If not, retrace the steps.

Send Notifications

Back on Visual Studio, create a new folder called Hubs under your project, and add a new SignalR Hub Class named NotificationHub.cs with the following code:

using Microsoft.AspNet.SignalR;

namespace SignalRDemo.Hubs
{
  public class NotificationHub : Hub
  {
    public void NotifyAll(string title, string message, string alertType)
    {
      Clients.All.displayNotification(title, message, alertType);
    }
  }
}

The above piece of code:

  1. By inheriting from the Hub class, instructs SignalR to work its magic and generate a JavaScript proxy automatically. This will allow JavaScript clients to communicate with the server and vice versa
  2. Creates a server method called NofifyAll that is available for calls from client
  3. Calls the JavaScript method displayNotification on the connected clients

Next, we would need a form to pass the notification info and call the NotifyAll method on the server.

For simplicity sake, I am going to use the route Home -> Notification and create a new view that will contain the form. Open Controllers -> HomeController.cs and add the following code to the HomeController class:

public ActionResult Notification()
{
    return View();
}

Next, we will need an associated View for the above route under Views -> Home -> Notification.cshtml. Because the default Asp.Net template uses Bootstrap, we will use it’s inbuilt styles to format our form elements.

@{
    ViewBag.Title = "Notification";
}
<h2>@ViewBag.Title.</h2>

<form role="form">
  <div class="form-group">
    <label for="title">Notification Title:</label>
    <input type="text" class="form-control" id="title">
  </div>
  <div class="form-group">
    <label for="message">Notification Message:</label>
    <input type="text" class="form-control" id="message">
  </div>
  <div class="form-group">
    <label for="alert-type">Notification Type:</label>
    <select class="form-control" id="alert-type">
      <option value="info" selected>Information</option>
      <option value="success">Success</option>
      <option value="warning">Warning</option>
      <option value="danger">Error</option>
    </select>
  </div>
  <button type="button" class="btn btn-primary" id="send-notification">Send to All</button>
</form>

Next, add the JavaScript code below to communicate with the SignalR autogenerated proxy and send the notification to the server when the user clicks the Send to All button.

@section Scripts{
  <script type="text/javascript">
    $(function () {     //execute on document ready

      //access the global hubConnector object created by master page
      window.notifyApp.hubConnector.done(function () {

        $('#send-notification').click(function () {

          var title = $('#title').val(),
              message = $('#message').val(),
              type = $('#alert-type').val();

          //Call the notifyAll method on the hub. Notice camelCasing on the method name.
          $.connection.notificationHub.server.notifyAll(title, message, type);

          //Clear values and reset focus for next comment.
          $('#title').val('').focus();
          $('#message').val('');

        });   //end send notification click handler

      });     //end hub started handler

    });       //end document ready event handler
  </script>
}


Let’s look at the code above:
Line 6: The SignalR hub must be started before we can send notifications. And because we will require a SignalR connection for receiving notifications too, we will start the connection in the master page (_Layout.cshtml). We will get to this in the Receive Notifications section below.

Line 15: The send-notification click handler requests the form values and calls the server method NotifyAll via the JavaScript hub proxy auto generated by SingalR. It’s important to note that the proxy automatically camelCases the hub and the server method names to conform to JavaScript conventions.

Receive Notifications

Now, we will include the html that will display the notification when the client receives it from the server. Like the form elements earlier, we will use Bootstrap’s inbuilt alert styles to display our notifications.

Here’s a sample of the notification HTML using Bootstrap alerts.

<div class="alert alert-info alert-dismissible" role="alert">
  <button type="button" class="close" data-dismiss="alert"><span>×</span></button>
  <strong>Title</strong> Message goes here
</div>

Ideally we would like the users to receive as many alerts and have them all visible until the user explicitly dismisses them. To achieve this, we will be creating the above HTML programatically and inject them into a container HTML element using a little bit of jQuery.

So open the Views->Shared->_Layout.cshtml file and add the following code where you would want the notification displayed:

<div id="alert-placeholder" style="padding: 5px;"></div>

I’ve used inline style to pad the container from the header, please use dedicated CSS classes for styling though. Now, add the following JavaScript below the jquery and bootstrap bundles.

Reference to the SignalR library and the auto-generated hub proxy

<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/SignalR/Hubs"></script>

JavaScript to receive the notification and convert into a Bootstrap alert.

<script type="text/javascript">
  //a helper function to encode HTML values.
  function htmlEncode(value) {
    return $('<div />').text(value).html();
  }

  //execute on document ready
  $(function () {

    //function that the hub can call when it receives a notification.
    $.connection.notificationHub.client.displayNotification = function (title, message, alertType) {

      //Create the bootstrap alert html
      var alertHtml = '<div class="alert alert-' + htmlEncode(alertType) + ' alert-dismissible" role="alert"><button type="button" class="close" data-dismiss="alert"><span>×</span></button><strong>' + htmlEncode(title) + '</strong> ' + htmlEncode(message) + '</div>';

      $(alertHtml)
        .hide()                           //hide the newly created element (this is required for fadeIn to work)
        .appendTo('#alert-placeholder')   //add it to the palceholder in the page
        .fadeIn(500);                     //little flair to grab user attention
    };

    window.notifyApp = {
      hubConnector: $.connection.hub.start()  //start the connection and store object returned globally for access in child views
    };

  });

</script>


Lines 16 through 18 intiates the SignalR connection and stores the return object globally for use in child views. (Refer Send Notifications section on this)

This takes care of the code that is required to display the notification. Hit F5 to compile the application and view in browser. To test, leave multiple tabs/windows of your application in your browser open. Open a new tab and navigate to:

http://<yourprojecturl>/Home/Notification

Fill the form fields and hit Send to All. You should see the notification displayed on all open tabs/windows. Try sending another notification and check the behavior.

Next Steps

It’s important to understand that this article is just an introduction into the fascinating world of real time communications using SignalR. I would highly recommend reading the reference material available as SignalR does provide a lot of customizable options.

Also the article does not deal with security. It effectively allows anyone to send a notification to all connected clients. Refer to the Introduction to SignalR Security article for information on using the Authorize attribute to secure access.

You can fork a copy of this project from GitHub.

Advertisements
.net, Asp.net, IIS, Tips

aspnet_wp.exe could not be launched because the username and/or password supplied in the processModel section of the config file are invalid.

I was running a WinXP box and all of a sudden I started getting a “Server Unavailable” error. I know for a fact that it had to do with the ASPNET account. So here’s what I did that did not help:

1. Give ASPNET account full control over your home directory
2. Delete ASPNET account and ran aspnet_regiis -i
3. Google for the error got me to this link KB315158.

Extract from the article:

RESOLUTION

To work around this problem, use one of the following methods:
•Create a weak account that has the correct permissions, and then configure the <processModel> section of the Machine.config file to use that account.
•Set the userName attribute to SYSTEM in the <processModel> section of the Machine.config file.
•Configure the <processModel> section of the Machine.config file to use an administrator account.

I chose to proceed with option 2. I opened up Machine.Config located in

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config

And modified the following line:

FROM: <processModel autoConfig=”true”/>

TO: <processModel userName=”SYSTEM”/>

I tried accessing the website and still the same error. Well, the one thing that was missing in the article is that the processModel section will only be called when IIS starts. So I did a

Start -> Run -> IISRESET

I tried accessing the website and it started working. I was a little worried about using the SYSTEM account so I went back to the machine.config, reverted the changes I made (set processmodel back to autoconfig) and restarted IIS. Well the site still works.Its crazy… I am not sure as to what happened, but If someone knows why this worked please let me know in the comments!

.net, Ajax, C#, Code, Microsoft, Technical

‘Sys’ is undefined – ASP.Net Ajax error

I was using ASP.NET 2.0 along with Ajax Extensions 1.0. I received this error ‘Sys’ is undefined error message every time I used an Ajax control. I was pulling my hair out on it and decided to give the Control Toolkit’s web.config a glance. The following lines were not available in my web.config, so i copied them over:

<httpHandlers>
            <remove verb=”*” path=”*.asmx”/>
            <add verb=”*” path=”*.asmx” validate=”false” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
            <add verb=”*” path=”*_AppService.axd” validate=”false” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
            <add verb=”GET,HEAD” path=”ScriptResource.axd” type=”System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ validate=”false”/>
</httpHandlers>
<httpModules>
            <add name=”ScriptModule” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
</httpModules>

P.S: These lines go inside the System.Web section of your web.config file

Bingo.. the error vanished and all my controls started to function as they should 🙂

 

Technorati Tags: ,,
.net, C#, Code, Microsoft, WPF

Hide a window instead of closing it in WPF

I wanted to give WPF a try and was creating a timer application which will pop up a window once a while. But what I wanted was for the application to keep running in the tray even when its closed. The following code does NOT work in WPF for some reason:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
            Window.Visibility = !Window.Visibility;
        }

 

In order to hide a closing window in WPF, this is what needs to be done:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {

            //Do some stuff here 

            //Hide Window
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (DispatcherOperationCallback)delegate(object o)
            {
                Hide();
                return null;
            }, null);

            //Do not close application
            e.Cancel = true;

        }

.net, C#, Code, Microsoft, Technical

Using StreamReader without locking the file in C#

I was using the StreamReader class to read the contents of a text file. I was under the assumption (well I know its a bad

thing)  that because I am only reading the contents of the file, the file would be available for other applications to read or write. Guess what, i was wrong. The StreamReader class does maintain a lock on the file until you call the Close() method. So to not have the lock, we have to explicitly set up the sharing mode.

FileStream fs = new FileStream(@”c:\test.txt”, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader sr = new StreamReader(fs);
txtContents.Text = sr.ReadToEnd();
sr.Close();

Technorati Tags: ,,
.net, C#, Microsoft, Technical

.Net CLR Windows Service and the ConfigurationManager class

I created a new windows service and attached a App.Config file to it. Then I went back to the code and tried this:

System.Configuration.ConfigurationManager.GetSection(“Extras”);

For some reason the compiler was not able to figure out the class and kept throwing an error. This does not happen with your standard EXE projects as well as ASP.NET projects. I also did not want to use the
ConfigurationSettings.GetConfig() method as it was obsolete. I fiddled around for a while and eventually ended up manually adding a reference to the
System.Configuration DLL. For those who don’t know, just right click on the References folder in your project, click on Add Reference. Select System.Configuration in the .NET tab and click OK. This should allow you to access the ConfigurationManager class. Back to work now..

I will some day write a post on how to implement custom configuration sections in the App.Config file.