Quantcast
Channel: Web API
Viewing all articles
Browse latest Browse all 4850

Trying to integrate Unity Dependency Resolver into web API

$
0
0

Hello,

I have a web API and I'm trying to implement dependency injection with unity. I'm using this guide to setup Unity:

http://www.asp.net/web-api/overview/advanced/dependency-injection

But it doesn't seem to be working.

My controller looks like this:

[code]
public class FileUploadController : ApiController
{
private readonly IPromComService _promComService;

public FileUploadController(IPromComService promComService)
{
_promComService = promComService;
}

public async Task<HttpResponseMessage> PostUploadFile()
{
// Uploads file
}
}
[/code]

And I have a static html page for testing. It looks like this:

[code]
<html>
<head></head>
<body>
<form name="form1" method="post" enctype="multipart/form-data" action="http://localhost:60209/api/FileUpload">
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
</body>
</html>
[/code]

When I run the API in Visual Studio 2015 and upload a file on the static page and then hit submit, I get this error back:

An error occurred when trying to create a controller of type 'FileUploadController'. Make sure that the controller has a
parameterless public constructor.
System.InvalidOperationException
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor
controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController
(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()

It doesn't help that my breakpoints aren't being hit because symbols aren't loaded (if anyone knows how to get symbols to
load, that would solve half the battle).

But in any case, I followed everything it says to do in the guide above, but I'm not sure if everything is set in place
properly. Other than the controller outlined above, I have this in Startup.cs:

[code]
[assembly: OwinStartup(typeof(WebAPI.App_Start.Startup))]
namespace WebAPI.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{

ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
}
}
[/code]

...and this in WebApiConfig.cs:

[code]
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

// For dependency injection into the controller constructors:
var container = new UnityContainer();
container.RegisterType<IPromComService, PromComService>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
}
}
[/code]

...and here's the Unity Dependency Resovler:

[code]
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;

public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}

public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException e)
{
return null;
}
}

public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException e)
{
return new List<object>();
}
}

public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}

public void Dispose()
{
container.Dispose();
}
}
[/code]

I also have these references that were added when I installed the unit package:

Microsoft.Practices.Unity
Microsoft.Practices.Unity.Configuration
Microsoft.Practices.Unity.RegisterByConvention
Microsoft.Practices.ServiceLocation

...and these added to packages.config:

<package id="CommonServiceLocator" version="1.3" targetFramework="net46" />
<package id="Unity" version="4.0.1" targetFramework="net46" />

Does anyone see anything missing/wrong?

Thanks

=================================

UPDATE:

I have since got symbols to load so my break points work now. The Startup.cs is being run and therefore the injected classes are being registered.

The error occurs in UnityResolver here:

public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException e)
{
return null;
}
}

Every time this method is run, an InvalidOperationException is thrown:

"Resolution of the dependency failed, type = \"____________________\", name = \"(none)\".\r\nException occurred while: while resolving.\r\nException is: InvalidOperationException - The current type, _______________________, is an interface and cannot be constructed. Are you missing a type mapping?\r\n-----------------------------------------------\r\nAt the time of the exception, the container was:\r\n\r\n  Resolving ____________________,(none)\r\n"

This exception is thrown 11 times on startup with different interfaces/abstract classes being put into the blanks above. The interfaces/abstract classes are (in order):

System.Web.Http.Hosting.IHostBufferPolicySelector

System.Web.Http.ExceptionHandling.IExceptionHandler

System.Web.Http.Metadata.ModelMetadataProvider

System.Web.Http.Tracing.ITraceManager

System.Web.Http.Tracing.ITraceWriter

System.Web.Http.Dispatcher.IHttpControllerSelector

System.Web.Http.Dispatcher.IAssembliesResolver

System.Web.Http.Dispatcher.IHttpControllerTypeResolver

System.Web.Http.Controllers.IHttpActionSelector

System.Web.Http.Controllers.IActionValueBinder

System.Net.Http.Formatting.IContentNegotiator

In addition to this, the exception is thrown 2 times again when I try to upload a file. The interfaces are:

System.Web.Http.Dispatcher.IHttpControllerActivator

WebAPI.Controllers.FileUploadController

^ This last one is my file upload controller. Why does it think it's an interface?


Viewing all articles
Browse latest Browse all 4850

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>