Multiple tab issue with Signal R

So, in the last project I worked in my previous company, We had developed an internal web portal using ASP.NET MVC and SQL, Signal R for realtime notifications. We leveraged Signal R to send realtime messages and notifications to the users. However there was this one unusual issue which people begun to notice — After opening X number of tabs, the newest tab does not load. It wont load until you close one of the already opened tabs. This over the time became very embarrassing and we decided to look for a fix.

After reading a little bit about this issue on the internet, found some interesting concepts. Sharing them below

Browsers have a maximum number of concurrent connections, usually around 6. After opening 6 or more tabs in the browser, all pointing to the same site, subsequent tabs would simply refuse to load.Source

So, all in all we found there are 2 ways in which this issue should be addressed. One of them is more like a quick fix, while the other one is the correct but time-consuming approach.

1. QUICK FIX – Close the connections from the client whenever the tab is not in use, and re-connect when tab is active

There are plenty of ways one can find when a tab is active or inactive. Using these events one can start/stop a connection. When the tab is not in focus, we killed off the connection of that tab, and when the user is back on that tab, we again reconnect to the hub.

window.addEventListener('focus', function() {
    signalRHub.connect();
});

window.addEventListener('blur', function () {
    signalRHub.disconnect();
});

2. Using localstorage as a message bus between the tabs

In this approach you will need only a single Signal R connection open, thereby preventing the multiple connection problem. Here localstorage can act like a message bus between the tabs, the storage event helps in broadcasting data between the tabs.

The concept is fairly simple. Only one tab keeps a push connection; we call this the master tab. When it receives a push event, it broadcasts it by setting the event as a property on local storage called “broadcast”. When a tab receives the storage event for this key, it reads the JSON-encoded event object from local storage and processes it as though it had been received via an EventSource object.Source

Further reading?
1. https://github.com/SignalR/SignalR/issues/2744
2. https://blog.fastmail.com/2012/11/26/inter-tab-communication-using-local-storage/

Hope this helps :)

Prevent Elmah to send mail on specific type of errors but log them to db.

Approach 1 :

The below filter when added, will stop both – sending out error email and logging to the db.

<errorFilter>
    <test>
        <!--<equal binding="HttpStatusCode" value="404" type="Int32" />-->
        <regex binding="BaseException.Message" pattern="404 request received" />
    </test>
</errorFilter>

Approach 2 :

The below filter will only stop sending out mail, but will continue to log to the db.

<errorFilter>
    <test>
        <or>
            <and>
                <regex binding="BaseException.Message" pattern="404 request received" />
                <regex binding="FilterSourceType.Name" pattern="mail" />
            </and>
            <and>
                <regex binding="BaseException.Message" pattern="Any xyz pattern can go in here..." />
                <regex binding="FilterSourceType.Name" pattern="mail" />
            </and>
        </or>
    </test>
</errorFilter>

Prevent elmah to be cached when using CDN.

It has been a common practice to use ELMAH for pretty much all of my web projects built using the ASP.NET stack.

One problem I kept running into was when using CDN with a website, there was no simple/direct way to tell the CDN to not cache the elmah urls. Here’s a solution which worked for me.

Step 1: Select website and add a url rewrite rule

Step 2: Make sure to select the “Outbound” rule when selecting the rule template

Step 3: Add a precondition, in this case add the elmah url

Step 4: Add a rule to update your response header’s Cache-Control with no-cache

Step 5: Done, now check the http response on your browser

References:

How to add an exclusion list to an HTTP Module in ASP.NET MVC

When writing your own HTTP Module you will need to have an exclusion list, so that not all HTTP request are intercepted by this module. Like for example: HTTP requests for CSS, JS, Images and even Html templates.

Here is what I used in one of our recent projects

private bool ShouldProcessRequestForSignUp(HttpRequest request)
{
    bool isAnAjaxRequest = request.RequestContext.HttpContext.Request.IsAjaxRequest();
    bool isRequestIsForLogoff = request.Url.AbsolutePath.ToLower().Contains("/account/logoff");
    bool isRequestIsForLogin = request.Url.AbsolutePath.ToLower().Contains("/account/login");
    bool isRequestForResources = (request.Url.AbsolutePath.ToLower().Contains("content") || request.Url.AbsolutePath.ToLower().Contains("scripts"));
    if (isAnAjaxRequest)
        return false;
    if (isRequestFortheSignupPage || isRequestIsForLogoff || isRequestIsForLogin)
        return false;
    if (isRequestForResources)
        return false;
    return true;
}

Updating one to many relationship tables using Entity Framework 6

Problem Statement

Consider the following diagram, where there is one to many relationship between the Employee and Assest table. Here 1 Employee can have M Assests.

enter image description here

Lets say an Employee has 2 assests namely –

OldList NewList
Home Home
Bike Car

So there are 3 things to be done when updating this data using the Entity Framework

  1. Look for items present in the newlist and missing in the oldlist, these items are to be added. The item “Car” in this example.
  2. Look for items present in the oldlist and missing in the newlist, these items are to be removed. The item “Bike” in this example.
  3. And finally the items that are present in both the list. The item “Home” in this example, is to be untouched.

Code

The following code uses ExceptBy extension method to compare two lists and return based on the key passed to it.

public void UpdateEmployeeAssests(int employeeId, List<EmpAssets> updatedAssests)
{
    using (var context = new SampleDbEntities())
    {
        List<EmpAssets> oldAssests = context.EmpAssets.Where(x => x.EmployeeId == employeeId).ToList();

        List<EmpAssets> addedAssests = updatedAssests.ExceptBy(oldAssests, x => x.CityId).ToList();
        List<EmpAssets> deletedAssests = oldAssests.ExceptBy(updatedAssests, x => x.CityId).ToList();

        deletedAssests.ForEach( x => context.Entry(x).State = EntityState.Deleted);
        addedAssests.ForEach(x => context.Entry(x).State = EntityState.Added);

        context.SaveChanges();
    }
}

References:

Injecting into Custom Validation or Authorization Attributes in ASP.NET MVC

Dependency Injection can be done when using Custom Validation or Authorization attributes in ASP.NET MVC. This can be achieved Ninject’s Property injection.

Here is an example of property injection. For a property to be injected it must be annotated with [Inject].

public class ZipCodeAttribute : ValidationAttribute
{
    [Inject]
    public IZipCodeService ZipCodeService { get; set; }

    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return true;
        }

        if ((value is string) && string.IsNullOrEmpty((string)value))
        {
            return true;
        }

        var zipCode = Convert.ToInt32(value);
        return this.ZipCodeService.IsValidZipCode(zipCode);
    }
}

More on “Injection of validators” can be read here.

Injecting dependencies into WebViewPages / Razor View in ASP.NET MVC

Even before you start reading this post, I am sure many of you ll would have already had discussions on this like

“Why would you need to access services on your view?”

or

“Why would you want to inject dependencies into your view?”

and even

“Shouldn’t your View be plain and dumb and be used only to render HTML from a model?”

But anyways here is something that should help you, should you want to inject dependencies in your views.

For example’s sake let’s consider you have a ‘PermissionService’ which has a method IsModuleAllowedForUser(Guid userId, string moduleName) which decides if the module is allowed for the user and only then renders it. Now I want to access this service method from my view.

Demo.Services.Core.PermissionService.cs

namespace Demo.Service.Core
{
    public class PermissionService : IPermissionService
    {
        public bool IsModuleAllowedForUser(Guid userId, string moduleName)
        {
            // blah
        }
    }
}

Here’s a way to do it.

To start with we’ll need to create a class which will inherit from the WebViewPage class. I have injected the IPermissionService using property inject with Ninject.

Demo.Web.Core.MyInjectedWebViewPage.cs

using System.Web.Mvc;
using Ninject;

namespace Demo.Web.Core
{
    public abstract class MyInjectedWebViewPage : WebViewPage
    {
        [Inject]
        public IPermissionService PermissionManager { get; set; }
    }
}

in my NinjectWebCommon.cs class I have added bindings for the same

Bind<WebViewPage>().To<MaxInjectedWebViewPage<dynamic>>();
Bind<IPermissionService>().To<PermissionService>();    

and now in the view I can use the services like as shown below

@inherits MyInjectedWebViewPage

@if(PermissionManager.IsModuleAllowedForUser(Helper.GetUserId(), "precious"))
{
    <div>My precious div!</div>
}

Hope this helps :)

References:

  1. ASP.NET MVC 3 Service Location, Part 3: View Engines/View Pages
  2. Can you inject dependencies into a constructor of a custom WebViewPage, using an IOC container?

Writing a Custom Html Helper for Button in ASP.NET Razor

Html Helpers are used when we want to have a custom html with/without some logic repeated across your application. Today I wanted to have all the buttons shown across the application behave in a particular way depending upon the logged in user, this can easily be done using HtmlHelper.

Code

public static class CustomHtmlHelpers
{
    public static MvcHtmlString CustomButton(this HtmlHelper htmlHelper, string innerHtml, IDictionary<string, string> htmlAttributes)
    {
        var builder = new TagBuilder("a") {InnerHtml = innerHtml};
        builder.MergeAttributes(htmlAttributes);
        return MvcHtmlString.Create(builder.ToString());
    }
}

In the IDictionary<string, string> htmlAttributes parameter you can pass all the html attributes you need your button to have, for example: class, href, or any other html attribute for that matter.

Example

@Html.CustomButton("<i class='fa fa-plus'></i>&nbsp; Create Something", new Dictionary<string, string> { { "class", "btn btn-primary" }, { "href", "#create" } })

You might wanna read another related article on Html Helpers.

How to pass values from ASP.NET MVC Razor Views to Angular Controller ?

I have been using a lot of AngularJs code on my razor views lately. On one of my page, I wanted to pass to my angular controller the model which is being passed to my razor view.

Can be done with the following code

ng-init="init(@JsonConvert.SerializeObject(Model))"

JsonConvert.SerializeObject helps you convert an object to a JSON string and you can use ng-init to pass and use this value in your controller.