Search code examples
.netcastle-windsorasp.net-web-api2owincastle

Owin application configuration with Castle TypedFactory


I have a WebAPI application with Owin and Castle configured. That application will be hosted on IIS (So I install package Microsoft.Owin.Host.SystemWeb)

I would like to configure a token based authentication and have a customized OAuthAuthorizationServerProvider that will use a Castle TypedFactoryFacility(I remove that code in provided sample as it does not cause the error).

Here is Startup class code of my Owin application

    public class Startup {
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var container = new WindsorContainer();

        //_windsorContainer.Install(FromAssembly.This());
        container.AddFacility<TypedFactoryFacility>();
        container.Register(Component.For<AuthorizationServerProvider>());
        config.Services.Replace(typeof(IHttpControllerActivator), new WindsorCompositionRoot(container));

        OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(15),
            Provider = container.Resolve<AuthorizationServerProvider>()
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

        app.UseWebApi(config);

    } }

WindsorCompositionRoot is the implentation proposed by Mark Seemann : http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor/

When I try to debug my application I got the following error :

No component for supporting the service System.Threading.Tasks.Task was found

And here is the corresponding stacktrace

[ComponentNotFoundException: No component for supporting the service System.Threading.Tasks.Task was found] Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy) +106 Castle.Facilities.TypedFactory.TypedFactoryComponentResolver.Resolve(IKernelInternal kernel, IReleasePolicy scope) +307

Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Resolve(IInvocation invocation) +256
Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Intercept(IInvocation invocation) +265 Castle.DynamicProxy.AbstractInvocation.Proceed() +484 Castle.Proxies.Func'2Proxy.Invoke(OAuthMatchEndpointContext arg) +174 Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerProvider.MatchEndpoint(OAuthMatchEndpointContext context) +59 Microsoft.Owin.Security.OAuth.d__0.MoveNext() +693 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24 Microsoft.Owin.Security.Infrastructure.d__0.MoveNext() +664 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__5.MoveNext() +287 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__2.MoveNext() +272 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +22 Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow() +33 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +150
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +42
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +415 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

If I do not add TypedFactoryFacility to my container my project work without that error ...

Why Castle is injecting a TypedFactory in that place ? What can I do to avoid that error ?


Solution

  • Based on Samy and Phil Degenhardt tips, here is a way to force castle to not fill OnMatchEndpoint property and make it work :

    container.Register(Component.For<AuthorizationServerProvider>()
                .PropertiesIgnore((m, p) => p.PropertyType == typeof(Func<OAuthMatchEndpointContext, Task>)));