wcf - error - metadata publishing for this service is currently disabled
Uso de Ninject WCF Extension con WCF Web Service (2)
La forma en que estoy usando Ninject (v3) con mi WCF se basa en la extensión Ninject WCF y en la gran publicación de blog de Pieter De Rycke .
En pocas palabras, esto es lo que estoy haciendo:
1) A través de NuGet, he agregado una referencia a Ninject.Extensions.Wcf en mi proyecto WCF. Esto crea la carpeta App_Start con NinjectWebCommon.cs, que se encarga de inicializar Ninject.
2) Normalmente, configuraría sus asignaciones de Ninject en el método CreateKernel en NinjectWebCommon.cs. Sin embargo, dado que tengo un sitio MVC3 en la misma solución y quiero las mismas asignaciones de Ninject para ese sitio, mi CreateKernel se ve así:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
InfrastructureSetup.RegisterServices(kernel);
return kernel;
}
3) En InfrastructureSetup.RegisterServices, tengo mis asignaciones de Ninject:
public static class InfrastructureSetup
{
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRepositoryContext>().To<MyEntityFrameworkContext>().InRequestScope();
kernel.Bind<IFooRepository>().To<FooRepository>().InRequestScope();
kernel.Bind<IBarRepository>().To<BarRepository>().InRequestScope();
// ... and so on. I want InRequestScope() for the EF context, since
// otherwise my repositories (which take IRepositoryContext in their
// constructors) end up getting different EF contexts, messing things up
}
}
4) También quiero inyectar cosas (IFooService, etc.) a mis constructores WCF, así que he editado Web.config para el proyecto WCF con el consejo de Pieter De Rycke:
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<!-- Add the Ninject behavior to the WCF service. This is needed to support dependency injection to the WCF constructors -->
<ninject />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!-- Add the Ninject behavior extension -->
<add name="ninject"
type="MyWCFProject.Infrastructure.NinjectBehaviorExtensionElement, MyWCFProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
5) En el espacio de nombres MyWCFProject.Infrastructure, tengo tres archivos que son básicamente copy-paste de Pieter:
NinjectBehaviorAttribute.cs:
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Web.Common;
namespace MyWCFProject.Infrastructure
{
public class NinjectBehaviorAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
Type serviceType = serviceDescription.ServiceType;
// Set up Ninject to support injecting to WCF constructors
var kernel = new Bootstrapper().Kernel;
IInstanceProvider instanceProvider = new NinjectInstanceProvider(kernel, serviceType);
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
}
NinjectBehaviorExtensionElement.cs:
using System;
using System.ServiceModel.Configuration;
namespace MyWCFProject.Infrastructure
{
public class NinjectBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(NinjectBehaviorAttribute); }
}
protected override object CreateBehavior()
{
return new NinjectBehaviorAttribute();
}
}
}
NinjectInstanceProvider.cs:
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Ninject;
namespace MyWCFProject.Infrastructure
{
public class NinjectInstanceProvider : IInstanceProvider
{
private Type serviceType;
private IKernel kernel;
public NinjectInstanceProvider(IKernel kernel, Type serviceType)
{
this.kernel = kernel;
this.serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext)
{
return this.GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return kernel.Get(this.serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
}
Por el momento, esta solución parece estar funcionando bien; la inyección de dependencia funciona tanto para el sitio WCF como para el MVC3, puedo solicitar dependencias para ser inyectadas a los constructores de WCF y el contexto de EF permanece durante la duración de la solicitud.
Tengo un servicio web WCF en el que deseo utilizar mis Repositorios y Servicios que deseo insertar en mi servicio web de WCF, sin embargo, el ejemplo de la Extensión WCF de Ninject tiene un ctor que ejemplifica una instancia de cada dependencia, que no quiero, quería una inyección de dependencia más pura.
Alguien ha tenido éxito con el uso de Ninject con WCF, Google parece devolver resultados poco relevantes para los temas que estoy buscando.
El código detrás de TimeService tiene:
<%@ ServiceHost Language="C#" Debug="true" Service="WcfTimeService.TimeService" CodeBehind="TimeService.svc.cs" **Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"** %>
Los ctors de inyección bastardos confunden el asunto: Ninject elegirá el constructor más específico. El problema general con la muestra es que está cubriendo todas las bases (alojado en IIS, alojado en EXE, servicio hospedado), y WCF no hace exactamente que todo esto sea fácil de administrar (@Ian Davis: podría equivocarme fácilmente, ¿me puede dar? algunos detalles más, por favor, tal vez en la forma de un resumen de lo que las muestras ilustran en el archivo README, y tal vez más detalles en el por qué de los diversos casos donde ha utilizado BI?)