Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST WebAPI Interface as parameter in API Call

I am building a REST API with ASP.NET WebAPI. Everything worked fine, but then I came up with the great idea to use interfaces in all my method calls. After I have changed all the methods i noticed that after setting the parameter in my Controller methods as interfaces, my API calls does not work. I am using OWIN Self host and Unity dependency injection. Here is my relevant code:

Resolving my Interface:

      IUnityContainer container = new UnityContainer();

      container.RegisterType<IMyInterface, MyInterfaceImpl>(new HierarchicalLifetimeManager());
      HttpConfiguration config = new HttpConfiguration();
      config.DependencyResolver = new UnityDependencyResolver(container);  

My Controller (the part where i get the error)

    [Route("test")]
    [HttpGet]
    public HttpResponseMessage GetSomeData([FromUri]IMyInterface searchObject)
    {
         return this._searchService.SearchForData(searchObject);

    }

When calling this method i get the error that an interface cannot be created. I unterstand that, but the problem is fixing it. I looked at ASP.NET Web API Operation with interfaces instead concrete class and also at https://brettedotnet.wordpress.com/2014/07/16/web-api-and-interface-parameters/ and at ASP.NET Web API Operation with interfaces instead concrete class, but none of the suggestions worked in my case (always getting the error that an interface cannot be created).

I was wondering if someone has a working example on something like this(on github or elsewhere) just to check what I am doing wrong (or even an idea what else I could try would be nice)

Thank you

like image 452
user3466562 Avatar asked Oct 19 '22 21:10

user3466562


1 Answers

Because you are passing data from the querystring a different approach is required here. In my blog post that you referenced I did not include that scenario. Since querystrings are handled via Model Binders you need to create a custom model binder.

In my situation I opted for creating a IoCModelBinder as seen below.

public class IocModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var targetObject = ServiceLocator.Current.GetInstance(bindingContext.ModelType);
        var valueProvider = GlobalConfiguration.Configuration.Services.GetValueProviderFactories().First(item => item is QueryStringValueProviderFactory).GetValueProvider(actionContext);

        foreach (var property in targetObject.GetType().GetProperties())
        {
            var valueAsString = valueProvider.GetValue(property.Name);
            var value = valueAsString == null ? null : valueAsString.ConvertTo(property.PropertyType);

            if (value == null)
                continue;

            property.SetValue(targetObject, value, null);
        }

        bindingContext.Model = targetObject;
        return true;
    }
}

And in use

    /// <summary>
    /// Searches by the criteria specified.
    /// </summary>
    /// <param name="searchCriteriaDto">The search criteria dto.</param>
    /// <returns></returns>
    [HttpGet]
    public HttpResponseMessage Search([ModelBinder(typeof(IocModelBinder))]IApplicationSearchCriteriaDto searchCriteriaDto)
    {

    }

Hope this helps.

Brette

like image 115
brettenet Avatar answered Oct 27 '22 22:10

brettenet