Injecting dependencies into MVC3 WCF services using Ninject extensions - wcf

I have an MVC3 application which should expose some functions via WCF. Some of these functions have dependencies and I'd like to inject them using Ninject, but I must be missing something obvious here as this does not work. Could anyone give a hint? Here's what I did:
1) in my MVC3 app, I add Ninject Wcf extensions via nuget.
2) I add a .svc file like:
<%# ServiceHost Service="MyWeb.LookupService"
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"%>
3) I add the corresponding code like (that's just a test so I'm using a dummy interface right here):
[ServiceContract]
public interface ILookupService
{
[OperationContract]
int GetProjectIdByCode(string sCode);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class LookupService : ILookupService
{
private readonly ISomeRepository _repository;
public LookupService(ISomeRepository repository)
{
_repository = repository;
}
public int GetProjectIdByCode(string sCode)
{
//... use _repository
}
}
4) in App_Start/NinjectMVC3.cs:
private static void RegisterServices(IKernel kernel)
{
string sConnection = ConfigurationManager.ConnectionStrings["SomeEntities"].ConnectionString;
// WCF
kernel.Bind<ServiceHost>().To<NinjectServiceHost>();
kernel.Bind<ISomeRepository>()
.To<AConcreteRepository>()
.WithConstructorArgument("sConnection", sConnection);
}
Now, when I access the svc I get the following exception from Ninject:
System.ArgumentNullException was unhandled by user code
Message=Cannot be null Parameter name: root Source=Ninject
ParamName=root StackTrace:
at Ninject.Infrastructure.Ensure.ArgumentNotNull(Object argument, String name) in
c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Infrastructure\Ensure.cs:line
20
at Ninject.ResolutionExtensions.GetResolutionIterator(IResolutionRoot
root, Type service, Func2 constraint, IEnumerable1 parameters,
Boolean isOptional, Boolean isUnique) in
c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line
258
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) in
c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line
37
at Ninject.Extensions.Wcf.NinjectServiceHostFactory.CreateServiceHost(Type
serviceType, Uri[] baseAddresses) in
c:\Projects\Ninject\Maintenance2.2\ninject.extensions.wcf\src\Ninject.Extensions.Wcf\NinjectServiceHostFactory.cs:line
48
at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String
constructorString, Uri[] baseAddresses)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String
normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String
normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String
normalizedVirtualPath)

Can you try to add a protected parameterless constructor to your implementation class.
Guess the servicehost needs a parameterless constructor as well.
I had a look at the Ninject service host factory and from the stack trace provided by you. It looks its failing whne making the following checks:
Ensure.ArgumentNotNull((object) root, "root");
Ensure.ArgumentNotNull((object) service, "service");
Ensure.ArgumentNotNull((object) parameters, "parameters");
Make sure that you are passing all the required parameters when using the NinjectServiceHostFactory. Worth trying to change the order of registration.
Also go through the following link here that explains how to use Ninject to host a wcf service.

Related

microsoft grpc-for-wcf-developers-master code fails on IIS

getting the grpc-for-wcf-developers-master, I tried to host the WCF service in the tradersys on IIS version 10 on Windows 10, which throws an exception:
Error by IIS
The AutofacServiceHost.Container static property must be set before services can be instantiated.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The AutofacServiceHost.Container static property must be set before services can be instantiated.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
I'm aware of this issue as discussed several times here, such as this post.
Yet the code by Microsft contains the appropriate autofac container.
the question is:
Is there any special settings on IIS for resolving this issue?
as I said earlier IISExpress just works fine.
seems the AppInitialize() method in which
AutofacHostFactory.Container = builder.Build();
resides, doesn't invoke.
Based on your code, I found that you need to integrate IOC with WCF, which needs to change your code.
Here is my demo:
This is my project directory.We need to add two classes: ManualProxy and CustomServiceHostFactory.
public class CustomServiceHostFactory : ServiceHostFactory
{
protected override System.ServiceModel.ServiceHost
CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
ManualProxy.TargetFactory = () => new PortfolioService(new PortfolioRepository());
return base.CreateServiceHost(typeof(ManualProxy), baseAddresses);
}
}
This is the CustomServiceHostFactory class.
public class ManualProxy : IPortfolioService
{
private readonly IPortfolioService _target;
public static Func<object> TargetFactory;
public ManualProxy()
{
_target = (IPortfolioService)TargetFactory();
}
public Task<Portfolio> Get(Guid traderId, int portfolioId)
{
return _target.Get(traderId,portfolioId);
}
public Task<List<Portfolio>> GetAll(Guid traderId)
{
return _target.GetAll(traderId);
}
}
This is the ManualProxy class.
The SVC file needs to be changed as above picture.

Ninject interception WCF service

I'm a newbie on the subject, so I'll try to make this as clear as I can...
I created a WcfModule, where I load the following package:
Bind<IDistributorService>().To<DistributorService>().InRequestScope().Intercept().With<ExceptionInterceptor>();
At first, I don't receive any error, but I put an InterceptAttribute on my function:
[AttributeUsage(AttributeTargets.Method)]
public sealed class HandleExceptionsAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Kernel.Get<ExceptionInterceptor>();
}
}
[HandleExceptions]
public virtual Result<List<DistributorDataContract>> GetDistributor(string id)
{
//...code...
I get an error in this function: (first line in method)
private ServiceHost CreateNewServiceHost(Type serviceType, Uri[] baseAddresses, WebHttpBehavior webBehavior, WebHttpBinding webHttpBinding)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
//...
}
With the error:
InvalidProxyConstructorArgumentsException was unhandled by user code
Can not instantiate proxy of class:
My.Namespace.DistributorService.
Could not find a parameterless constructor.
Anyone who knows what the problem could be? Thanks!
This exception is thrown by castle core dynamic proxy when it is instructed to create a "class proxy" which does not have a parameterless (default) constructor and no constructor-arguments are passed to castle (see source).
My best guess is, that when you use ninject interception by attributes, ninject will instruct castle core to create a class-proxy, no matter whether your binding is Bind<IFoo>().To<Foo>() or Bind<Foo>().ToSelf().
It seems a bit strange, however, that ninject is not resolving and passing along all required constructor parameters.
What is the implementation of DistributorService and what's the implementation of the base class of the class containing CreateNewServiceHost?
Workaround:
Of course, switching to the Intercept().With<TInterceptor>() syntax will probably also enable you to use interception (see http://codepyre.com/2010/03/using-ninject-extensions-interception-part-2-working-with-interceptors/)

WCF RIA Service with Unity 3.5.1.0

I'm trying to Use this Blog for WCF RIA Applcation . So I Create a Silverlight Nevigation Applciation which gave me 2 projects abs & abs.Web
More I create 3 project in solution :
abs.Data (c#), DbContext Implemeantion of Repository Interfaces +Factory to provide What user want.
abs.Data.Contarct (c#) Interfaces for Operations Repository
abs.Data.Model (c#) - Contains POCO - EF 6
Now I created A wcf Service in abs.Web project which have constructor injection of a Repository to get my job done in operation contracts.
So I tried using Unity here under the guidence with below blog
http://jamesheppinstall.wordpress.com/2012/06/20/windows-communication-foundation-resolving-wcf-service-dependencies-with-unity/
Now I'm getting
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.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: 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.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
**Stack Trace: **
[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.]
System.ServiceModel.Dispatcher.InstanceBehavior..ctor(DispatchRuntime dispatch, ImmutableDispatchRuntime immutableRuntime) +12761206
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime..ctor(DispatchRuntime dispatch) +173
System.ServiceModel.Dispatcher.DispatchRuntime.GetRuntimeCore() +85
System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpened() +148
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +321
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +139
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +310
System.ServiceModel.Channels.CommunicationObject.Open() +36
System.ServiceModel.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity) +91
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +598
[ServiceActivationException: The service '/DomainServices/UserWcfService.svc' cannot be activated due to an exception during compilation. The exception message is: 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..]
System.Runtime.AsyncResult.End(IAsyncResult result) +499812
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +178
System.ServiceModel.Activation.ServiceHttpHandler.EndProcessRequest(IAsyncResult result) +6
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +129
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18446
My all classes are same as like Blog.
WCF Ria has its own factory.
Simply put
public class MyDomainServiceFactory : IDomainServiceFactory
{
#region IDomainServiceFactory Members
public DomainService CreateDomainService(Type domainServiceType, DomainServiceContext context)
{
try
{
if (!typeof (DomainService).IsAssignableFrom(domainServiceType))
{
throw new ArgumentException(String.Format("Cannot create an instance of {0} since it does not inherit from DomainService", domainServiceType), "domainServiceType");
}
if (IoC.IsRegistered(domainServiceType))
{
var dmnService = (DomainService) IoC.Resolve(domainServiceType);
dmnService.Initialize(context);
return dmnService;
}
else
{
//if the IoC container doesn't know the service, simply try to call its default constructor
//could throw proper exception as well
var dmnService = (DomainService) Activator.CreateInstance(domainServiceType);
dmnService.Initialize(context);
return dmnService;
}
}
catch (Exception ex)
{
ExceptionHandler.HandleException(ex);
return null;
}
}
public void ReleaseDomainService(DomainService domainService)
{
domainService.Dispose();
}
#endregion
}
and somewhere on your bootstrapping code add
DomainService.Factory = new MyDomainServiceFactory();
of course, the word IoC in the factory identify the unityContainer (is actually a static façade against it)

Performing action before WCF service is shutdown

I have a WCF service hosted in IIS7. The service has a static class with a static list containing strings (sort of log). It periodically write the entries to a file or db.
However when the IIS decides the recyle the app or terminate for whatever reason, the entries in the static field are lost.
Is there any way I can handle the service shuttingdown kind event and persist the data from memory?
Thanks
Shreedhar
I've implemented several services via IIS with a custom service host (originally I did this so I could implement IErrorHandler for global error handling).
You'll need two things - an implementation of ServiceHost and an implementation of ServiceHostFactory, which will call your custom service host. For example (just the relevant parts of code shown):
public class MyCustomServiceHost : ServiceHost
{
protected override void OnClosing()
{
// logic to save off your static data
base.OnClosing();
}
}
public class MyCustomServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyCustomServiceHost(serviceType, baseAddresses);
}
}
In your .svc file, you'd have something like this:
<%# ServiceHost Service="MyCompany.MyServiceName" Factory="MyCompany.MyCustomServiceHostFactory" %>
<%# Assembly Name="MyCustomServiceHost" %>
This is one way to do this (and this dates back to .NET 3.5 days); there are quite likely other ways to accomplish this, but at least this should give you some direction.

Adding Operation Behaviors with WCF Facility

I'm using the WCF Facility for the first time to host a couple
services, both in a console app (for easy debugging) and IIS (for
production). The services use a net.msmq endpoint.
This is how I'm hosting the service in the console app (simplified):
using (var host = new DefaultServiceHostFactory()
.CreateServiceHost(typeof(MyService).AssemblyQualifiedName,
new Uri[0]))
host.Open();
And here's how it's registered:
container.Register(Component.For<UserRequestService>()
.LifestylePerWcfOperation())
What I'd like to do is to add the following behavior to all operations:
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
Here's what I tried:
container.Register(Component.For<IOperationBehavior>()
.UsingFactoryMethod(
x => new OperationBehaviorAttribute
{
TransactionScopeRequired = true,
TransactionAutoComplete = true
}));
But that results in an exception:
System.ArgumentException: The value could not be added to the collection, as the collection already contains an item of the same type: 'System.ServiceModel.OperationBehaviorAttribute'. This collection only supports one instance of each type.
Parameter name: item
at System.Collections.Generic.KeyedByTypeCollection`1.InsertItem(Int32 index, TItem item)
at Castle.Facilities.WcfIntegration.Internal.WcfUtils.AddBehaviors[T](IKernel kernel, WcfExtensionScope scope, KeyedByTypeCollection`1 behaviors, IWcfBurden burden, Predicate`1 predicate)
at Castle.Facilities.WcfIntegration.WcfEndpointExtensions.Install(ServiceEndpoint endpoint, Boolean withContract, IKernel kernel, IWcfBurden burden)
at Castle.Facilities.WcfIntegration.ServiceHostExtensions.Castle.Facilities.WcfIntegration.IWcfExtensionVisitor.VisitEndpointExtension(IWcfEndpointExtension extension)
at Castle.Facilities.WcfIntegration.ServiceHostExtensions.Install(ICollection`1 extensions, IWcfBurden burden)
at Castle.Facilities.WcfIntegration.AbstractServiceHostBuilder.ConfigureServiceHost(ServiceHost serviceHost, IWcfServiceModel serviceModel, ComponentModel model)
at Castle.Facilities.WcfIntegration.AbstractServiceHostBuilder`1.Build(ComponentModel model, Uri[] baseAddresses)
at Castle.Facilities.WcfIntegration.WindsorServiceHostFactory`1.CreateServiceHost(String constructorString, Uri[] baseAddresses)
at Program.Main()
Any ideas?