4

When I have the following packages installed in an Azure worker role:

  <package id="Microsoft.AspNet.WebApi.Client" version="5.1.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.1.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.OData" version="5.1.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.1.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.1.0" targetFramework="net451" />
  <package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.Data.Services.Client" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.Owin" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.WindowsAzure.ConfigurationManager" version="2.0.3" targetFramework="net451" />
  <package id="Newtonsoft.Json" version="5.0.8" targetFramework="net451" />
  <package id="Owin" version="1.0" targetFramework="net451" />
  <package id="RavenDB.Client" version="2.5.2750" targetFramework="net451" />
  <package id="System.Spatial" version="5.6.0" targetFramework="net451" />
  <package id="Unity" version="3.0.1304.1" targetFramework="net451" />
  <package id="Unity.WebAPI" version="5.1" targetFramework="net451" />
  <package id="WindowsAzure.Storage" version="3.0.2.0" targetFramework="net451" />

I can get the application working as long as I don't try to register an IoC container.

As soon as I put this line in my Startup.cs file:

config.DependencyResolver = new UnityDependencyResolver(new UnityContainer());

I get the following exception:

An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in Microsoft.WindowsAzure.ServiceRuntime.dll

If I put the exact same code in a console application, it works without throwing an exception.** Here is the full content of my WorkerRole.cs class:

    public class WorkerRole : RoleEntryPoint
    {
        IDisposable _app;

        public override void Run()
        {
            Trace.TraceInformation("Timbre.Catalogue.ApiRole entry point called");

            while (true)
            {
                Thread.Sleep(10000);
                Trace.TraceInformation("Working");
            }
        }

        public override bool OnStart()
        {
            ServicePointManager.DefaultConnectionLimit = 12;

            var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ApiEndpoint"];
            var baseUri = string.Format("{0}://{1}", endpoint.Protocol, endpoint.IPEndpoint);
            Trace.TraceInformation("Starting OWIN at {0}", baseUri);
            _app = WebApp.Start<Startup>(new StartOptions(baseUri));

            return base.OnStart();
        }

        public override void OnStop()
        {
            if (_app != null)
                _app.Dispose();

            base.OnStop();
        }
    }

And hers is the full content of my Startup.cs class:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var config = new HttpConfiguration();
            config.Formatters.Remove(config.Formatters.XmlFormatter);
            config.MapHttpAttributeRoutes();
            config.DependencyResolver = new UnityDependencyResolver(new UnityContainer());

            app.UseWebApi(config);
        }
    }

I have the same problem when trying to use Castle.Windsor with the following package:

<package id="WebApiContrib.IoC.CastleWindsor" version="0.10.0.0" targetFramework="net451" />

and this line of code instead:

config.DependencyResolver = new WindsorResolver(new WindsorContainer().Install(FromAssembly.This()));

Can anyone give me a clue as to what is wrong here? I suspect it is a problem with the Azure compute emulator because it works perfectly in a console application, however I have no idea how to diagnose it any further than that.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Shayne
  • 195
  • 1
  • 10
  • 1
    I do not see why it works in Console and not in Azure...from what i have found looks like Unity.WebAPI package (even though it says its 5.1 version) was built with dependency on 5.0 version of Web API. So I am wondering if you need to have binding redirects pointing to 5.1 version of Web API. Do you have any binding redirects in your configuration file in case of the working Console application? – Kiran Jan 24 '14 at 14:08
  • No, I don't have binding redirects in the console application version. Also, the same problem happens if I try to use a WindsorResolver from the WebApiContrib.IoC.CastleWindsor NuGet package. I even get the same problem if I use my own hand-rolled implementation of IDependencyResolver which uses Activator.CreateInstance internally. – Shayne Jan 24 '14 at 14:20
  • 1
    Are you sure about the binding redirects as I just now tried a OWIN selfhost console application where when i install the Unity.WebAPI package the nuget engine adds a binding redirect like `` – Kiran Jan 24 '14 at 14:27
  • 1
    Facepalm. You're right. I hadn't checked the app.config in the console application. There was a binding redirect in there and when I added that to the worker role it now works without throwing an exception. So thank you very much! Although I get a different (I think unrelated) error now - the HTTP response is `{"Message":"An error has occurred."}` with a status code of 500. I think it may be my routing or IoC registration of the controller that iw wrong. Any idea on how I can get a more detailed error message and a stacktrace perhaps? – Shayne Jan 24 '14 at 14:53
  • 2
    To get more details, you would need to change the policy of error details in the repsonse...you can do this by configuring `IncludeErrorDetailPolicy` on `HttpConfiguration` and set it as `Always` to figure out the issue. You can also check the Global Error Handling Feature which is new in Web API 5.1, in which case you need not set the policy to Always but can still know that something bad happened. – Kiran Jan 24 '14 at 14:58
  • just fyi..i updated my reply with a snippet which uses global error handling feature – Kiran Jan 24 '14 at 15:05

1 Answers1

3

5.1 version of Unity.WebApi nuget package was built with reference to 5.0 version of Web API. So we need a binding redirect to make Unity work with 5.1 version of Web API.

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

Related to your later comment about figuring out the exception details:

You can checkout the new Global Error Handling feature in Web API 5.1. Following is a snippet of it.

config.Services.Add(typeof(IExceptionLogger), new CustomExceptionLogger());

public class CustomExceptionLogger : ExceptionLogger
{
    public override void Log(ExceptionLoggerContext context)
    {
        //TODO: Log the exception details
        //context.Request
        //context.Exception
    }
}
Kiran
  • 56,921
  • 15
  • 176
  • 161
  • I've hooked up the global error handling as shown in the sample at http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/Elmah/ReadMe.txt and it is working correctly, but the sample is a normal web application so there is a module registered for /elmah.axd. How do I view the error log in a Katana application? – Shayne Jan 24 '14 at 16:18
  • 2
    For Katana application, you might need to have your own custom way of logging...for example, you could probably write out using azure diagnostics...the idea is that ExceptionLogger provides a way for you to write to any kind of component if you like.. – Kiran Jan 24 '14 at 16:41
  • 1
    Okay, I suppose ELMAH is not a good fit for a Katana application then. Thanks for the reply. – Shayne Jan 24 '14 at 17:18