Cover

Table Of Contents

Table of Contents

The Story behind the Succinctly Series of Books

About the Author

Chapter 1   Introduction

Chapter 2   Setup

Chapter 3   Concepts

Chapter 4   ASP.NET Web Forms

Chapter 5   ASP.NET MVC

Chapter 6   Web Services

Chapter 7   Routing

Chapter 8   OWIN

Chapter 9   Application Services

Chapter 10   Security

Chapter 11   Data Access

Chapter 12   Putting It All Together

References

Detailed Table of Contents

Chapter 1 Introduction

Chapter 1  Introduction

About this book

This is a book about building multitenant applications using ASP.NET. We will be discussing what multitenancy means for a web application in general, and then we’ll be looking at how ASP.NET frameworks like Web Forms and MVC can help us implement multitenant solutions.

You can expect to find here working solutions for the problems outlined, some of which certainly can be enhanced and evolved. Whenever appropriate, I will leave references so that interested readers can improve upon what I’ve built and further their understanding of these matters.

Some knowledge of ASP.NET (Web Forms or MVC) is required, but you do not have to be an expert. Hopefully, both beginners and experts will find something they can use here.

Throughout the book, we will be referring to two imaginary tenants/domains, ABC.com and XYZ.net, which will both be hosted in our server.

What is multitenancy and why should you care?

What is multitenancy and why should you care?

Multitenancy is a concept that has gained some notoriety in the last years as an alternative to multiple deployments. The concept is simple: a single web application can respond to clients in a way that can make them think they are talking to different applications. The different “faces” of this application are called tenants, because conceptually they live in the same space—the web application—and can be addressed individually. Tenants can be added or removed just by the flip of a configuration switch.

Why is this useful? Well, for one, it renders it unnecessary to have multiple servers online, with all the maintenance and costs they require. In general, among other things, one has to consider the following:

  • Resource isolation: A dedicated server is better shielded from failures in other infrastructure components than a shared solution.
  • Cost: Costs are higher when we need to have one physical server per service, application, or customer than with a shared server.
  • Quality of service: You can achieve a higher level of quality and customization if you have separate servers, because you are not concerned with how it might affect different services, applications, or customers.
  • Complexity of customization: We must take extra care in customizing multitenant solutions because we typically don’t want things to apply to all tenants in the same way.
  • Operation and management: “Hard” management, like backups, monitoring, physical allocation, power supplies, cooling, etc., are much easier when we only have one server.

Figure 1:  Decision criteria for dedicated versus shared (multitenant) deployments

In general, a multitenant framework should help us handle the following problems:

  • Branding: Different brandings for different tenants; by branding I mean things like logo images, stylesheets, and layout in general.
  • Authentication: Different tenants should have different user registrations; a user registered in a specific tenant should not be able to login to another tenant.
  • Workflow: It makes sense that different tenants handle the same basic things in a (slightly) different way; a multitenant framework is supposed to make this as transparent as possible with regard to code.
  • Data Model: Different tenants may have (slightly) different data needs; again, we should accommodate this need when possible, considering that we are talking about the same shared application.

Throughout the book we will give some attention to these problems.

Multitenancy requirements

Multitenancy requirements

As high-level requirements, our application framework should be able to:

  • Load a number of tenants and their information automatically
  • Identify, from each HTTP request, the tenant that it was meant to, or use a fallback value
  • Apply a branding theme to each tenant’s requested pages
  • Allow users to log in only to the tenant they are associated with
  • Offer common application services to all tenants that don’t collide; for example, something stored in application cache for one tenant will not be overwritten by another tenant

Application services

Application services

Application services offer common functionality that .NET/ASP.NET provides out of the box, but not in a multitenant way. These will be discussed in Chapter 9, “Application Services.”

Frameworks

Frameworks

ASP.NET is an umbrella under which different frameworks coexist: while the venerable Web Forms was the first public implementation that Microsoft put out, MVC has gained a lot of momentum since its introduction, and is now considered by some as a more modern approach to web development. SharePoint is also a strong contender, and even more so with SharePoint Online, part of the Office 365 product. Now it seems that OWIN (and Katana) is the new cool kid on the block, and some of the most recent frameworks that Redmond introduced recently even depend on it (take SignalR, for example).

On the data side, Entity Framework Code First is now the standard for data access using the Microsoft .NET framework, but other equally solid—and some would argue, even stronger—alternatives exist, such as NHibernate, and we will cover these too.

Authentication has also evolved from the venerable, but outdated, provider mechanism introduced in ASP.NET 2. A number of Microsoft (or otherwise) sponsored frameworks and standards (think OAuth) have been introduced, and the developer community certainly welcomes them. Here we will talk about the Identity framework, Microsoft’s most recent authentication framework, designed to replace the old ASP.NET 2 providers and the Simple Membership API introduced in MVC 4 (not covered since it has become somewhat obsolete with the introduction of Identity).

Finally, the glue that will hold these things together, plus the code that we will be producing, is Unity, Microsoft’s Inversion of Control (IoC), Dependendy Injection (DI), and Aspect-Oriented Programming (AOP) framework. This is mostly because I have experience with Unity, but, by all means, you are free to use whatever IoC framework you like. Unity is only used for registering components; its retrieval is done through the Common Service Locator, a standard API that most IoC frameworks comply to. Most of the code will work with any other framework that you choose, provided it offers (or you roll out your own) integration with the Common Service Locator. Except the component registration code, which can be traced to a single bootstrap method, all the rest of the code relies on the Common Service Locator, not a particular IoC framework.

Chapter 2 Setup

Chapter 2  Setup

Introduction

This chapter will walk you through setting up your development and test environment.

Visual Studio

Visual Studio

In order to be able to follow the concepts and code described here, you will need a working installation of Visual Studio; any version from 2012 upwards will do, including the shiny new Community Edition. I myself have used Visual Studio 2013, but you are free to use a different version; basically, you’ll need a Visual Studio version that can handle .NET 4.x and NuGet packages.

NuGet

NuGet

NuGet is Visual Studio’s native packaging system. Most software companies, including Microsoft, as well as independent developers and communities (such as the NHibernate community) provide their libraries and frameworks through NuGet. It’s an easy way to fetch software packages and their dependencies.

For the purpose of the examples in this book, you will need the following packages:

OWIN Self Host

OWIN Web API

Entity Framework Code First

NHibernate

Unity

Unity Bootstrapper for ASP.NET MVC

Enterprise Library Logging Application Block

ASP.NET Identity (Entity Framework)

ASP.NET Identity (NHibernate)

OWIN Identity

AspNet.Identity.EntityFramework.Multitenant

WatiN

 

Address mapping

Address mapping

If you want to follow the examples described in this book, you will need to set up different host names for you development machine. This is so that we can make use of the host header tenant identification pattern, described in Chapter 3. If you have administrative access to the DNS server that serves your local connection (work or home), you can add different aliases to a static IP address and then use that IP address instead of using a DHCP-assigned one.

Another option is to use a free service such as xip.io, which translates host names in domain xip.io into IP addresses; for example, 127.0.0.1.xip.io will automatically translate to 127.0.0.1, 192.168.1.1.xip.io becomes 192.168.1.1, and so on. This is so we can use the strategy for identifying tenants based on the host header mentioned earlier, but it only works with IP addresses, not host names.

Another option is to configure static IP-name mappings through the %WINDIR%\System32\Drivers\Etc\hosts file. This file contains lines in the format:

 

Code Sample 1

<IP address> <host name>  <alias 1>    …      <alias n>

 

For example, you can add the following entry:

Code Sample 2

127.0.0.1    localhost    abc.com             xyz.net

This will tell the IP stack on Windows that the hosts named abc.com and xyz.net will both translate to the loopback address 127.0.0.1, without the need for a DNS lookup.

IIS

IIS

Setting up a multitenant site in Internet Information Services (IIS) is easy: just open the IIS Manager applet and select Sites > Add website. Then add a host name that you wish to handle:

Figure 2:  Setting up a multitenant site in IIS

Now add a host name for all the additional tenants, select the site, and click Bindings.

Figure 3:  Adding additional host names to a site

Figure 4:  All the site's host names

Also important is the application pool: you can have different application pools serving each of the different tenants (the site bindings). This provides better isolation, in the sense that if something goes wrong for one of the tenants—perhaps an unhandled exception that renders the site unusable—it will not affect the others. Also, you can have the application pools running under different identities, which is nice if you wish to access different databases, or have different access levels. Just create as many application pools as you like in IIS Manager:

Figure 5:  Creating an application pool for a tenant

IIS Express

IIS Express

In case you will be using IIS Express, besides DNS or hosts file, you will also need to configure the website’s bindings to allow for other host names. Unfortunately, you will have to do it by hand, since IIS Express does not offer any graphical tool for that purpose; the site’s configuration file is located at: %HOMEPATH%\Documents\IISExpress\Config\ApplicationHost.config. Open it and locate the site entry that you wish to change; it should look like the following (minus name, id, physicalPath, and bindingInformation):

Code Sample 3

<sites>

       <site name="Multitenant" id="1">                                 

              <application path="/" applicationPool="Clr4IntegratedAppPool">                         <virtualDirectory path="/" 

                           physicalPath="C:\InetPub\Multitenant" />

             </application>

             <bindings>

                    <binding protocol="http" bindingInformation="*:80:localhost" />

              </bindings>

       </site>

</sites>

You will probably see some sites already configured. In that case, you have to find the one you’re interested in, maybe through the physicalPath attribute, and add a binding element with a bindingInformation attribute pointing to the proper host name and port.

Code Sample 4

<bindings>

      <binding protocol="http" bindingInformation="*:80:localhost" />

      <binding protocol="http" bindingInformation="*:80:abc.com" />

      <binding protocol="http" bindingInformation="*:80:xyz.net" />

</bindings>

This instructs IIS Express to also accept requests for hosts abc.com and xyz.net, together with localhost.

Chapter 3 Concepts

Chapter 3  Concepts

Who do you want to talk to?

As we’ve seen, the main premise of multitenancy is that we can respond differently to different tenants. You might have asked yourself: how does the ASP.NET know which tenant’s contents it should be serving? That is, who is the client trying to reach? How can ASP.NET find out?

There may be several answers to this question:

  • From the requested host name; for example, if the browser is trying to reach abc.com or xyz.net, as stated in the request URL
  • From a query string parameter, like http://host.com?tenant=abc.com
  • From the originating (client) host IP address
  • From the originating client’s domain name

Probably the most typical (and useful) use case is the first one; you have a single web server (or server farm) which has several DNS records (A or CNAME) assigned to it, and it will respond differently depending on how it was reached, say, abc.com and xyz.net. Being developers, let’s try to define a generic contract that can give an answer to this question. Consider the following method signature:

Code Sample 5

String GetCurrentTenant(RequestContext context)

We can interpret it as: “given some request, give me the name of the corresponding tenant.”

 Note: If you want to know the difference between DNS A and CNAME records, you can find a good explanation here.

The RequestContext class is part of the System.Web.Routing namespace, and it encapsulates all of a request’s properties and context. Its HttpContext property allows easy access to the common HTTP request URL, server variables, query string parameters, cookies and headers and RouteData to routing information, if available. I chose this class for the request instead of what might be more obvious ones—HttpContext and HttpContextBase—precisely because it eases access to route data, in case we need it.

Impressum

Verlag: BookRix GmbH & Co. KG

Tag der Veröffentlichung: 01.02.2016
ISBN: 978-3-7396-3496-8

Alle Rechte vorbehalten

Nächste Seite
Seite 1 /