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/)
Related
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.
With .NET 4.5, my WCF creation using svcutil suddenly seems to break (I've been using only .NET 4.0 until very recently) ....
With the default settings I'm using to convert a pre-existing WSDL to my C# WCF proxy class:
c:> svcutil.exe /n:*,MyNamespace /out:WebService MyService.wsdl
I get this C# file created:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="MyService.IMyService1")]
public interface IMyService1
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(MyService.MyFault), Action="http://tempuri.org/IMyService1/IsAliveErrorInfoFault", Name="MyServiceErrorInfo", Namespace="http://schemas.datacontract.org/2004/07/MyService.Types")]
string IsAlive();
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
System.Threading.Tasks.Task<string> IsAliveAsync();
This doesn't work - if I try to instantiate an implemention of this interface in a ServiceHost
using (ServiceHost svcHost = new ServiceHost(typeof(MyService01Impl)))
{
svcHost.Open();
Console.WriteLine("Host running ...");
Console.ReadLine();
svcHost.Close();
}
I get this error:
Cannot have two operations in the same contract with the same name, methods 'IsAlive' and 'IsAliveAsync' in type 'MyService01Impl' violate this rule. You can change the name of one of the operations by changing the method name or by using the Name property of OperationContractAttribute.
Why does svcutil suddenly generate code that doesn't work??
If I use the /async keyword with svcutil, then I get the "old-style" async pattern with BeginIsAlive and EndIsAlive and things work again - but how can I tell WCF / svcutil to generate no async stuff at all?
svcutil by default generates a proxy class with both synchronous and Task-based methods, eg:
public interface IService1
{
...
string GetData(int value);
...
System.Threading.Tasks.Task<string> GetDataAsync(int value);
...
}
To generate a proxy with only synchronous methods, you need to use /syncOnly. This will omit the Task-based version:
public interface IService1
{
...
string GetData(int value);
...
}
In both cases, the proxy class itself inherits from ClientBase:
public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1
Finally, the /serviceContract switch generates only the interface and DTOs necessary for generating a dummy service
I followed : this article and implemented it in a WCF Service.
It allows us to create a instance of a Service that doesn't have a parameterless constructor, by implementing a custom IServiceBehavior, and then decorating the service with that Service Behavior, so instead of having for example:
[ServiceBehavior]
public class MyService : IMyService
I would have
[InstanceProviderBehavior]
public class MyService : IMyService
I then implement the ApplyDispatchBehavior like this:
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers) {
foreach (EndpointDispatcher ed in cd.Endpoints) {
if (!ed.IsSystemEndpoint) {
Console.WriteLine("Using InstanceProviderBehaviorAttribute");
ed.DispatchRuntime.InstanceProvider = new ServiceInstanceProvider(Configuration.Instance.Container);
}
}
}
And to provide an instance of the service I just do:
public object GetInstance(InstanceContext instanceContext, Message message)
{
AlertQueryService result = Container.Resolve<AlertQueryService>();
return result;
}
I ran it in windows and it worked as expected. But in linux with mono, it throws the exception
Exception Default constructor not found for type MyService
which indicates that maybe mono is ignoring the InstanceProviderBehaviorAttribute.
Another thing i noticed was that the line:
Console.WriteLine("Using InstanceProviderBehaviorAttribute");
Is executed in windows when the service host is opened. While in linux when the service host is opened, it doesn't write that in the console. Also the exception in linux is not thrown when we open the service host, but when the IsInitiating operation is called in MyService:
[OperationContract(IsInitiating = true)]
void Initialize();
Which indicates that with mono the service instance is only being resolved when we call the IsInitiating operation.
Any idea why this is works in windows and not in linux with mono? And why is the initialization behavior different?
Thanks
Try adding an InstanceContextProvider as well as your InstanceProvider in your EndpointBehavior. It seems the Mono implementation of ChannelDispatcher.ListenerLoopManager.Setup doesn't like the idea of being sans InstanceContextProvider if there is no parameterless constructor.
The InstanceContextProvider can be essentially a no-op implementation. So long as there is an instance, it will pass that check in ListenerLoopManagerSetup and happily proceed to utilize your InstanceProvider.
Re: why the different implementation... Mono is a re-implementation rather than a cross-compilation or even port. Consider the Important Rules section of their Contribution Guidelines. It wasn't until very recently that developers could contribute to the project if they had so much as looked at MS source code.
I tried to minimize writing of code for WCF CRUD part of big project with use of generics and castle WCF facility.
I have WCF service contract:
[ServiceContract]
public interface IResourceService : ICRUDService<DTOResource>
{
[OperationContract]
DTOResource Get(long id);
}
and generic interface
public interface ICRUDService<T> where T is IDTO
{
T Get(long id);
}
also generic MVC controller (1 controller for all basic crud for dtos and services)
public class CRUDController<T> : Controller where T is IDTO
{
readonly ICRUDService<T> service;
public CRUDController(ICRUDService<T> service)
{
this.service = service;
}
}
On the client side i register WCF client in Windsor Container
Component
.For<IResourceService , ICRUDService<DTOResource>>()
.AsWcfClient(... standard stuff... )
Everythig is working fine, components and services registered, controller created properly,
service
readonly ICRUDService<T> service;
in controller is of type
Castle.Proxies.IResourceService
But when i try to use service in controller i have error
Method Get is not supported on this proxy, this can happen if the method is
not marked with OperationContractAttribute or if the interface type is not
marked with ServiceContractAttribute.
When in controller i hardcode cast
((IResourceService)service).Get(id);
all is running properly, so i believe this problem is solvable.
I've also tried to use Forward (with same result) :
Component
.For<IActionTypeService>
.Forward<ICRUDService<DTOResource>>().AsWcfClient(...
How to make it work?
In the end i had to use 'Channel Factory' on client side.
I was able to use Windsor WCF Facility on server side to register generic contract :
[ServiceContract]
public interface ICRUDService<I>
{
[OperationContract]
I Get(int id);
}
with generic implementation
public class CRUDService<I, IEntity> : ServiceBase, ICRUDService<I>
{
public I Get(int id)
{
...
}
in standard way (for multiple types)
private void InstallExample<I, IEntity>(IWindsorContainer container)
{
container.Register(
Component
.For<ICRUDService<I>>()
.ImplementedBy(CRUDService<I, IEntity>)
.Named("somename")
.AsWcfService(
new DefaultServiceModel()
.Hosted()
.PublishMetadata(x => x.EnableHttpGet())
.AddEndpoints(WcfEndpoint
.BoundTo(new BasicHttpBinding())
.At("someAddress")
)
)
.LifeStyle.PerWcfOperation();
}
with fileless activation in web.config
<add factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" service="ClientService" relativeAddress="./ClientService.svc" />
On server side it works perfectly. Sadly on client side i didn't found working solution for WCFFacility and i had to use ChannelFactory (which is working perfectly)
ChannelFactory<ICRUDService<I>> factory = new ChannelFactory<ICRUDService<I>>(someBinding, someEndpoint);
For the rest (standard non generic services i'm using WCF Facility without any problems.
I think you need to put the ServiceContract attribute on ICrudService<>, add the OperationContract to the method there and remove the duplicate declaration of Get() from IResourceService.
I installed Ninject via nuget, and I registered my binds in NinjectMVC3's RegisterServices method (created by nuget). Follow my code:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind<IRepository<Action>>().To<ActionRepository>();
kernel.Bind<IRepository<ActionType>>().To<ActionTypeRepository>();
kernel.Bind<IRepository<City>>().To<CityRepository>();
kernel.Bind<IRepository<Country>>().To<CountryRepository>();
kernel.Bind<IRepository<Goods>>().To<GoodsRepository>();
kernel.Bind<IRepository<Media>>().To<MediaRepository>();
kernel.Bind<IRepository<MediaType>>().To<MediaTypeRepository>();
kernel.Bind<IRepository<Ranking>>().To<RankingRepository>();
kernel.Bind<IRepository<Role>>().To<RoleRepository>();
kernel.Bind<IRepository<Sponsor>>().To<SponsorRepository>();
kernel.Bind<IRepository<State>>().To<StateRepository>();
kernel.Bind<IRepository<UserAccountInfo>>().To<UserAccountInfoRepository>();
kernel.Bind<IRepository<UserAction>>().To<UserActionRepository>();
kernel.Bind<IRepository<UserDeservesGoods>>().To<UserDeservesGoodsRepository>();
kernel.Bind<IRepository<UserGoods>>().To<UserGoodsRepository>();
kernel.Bind<IRepository<User>>().To<UserRepository>();
kernel.Bind<IUserService>().To<UserService>();
kernel.Bind<IAccountService>().To<AccountService>();
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
here is my HomeController:
readonly IRepository<Ranking> repoRanking;
public HomeController(IRepository<Ranking> repoRanking)
{
this.repoRanking = repoRanking;
}
When I execute HomeController, I get follow exception:
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: Ninject.ActivationException: Error activating IRepository{Ranking}
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IRepository{Ranking} into parameter repoRanking of constructor of type HomeController
1) Request for HomeController
Suggestions:
1) Ensure that you have defined a binding for IRepository{Ranking}.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
What I doing wrong?
Have you created a default module where you set your bindings instead of in the register services method?
public class DefaultModule : NinjectModule {
public override void Load() {
Bind<IProductService>().To<ProductService>().InTransientScope();
}
}
and then in your Global.asax file do this:
protected override IKernel CreateKernel() {
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}