I'm using the WCF REST Template where services are implemented with just a class and registered in the Global.ascx (much like MVC controllers are).
RouteTable.Routes.Add(new ServiceRoute("Games/Games", new WebServiceHostFactory(), typeof(Games.Games)));
Games.Games has a ctor accepting a Dal.Games.IGames and I have a NinjectModule with the Bindings ready but I cant for the life of me figure out where to pass the kernel to to have it control the creation of the service classes.
My services dont have a markup (svc) file so I'm guessing that it will have something do with replacing the WebServiceHostFactory with one from Ninject. I was able to find one in the Ninject Web extension but just dropping that in didnt change anything not to mention I coulnt find anywhere to setup the kenel in that class.
Any solutions, hints or tips are greatly appreciated.
Let me preface this by saying, someone who actually knows inner workings of Ninject could probably provide a much cleaner solution. I've been wrestling with the same issue as you mentioned though.
Mostly through trial & error I determined that if you make the following code changes in the Ninject.Extensions.Wcf library, Ninject will work its magic on your service classes.
In NinjectServiceHostFactory.cs, i changed the base class and the type passed to .Get<T>
public class NinjectServiceHostFactory : WebServiceHostFactory //<-- Changed base class
{
protected override ServiceHost CreateServiceHost( Type serviceType, Uri[] baseAddresses )
{
var serviceTypeParameter = new ConstructorArgument( "serviceType", serviceType );
var baseAddressesParameter = new ConstructorArgument( "baseAddresses", baseAddresses );
return KernelContainer.Kernel.Get<NinjectServiceHost>( serviceTypeParameter, baseAddressesParameter );
}
}
In the NinjectServiceHost.cs i changed the base class to WebServiceHost.
Also, I added this reference to both:
using System.ServiceModel.Web;
I'm sure this solution breaks this extension for other WCF service types so hopefully a Ninject guru will come along and provide a real solution.
Related
When creating a .NET application where the controller calls a service, then the service calls a DAO for the database work, and I'm using Entity Framework Core 6.0 for the database services, do I also add the service layer objects in ConfigureServices, or just the data layer, and pass them in to constructors?
I'm not sure this is exactly a preference, rather I'm worried about multithreading, specifically.
The scheme is: API -> Controller -> Service -> DAO -> Database then back for the result.
Sample code:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CRM_MSCRMContext>();
services.AddScoped<HomeService>();
}
See above, I've added both the service that calls the context, as well as the context.
I'm injecting the DAO using the constructor:
Sample code:
public CRMDAO(CRM_MSCRMContext crmContext)
{
_crmContext = crmContext;
}
And I could be injecting the service into the controller, if I add to Scoped. Otherwise I think I'm just instantiating new in the constructor anyway:
public HomeController(HomeService homeService)
{
_homeService = homeService;
}
or I could use a constructor and forget injection here:
public HomeController()
{
_homeService = new HomeService();
}
Why would one be better than the other from a multithreading or database connection standpoint? I understand that this is going to be scoped per-request, so maybe it's no different than using the constructor to New the service object on every request anyway from the controller?
Thank you,
Dan Chase
OK so after reading documentation and experimenting, I found it seems to be all or nothing. I had to add everything in ConfigureServices, all DAO's and all Services, as well as all Contexts. Otherwise I kept getting "Unable to resolve while attempting to activate" errors. I also had to move everything to an Interface, or it doesn't seem to work at all.
If anyone has any tips let me know, but I figured best to answer my own question than to delete, because someone might be able to fill in more info.
I have an asmx web service I am converting to WCF. In the old structure I had a number of web service methods that accessed business classes to do the work. For example:
public DataSet GetAppointmentDataToConvert(string aAccessToken, string aStartingId)
{
//verify that the user is allowed to use this web service
if (!isAuthorized(aAccessToken))
{
throw new Exception("Not authorized");
}
cls256_BitEncryptionConversion cls256 = new cls256_BitEncryptionConversion();
return cls256.GetAppointmentDataToConvert(aStartingId);
}
This method initialized the cls256_BitEncryptionConversion class and called a method inside it to do the work, then returned the result.
I am trying to set up a WCF Service that will use the cls256_BitEncryptionConversion class, but despite both the class and the service being in the same namespace, my service method is unable to "see" the class. What am I doing wrong?
These are few tips for you to resolve it your self:
Make it sure that even they have the same namespace are they in the same project?
If they are in different project add it as you reference where you want to use it. And probably add a using directive if necessary.
I was able to resolve the issue by restructuring the project. I moved all the classes from the app_code folder into the root of the project.
I'm trying to have Castle (3.0) inject constructor params into a WCF service, like this
ServiceHostBase clientServiceHost = new Castle.Facilities.WcfIntegration.DefaultServiceHostFactory()
.CreateServiceHost(typeof(IClientExchange).AssemblyQualifiedName, new Uri[0]);
However I get the following exception 'The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor.'
The service impl of type ClientExchange takes a constructor param of type IProviders
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class ClientExchangeService : ExchangeService, IClientExchange
{
public ClientExchangeService(IProviders providers)
: base(providers) { }
}
My windsor installer looks like this:
container.AddFacility<WcfFacility>()
.Register
(
Component.For<IProviders>().Instance(Providers.DbInstance),
Component.For<IClientExchange>().ImplementedBy<ClientExchangeService>(),
);
At the moment it seems like WCF is trying to new up the service without castle providing the dependency. Tried a few alternative examples out there but many are for previous versions of castle pre 3.0. I must be missing a hook somewhere? How do I tell WCF to defer construction responsibility to castle?
I think this: how do i pass values to the constructor on my wcf service might be the answer to your problem. Or, for something more Windsor specific this might help: Dependency Injection in WCF Using Castle Windsor.
UPDATE
OK, so I think I have figured this out. First of all the problem is this attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
If you do not specify that Windsor will be able to inject the dependencies into the constructor perfectly fine - with that it cannot.
From looking at the description of that attribute here I see that you want your service to be a singleton so since that is the default for Windsor you can simply remove that attribute and it should start working for you and behave as you expect.
There are two other lifestyles that you may be interested in that are specifically for WCF:
LifestylePerWcfOperation()
LifestylePerWcfSession()
(specify them in the normal place - more information is available here)
Incidentally, you do not have to do the ServiceHostBase stuff at all, instead you can use the AsWcfService extension method like so (personally I prefer this way of doing it):
container
.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
.Register(
Component
.For<IProviders>()
.Instance(Providers.DbInstance),
Component
.For<IClientExchange>()
.ImplementedBy<ClientExchangeService>()
.AsWcfService(new DefaultServiceModel()
.AddEndpoints(WcfEndpoint
.BoundTo(new BasicHttpBinding())
.At("http://localhost:8000/ClientExchangeService"))));
I just started learning on WCF and is trying to create a WCF service for my client application.
From the msdn tutorial, I have went through all the individuals steps and sort of grasp how WCF works and now I am trying to start coding the service on my part. For the first step it says, defining a service contract. and the sample code msdn gives are as follows
namespace Microsoft.ServiceModel.Samples
{
class Program
{
static void Main(string[] args)
{
}
}
}
and the service contract.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
what i would like to ask is, what can i actually substitute the namespace with since I am developing for my own application?
The namespace can be a string - typically it's a URI, like in your question, but it could also be a simple dotted namespace
[ServiceContract(Namespace = "Microsoft.ServiceModel.Samples")]
Contract namespaces are just strings to resolve possible conflicts (can be useful when versioning, for example). If you omit it your WSDL will contain http://tempuri.org. Not what you want in production. However, it's not that easy to just set proper name in ServiceContractAttribute, there are also binding and schema namespaces. For better understanding WSDL namespaces in context of WCF I highly recommend this blog post.
I have a plugin that I will instantiate at runtime and I want to pass it a WCF service from the application host. The application host is responsible for creating the connection to the service. The reason for this is that a single service can be used by multiple plugins, but the plugins should only know about its interface since there may be several implementation of IMyPluginServices. For instance, the Run method of the plugin instance would be:
public void Run(IMyPluginServices services)
{
services.DoSomething();
}
The problem I am running into is that I don't know how to create a service of type IMyPluginServices and pass it to the Run function. The service reference generated by VS 2010 doesn't seem to create an object of type IMyPluginServices that I can pass to it. Any help would be greatly appreciated. Thanks.
When you add a service reference in VS 2010 for a service it generates an interface named IMyService which contains methods for each OperationContract in your service. It also generates a concrete class named MyServiceClient, which can be constructed and then used to invoke your service.
Now, the problem that you're running into, I believe, is that MyServiceClient is a subclass of ClientBase<IMyService>, and does not implement the generated IMyService interface (which is a real pain).
To get around this problem I ended up making a new interface:
public interface IMyServiceClient : IMyService, IDisposable, ICommunicationObject
{
}
(Note: IDisposable and ICommunicationObject are only required if you want your module to be able to detect/react to faulted channels and other such things).
I then extend MyServiceClient with a partial class (in the assembly that contains my WCF Service reference):
public partial class MyServiceClient : IMyServiceClient
{
}
Now in my modules I can accept an IMyServiceClient instead of an IMyService, and still execute all of the methods that I need to. The application in control of the modules can still create instances of MyServiceClient as it always did.
The beauty of this is that your new interface and partial class don't need any actual code - the definitions suffice to get the job done.