Blog

A catalogue of my discoveries in software development and related subjects, that I think might be of use or interest to everyone else, or to me when I forget what I did!

Spatial Queries using Entity Framework without Microsoft.SqlServer.Types.dll

May 18, 2017

You can use entity framework to make spatial queries against your Microsoft SQL Server database, which is great when the majority of the ORM code is using EF. What isn't great is that for this to work you have to add some native DLLs into your project, namely the "Microsoft.SqlServer.Types.dll" - this comes in 32 bit and 64 bit variants. Seemingly this also needs to appear in any top level application container, which is usually a different project to the one housing your ORM code. In the end these DLLs seem to get everywhere, except the deployed environment and cause a lot of problems at runtime if they're missing. For my purposes though, I didn't need full in-memory spatial support, I simply wanted to add spatial predicates to my where clauses and return normal "non-spatial" objects back from SQL Server. This is really easy to do in isolation, just write the SQL text and execute it directly using EF. However, most of the time you actually want to combine this with another set of undeterminate predicates which have been applied to the IQueryable in other parts of the code. To solve this issue, I wrote a helper which allows me tag on my spatial query as the last execution step of the IQueryable (e.g. replacing the ToList()) as follows:
internal static class EFSpatialHelper
{
        public static Task<List<T>> QueryByProximityAsync<T>(DbContext context, IQueryable<T> query, Proximity proximity)
        {
            string sqlPointGeogPreamble = $@"
Declare @GeogPoint as geography
Declare @GeogShape as geography

SET @GeogPoint = geography::STGeomFromText('POINT (' + Cast(@longitude as varchar) + ' ' + Cast(@latitude as varchar) + ')', 4326)
SET @GeogShape = @GeogPoint.STBuffer(@buffer)

";
            string sqlGeogPredicate = "@GeogShape.STIntersects(Point) = 1";

            List<SqlParameter> sqlParams = new List<SqlParameter>();
            sqlParams.Add(new SqlParameter("@longitude", proximity.Longitude));
            sqlParams.Add(new SqlParameter("@latitude", proximity.Latitude));
            sqlParams.Add(new SqlParameter("@buffer", proximity.RadiusInMeters));

            return InjectAndExecuteSql(context, query, sqlPointGeogPreamble, sqlGeogPredicate, sqlParams.ToArray());
        }

        internal static Task<List<T>> GetByWellKnownTextAsync<T>(DbContext context, IQueryable<T> query, string wellKnownText)
        {
            string sqlWktGeogPreamble = @"
Declare @GeogPolygon as geography
Declare @GeomPolygon as geometry

Set @GeomPolygon = Geometry::STGeomFromText(@WKT, 4326)
Set @GeogPolygon = Geography::STGeomFromWKB(@GeomPolygon.MakeValid().STUnion(@GeomPolygon.STStartPoint()).STAsBinary(), 4326)

";
            string sqlGeogPredicate = "Point.STIntersects(@GeogPolygon)=1";

            return InjectAndExecuteSql(context, query, sqlWktGeogPreamble, sqlGeogPredicate, new SqlParameter("@WKT", wellKnownText));
        }

        private static Task<List<T>> InjectAndExecuteSql<T>(DbContext context, IQueryable<T> query, string spatialPreamble, string spatialPredicate, params SqlParameter[] spatialParams)
        {
            ObjectQuery<T> objectQuery = GetQueryFromQueryable(query);
            string sqlQryText = $"{spatialPreamble}{objectQuery.ToTraceString()}";

            // the query text in here is quite simple, we know it doesnt have an order by or a group by, so just stick predicates on the end.
            if (!sqlQryText.ToUpper().Contains("WHERE"))
            {
                sqlQryText = $"{sqlQryText} WHERE {spatialPredicate}";
            }
            else
            {
                sqlQryText = $"{Regex.Replace(sqlQryText, "WHERE", "WHERE (", RegexOptions.IgnoreCase)}) AND {spatialPredicate}";
            }

            List<SqlParameter> sqlParams = new List<SqlParameter>();
            if (spatialParams != null)
            {
                sqlParams.AddRange(spatialParams);
            }

            foreach (var p in objectQuery.Parameters)
            {
                sqlParams.Add(new SqlParameter(p.Name, p.Value));
            }

            return context.Database.SqlQuery<T>(
                sqlQryText,
                sqlParams.ToArray()).ToListAsync();
        }

        private static ObjectQuery<T> GetQueryFromQueryable<T>(IQueryable<T> query)
        {
            var internalQueryField = query.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Where(f => f.Name.Equals("_internalQuery")).FirstOrDefault();
            var internalQuery = internalQueryField.GetValue(query);
            var objectQueryField = internalQuery.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Where(f => f.Name.Equals("_objectQuery")).FirstOrDefault();
            return objectQueryField.GetValue(internalQuery) as ObjectQuery<T>;
        }
}
Here is an example of the modified logic for executing a query:
if (wellKnownText != string.Empty)
{
    return await this.GetItemsInWellKnownTextAsync(context, fullQuery, wellKnownText).ConfigureAwait(false);
}
else if (proximity != null)
{
    return await this.GetItemsInProximityAsync(context, fullQuery, proximity).ConfigureAwait(false);
}
else
{
    return await fullQuery.ToListAsync().ConfigureAwait(false);
}
Permalink: Spatial Queries using Entity Framework without Microsoft.SqlServer.Types.dll

Dealing With Map Related Data on the Server in C#

February 07, 2017

It is possible to create interactive graphical maps in many front end frameworks. In the past I have written mapping applications using Virtual Earth (JavaScript), Bing Maps (Silverlight), Bing Maps (JavaScript) and MapBox (JavaScript). The client side implementations vary, but there are common themes especially from a server side point of view. There are a lot of concepts that be represented in re-usable C# code. For this reason, I have created a class library of ".NET Mapping" objects and helpers, which represent the mapping concepts such as geographical points, bounding boxes, proximities, distance calculation and zoom level calculation. You can view or download the library on GitHub.
Permalink: Dealing With Map Related Data on the Server in C#

Azure AAD Login Redirect Loop

January 11, 2017

Sometimes when using Microsoft Azure AAD for authentication the website goes into a redirect permaloop. So far, this has been caused by two different things for me - so I will collate the causes and solutions below:
  1. HTTP vs HTTPS - Since the Microsoft login server is running on HTTPS you must also run your website on HTTPS, since the login cookie will be issued using the secure flag, which prevents it from being read using HTTP. There are various ways to force SSL on your website, from global filters to URL re-writing, but in general make sure to setup your site URLs using HTTPS in the Azure portal and to browse to HTTPS.
  2. OWIN Middleware Cookie issue - There is a known issue with the OWIN middleware which means that it's cookies are sometimes lost when issued in conjunction with some other cookie, e.g. the session cookie. The easiest solution to this one I have found is to install a NuGet package called "Kentor.OwinCookieSaver" and then add the following line to startup.auth.cs
     public void ConfigureAuth(IAppBuilder app)
            {
                app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
                app.UseKentorOwinCookieSaver(); // <-- ADD THIS LINE
    
Permalink: Azure AAD Login Redirect Loop

C# HttpClient for Calling Azure based WebAPI with OAuth Client Credentials

January 06, 2017

The below C# code creates a sub-class of the System.Net.Http.HttpClient that deals with adding the "Authorization" header to subsequent calls, using OAuth client credentials grant.
using System;
using System.Collections.Generic;
using System.Net.Http;
using Newtonsoft.Json.Linq;

namespace SomeProject.WebAPI.Client
{
    internal sealed class SomeWebApiHttpClient : HttpClient
    {
        private static string authToken;
        private static DateTime authTokenTime;

        private SomeWebApiHttpClient(ISomeWebApiClientConfig config)
        {
            this.BaseAddress = new Uri(config.SomeWebApiBaseAddress);
        }
        
        public static async Task<SomeWebApiHttpClient> CreateInstanceAsync(ISomeWebApiClientConfig config)
        {
            var instance = new SomeWebApiHttpClient(config);
            instance.DefaultRequestHeaders.Add("Authorization", await GetAuthAsync(config.SomeWebApiTenantId, config.CallingClientId, config.CallingClientKey));

            return instance;
        }

        private static async Task<string> GetAuthAsync(string tenantId, string callingClientId, string callingClientKey)
        {
            if (string.IsNullOrEmpty(authToken) || DateTime.Now.Subtract(authTokenTime).TotalMinutes > 45)
            {
                using (var authClient = new HttpClient())
                {
                    authClient.BaseAddress = new Uri("https://login.microsoftonline.com/");

                    Dictionary<string, string> bodyContent = new Dictionary<string, string>();
                    bodyContent.Add("grant_type", "client_credentials");
                    bodyContent.Add("client_id", callingClientId);
                    bodyContent.Add("client_secret", callingClientKey);
                    bodyContent.Add("resource", "https://somedomain.onmicrosoft.com/APP-URI-ID");

                    var result = await authClient.PostAsync(
                        $"{tenantId}/oauth2/token",
                        new FormUrlEncodedContent(bodyContent)).ConfigureAwait(false);

                    if (result.IsSuccessStatusCode)
                    {
                        dynamic tokenResult = (dynamic)JValue.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false));

                        authToken = $"{tokenResult.token_type} {tokenResult.access_token}";
                        authTokenTime = DateTime.Now;
                    }
                    else
                    {
                        Trace.WriteLine($"Failed to login to API - {await result.Content.ReadAsStringAsync().ConfigureAwait(false)}");
                        
                        return string.Empty;
                    }
                }
            }

            return authToken;
        }
    }
}
In the above code you must correctly set the domain and APP-URI-ID for the WebAPI this client is supposed to be using (or pass them in the config if they are variable). The configuration is passed in via an interface so that the calling code can inject whatever implementation they have for storing the configuration. E.g. In the web project composition root, a class that reads from the web.config using ConfigurationManager. The interface is defined as below:
public interface ISomeWebApiClientConfig
    {
        string SomeWebApiBaseAddress { get; }
        string SomeWebApiTenantId { get; }
        string CallingClientId { get; }
        string CallingClientKey { get; }
    }
These settings can be found in the Azure portal within the active directory that defines the client/server applications. Now the rest of the code base can use this client to call the API's endpoints, without worrying about injecting the auth header. Example usage of the HttpClient to call an example API endpoint:
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json.Linq;

namespace SomeProject.WebAPI.Client
{
    public class ExampleDataClient
    {
        private readonly ISomeWebApiClientConfig config;

        public ExampleDataClient(ISomeWebApiClientConfig config)
        {
            this.config = config;
        }

        public async Task<IEnumerable<SomeExampleData>> GetSomeExampleData(string someParam)
        {
            using (var client = await SomeWebApiHttpClient.CreateInstanceAsync(this.config).ConfigureAwait(false))
            {
                var result = await client.GetAsync($"api/SomeExampleData").ConfigureAwait(false);

                if (result.IsSuccessStatusCode)
                {
                    var returnValue = JValue.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false));

                    if (returnValue.HasValues)
                    {
			List<SomeExampleData> outputList = new List<SomeExampleData>();
                       foreach (var item in returnValue)
                       {
                           outputList.Add(SomeExampleData.FromJObject(item));
                       }
                       
                       return outputList.AsEnumerable();
                    }
                    else
                    {
                        return Task.FromResult<IEnumerable<SomeExampleData>>(null);
                    }
                }
                else
                {
                    Trace.WriteLine($"HTTP error: {result.RequestMessage.RequestUri} ({result.StatusCode}) - {await result.Content.ReadAsStringAsync().ConfigureAwait(false)}");
                    return Task.FromResult<IEnumerable<SomeExampleData>>(null);
                }
            }
        }
    }
}
Permalink: C# HttpClient for Calling Azure based WebAPI with OAuth Client Credentials

Exception Handling in ASP.NET MVC and WebAPI

January 04, 2017

This is an amalgmation of techniques taken from various sources on how best to handle exceptions/errors in ASP.NET MVC. There are many ways to approach this, but this is one that I'm happy with at the moment, it is based on the premise that the application doesn't swallow up exceptions in try catch blocks and silently fail, instead the error is logged and then reported to the user so they can make a decision as to whether they can fix the issue/try again to resolve (e.g. for validation exceptions). Firstly, override the "Application_Error" in the global.asax so that any unhandled exceptions are caught and handled in a nicer way than the "yellow screen of death" provided by ASP.NET.
/// <summary>
/// http://www.codeproject.com/Articles/422572/Exception-Handling-in-ASP-NET-MVC#handleerror
/// http://prideparrot.com/blog/archive/2012/5/exception_handling_in_asp_net_mvc#elmah
/// http://stackoverflow.com/questions/5226791/custom-error-pages-on-asp-net-mvc3
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Args</param>
protected void Application_Error(object sender, EventArgs e)
{
    var httpContext = ((MvcApplication)sender).Context;

    var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
    var currentController = " ";
    var currentAction = " ";

    if (currentRouteData != null)
    {
        if (currentRouteData.Values["controller"] != null && !string.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
        {
            currentController = currentRouteData.Values["controller"].ToString();
        }

        if (currentRouteData.Values["action"] != null && !string.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
        {
            currentAction = currentRouteData.Values["action"].ToString();
        }
    }

    var ex = this.Server.GetLastError();
    Trace.TraceError(ex.MessageEx());

    var routeData = new RouteData();
    var controller = new ErrorController();
    var action = "Index";
    int httpStatusCode = (int)HttpStatusCode.InternalServerError;

    if (ex is HttpException)
    {
        var httpEx = ex as HttpException;

        switch (httpEx.GetHttpCode())
        {
            case 404:
                action = "Http404";
                break;

            // define additional http code error pages here
            default:
                action = "Index";
                break;
        }
    }

    httpContext.ClearError();
    httpContext.Response.Clear();
    httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : httpStatusCode;
    httpContext.Response.TrySkipIisCustomErrors = true;
    httpContext.Response.Headers.Add("Content-Type", "text/html");
    routeData.Values["controller"] = "Error";
    routeData.Values["action"] = action;

    controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
    ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
This works by interpreting the exception, logging the error to the trace listeners and then redirecting the users to an "/Error/Index" action (or 404). The content of the error page can be something like this:
@model HandleErrorInfo

@{
    ViewBag.Title = "Error";
}

<h1>Error</h1>

<div class="alert alert-danger" role="alert">
    <p><i class="fa fa-warning"></i> Sorry, an error occurred whilst processing your request.</p>
    <p>@Model.Exception.Message</p>
</div>
That will take care of problems in "normal" page loads and postbacks, i.e. non-async calls. For async calls this is handled slightly differently. Create an action filter that will check for exceptions and wrap the message inside a JsonResponse object (see http://www.dotnetcurry.com/ShowArticle.aspx?ID=496 ):
public class HandleJsonExceptionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
        {
            filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
            filterContext.Result = new JsonResult()
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new
                {
                    Message = filterContext.Exception.MessageEx()
                }
            };

            Trace.TraceError(filterContext.Exception.MessageEx());
            filterContext.ExceptionHandled = true;
        }
    }
}
Now decorate the actions you will be calling asynchronously with this attribute, usually these are the actions that return a JsonResult or a Partial View. For a consistent theme, you can return the same response "Message" for your WebAPI calls by applying the following exception filter:
public class HandleExceptionAttribute : ExceptionFilterAttribute, IFilter
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        actionExecutedContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);

        actionExecutedContext.Response.Content = new StringContent(
            JObject.Parse(
                    $"{{'Message': '{actionExecutedContext.Exception.MessageEx().Replace("'", "\"")}'}}"
        ).ToString(), Encoding.UTF8, "application/json");

        Trace.TraceError(actionExecutedContext.Exception.MessageEx() + "Stack:" + actionExecutedContext.Exception.StackTrace);
    }
}


// --- Register this in the WebApiConfig "Register" section..

config.Filters.Add(new HandleExceptionAttribute());
Noting that WebAPI doesn't use the global.asax error handler (since there are no views). Now if you are calling the MVC action or webAPI endpoint from a jQuery style $.Ajax request, then this response object can be read in the fail block of that code structure:
$.ajax({
    url: '/Controller/Action',
    method: "POST",
    data: {
        'example': data
    }
}).done(function (result) {            
        // process a good result
}).fail(function (errorResult) {
    alert("Could not perform the operation\n" + errorResult.responseJSON.Message);
});
If you are using the Ajax.BeginForm approach, you can handle the failure condition by referencing your handler function in the "OnFailure" attribute of "AjaxOptions", (see http://johnculviner.com/ajax-beginform-ajaxoptions-custom-arguments-for-oncomplete-onsuccess-onfailure-and-onbegin/)
Ajax.BeginForm(
        "Controller",
        "Action",
        FormMethod.Post,
        new AjaxOptions()
        {
            HttpMethod = "POST",
            InsertionMode = InsertionMode.Replace,
            UpdateTargetId = "",
            OnSuccess = "HandleGoodResult();",
            OnFailure = "HandleFailure(xhr);"
        }, 
        new { id = "myForm" }))
Finally, you may be calling the API from some c# web client code, so you can parse the error as follows:
public string ParseErrorResponse(string responseText)
{
       string errorText = responseText;

       try
       {
           dynamic errorJson = (dynamic)JToken.Parse(errorText);
           errorText = errorJson.Message;
       }
       catch (Exception)
       {
       }

       return errorText;
}
Note: Remember that the exceptions you allow to arrive to user's browser should be legible and meaningul. Also, some exceptions can be "survived" so no need to bubble them, and finally exceptions in general are costly and so should be avoided in the first place (e.g. add clientside validation, add checks before calling dependencies that throw exceptions). For information on the "MessageEx()" extension, see my other post. NOTE: If you are deploying this website to Azure you will need to add the following tag to your system.webServer node of your web.config
<httpErrors existingResponse="PassThrough"/>
Permalink: Exception Handling in ASP.NET MVC and WebAPI

Exception Extension for Simple Logging

January 03, 2017

There is nothing more annoying than tracing an exception that only says "see inner exception for details". For this reason, I have started to use this simple extension method which traverses the entire exception structure, concatenating the messages together:
internal static class ExceptionExtensions
    {
        public static string MessageEx(this Exception ex)
        {
            StringBuilder errorMessageBuilder = new StringBuilder();

            Exception exception = ex;
            while (exception != null)
            {
                errorMessageBuilder.AppendLine(exception.Message);
                exception = exception.InnerException;
            }

            return errorMessageBuilder.ToString();
        }
    }
Permalink: Exception Extension for Simple Logging

Partially re-hydrating a class instance

August 22, 2016

I was working with some legacy Silverlight code, to add the functionality of saving the current state to a file and re-opening it later. The way that I chose to implement this was simply using the DataContractSerializer to turn the viewmodel state into a string and write it to a file. I marked the viewmodels with the DataContract attribute and marked any user related properties as DataMember. This worked great for saving the state to a file, and to some extent it worked when re-hyrating the state back to a viewmodel instance. However the problem I had, is that the viewmodel instances that are created when the application is initialised are part of a web of events registrations and dependancies between other viewmodels in the app. It was going to be a pain to re-wire the newly hydrated instances into all the places where the "initialised" viewmodels already were. So my solution was to simply "partially re-hydrate" the already existing viewmodel instances. To acheive this with minimal on-going maintenance, I wrote a simple generic class that uses reflection to identify all the DataMember properties of a class and copies the values from one instance to another. I could then re-hydrate an instance from the file and from that partially rehydrate the plumbed in existing instance. Class below:
using System.Runtime.Serialization;

namespace Project.Silverlight.Helpers
{
    public class PartialRehydrator<T>
    {
        public void Rehydrate(T source, T target)
        {
            // loop through each property of the given type
            foreach (var prop in typeof(T).GetProperties())
            {
                // look for the DataMemberAttribute on this property
                var dma = prop.GetCustomAttributes(typeof(DataMemberAttribute), true);

                // if it has a "DMA" then it's in scope for hydration
                if (dma != null && dma.Length > 0)
                {
                    // get the value from the source
                    var sourceValue = prop.GetGetMethod().Invoke(source, null);

                    // copy the value to the target
                    prop.GetSetMethod().Invoke(target, new object[] { sourceValue });
                }
            }
        }
    }
}
Permalink: Partially re-hydrating a class instance

Simple Responsive IFrame using JavaScript

June 23, 2016

I had a requirement to host the content of one responsive web application inside a view of another responsive web application. Since both applications were responsive in design there was no definitive height, width or aspect ratio. I found a tutorial here: https://benmarshall.me/responsive-iframes/ which talks about a library called Pym.js and also has some css/js examples of a simpler approach. I decided that using Pym.js was overkill for my needs, mostly because I didn't want to make any code changes to the target site. The code I found on the above link also didn't quite work for my needs, since I didn't have a particular aspect ratio (it will depend on the viewing device) and also couldn't give a hard-coded initial width/height to the iframe. In my case, the aspect ratio is actually dependant on the viewing devices screen, therefore I changed the script slightly as below:
$(document).ready(function () {
            var $responsive_iframes = $(".responsive_iframe");

            // Resize the iframes when the window is resized
            $(window).resize(function () {
                $responsive_iframes.each(function () {
                    // Get the parent containe's width and the screen ratio
                    var width = $(this).parent().width();
                    var ratio = $(window).height() / $(window).width();

                    $(this).width(width)
                          .height(width * ratio);
                });
                // Resize to fix all iframes on page load.
            }).resize();
        });
(I also made the jQuery selector look for a class name, rather than all iframes)
Permalink: Simple Responsive IFrame using JavaScript

Visual Studio Shared Project "call is ambiguous"

June 01, 2016

Shared projects are a relatively new thing in Visual Studio, they allow you to share code across multiple assemblies without compiling it in its own dll (the code is compiled into the referencing projects dll). Today I came across a bit of a gotcha - If you reference a shared project in an assembly A and in assembly B, now both of those projects define and export all of the public code from the shared project. Now you have a 3rd project C that also has a reference to the shared project, but also references A and B. You will get a compiler error "call is ambiguous" since the namespace/class/method you are trying to use is now defined 3 times. The simple answer, which is counter intuitive to "normal" library development is to make all of your "shared project" classes "internal" instead of "public". That way each assembly that references the shared project can use the code internally but will not export it to other assemblies.
Permalink: Visual Studio Shared Project "call is ambiguous"

User defined repository injection at runtime

March 01, 2016

A common design pattern is to use a dependency injection container in the composition root to switch between various concrete implementations of an interface abstraction (such as for services, repositories etc.). The configuration for these bindings are often dependant on the build configuration, or an application configuration settings and are singular, as such that only one "concrete implementation" is bound at run time. While recently working on a project, we needed to swap out the implementation of each IRepository based on the user's selection. To put this into context, the application is an ASP.NET MVC 5 website that has some common UI functionality, which we can then plug into multiple different data sources, as per the user's choice of repository. Since we are using Ninject, we can rely on it's ability to bind multiple implementations of an abstraction, by name. We can then use that name (as selected by the user) in a factory method to create instances of each type. Example Ninject module:
using MyProject.ApplicationServices.ExampleData;
using MyProject.Domain.RepositoryDefinitions.ExampleDataRepository;
using Ninject.Modules;

namespace MyProject.UI.MVC.DependencyInjection
{
    public class ExampleDataRepositoryModule : NinjectModule
    {
        public override void Load()
        {
            // define the repo names
            var exampleRepo1Name = "Example Repo 1";
            var exampleRepo2Name = "Example Repo 2";
            var exampleRepo3Name = "Example Repo 3";
            
            // setup all the named versions of the service layers for each of the repository names
            this.Bind<ExampleDataService>().ToSelf().Named(exampleRepo1Name);
            this.Bind<ExampleDataService>().ToSelf().Named(exampleRepo2Name);
            this.Bind<ExampleDataService>().ToSelf().Named(exampleRepo3Name);
            
            // set up the repositories that are bound in each of the above cases
            this.Bind<IExampleDataRepository>().To<Repositories.ExampleRepo1.ExampleDataRepository>().WhenAnyAncestorNamed(exampleRepo1Name);
            this.Bind<IExampleDataRepository>().To<Repositories.ExampleRepo2.ExampleDataRepository>().WhenAnyAncestorNamed(exampleRepo2Name);
            this.Bind<IExampleDataRepository>().To<Repositories.ExampleRepo3.ExampleDataRepository>().WhenAnyAncestorNamed(exampleRepo3Name);
        }
    }
}
We can store the user's selection in some kind of state (in ASP.NET this can be backed by the web session), so we can now use this selection along with the above bindings in a service factory, to create instances of the service with the specified repository.
using MyProject.ApplicationServices.ExampleData;
using MyProject.UI.MVC.Helpers;
using Ninject;

namespace MyProject.UI.MVC.ServiceFactories
{
    public class ExampleDataServiceFactory
    {
        private readonly IKernel ninjectKernel;
        private readonly ISessionHelper sessionHelper;

        public ExampleDataServiceFactory(IKernel ninjectKernel, ISessionHelper sessionHelper)
        {
            this.ninjectKernel = ninjectKernel;
            this.sessionHelper = sessionHelper;
        }

        public ExampleDataService CreateInstance()
        {
            return this.ninjectKernel.Get<ExampleDataService>(this.sessionHelper.CurrentExampleRepoName);
        }
    }
}
Now in the controller, we can take a dependency on the factory and have it create us an instance:
public class ExampleDataController : Controller
    {
        private ExampleDataService exampleDataService;
        private ISessionHelper sessionHelper;

        public ExampleDataController(ExampleDataServiceFactory exampleDataServiceFactory, ISessionHelper sessionHelper)
        {
            this.exampleDataService= exampleDataServiceFactory.CreateInstance();
            this.sessionHelper = sessionHelper;
        }
}
Permalink: User defined repository injection at runtime