Multitenancy with Subdomains in ASP.NET MVC 5

Developing a product that is multi-tenant is a pretty interesting challenge. Recently I was in the fortunate situation of having to work on such a thing. By giving organisations access to a tenant through a subdomain of choice is a pretty neat approach that provides users a sense of personal ownership of the product. In this post I will show a simple approach of how to use subdomains to identify the corresponding tenant in ASP.NET MVC 5.

First things first – what is the goal. Consider a CRM product, United CRM available on www.unitedcrm.com. ABC Inc. wishes to purchase access to United CRM for its employees. As part of signing up, ABC Inc. chooses the domain www.abc.unitedcrm.com for accessing it’s tenant. Let us see how this might be implemented.

Extract Tenant in Requests

Whenever you navigate to a site, your browser will add the Host header to the request. Visiting www.news.google.com, will result in the Host header value “news.google.com”. HttpContext provides all information about an HTTP request in ASP.NET and can be used to read the headers. Your have a range of options, where in the request pipeline this should be extracted.

Use a Route Constraint

Using a route constraint has the added benefit of being able to route all tenant specific request where appropriate. The following is a sample route constraint that extracts the subdomain and adds the tenant id to the route values dictionary:

Add the route constraint when creating routes:

The tenant id can then be extracted in controllers that end up handling the request:

Note that routing is used may be used several times for a single a request, specifically when Razor needs to resolve routes.

Use an Action Filter

Using a custom action filter, we add logic to extract the tenant before controller actions execute:

And extracting the tenant is done in the same way as with a route constraint:

Use a Base Controller

Finally, using a base controller is more or less exactly the same as the custom action filter, as MVC Controllers implements IActionFilter:

Enabling Subdomain Testing for Localhost

So far so good – we can identify the tenant a user is trying to access. In order to test it on a development machine, a couple of small additions needs to be done to allow subdomains with localhost (e.g. tenant1.localhost) together with IIS Express:

  1. Go to project Properties ,  Web  and hit Create Virtual Directory if the solution is completely new. This will add a site and bindings to the IIS Express application config file (or just run the solution once to make sure its added).
  2. Open the IIS Express application config file located in folder %USERPROFILE%\My Documents\IISExpress\config\applicationhost.config – find the project and add a binding to a test subdomain:
  3. Add the following entry to the hosts file: 127.0.0.1 test.localhost

If you run Visual Studio as Administrator, test.localhost will work at this time. If you are not running Visual Studio as Administrator, you will need to add it to HTTP.sys to allow the traffic:

netsh http add urlacl url="http://test.localhost:59920/" user=everyone

Xamarin Forms – Customizing Tabbed Page Header and Title on Windows Phone

In this post I will show how to customize the title and header section of the Tabbed Page control, when running on Windows Phone. On WP this is the pivot control being used, which is quite different from the tabs used on both iOS and Android.

Let’s say you wish to just change the font or completely restyle the title or the header showing the sections. You can create the complete page as a native Windows Phone XAML page with a pivot control and let that render. This gives complete control of the page and the pivot control, but makes the sacrifice of reducing how much code is shared.

The basic elements of the pivot is illustrated in Figure 2. With Xamarin Forms, the content area renders the content of the selected page. The title and header uses the default pivot title and header templates which is basically a TextBlock showing the Title property of the data context. Lets modify this and change the font and make the title text larger than the header.

Figure 2 - Pivot Control Elements

Figure 2 – Pivot Control Elements

First create a class that derives from TabbedPage in the shared project / PCL – it may be as simple as the following:

On any page you wish to use the styled one, derive from StyledTabbedPage instead.

In the Windows Phone project, create the class StyledTabbedPageRenderer that derives from TabbedPageRenderer. In addition, put the ExportRenderer attribute outside the namespace that instructs Xamarin to use the class when rendering the StyledTabbedPage control:

If we look at the definition of the TabbedPageRenderer on Windows Phone we can see it is deriving from the Pivot control:

When the instance of StyledTabbedPageRenderer is created instead of the default TabbedPageRenderer this will be the pivot control itself. Here we can access the template properties. The OnElementChanged override provides one to modify the control after setup. The following changes the title and header by constructing a new data template for the TitleTemplate and HeaderTemplate properties:

Note that by default, the Title property itself of the StyledTabbedPage instance is the context for the title element, whereas the child page instance is the instance for the header element. This is the reason that Line 16 is simply a binding directly to the context, whereas the binding expression for the header template must have the Title path added (or any other property you want to write out in the header).

Capptain (or your app telemetry service of choice) with Xamarin Forms

We are increasingly developing applications targeting both iOS and Windows Phone using Xamarin Forms. In this case, when it comes to telemetry, we are interested in putting as much as possible in the shared code. Here is a way to incorporate Capptain into a Xamarin Forms app using DependencyService and a proxy on each platform. You can use the same approach with other telemetry services, as long as a native SDK is provided for the platforms you target.

Xamarin Insights is currently in preview, but looks very promising. You might want to check it out first and see if it suits your needs.

Define the Interface in the Shared Project / PCL

First, the interface through which the shared code will use, is defined in the shared project or PCL depending on which approach you are using in the Xamarin Forms solution. The interface can be as simple as a one-to-one mapping to the desired methods you wish to use on the original interface exposed in the Capptain SDK. Here is an example that supports registering activities and events:

Provide Platform Specific Implementations

Next we provide the platform specific implementations which basically just forwards a call to the SDK. Here it is for Windows Phone (install the Capptain NuGet package into the Windows Phone solution).:

For Android and iOS it is a little more tricky, since we will need to provide bindings to the Java and Objective-C libraries.

For Android, download the Capptain JAR file and use add it to a binding project with Build Action set to EmbeddedJar. Some errors will show up – I was able to handle this by removing the class CapptainNativePushToken (you will not be able to use the push features of Capptain) by adding the following to the Meta file:

The Android proxy class follows the same approach as the Windows Phone one, except any additional data you send along is provided in a Bundle on the Android platform. You will have to make a convertion from the dictionary to a bundle (I wrote an extension method for this).

Wire Up Platform Specific Configuration

Telemetry services usually require some configuration initialization and event wiring in app life cycle events. For Windows Phone we add the following in App.xaml.cs to Application_Launching and Application_Activated:

For Android this should suffice in the MainActivity class (remember setting up the manifest file as described in the documentation):

Use DependencyService to Access Implementations

And now, finally in our Xamarin Forms page we can start shipping data about usage or errors:

Automatically Register Each Xamarin Forms Page as an Activity

If you want to track navigating between pages in general an easy way is to subclass e.g. ContentPage and wire up some activity tracking:

And then let your page inherit from CapptainContentPage instead of ContentPage. By default this will register the activity using the type name, but you can override the GetPageActivityName method in your page to change this.

Dynamics CRM 2011/2013 – Re-register Plugin Assembly With New Strong Name Key

All CRM plugins must be signed with a strong key in order to be deployed (both for letting Dynamics CRM be able to handle assembly naming conflicts and if you deploy it to the GAC on the server). I have come across a couple of projects where the password for the strong name key file was stuck in the head of another person – and later forgotten – making it troublesome set up a new development machine to build and deploy a solution.

For good reasons, the password cannot be retrieved, so here is a simple approach to re-registering your plugin/workflows with all existing steps and images as defined in the .crmregister file preserved.

1. Delete the Assembly From Server

This can be done either via. the CRM Explorer in Visual Studio or the Plugin Registration Tool. Note that this will leave your VS solution completeley intact and will not change anything in the .crmregister file.

Using the CRM Explorer in Visual Studio – connect to the organisation, choose “Plug-in Assemblies” in the menu, right click the assembly and choose “Delete Assembly”:

deleteassembly

Using the Plugin Registration Tool – connect to to the organisation, right click the existing assembly and select “Unregister”:

deleteassembly2

2. Create the New Signed Name Key File

Right click the project and choose Properties. Go to the Signing tab and choose a new strong name key file.

pluginkey

 

3. Reset Id Attributes in the .crmregister File

Here comes the part where we tell the CRM server to consider this a new plugin with all the existing configuration defined in the .crmregister file.

Open the .crmregister file in the CRM Package Project:

crmregister

Change all Id="{some-guid}"  attributes to  Id="00000000-0000-0000-0000-000000000000" . This must be done for all types of elements in the registration file (solution, plugin, step, image and so on).

4. Deploy Solution to CRM Server

Hit F5 and let the solution be deployed to a CRM server. This will cause everything to be registered as new. Re-open the .crmregister file and all Id attributes will contain a newly generated GUID.

Application Insights – Browser Debug Streaming Data Not Showing

Application Insights is the new analytics platform from Microsoft, currently in preview and part of Visual Studio Online. I had the honor of giving a talk on Application Insights during Danish Developer Conference last week which was very exciting. I plan to write a walk through of the new service soon, but for now I will address a small issue people run into.

Application Insights has a great development feed that provides raw and instant analysis data that can be used to verify that you send the right data before shipping your app: aifeed So, you have a web solution, you added Application Insights using the Application Insights Tools extension (or the functionality included if you use VS2013 Update 2 RC) to your solution, and then inserted some JavaScript analytics code that you got from the Application Insights portal into your views that looks like the following:

And all psyched up, you hit F5 while, at the same time, you have the Application Insights portal open on the stream data page. Ready to see the logs of you browsing around your site, you see that nothing shows. Except for the two server logs that gently tells you everything is ok and that a telemetry session has started. If you have any server side event loggings these show up just fine, but any client side events and page views logged in JavaScript does not.

Configure Streaming Data for JavaScript Analytics

First of all – do check the Visual Studio Online Service Blog. Application Insights is in preview and service level is not guaranteed at this time.

The best way is to set up the JS to load the values from the  ApplicationInsights.config  file that is added to the solution when you add Application Insights via. Visual Studio. This file contains a two profiles by default- one for Development and one for Production. The Application Insights SDK correctly switches between these when you run in the solution in Debug and Release mode respectively. As you can see, the Development profile has the following element that ensures that server side events logged using the API, are sent directly instantaneously to the feed in debug mode:

Part of the .NET SDK, is the ConfigurationHandler type in the Microsoft.ApplicationInsights.Telemetry.Web namespace. This type generates the JavaScript code that sets up configuration client-side based on the profile that is active server-side. The ConfigurationHandler type implements IHttpHandler. First we need to add in the Web.config an endpoint that invokes the handler to generate the JavaScript code. Add the following to your web config file as a child of the <configuration><system.web> element:

Change your JavaScript analytics code to the following:

Run your solution again in Debug mode and voila. The configuration file is now used to configure the client-side as well. If you want to see the the generated JS that is injected, just navigate to http://localhost:xxx/ApplicationInsights.axd. (Note that if you create a new solution in VS2013 with Update 2 RC, and tick Application Insights to be added, this is how it will set up new solutions!)

You can also configure it purely client-side. The JS API is not very well documented (actually not at all) in terms of setting up profiles. And for good reason – the above method should be used, since any configuration done in JavaScript will have to be maintained separately. It will also not switch between debug and release automatically. However, here is how it would look like:

And that is it – happy debugging your analytics!