Sto cercando di impostare Castle Windsor con ASP.NET WebAPI.ASP Web Api - IoC - Risolvi HttpRequestMessage
Inoltre sto usando il pacchetto Hyprlinkr (https://github.com/ploeh/Hyprlinkr) e quindi hanno bisogno di un'istanza di HttpRequestMessage iniettato a una delle dipendenze di mio controller.
Sto seguendo questo articolo di Mark Seemann - http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx, ma sto trovando che anche se l'API viene eseguita, quando faccio una chiamata, la richiesta si blocca. Nessun messaggio di errore. È come se fosse in un ciclo infinito. È in attesa della chiamata a Risolvi il mio controller personalizzato. Attivatore
Sto pensando di avere alcune delle mie registrazioni di Castello errate. Se rimuovo quelli menzionati nell'articolo sopra, allora posso effettuare con successo una chiamata all'API (anche se senza le dipendenze ho bisogno di essere risolto)
Qualche idea?
codice è al di sotto
//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 *********** INFORMAZIONI AGGIUNTIVE ****************
Così ho creato uno scenario in cui il controllore vuole solo un HttpRequestMessage come argomento ctor e ha trovato:
Questo funziona:
//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;
Tuttavia, questo non.
//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;
cioè quando l'oggetto anon ha una proprietà chiamata "richiesta" e arg controllore ctor è chiamato "richiesta". In qualche modo, il controllore pensa che la proprietà della richiesta sia nulla. Qual è la causa dell'errore che vedo:
Impossibile riutilizzare un'istanza 'ApiController'. 'ApiController' deve essere costruito per messaggio in arrivo. Controlla il tuo custom 'IHttpControllerActivator' e assicurati che non produca la stessa istanza. .
a System.Web.Http.ApiController.ExecuteAsync (HttpControllerContext controllerContext, CancellationToken CancellationToken) a System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal (HttpRequestMessage richiesta, CancellationToken CancellationToken) a System.Web.Http .Dispatcher.HttpControllerDispatcher.SendAsync (HttpRequestMessage richiesta, CancellationToken CancellationToken)
hanno una lettura di questo How can I enrich object composition in StructureMap without invoking setter injection?
Spiega uno scenario simile.
Ovviamente, hyprlinkr ha il suo argomento per HttpRequestMessage chiamato "richiesta", quindi è necessario specificare l'oggetto anon con tale nome di proprietà.
Qualche idea?
Il post collegato a sopra descrive come utilizzare Castle Windsor con un'anteprima dell'API Web. Poiché vi sono state interruzioni delle modifiche tra l'anteprima e la versione RTM, l'approccio descritto non funziona più. Si prega di fare riferimento a http://blog.ploeh.dk/2012/10/03/DependencyInjectionInASPNETWebAPIWithCastleWindsor.aspx per una descrizione di come rendere DI lavorare con Castle Windsor in Web API RTM. –
grazie - sì - l'ho seguito. Semplicemente non capisco come fare la registrazione per HttpRequestMessage di cui hyprlinkr ha bisogno. Puoi indicarmi la giusta direzione? – ChrisCa
In questo modo: http://stackoverflow.com/q/10854701/126014 –