2010-07-28 18 views
14

Tengo problemas para inyectar dependencias de servicios en mi servicio WCF utilizando Autofac 1.4.5. He leído y seguido el Autofac wiki page on WcfIntegration pero mi depuración me muestra que mi servicio WCF está creado por el método System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance() y no por el AutofacWebServiceHostFactory. ¿Qué estoy haciendo mal?Uso de Autofac para DI en el servicio WCF alojado en la aplicación ASP.NET

He creado mi archivo ajax.svc para parecerse a la del ejemplo para su uso con WebHttpBinding:

<%@ ServiceHost Language="C#" Debug="true" 
    Service="Generic.Frontend.Web.Ajax, Generic.Frontend.Web" 
    Factory="Autofac.Integration.Wcf.AutofacWebServiceHostFactory, 
      Autofac.Integration.Wcf" %> 

Mi clase de servicio WCF Ajax se define así:

namespace Generic.Frontend.Web 
{ 
    [ServiceContract] 
    [AspNetCompatibilityRequirements(
     RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    public class Ajax 
    { 
     public MapWebService MapWebService { get; set;} 

     public Ajax() { 
      // this constructor is being called 
     } 

     public Ajax(MapWebService mapWebService) 
     { 
      // this constructor should be called 
      MapWebService = mapWebService; 
     } 

     [WebGet(ResponseFormat = WebMessageFormat.Json)] 
     [OperationContract(Name = "mapchange")] 
     public MapChangeResult ProcessMapChange(string args) 
     { 
      // use the injected service here 
      var result = MapWebService.ProcessMapChange(args); 
      return result; 
     } 
    } 
} 

Ahora He utilizado el cableado en el Global.asax.cs como se muestra en el wiki mencionado anteriormente:

var builder = new ContainerBuilder(); 
builder.RegisterModule(new AutofacModuleWebservice()); 
var container = builder.Build(); 
AutofacServiceHostFactory.Container = container; 

con

class AutofacModuleWebservice : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.Register<Ajax>(); 
     builder.Register<MapWebService>().ContainerScoped(); 
    } 
} 

En mi web.config que tienen

<services> 
    <service name="Generic.Frontend.Web.Ajax"> 
     <endpoint address="http://mysite.com/ajax.svc/" binding="webHttpBinding" 
        contract="Generic.Frontend.Web.Ajax" /> 
    </service> 
</services> 

.

El servicio ya funciona bien pero no puedo hacer funcionar los bits de Autofac (léase: creación/inyección). ¿Algunas ideas?

Editar: Extracción del constructor por defecto lamentablemente conduce a la siguiente excepción:

System.InvalidOperationException: 
The service type provided could not be loaded as a service because it does not 
have a default (parameter-less) constructor. To fix the problem, add a default 
constructor to the type, or pass an instance of the type to the host. 

Cheers, Oliver

+0

¿Has resuelto esto? Tengo un problema similar y he hecho mi pregunta aquí -> http://stackoverflow.com/questions/16489403/using-autofac-with-ajax-enabled-wcf-service – codingjoe

+0

Desafortunadamente, no. Esa es también la razón por la que no hay nada marcado como respuesta, aquí: - | – Oliver

+0

¿Cómo lo hospedas? iis, fue, selfhosting? Deberías escribir eso en tu pregunta, creo. Usted escribe un código diferente dependiendo de esto. – Johan

Respuesta

0

Intente eliminar el constructor por defecto Ajax y la modificación de su constructor para esto. Si se ejecuta con mapWebService == null, eso indicaría un problema de resolución.

public Ajax(MapWebService mapWebService = null) 
    { 
     // this constructor should be called 
     MapWebService = mapWebService; 
    } 
+0

Gracias por la sugerencia, pero en realidad ya lo he intentado para recibir la siguiente System.InvalidOperationException: El servicio El tipo proporcionado no se pudo cargar como un servicio porque no tiene un constructor predeterminado (sin parámetros). Para solucionar el problema, agregue un constructor predeterminado al tipo o pase una instancia del tipo al host. Así es como me imaginé que Autofac realmente no estaba creando la instancia de servicio. – Oliver

1

¿Su configuración de servicio es InstanceContextMode.Single? Si es así, wcf creará su servicio utilizando el constructor predeterminado. Para evitar esto, cambie el modo de contexto de su instancia y permita que autofac administre la vida útil de su servicio.

+0

Hola Jon, no, no está configurado con InstanceContextMode.Single. También intenté configurarlo para PerSession explícitamente, sin ningún efecto. – Oliver

+0

También puede ser una clase base configurada con InstanceContextMode.Single (ese era mi caso) – lvmeijer

0

Acabo de recibir la misma System.InvalidOperationException y la solucioné cambiando el ServiceBehavior InstanceContextMode de la implementación de InstanceContextMode.PerCall a InstanceContextMode.PerSession, ¿quizás su alcance de AutoFac lifetime no está sincronizado con la implementación de su servicio web?

Para probar la creación del servicio AutoFac, recomiendo crear una prueba de unidad y resolverla directamente, ya que esto resaltará cualquier problema y dará más mensajes de excepción significativos. Para los servicios con un alcance de por vida de solicitud, cree una página aspx de prueba y vuelva a resolverlos directamente.

0

Tuve el mismo problema y encontré esta pregunta mientras buscaba una respuesta.

En mi caso, el uso de la inyección de la propiedad trabajado, y el código en la pregunta ya tiene una propiedad que puede ser utilizado:

namespace Generic.Frontend.Web 
{ 
    [ServiceContract] 
    [AspNetCompatibilityRequirements(
     RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    public class Ajax 
    { 
     // inject the dependency here 
     public MapWebService MapWebService { get; set;} 

     [WebGet(ResponseFormat = WebMessageFormat.Json)] 
     [OperationContract(Name = "mapchange")] 
     public MapChangeResult ProcessMapChange(string args) 
     { 
      // use the injected service here 
      var result = MapWebService.ProcessMapChange(args); 
      return result; 
     } 
    } 
} 

y registrarse para utilizar la inyección de propiedad (código de ejemplo de la wiki y la sintaxis tiene cambiado, ya que ahora está utilizando la versión 2.5.2.830):

builder.RegisterType<Ajax>().PropertiesAutowired(); 
0

Siguiendo las instrucciones resuelto por mí:

code.google.com/p/autofac/wiki/... simplemente do: builder.RegisterType();

y he seguido sus instrucciones para cambiar el archivo .svc.

Cuando miras tu archivo .svc no encuentras ninguna pista de que algo anda mal allí por cierto?

Usted alojarlo throu los IIS y no utilizan FUE, no veo su código de global.asax.cs primordiales

Añadir el archivo global de su solución y hay que implemente:

protected void Application_Start(object sender, EventArgs e) 
     { 
      // build and set container in application start 
      IContainer container = AutofacContainerBuilder.BuildContainer(); 
      AutofacHostFactory.Container = container; 


     } 

AutofacContainerBuilder es mi creador de contenedores.

Cuestiones relacionadas