Menu

Creating a Azure Mobile Service (also using OData) to create a generic BaseController for CURD operations.

Product that I am currently working on require Azure Mobile Service, as we have mobile app created with Xamarin using Azure Mobile Services to sync down the reference data. This is using .net 4.5

I am using exciting entities in the database, utilising exciting entities with Entity framework is quit easy, I just need to disable migrations in Mobile Service project – just to be safe.

This is my base entity is like

public abstract class EntityBase : EntityData, ICreateEntityBase, IModifyEntityBase
{
   public string CreatedBy { get; set; }
   public string UpdatedBy { get; set; }
}

public interface ICreateEntityBase
{
   string CreatedBy { get; set; }
}

public interface IModifyEntityBase
{
   string UpdatedBy { get; set; }
}

EntityData is part of Microsoft.WindowsAzure.Mobile.Service.

This will be my sample Question entity.

[Table("Question")]
public class Question : EntityBase
{
   public string Caption { get; set; }
   public string QuestionType { get; set; }
   public bool IsRequired { get; set; }
}

This is how my Glabal.asax.cs looks like

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
       WebApiConfig.Register();
    }
}

I am using WebApiConfig.Register() to register my dependancies using Autofac, later I will inject them to my controllers

public static class WebApiConfig
{
    public static void Register()
    {
        var options = new ConfigOptions();

        var config = ServiceConfig.Initialize(new ConfigBuilder(options, (configuration, builder) => {
        builder.RegisterType().As();
        ........................
        ........................
        builder.RegisterType().AsImplementedInterfaces().InstancePerLifetimeScope();
        }));

        Database.SetInitializer(null); // Ignore the migrations, let me know if there is a better way.....
    }
}

My DbContext is like below

public class MobileServiceContext : DbContext
{
    private const string ConnectionStringName = "Name=Questions";

    public MobileServiceContext() : base(ConnectionStringName)
    {
    }
    public DbSet Questions { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("Questions");
        modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>("ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));
    }
}

I will create the BaseController extending the TableController.

[MobileAppController]
public class BaseController : TableController where T : class, ITableData, new()
{
    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);
        MobileServiceContext context = new MobileServiceContext(); // TODO : DI this in the constractor
        DomainManager = new EntityDomainManager(context, Request, Services);
    }

    public readonly IDateService DateService;
    public BaseController(IDateService dateService)
    {
        DateService = dateService;
    }

    // GET tables/{Table}
    public IQueryable GetAll()
    {
        return Query();
    }

    // GET tables/{Table}/{id}
    public SingleResult GetSingle(string id)
    {
        return Lookup(id);
    }

    // PATCH tables/{Table}/{id}
    public Task Patch(string id, Delta model)
    {
        return UpdateAsync(id, model);
    }

    // POST tables/{Table}
    public async Task Post(T model)
    {
        T current = await InsertAsync(model);

        return CreatedAtRoute("Tables", new { id = current.Id }, current);
    }
}

In the actual QuestionController will on ly have the constructor. below is the sample code

public class QuestionController : BaseController
{
    public QuestionController(IDateService dateService) : base(dateService)
    {
    }
}

Using OData for querying
Now you can use mobile service on your Xamarin app as usual, But if you want to use the same controllers in a web app u can use the OData for your queries.

Get All 
http://XXXXXXXXXXXXXXXXXX.azurewebsites.net/tables/Question

Get All and set the columns to return
http://XXXXXXXXXXXXXXXXXX.azurewebsites.net/tables/Question?$select=id,questionType,caption

Get By ID
http://XXXXXXXXXXXXXXXXXX.azurewebsites.net/tables/ActivityType?id=0B9BD81F-90D7-4C44-B522-B95F0F9C9D48

For more information on odata please click here

yeah its that simple, I think I love OData….

Leave a comment