Wednesday, November 4, 2015

MVC 6 and Dependency Injection on object with Parameters:

Sometimes things aren't obvious like this, which I spent a good portion of the day on.

In Startup.cs in method ConfigureServices(), 


   
            services.AddMvc();
            

            // Uncomment the following line to add Web API services which makes it easier to port Web API 2 controllers.
            // You will also need to add the Microsoft.AspNet.Mvc.WebApiCompatShim package to the 'dependencies' section of project.json.
            // services.AddWebApiConventions();

            // Register application services.
            services.AddTransient();
            services.AddTransient();
#if DNX451
           services.AddSingleton(provider => {
                var endPt = Configuration["Data:DocumentDbConnection:EndpointUrl"];
                var authKey = Configuration["Data:DocumentDbConnection:RWAuthKey"];
                var dbName = Configuration["Data:JobApp:DatabaseName"];
                var collName = Configuration["Data:JobApp:CollectionName"];
                return new JobAppDb(authKey, endPt, dbName, collName);
            }); 
#endif

Sunday, November 1, 2015

11/2015

After Struggling a bit to find documentation on how to create a Repository for DocumentDb in Azure for MVC 6, I decided to publish what I created last night. I hope someone finds this helpful.

-Jonathan Ulfeng

Basic DocumentDb class for Azure, MVC 6:

1. Create a Base Class for the document repository:

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Threading.Tasks;  
 using Newtonsoft.Json;  
 using JobApp33.Util;  
 #if DNX451  
 using Microsoft.Azure.Documents.Client;  
 using Microsoft.Azure.Documents.Linq;  
 using Microsoft.Azure.Documents;  
 using JobApp33.Models;  
 #endif  
 namespace JobApp33.Db  
 {  
   public abstract class DocumentDb  
   {  
     protected string DatabaseName { get; set; }  
     protected string CollectionName { get; set; }  
     protected string EndpointUrl { get; set; }  
     protected string AuthorizationKey { get; set; }  
     protected string CollectionLink => string.Format("dbs/{0}/colls/{1}", DatabaseName, CollectionName);  
     protected string DatabaseLink => string.Format("dbs/{0}", DatabaseName);  
     public DocumentDb()  
     {  
     }  
 #if DNX451  
     protected DocumentClient _client;  
     protected DocumentClient Client  
     {  
       get  
       {  
         if (_client == null)  
           _client = GetClient();  
         return _client;  
       }  
     }  
     protected Database _database;  
     protected Database Database  
     {  
       get  
       {  
         if (_database == null)  
         {  
           _database = ReadOrCreateDatabase();  
         }  
         return _database;  
       }  
     }  
     protected DocumentCollection _collection;  
     protected DocumentCollection Collection  
     {  
       get  
       {  
         if (_collection == null)  
           _collection = ReadOrCreateCollection();  
         return _collection;  
       }  
     }  
     protected DocumentCollection ReadOrCreateCollection()  
     {  
       DocumentCollection col = Client.CreateDocumentCollectionQuery(Database.SelfLink)  
                  .Where(c => c.Id == CollectionName)  
                  .AsEnumerable()  
                  .FirstOrDefault();  
       if (col == null)  
       {  
         col = Client.CreateDocumentCollectionAsync(DatabaseLink, new DocumentCollection { Id = CollectionName }).Result;  
       }  
       return col;  
     }  
     protected Database ReadOrCreateDatabase()  
     {  
       Database db = Client.CreateDatabaseQuery()  
               .Where(d => d.Id == DatabaseName)  
               .AsEnumerable()  
               .FirstOrDefault();  
       if (db == null)  
       {  
         db = Client.CreateDatabaseAsync(new Database { Id = DatabaseName }).Result;  
       }  
       return db;  
     }  
     //private async Task<DocumentClient> GetClientAsync() => new DocumentClient(new Uri(config.EndpointUrl), config.AuthorizationKey);  
     protected DocumentClient GetClient() => new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);  
     #region "CRUD Methods"  
     public async Task<Document> CreateItemAsync<T>(T item) where T : class  
     {  
       return await Client.CreateDocumentAsync(Collection.SelfLink, item);  
     }  
     public async Task<Document> UpsertItemAsync<T>(T item) where T : class  
     {  
       return await Client.UpsertDocumentAsync(Collection.SelfLink, item);  
     }  
     public async Task DeleteItemAsync<T>(string id) where T : class  
     {  
       foreach (Document document in Client.CreateDocumentQuery(  
           CollectionLink,  
           new SqlQuerySpec(  
             string.Format("SELECT * FROM {0} col WHERE col.id = @id", CollectionName),  
             new SqlParameterCollection(new[] { new SqlParameter { Name = "@id", Value = id } }))))  
         {   
           // Optionally, cast to CrawlResult using a dynamic cast  
           var result = (T)(dynamic)document;  
           await Client.DeleteDocumentAsync(document.SelfLink);  
         }  
     }  
     protected async Task<T> GetDocument<T>(string id) where T : class  
     {  
       // Query the documents using DocumentDB SQL.  
       IQueryable<Document> jobApps = from f in Client.CreateDocumentQuery(CollectionLink) where f.Id == id select f;  
       Document d = jobApps.AsEnumerable().FirstOrDefault();  
       T deserializedJobApp = JsonConvert.DeserializeObject<T>(d.ToString());  
       return deserializedJobApp;  
     }  
     #endregion  
 #endif  
   }  
 }  

2. Override that class to handle your poco Objects:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JobApp33.Util;
using Microsoft.Framework.OptionsModel;
using JobApp33.Models;

namespace JobApp33.Db
{

    public class JobAppDb : DocumentDb
    {
        public JobAppDb(IOptions settings) : base()
        {
            this.AuthorizationKey = settings.Options.AuthorizationKey;
            this.EndpointUrl = settings.Options.EndpointUrl;
            this.DatabaseName = settings.Options.JobAppDatabase;
            this.CollectionName = settings.Options.JobAppCollection;
        }
#if DNX451
        public JobApp GetJobApp(string id)
        {
            JobApp jobApp = null;
            Task.Run(async () =>
            {
                jobApp = await this.GetDocument(id);
            }).GetAwaiter().GetResult();
            return jobApp;
        }

        public Microsoft.Azure.Documents.Document UpsertJobApp(JobApp item)
        {
            Microsoft.Azure.Documents.Document doc = null;
            if (item != null)
            { 
                Task.Run(async () =>
                {
                    doc = await this.UpsertItemAsync(item);
                }).GetAwaiter().GetResult();
            }
            return doc;
        }

        public void DeleteJobApp(string id)
        {
            if (!string.IsNullOrEmpty(id))
            {
                Task.Run(async () =>
                {
                    await this.DeleteItemAsync(id);
                }).GetAwaiter().GetResult();
            }

        }

#endif
    }
}