ASP网页API - 国际奥委会 - 解决型Htt prequestMessage [英] ASP Web Api - IoC - Resolve HttpRequestMessage

查看:301
本文介绍了ASP网页API - 国际奥委会 - 解决型Htt prequestMessage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立温莎城堡与ASP.NET的WebAPI。

I am trying to set up Castle Windsor with ASP.NET WebAPI.

我也是用的Hyprlinkr包( https://github.com/ploeh/Hyprlinkr )所以需要注入的Htt prequestMessage的实例,以我的控制器的一个依赖项。

I am also using the Hyprlinkr package (https://github.com/ploeh/Hyprlinkr) and so need an instance of HttpRequestMessage injected in to one of the dependencies of my controller.

我下面这篇文章由马克·西曼 - HTTP://blog.ploeh没有自动跳转/ 2012/04/19 / WiringHttpControllerContextWithCastleWindsor.aspx ,但我发现,虽然API运行,当我做给它打电话,请求只是挂起。没有错误消息。这是因为如果它在一个无限循环。它挂在呼叫我的自定义ControllerActivator化解

I am following this article by Mark Seemann - http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx , but I am finding that although the API runs, when I make a call to it, the request just hangs. No error message. It’s as if it’s in an infinite loop. It’s hanging on the call to Resolve in my Custom ControllerActivator

我想我有一些我的城堡登记错误的。如果我删除上面则文章中提到的那些我可以成功做出了API的调用(虽然没有dependacies我需要得到解决)

I am thinking I have some of my Castle registrations wrong. If I remove the ones mentioned in the article above then I can successfully make a call to the API (albeit without the dependacies I need getting resolved)

任何想法?

code是在

//Global.asax
public class WebApiApplication : HttpApplication
{
    private readonly IWindsorContainer container;

    public WebApiApplication()
    {
        container = 
            new WindsorContainer(
                new DefaultKernel(
                    new InlineDependenciesPropagatingDependencyResolver(), 
                    new DefaultProxyFactory()), 
                new DefaultComponentInstaller());

        container.Install(new DependencyInstaller());
    }

    protected void Application_Start()
    {        
        GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorCompositionRoot(this.container));
    }

// installer
public class DependencyInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.AddFacility<TypedFactoryFacility>();

        container.Register(
            Component.For<ValuesController>()
                .Named("ValuesController")
                .LifeStyle.PerWebRequest,

            Component.For<IResourceLinker>()
                .ImplementedBy<RouteLinker>()
                .LifeStyle.PerWebRequest,

            Component.For<IResourceModelBuilder>()
                .ImplementedBy<ResourceModelBuilder>()
                .LifeStyle.PerWebRequest,

                Component.For<HttpRequestMessage>()
                .Named("HttpRequestMessage")
                .LifeStyle.PerWebRequest
            );
    }
}

//Activator

public class WindsorCompositionRoot : IHttpControllerActivator
{
    private readonly IWindsorContainer container;

    public WindsorCompositionRoot(IWindsorContainer container)
    {
        this.container = container;
    }

    public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
    {
        var controller = (IHttpController)this.container.Resolve(controllerType, new { request = request });

        request.RegisterForDispose(
            new Release(
                () => this.container.Release(controller)));

        return controller;
    }

// DependencyResolver   
public class InlineDependenciesPropagatingDependencyResolver : DefaultDependencyResolver
{
    protected override CreationContext RebuildContextForParameter(CreationContext current, Type parameterType)
    {
        if (parameterType.ContainsGenericParameters)
        {
            return current;
        }

        return new CreationContext(parameterType, current, true);
    }
}

编辑***********
附加信息****************

EDIT*********** ADDITIONAL INFO****************

因此​​,我成立了一个场景,该控制器只需要一个Htt的prequestMessage作为一个构造函数参数,结果发现:

So I set up a scenario where the controller just takes a HttpRequestMessage as a ctor argument and found :

本作品:

//controller
public class ValuesController : ApiController
    {
        private readonly HttpRequestMessage _httpReq;

        public ValuesController(HttpRequestMessage httpReq)
        {
            _httpReq = httpReq;
        }
//IHttpControllerActivator
public IHttpController Create(
            HttpRequestMessage httpRequest,
            HttpControllerDescriptor controllerDescriptor,
            Type controllerType)
        {

            var controller = (IHttpController)this.container.Resolve(
                controllerType, new { httpReq = httpRequest });

            return controller;

不过,这并没有。

However, this Doesn't.

//controller
public class ValuesController : ApiController
    {
        private readonly HttpRequestMessage _httpReq;

        public ValuesController(HttpRequestMessage request)
        {
            _httpReq = request;
        }

//IHttpControllerActivator
public IHttpController Create(
            HttpRequestMessage request,
            HttpControllerDescriptor controllerDescriptor,
            Type controllerType)
        {

            var controller = (IHttpController)this.container.Resolve(
                controllerType, new { request = request });

            return controller;

即。当匿名对象有一个名为请求属性和控制器构造函数ARG被称为请求。它在某种程度上使控制器认为它的请求属性为null。这是什么原因我看到的错误:

i.e. when the anon object has a property called "request" and the controller ctor arg is called "request". It is somehow making the controller think it's request property is null. Which is what causes the error I see:

不能重​​用ApiController实例。 'ApiController'必须
  每一个进入的消息构成。请检查您的自定义
  IHttpControllerActivator,并确保它不会制造
  相同的实例。

Cannot reuse an 'ApiController' instance. 'ApiController' has to be constructed per incoming message. Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance.

在System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext
  controllerContext,的CancellationToken的CancellationToken)在
  System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HTT prequestMessage
  请求的CancellationToken的CancellationToken)在
  System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HTT prequestMessage
  请求的CancellationToken的CancellationToken)

at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

对此有读
<一href=\"http://stackoverflow.com/questions/12646657/how-can-i-enrich-object-composition-in-structuremap-without-invoking-setter-inje\">How我可以丰富对象组成StructureMap,而不必调用setter注入?

它说明了类似的情况。

当然,hyprlinkr有它的Htt的prequestMessage名为请求男星ARG的,所以我需要指定与属性名称的匿名对象。

Of course, hyprlinkr has it's ctor arg for HttpRequestMessage called "request", so I do need to specify the anon object with that property name.

任何想法?

推荐答案

下面是一个组合的根,对我的作品:

Here's a Composition Root that works for me:

public class WindsorCompositionRoot : IHttpControllerActivator
{
    private readonly IWindsorContainer container;

    public WindsorCompositionRoot(IWindsorContainer container)
    {
        this.container = container;
    }

    public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
    {
        var controller = (IHttpController)this.container.Resolve(
            controllerType,
            new
            {
                request = request
            });

        request.RegisterForDispose(
            new Release(
                () => this.container.Release(controller)));
        return controller;
    }

    private class Release : IDisposable
    {
        private readonly Action release;

        public Release(Action release)
        {
            this.release = release;
        }

        public void Dispose()
        {
            this.release();
        }
    }
}

下面是我如何创建容器:

Here's how I create the container:

this.container =
    new WindsorContainer(
        new DefaultKernel(
            new InlineDependenciesPropagatingDependencyResolver(),
            new DefaultProxyFactory()),
        new DefaultComponentInstaller())
        .Install(new MyWindsorInstaller());

和这里的InlineDependenciesPropagatingDependencyResolver:

and here's the InlineDependenciesPropagatingDependencyResolver:

public class InlineDependenciesPropagatingDependencyResolver : 
    DefaultDependencyResolver
{
    protected override CreationContext RebuildContextForParameter(
        CreationContext current,
        Type parameterType)
    {
        if (parameterType.ContainsGenericParameters)
        {
            return current;
        }

        return new CreationContext(parameterType, current, true);
    }
}

最后,这里是我如何注册RouteLinker:

Finally, here's how I register RouteLinker:

container.Register(Component
    .For<RouteLinker, IResourceLinker>()
    .LifestyleTransient());


有一点要注意的是,ApiController基类有请求中的Htt prequestMessage型命名的公共属性。如我的书温莎将尝试一个值分配给每个可写的财产,如果它有一个匹配的部件 - 而且那场比赛是不区分大小写


One thing to be aware of is that the ApiController base class has a public property named Request of the HttpRequestMessage type. As explained in section 10.4.3 of my book Windsor will attempt to assign a value to each writeable property if it has a matching component - and that match is case-insensitive.

当你传递一个Htt的prequestMessage名为要求的解决方法,这正是发生什么事,所以你需要告诉温莎城堡,它应该放弃房产注射ApiControllers。以下是我不要在基于约定注册:

When you pass an HttpRequestMessage named request to the Resolve method, this is exactly what happens, so you need to tell Castle Windsor that it should forego Property Injection for ApiControllers. Here's how I don that in a convention-based registration:

container.Register(Classes
    .FromThisAssembly()
    .BasedOn<IHttpController>()
    .ConfigureFor<ApiController>(c => c.Properties(pi => false))
    .LifestyleTransient());

这篇关于ASP网页API - 国际奥委会 - 解决型Htt prequestMessage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆