2
votes

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 ?

2

2 Answers

1
votes

I'm posting this as an answer, but it is rather some avenues you may want to investigate.

I've had some bad surprises with the TypedFactoryFacility when using it, since it tried to resolve any Func<> and/or Lazy<> type property or constructor parameter to a typed factory. You may have one of these types in your component that castle is trying to resolve.

If this is the case, you may need to configure the resolution explicitly as shown in the Typed factory facility page. An alternative is to remove the DelegateFactory from the container

1
votes

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>)));