ASP Web Api - IoC - Resolver HttpRequestMessage
Eu estou tentando configurar Castle Windsor com o ASP.NET WebAPI.
Eu também estou usando o pacote Hyprlinkr (https://github.com/ploeh/Hyprlinkr) e assim precisa de uma instância de HttpRequestMessage injetada em uma das dependências do meu controlador.
Estou seguindo este artigo de Mark Seemann -http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx , mas estou descobrindo que, embora a API seja executada, quando faço uma chamada para ela, a solicitação é interrompida. Nenhuma mensagem de erro. É como se estivesse em um loop infinito. Está pendente na chamada para resolver no meu Custom ControllerActivator
Estou a pensar que tenho algumas das minhas inscrições no Castelo erradas. Se eu remover os mencionados no artigo acima, posso fazer uma chamada à API com sucesso (embora sem as dependências eu precise ser resolvido)
Alguma ideia?
Código está abaixo
//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);
}
}
EDITAR *********** INFORMAÇÕES ADICIONAIS ****************
Então eu configurei um cenário em que o controller apenas pega um HttpRequestMessage como um argumento ctor e encontrou:
Isso funciona:
//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;
No entanto, isso não acontece.
//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;
isto é, quando o objeto anon tem uma propriedade chamada "request" e o controlador ctor arg é chamado "request". De alguma forma, o controlador acha que a propriedade request é nula. Qual é o que causa o erro que eu vejo:
Não é possível reutilizar uma instância 'ApiController'. 'ApiController' tem que ser construído por mensagem recebida. Verifique seu 'IHttpControllerActivator' personalizado e verifique se ele não produzirá a mesma instância.
em System.Web.Http.ApiController.ExecuteAsync (HttpControllerContext controllerContext, CancellationToken cancelamentToken) em System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal (solicitação HttpRequestMessage, CancellationToken cancelamentToken) em System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync (HttpRequestMessage solicitação, CancellationToken cancellationToken)
ter uma leitura desteComo posso enriquecer a composição de objetos no StructureMap sem chamar injeção de setter?
Explica um cenário semelhante.
É claro que o hyprlinkr tem seu ctor arg para HttpRequestMessage chamado "request", então eu preciso especificar o objeto anon com esse nome de propriedade.
Alguma ideia?