Dela via


Making it Yours: Configuring Mobile Services .NET Backend

The Azure Mobile Services .NET backend has a lot of flexibility in how you can configure and use it. It allows you to plug in additional components, change existing components, and configure how it works. Here we describe the main configuration and extensibility points as well as the common path. Typically you should be able to get by with very little -- the goal is to be there when you want it and get out of the way when you need it.

Bootstrapping

The first step is to define which method is to be called on start-up – we call this the bootstrapper. By default the backend looks for a static class called WebApiConfig (the CLR namespace doesn’t matter) with a public static, parameter-less method called Register. This is by far the common way of bootstrapping and is what the tooling will suggest. If the .NET backend finds a Register class then it is simply called and initialization happens from there. A basic example of the static class looks like this:

    1: public static void Register()
    2: {
    3:     ServiceConfig.Initialize(new ConfigBuilder());
    4: }

This will give you the default configuration all-around. Initialize returns the current HttpConfiguration so if you want to add or modify that then you can easily do it right then and there, for example:

    1: public static class WebApiConfig
    2: {
    3:     public static void Register()
    4:     {
    5:         HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder());
    6:         config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    7:     }
    8: }

However, if you would like to easily swap between different configurations, then you can use the BootstrapperAttribute to identify a class implementing the IBootstrapper interface, for example by declaring it as follows:

    1: [assembly: Bootstrapper(typeof(Local.MyBootstrapper))]

The IBootstrapper interface has a single method called Initialize which will get called, for example:

    1: public class MyBootstrapper : IBootstrapper
    2: {
    3:     public void Initialize()
    4:     {
    5:         HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder());
    6:         config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    7:     }
    8: }

Now, instead of the static Register class, the MyBootstrapper class will get called upon startup.

Service Configuration

The next step is for the bootstrapper to call the service configuration. This happens by calling the ServiceConfig.Initialize class like this:

    1: HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));

This class is responsible for getting config from the host, extensions, as well as from your code. As mentioned above, it returns the resulting HttpConfiguration which can then be further modified by your code.

Config Builder

The ServiceConfig.Initialize method takes an IConfigBuilder implementation which is responsible for initializing ASP.NET Web API, the OWIN application pipeline, and the Autofac Dependency Injection engine. The .NET backend comes with a default ConfigBuilder implementation which should be sufficient for most cases. It sets up ASP.NET Web API routes, message handlers, filters, etc. which are used by the backend.

The default ConfigBuilder takes two optional arguments: the first is ConfigOptions which is described below, and the second is a delegate which allows you to add additional services to the Autofac Dependency Injection container, for example

    1: public static class WebApiConfig
    2: {
    3:     public static void Register()
    4:     {
    5:         ConfigOptions options = new ConfigOptions();
    6:         HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options, (httpConfig, autofac) =>
    7:         {
    8:             autofac.RegisterInstance(new MyDependency()).As<IMyDependencyInterface>();
    9:         }));
   10:         config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
   11:     }
   12: }

Wherever you have a dependency on IDependencyInterface it can now be provided by Autofac. As described in FilipW’s blog, you can even manipulate the OWIN application pipeline as an Autofac dependency:

    1: public static class WebApiConfig
    2: {
    3:     public static void Register()
    4:     {
    5:         ConfigOptions options = new ConfigOptions();
    6:         HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options, (httpConfig, autofac) =>
    7:         {
    8:             autofac.RegisterInstance(new AuthOwinAppBuilder(httpConfig)).As<IOwinAppBuilder>();
    9:         }));
   10:     }
   11: }

In addition, it is possible to provide your own IConfigBuilder where you can either modify or otherwise manipulate the default configuration. Here is an example of an IConfigBuilder implementation that inherits from the default implementation and hooks into one of the virtuals:

    1: public class MyConfigBuilder : ConfigBuilder
    2: {
    3:     protected override void OnComplete(HttpConfiguration config)
    4:     {
    5:         // Additional configuration
    6:         base.OnComplete(config);
    7:     }
    8: }

Config Options

The ConfigOptions class is a simple property bag which contains easy setup for a bunch of backend settings. For example, you can set the minimum trace level which will get logged or include/exclude the trace categories you want to see. You can also set the minimum authorization level required to access the Diagnostics controller and other baked-in controllers. Finally you can set the default caching policy for which HTTP caching headers should get included on HTTP responses unless they already have been set by the application.

Extension Configuration

The last extensibility hook for the .NET backend provides a mechanism for extensions to also participate in the configuration. This allows extensions to hook into the configuration code path, for example, to set up their own per-controller configuration etc. This works very similar to the bootstrapper mechanism in that there is an assembly level attribute indicating the type of the extension configuration:

    1: [assembly: ExtensionConfigProvider(typeof(MyExtensionConfig))]

The MyExtensionConfig must implement the IExtensionConfigProvider interface so that the configuration can call it. For example, the MyExtensionConfig can register types with Autofac as well as manipulating the HttpConfiguration for the service:

    1: public class MyExtensionConfig : IExtensionConfigProvider
    2: {
    3:     public void Initialize(HttpConfiguration config, ContainerBuilder autofac)
    4:     {
    5:         autofac.RegisterInstance(new MyDependency()).As<IMyDependencyInterface>();
    6:     }
    7: }

Confused Yet?

Don’t panic -- the common case is that you need very little of this – typically you would use the static bootstrapper with some ConfigOptions like this:

    1: public static class WebApiConfig
    2: {
    3:     public static void Register()
    4:     {
    5:         ConfigOptions options = new ConfigOptions();
    6:         options.MinimumTraceLevel = TraceLevel.Debug;
    7:  
    8:         HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));
    9:         config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
   10:  
   11:         // Set up local DB etc.
   12:         Database.SetInitializer(new MyInitializer());
   13:     }
   14: }

This is just to show you how go beyond and truly make the .NET backend yours Smile

Have fun!

Henrik

Comments

  • Anonymous
    May 20, 2014
    Henrik,I noticed that if I change the action names in the API controller, it doesn't break (from client SDK perspective).  Does the mean you are (using the methods above) using Action Attributes to ensure a stable end point for things like table.InsertAync()?...Thanks

  • Anonymous
    May 21, 2014
    Bob, the route which maps to the table controllers is based on the controller name - the action isn't part of the route template (you can check the value of "this.RequestContext.RouteData.Route.RouteTemplate" in one of the actions in your controller - it will show "tables/{controller}/{id}", where "id" is optional). So you can change the action names, and as long as you continue to prefix them with the HTTP method name (i.e., GetSomethingOtherThanTodoItems) or use the System.Web.Http.Http*Attribute class to explicitly set the HTTP verb the action responds to, then the URI for the action won't change.

  • Anonymous
    May 21, 2014
    Thanks Carlos!

  • Anonymous
    August 13, 2015
    Hi Carlos, Is it possible to dynamically change the minimum trace level for a service without actually rebooting it?

  • Anonymous
    August 17, 2015
    Saquib, not really - if you change something in either the DLL of the service or the web.config, and push the changes via git, IIS will recycle the process and your service will be "rebooted" (actually a recycle). Notice that any client that is connected should not be disconnected / receive a 5xx response - the service should handle current clients while the recycle is happening.