Tuesday 25 February 2014

Windows Azure Mobile Services - Web API Backend – First Look

A new set of Windows Azure enhancements were released today, one of which is support for ASP.Net Web API backend on Mobile Services. Prior to this update, all backend services were written in NodeJS which is a fantastic platform, but it can feel a bit alien to a lot of .Net developers to develop server-side code in JavaScript.

This article is the first of a series I plan on writing on the new Web API backend feature, in a follow up to my book released last month on Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 https://www.packtpub.com/learning-windows-azure-mobile-services-for-windows-8-and-windows-phone-8/book.
We’ll look at creating a new service using the new Web API backend, download the service template and see what’s in there.

ASP.Net Web API

Microsoft ASP.Net Web API is a framework for creating RESTful web services using the .Net Framework which can be hosted on a web server or self-hosted inside a process like a client application or Windows Service. Web API is similar to MVC where HTTP requests routed (Web API used convention-based routing where a URI is matched to a controller action and Web API 2 adds attribute routing)  through to a controller which actions the request and returns a response.

Creating a Web API Backend Mobile Service

1. If you haven’t got a Windows Azure Account, go and create one
2. In the portal, click on the Mobile Services tab down the left side, then click the ‘+ NEW’ button on the bottom toolbar.

3. Select COMPUTE | MOBILE SERVICE | CREATE:


4. Next, choose a name for your API, pick the subscription you want to use, the hosting region where the service will reside and most importantly select ‘.NET (PREVIEW)’ from the ‘BACKEND’ picker:



5. Now enter the details for the database server you want to use (I’m using a server I already have, if you haven’t got one yet, you will have the option to create one):



6. Finally we will see our newly created service listed in the ‘MOBILE SERVICES’ tab. Here you can see a Node.js and .NET (Web API) service listed:

Backend Differences

If we compare a Node.js and .Net services, we will see some differences due to the nature of these platforms:

DATA and API Tabs

First off, there are some tabs missing from the portal of the Web API service:



We no longer have ‘DATA’ and ‘API’ tabs. In the Node.js (top) service, we can go into the ‘DATA’ tab, create tables and customise their REST API scripts; we can also go and create our own bespoke REST API scripts in the API tab. These customisations can be done in the portal directly with the JavaScript editor and become live immediately (they can also be pulled and modified locally using Git).

Our new Web API doesn’t have these tabs as all these API customisations are done locally, compiled and then published. The big difference is the Node.js script is interpreted at runtime and the Web API code is compiled.

Source Control

If we look at the ‘CONFIGURE’ tab, we see ‘source control’ ‘dynamic schema’ and ‘cross-origin resource sharing (cors)’ is missing. Node.js services can use Git source control to manage service scripts, however this is not needed for Web API as we publish directly to the service from visual studio.

Dynamic Schema

This is a really nice feature of Node.js services; whereby you can create typed models in your apps, then as the services discover them through table APIs, it dynamically adjusts the database schema to match. Web API doesn’t do this because the controller methods are strongly-typed, so the models need pre-defining in the service; however, Entity Framework code-first migrations are used, which means the database schema can be adjusted to match these models (depending on the initialiser used).

CORS

Browser security stops pages making AJAX requests to hosts other than to its originating host. The Cross Origin Site Scripting (CORS) settings in the Node.js service allows you to add trusted domains to you service. Web API 2 allows you to control this in the code yourself. There’s a good example of doing this here: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api.

Exploring the Template API

From the Mobile Service portal under ‘CONNECT AN EXISTING WINDOWS STORE APP’ click ‘Download’:


Unblock and unzip the file, then open the solution in Visual Studio 2013. The solution explorer should look something like this:


DataObjects

If we take a look at ‘TodoItem.cs’ we see we have two simple properties:
using Microsoft.WindowsAzure.Mobile.Service;

using Microsoft.WindowsAzure.Mobile.Service;

namespace TileTapperWebAPIService.DataObjects
{
    public class TodoItem : EntityData
    {
        public string Text { get; set; }

        public bool Complete { get; set; }
    }

}

You’ll notice though that it’s not just a POCO, it actually has an 'EntityData' base class which is an abstract implementation of ‘ITableData’ which enforces the default table requirements:

public abstract class EntityData : ITableData
{
    protected EntityData();

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Index(IsClustered = true)]
    [TableColumn(TableColumnType.CreatedAt)]
    public DateTimeOffset? CreatedAt { get; set; }
    [TableColumn(TableColumnType.Deleted)]
    public bool Deleted { get; set; }
    [Key]
    [TableColumn(TableColumnType.Id)]
    public string Id { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    [TableColumn(TableColumnType.UpdatedAt)]
    public DateTimeOffset? UpdatedAt { get; set; }
    [TableColumn(TableColumnType.Version)]
    [Timestamp]
    public byte[] Version { get; set; }

}

The attributes on these properties help Entity framework build the table schema from the model.

Database Context

If we look at the ‘YourServiceWebAPIContext’ we see that it is a standard Entity Framework DbContext:

namespace TileTapperWebAPIService.Models
{

    public class TileTapperWebAPIContext : DbContext
    {
        // You can add custom code to this file. Changes will not be overwritten.
        //
        // If you want Entity Framework to alter your database
        // automatically whenever you change your model schema, please use data migrations.
        // For more information refer to the documentation:
        // http://msdn.microsoft.com/en-us/data/jj591621.aspx

        private const string connectionStringName = "Name=MS_TableConnectionString";

        public TileTapperWebAPIContext() : base(connectionStringName)
        {
        }

        // When using code first migrations, ensure you use this constructor
        // and you specify a schema, which is the same as your mobile service name.
        // You can do that by registering an instance of IDbContextFactory<T>.
        public TileTapperWebAPIContext(string schema) : base(connectionStringName)
        {
            Schema = schema;
        }

        public string Schema { get; set; }

        public DbSet<TodoItem> TodoItems { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            if (Schema != null)
            {
                modelBuilder.HasDefaultSchema(Schema);
            }

            modelBuilder.Conventions.Add(
                new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
                    "ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));
        }
    }

}

We have a ‘TodoItems’ property for accessing the ‘TodoItem’ table and an overridden ‘OnModelCreating’ method which tells EF how to build the model.


The Controller

The ‘TodoItemController’ has a set of HTTP methods which map onto database CRUD operations:

namespace TileTapperWebAPIService.Controllers
{
    public class TodoItemController : TableController<TodoItem>
    {
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            TileTapperWebAPIContext context = new TileTapperWebAPIContext(Services.Settings.Name.Replace('-', '_'));
            DomainManager = new EntityDomainManager<TodoItem>(context, Request, Services);
        }

        // GET tables/TodoItem
        public IQueryable<TodoItem> GetAllTodoItems()
        {
            return Query();
        }

        // GET tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public SingleResult<TodoItem> GetTodoItem(string id)
        {
            return Lookup(id);
        }

        // PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)
        {
            return UpdateAsync(id, patch);
        }

        // POST tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
        {
            TodoItem current = await InsertAsync(item);
            return CreatedAtRoute("Tables", new { id = current.Id }, current);
        }

        // DELETE tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task DeleteTodoItem(string id)
        {
            return DeleteAsync(id);
        }
    }

}

The controller implements the ‘TableController<T>’ base class which itself derived from TableController and APIController and enforces the methods required to make a Mobile Service Table API. The EntityDomainManager manages access to the EF database context.

WebApiConfig

This contains code to bootstrap the Web API service and Entity Framework. We can see by default database initialiser class derives from DropCreateDatabaseIfModelChanges<T> which is one to be careful of as your database will be dropped and recreated if the model changes, losing all your data! There are a number of other database initialisers available.

Scheduled Jobs

The ‘SampleJob’ class shows us how to create a job which can be run on demand or on a schedule. This class stands out from the other template code as it’s not a standard Web API project component, it does not derive from APIController, but can be called via a POST request:

namespace TileTapperWebAPIService
{
    // A simple scheduled job which can be invoked manually by submitting an HTTP
    // POST request to the path "/jobs/sample".

    public class SampleJob : ScheduledJob
    {
        public override Task ExecuteAsync()
        {
            Services.Log.Info("Hello from scheduled job!");
            return Task.FromResult(true);
        }
    }

}

There is actually a 'JobsController' controller with a single POST method built into 'Microsoft.WindowsAzure.Mobile.Service.Controllers' which controls the jobs:



Finally

I think this is a really exciting addition to Windows Azure Mobile Services, it will greatly enhance the development experience for .Net developers by offering a familiar technology to build back-end services with. Because we now full control of the database using Entity Framework, we can easily create a relational database schema, which was previously unsupported.

I plan on continuing with articles about customising table API methods to do various things like validating data and filtering on user, creating custom APIs sending push notifications using the push notifications API and Notifications Hub and creating scheduled tasks.

Monday 24 February 2014

Windows Azure Mobile Services - Web API - Custom APIs

So what about the API tab that is in the Node.js service and missing from the Web API service? Well, the clue is in the name! We can simply add a Web API 2 controller to our solution like this:


And start coding in our controller methods. The 'RequiresAuthorization' security attributes we looked at in this article still work and we can create a reference to the 'ApiServices' object to access logging, push client etc:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Microsoft.WindowsAzure.Mobile.Service;
using Microsoft.WindowsAzure.Mobile.Service.Security;

namespace TileTapperWebAPIService.Controllers
{
    public class HighScoreController : ApiController
    {
        // GET api/<controller>
        [RequiresAuthorization(AuthorizationLevel.Application)]
        public IEnumerable<string> Get()
        {
            var service = new ApiServices(base.Configuration);
            service.Log.Info("Hello from HighScoreController!");

            return new string[] { "value1", "value2" };
        }

        // GET api/<controller>/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/<controller>
        public void Post([FromBody]string value)
        {
        }

        // PUT api/<controller>/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/<controller>/5
        public void Delete(int id)
        {
        }
    }

}