Singleton Broadcaster in Angular2

A simple way to subscribe and/or broadcast from anywhere in an app to anywhere else.

Basically, I needed a simple way to send out global messages not knowing what components would be loaded and didn't want to deal with injecting this anywhere in older components.  With a little messing around with some online guides (sorry I don't remember which ones) I came up with the following:

broadcast.service.ts
import { Injectable } from "@angular/core";
import { Subject } from "rxjs/Subject";

@Injectable()
export class BroadcastService {

    static instance: BroadcastService;
    static isCreating: Boolean = false;

    private broadcastMessageSource = new Subject<string>();
    broadcastMessage$ = this.broadcastMessageSource.asObservable();
    
    constructor() {
        if (!BroadcastService.isCreating) {
            throw new Error("You can't call new in Singleton instances");
        }
    }

    static getInstance() {
        if (BroadcastService.instance == null) {
            BroadcastService.isCreating = true;
            BroadcastService.instance = new BroadcastService();
            BroadcastService.isCreating = false;
        }
        return BroadcastService.instance;
    }

    broadcastMessage(modal: string) {
        this.broadcastMessageSource.next(modal);
    }
}

Then simply make sure to import it where you need it, and send out a broadcast:

BroadcastService.getInstance().broadcastMessage('message-i-care-about');

Where you need to,  subscribe in the constructor (or ngOnInit):

BroadcastService.getInstance().broadcastMessage$.subscribe(this.receiveBroadcastMessage.bind(this));

And deal with the broadcast however you will:

receiveBroadcastMessage(broadcast: string): void {
    console.log('broadcast received: ' + broadcast);

    // I generally run it through a switch to see if its something this component cares about
    switch (broadcast) { 
        case 'message-i-care-about': doSomething(); break;
    }
    // or just ignore it
}

There you go, just sent and received a global broadcast message.

Azure Service Fabric ServiceProxy failing silently

Inside my service fabric, I was creating a ServiceProxy to call another part of the fabric which I had working in multiple other places in my code like this:

var uri = new Uri("fabric:/MyNameSpace.MyClass");
var proxy = ServiceProxy.Create<ISomeInterface>(uri);
proxy.DoSomething(someString, someObjectCollection);

And it worked perfectly fine, next I tried with a different interface and it just silently failed, literally the exact same setup, but a new interface.

public interface ISignalRelay : IService
{
    Task Broadcast(string group, string message, object details);
}

Then my code:

var uri = new Uri("fabric:/MyNameSpace.MyClass");
var signalRelay = ServiceProxy.Create<ISignalRelay>(uri);
signalRelay.Broadcast(group, message, nonPrimitiveObject);

When stepping through the code, it would work fine until I hit Broadcast() and then just continue on, but that code was never hit.  From what I deduced, it was the ability of the proxy to deal with the base object class when it was passed something that was not a primitive type.

I was able to work around this as I was able to pass in a serialized string version of the object instead, but this is definitely a limitation of the way fabric works.  As an FYI, I tried generics, but you can not use the cross class fabric structure with generics (I forget the actual exception, but it's explicitly stated you cannot).  

If anyone has a way around this, or a better understanding, I would love to hear it.  Otherwise, I hope this saves someone from bashing their head on the desk all day like it did me.

 

Run a Controller action from inside another Controller as the current User

manually creating a controller and running its action does not run as the logged in user

If you want to run an action of another controller from inside a separate controller, it will work fine *if* you do not need any current HttpContext values such as User, etc. If you want to do that, you will need to force that context into the controller instance. To do this, I added a simple method to my base Controller class:
public T RunAsCurrentUser(
    T controller, RouteData routeData = null) 
        where T : ControllerBase
{
    var newContext = new ControllerContext(
        new HttpContextWrapper(
            System.Web.HttpContext.Current), 
            routeData ?? new RouteData(), controller);
    controller.ControllerContext = newContext;
    return controller;
}

then to use it:
var someController = RunAsCurrentUser(
    new Some.NameSpace.SomeController());
var result = someController.SomeAction();

Kendo Grid "TypeError: u is undefined"

possible reason you may find this nondescript error

TypeError: u is undefined

I was getting this strange error while using KendoGrid which I had used many times before and I couldn't figure out why. I was simply calling:
$('#grid').kendoGrid();

On a simple table, nothing special. Turns out it was simply because I had used some <th> in the <tbody>, but it can only be located in the <thead>.

MVC Bundling not working on Azure deploy

working locally, but not on deploy

When using your bundler, everything may work fine, but quirks often pop up on Azure deployment, these are some of them I came across:

Styles/Javascript not rendering at all

This my be because your names resemble your directory structure, which apparently it does not like. For example, if this is your Bundle:
bundles.Add(new StyleBundle("~/Styles/Metro").Include(
            "~/Styles/Metro/metro-bootstrap.css",
            "~/Styles/Metro/metro-ui-icons.css"));

And you use the render:
@Styles.Render("~/Styles/Metro")

It will not render on Azure! Simply change it so your render string does not resemble your actual directory structure, and it will work:
bundles.Add(new StyleBundle("~/Styles/MetroCss").Include(
            "~/Styles/Metro/metro-bootstrap.css",
            "~/Styles/Metro/metro-ui-icons.css"));

And you use the render:
@Styles.Render("~/Styles/MetroCss")

Notice that the directory is ~/Styles/Metro but the render string is ~/Styles/MetroCss.

If that is not it, be sure you are using
@Styles.Render("~/Styles...")

for css, and:
@Scripts.Render("~/Scripts...")

for Javascript.

Images or Fonts not rendering

This is because you assume things will behave the same when they are up in Azure, which is not always the case. If you have this stuff outside of the ~/Content/ folder, your program will not, by default, know how to handle it. You will get a Controller error if you try to navigate to it manually.

The answer? Simply move everything somewhere within the ~/Content/ folder which MVC makes public by default. Don't forget to update your css and JavaScript accordingly!

Otherwise you can make a controller to handle these requests, but that involves more work.

KendoUI : TypeError: n.slice is not a function

common error in Kendo UI that has a simple solution

The error:
TypeError: n.slice is not a function

Is not very clear, but it is pretty simple. You are generally using some sort of AutoComplete, DataGrid, etc. This simply means that you are not returning a collection (JSON), but a layer (or more) up from that collection you want to include. For example, you would be returning this JSON:
{
    "TrackingModels":[
        {"Id":17,"Name":"Bill"},
        {"Id":17,"Name":"Bob"}
    ]
}

When what Kendo is expecting is just this:
{[
    {"Id":17,"Name":"Bill"},
    {"Id":17,"Name":"Bob"}
]}

Azure Error - .NET Runtime version 4.0.30319.18033 - Loading profiler failed during CoCreateInstance.

frustrating profiler error when you aren't actually using a profiler

The other day I was troubleshooting an Azure problem, and I had turned on my profiler:

Once I figured out the problem, I then turned off profiling, then re-published. Now my application would not work at all and I kept getting the error:

.NET Runtime version 4.0.30319.18033 - Loading profiler failed during CoCreateInstance.
Despite the fact that I wasn't using a profiler anymore. I rebooted and tried all sorts of other things, nothing seemed to work.

The Fix

Not to say there is not a better fix (I tried all I could find elsewhere, nothing seemed to relate to my specific problem) but here is what I ended up doing. Simply delete your deployment, and re-publish. This must re-set whatever turning on your profiler sets.

Remember that if this is a non domain dns instance, your address will be changed. Hope this can save someone a few hours.

jQuery moveTo() plugin

simple way to move an element from A to B

Say you have these elements:
<ul id="A">
    <li id="L1">Stan</li>
    <li id="L2">Arnold</li>
</ul>
<ul id="B">
</ul>

And you want to move 'L1' (Stan) to ul 'B' - using this simple short plugin:
(function ($) {
    $.fn.moveTo = function (selector) {
        return this.each(function () {
            var element = $(this).detach();
            $(selector).append(element);
        });
    };
})(jQuery);

You can do that with this:
$('#L1').moveTo('#B');

Now you have this in your DOM:
<ul id="A">
    <li id="L2">Arnold</li>
</ul>
<ul id="B">
    <li id="L1">Stan</li>
</ul>

Or, similarly, you can do something like this:
$('li').moveTo('#B');

Now you have this in your DOM:
<ul id="A">
</ul>
<ul id="B">
    <li id="L1">Stan</li>
    <li id="L2">Arnold</li>
</ul>

Double Input problem with CheckBoxFor in MVC while serializing

if you have tried to serialize a CheckBoxFor from MVC to JSON, you will notice that you get two inputs, and it can mess up the data you are sending

It's no surprise that JavaScript is not sure how MVC works so when you try data.serialize() on MVC form data, you get odd results. Here is a simple workaround for when you need something to be serialized. I modified the GetPropertyName method from this post on StackOverflow.
public static string GetPropertyName<TModel, TValue>
    (Expression> exp)
{
    MemberExpression body = exp.Body as MemberExpression;
    if (body == null)
    {
        UnaryExpression ubody = (UnaryExpression)exp.Body;
        body = ubody.Operand as MemberExpression;
    }
    return body.Member.Name;
}

public static MvcHtmlString CheckBoxForJson<
    TModel, TValue>(this HtmlHelper<TModel> helper, 
    Expression<Func<TModel, TValue>> expression)
{
    string propName = GetPropertyName(expression);
    string html = "<input type=\"checkbox\" name=\"" 
        + propName + "\" id=\"" 
        + propName + "\" value=\"true\" />";
    return MvcHtmlString.Create(html);
}

And use it like this:
@Html.CheckBoxForJson(x => x.SomeBool)

The reason for the 'true' is because otherwise it will always pass as false since 'on' is not a bool value (html default).