Provide multiple interface in a single service - wcf

I want to separate my service contracts from their properties.
Example:
IWirelessService
IWiredService
I want my IWirelessService implemented in IRasadService, but when i add wsdl into the wcf test client, it gives following error:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
I want to only provide IRasadService as my main webservice. How can i do this?
Relevant Code:
[ServiceContract]
public interface IWirelessService
{
[OperationContract]
void AddUser();
}
public class WirelessService : IWirelessService
{
UserProvider userProvider;
#region User Operations
public void AddUser()
{
throw new NotImplementedException();
}
}
[ServiceContract]
public interface IRasadService :IWirelessService
{
[OperationContract]
BoxRasadWCFReturn GetDataUsingDataContract(CompositeType composite);
// TODO: Add your service operations here
}

Related

Running WCF service method during start of Windows Service

I have got WCF service running as Windows service and I need to run a method of the WCF Service when Windows Service is starting. Is it possible in any way?
[ServiceContract]
public interface IWebMonitorServiceLibrary
{
[OperationContract]
void TestMethod();
}
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WebMonitorServiceLibrary : IWebMonitorServiceLibrary
{
#region properties
#endregion
#region events
#endregion
public WebMonitorServiceLibrary()
{
Initialization();
}
private void Initialization()
{
/////////
}
public void TestMethod()
{
//////////
}
}
You don't explain why you want this initialization code to run, but given you almost never want to use a single-instance WCF service, the proper way would be to use dependency injection (see How do I pass values to the constructor on my wcf service?).
Create an object in which you store the things you want to initialize, which you initialize on your Windows Service start:
public class SomeSettingsYouWantToInitialize
{
public string SomeSetting { get; set; }
}
public class WindowsServiceInstance : ServiceBase
{
protected override void OnStart(string[] args)
{
InitializeWcfService();
}
private void InitializeWcfService()
{
var settings = new SomeSettingsYouWantToInitialize
{
SomeSetting = "Foo"
};
_yourDependencyContainer.Register<SomeSettingsYouWantToInitialize>(settings);
}
}
Then (using whatever dependency injection framework you use), inject that into your service's constructor:
public class WebMonitorServiceLibrary
{
public WebMonitorServiceLibrary(SomeSettingsYouWantToInitialize settings)
{
// do stuff with settings
}
}
Generally, no. This is because by default (and following best practice) you will have configured your service to run per-call (or per session), which means there can be multiple instances of your actual service running in your service host.
Therefore, any requirement for you to be able to return an instance of the service from the service host will involve some nasty plumbing code and is not advised.
Specifically, however, there are two approaches you could use to do what you want.
The first involves running your service in InstanceContextMode.Single - this means there will be a single service instance which will handle all requests. If you do this then you can simply create the service instance and then pass it into the servicehost when you start the windows service:
var service = new MyService();
var host = new ServiceHost(service);
You then have access to the service instance and can call the operation directly.
service.MyOperation("something");
The second thing you can do for when you don't want to run a singleton service you can make your service implementation just a wrapper around a static instance of a shared class that actually process the requests. As an example:
public class MyService : IMyService
{
private static IMyService instance = new MySharedServiceClass();
public static IMyService Instance
{
get { return instance ; }
}
public bool MyOperation(string something)
{
return instance.MyOperation(something);
}
}
Then you can call the method on the class like this:
var host = new ServiceHost(typeof(MyService));
var instance = MyService.Instance;
instance.MyOperation("something");
I would still avoid doing this if at all possible. Think to yourself why do you even want this method called on startup? Surely it would be better to have this code directly in the windows service if it's something that needs to be run on startup?

WCF with Sharp architecture - The needed dependency of type could not be located with the ServiceLocator

I'm working with an application which uses wcf and sharp architecture, I'm trying to create a service to write to the database. Here is my service: (Sicaf.Core.Services.Wcf)
[ServiceContract]
public interface IFacturaWcfService : ICloseableAndAbortable
{
[OperationContract]
string ConsultarValorMatricula(string xmlData);
}
[ServiceBehavior, AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class FacturaWcfService : IFacturaWcfService
{
private readonly IFacturaBusiness facturaBusiness;
public FacturaWcfService(IFacturaBusiness facturaBusiness)
{
this.facturaBusiness = facturaBusiness;
}
public string ConsultarValorMatricula()
{
return facturaBusiness.GetFactura();
}
public void Abort() { }
public void Close() { }
}
In the ComponentRegistrar.cs: (Sicaf.Core.Services.WebServices)
private static void AddWcfServicesTo(IWindsorContainer container)
{
// Since the TerritoriesService.svc must be associated with a concrete class,
// we must register the concrete implementation here as the service
container.AddComponent("facturaWcfService", typeof(FacturaWcfService));
}
I created a client but I get this exception:
The needed dependency of type FacturaWcfService could not be located with the ServiceLocator. You'll need to register it with the Common Service Locator (CSL) via your IoC's CSL adapter.
I've finally found my mistake.
Before:
private static void AddCustomRepositoriesTo(IWindsorContainer container)
{
// Register Data Layer Services
container.Register(
AllTypes.Pick()
.FromAssemblyNamed("Sicaf.Core.Services.Data")
.WithService.FirstNonGenericCoreInterface("Sicaf.Core.Services.Services.Data"));
}
After:
private static void AddCustomRepositoriesTo(IWindsorContainer container)
{
// Register Data Layer Services
container.Register(
AllTypes.Pick()
.FromAssemblyNamed("Sicaf.Core.Services.Data")
.WithService.FirstNonGenericCoreInterface("Sicaf.Core.Services.Services.Data"));
container.Register(
AllTypes.Pick()
.FromAssemblyNamed("SismatV2.Data")
.WithService.FirstNonGenericCoreInterface("SismatV2.Services.Data"));
}

Wcf service inheritance (Extend a service)

The program I am working on exposes both callbacks and services using wcf.
Basically, what the services do is simply return some variables value. As for the callback, they simply update those variables.
I want to be able to expose one class containing only the services and one class containing the services and the callbacks.
For example :
[ServiceContract]
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceClass
{
[OperationContract]
public int getValue()
{
return mValue;
}
protected static int mValue;
};
[ServiceContract]
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceAndCallbackClass : ServiceClass
{
[OperationContract]
public bool subscribe()
{
// some subscribing stuff
}
public void MyCallback()
{
++mValue;
// Notify every subscriber with the new value
}
};
If I want only the services, I can use the base class. However, if I want to subscribe to the callback and use the service, I can use ServiceAndCallbackClass.
Is this possible ?
One solution I found :
Make 2 interfaces. The first one containing only the services and the second one inheriting from the first one and adding the callbacks.
An implementation class would implement the 2 interfaces.
Example :
[ServiceContract]
[ServiceKnownType(typeof(ICallback))]
public interface IService
{
[OperationContract]
int GetData();
}
[ServiceContract]
public interface ICallback : IService
{
[OperationContract]
public bool subscribe();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceClass : IService, ICallback
{
public int getValue()
{
return mValue;
}
public bool subscribe()
{
// some subscribing stuff
}
public void myCallback()
{
++mValue;
// Notify every subscriber with the new value
}
protected static int;
};
[ServiceBehavior(InstanceContextMode=InstanceContextMode::Single, ConcurrencyMode=ConcurrencyMode::Multiple)]
public ServiceAndCallbackClass : ServiceClass
{
// Dummy implementation used to create second service
};
From there, we can create 2 services. One based on the implementation class and one based on the "Dummy" class. Each service would be created from a different interface and thus exposing different methods.

How do I solve the error that I received when implementing the callback method?

I am currently developing a WCF duplex service and I am trying to implement the callback method in my client app however there is a error of
'App.CallbackHandler' does not implement interface member IPostingServiceCallback.retrieveNotification(Service.Posting)'
the service contract for my service are as follow
[ServiceContract(SessionMode=SessionMode.Required , CallbackContract = typeof(IPostingServiceCallBack))]
public interface IPostingService
{
[OperationContract(IsOneWay = true)]
void postNotification(Posting post);
}
public interface IPostingServiceCallBack
{
[OperationContract]
String retrieveNotification(Posting post);
}
I have generated the proxy and added into the project file of my client and adding the endpoint address into the app.config.
EDIT
The code I have in my client app currently is
public class CallBackHandler : IPostingServiceCallback
{
public void retrieveNotification()
{
//planning to do something
}
}
Your client application needs to implement IPostingServiceCallBack and define the retrieveNotification method.
Say you have a client (not the proxy) that will be consuming your duplex service:
public class MyClient : IPostingServiceCallBack
{
public String retrieveNotification(Posting post)
{
// Implement your logic here
}
}
Note the above is a bare-bones example as a simple illustration. Your client will probably derive from another class as well (depending on whether it's ASP.NET, WinForms, WPF, etc).
Updated
You're still not implementing the method. Your callback interface is:
public interface IPostingServiceCallBack
{
[OperationContract]
String retrieveNotification(Posting post);
}
Your implementation is:
public class CallBackHandler : IPostingServiceCallback
{
public void retrieveNotification()
{
//planning to do something
}
}
You have public void retrieveNotification(), whereas the interface has String retrieveNotification(Posting post). The method signatures don't match.
You need to do:
public class CallBackHandler : IPostingServiceCallback
{
public String retrieveNotification(Posting post)
{
// planning to do something
}
}

Injecting an unrelated contract into the WSDL created by WCF's MEX provider

I am implementing a WCF service (Contract A) that will eventually make calls to a standalone service (Contract B) hosted by the client. At design-time when the client queries my service's WSDL to build its proxy, I'd like to include the WSDL for Contract B so the client can build its service around that. Unfortunately, I can't figure out how to inject Contract B into the WSDL emitted by the service. Since the contract is an interface and doesn't have the [DataContract] attribute I can't add it as a known type. Is there any other way to inject a contract into emitted WSDL?
Here's an example:
[ServiceContract]
public interface IServerService
{
[OperationContract]
void GiveTheServerMyServiceUri(string uri);
[OperationContract]
void TellAllClientsSomething(string message);
}
// THIS IS THE INTERFACE I WANT TO INCLUDE IN THE WSDL
[ServiceContract]
public interface IClientService
{
[OperationContract]
void ReceiveMessageFromServer(string message);
}
public class ServerService : IServerService
{
private List<string> knownClients;
public void GiveTheServerMyServiceUri(string uri)
{
knownClients.Add(uri);
}
public void TellAllClientsSomething(string message)
{
foreach (string clientUri in knownClients)
{
// 1. Create instance of ClientServiceProxy using client's uri
// 2. Call proxy.ReceiveMessageFromServer(message)
}
}
}
At first it seems that this is a textbook example of a duplex contract. However, for this particular application, for a variety of reasons, I need a bit more separation between client and server so I was hoping to just give the client an interface to implement (via the WSDL), let it host its own service, then just tell me the service's url.
I don't see that this makes sense. Unless your service is implementing the service contract of the other service, then don't do this.
On the other hand, your service can implement the other service contract, and become a client to the other service. It can then delegate calls to the other service contract to that other service.
I just tried this to make sure. I created a new WCF Service library project. This created a Service1 implementing IService1, with two operations. I modified the [ServiceContract] attribute to use a specific namespace (http://localhost/service1).
I then added a new service, which gave me Service2, implementing IService2, with a single operation (DoWork). I updated the [ServiceContract] to use http://localhost/service2/.
I then updated Service1 to implement IService2 as well as IService1, and to delegate IService2.DoWork to the Service2 service. I did also have to add a new endpoint implementing IService2, and I had to specify a relative address, so that the two would not conflict (since they were in the same project). Here's the result:
using System;
namespace WcfServiceLibrary1
{
public class Service1 : IService1, IService2
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
public void DoWork()
{
Service2Reference.IService2 svc = null;
try
{
svc = new Service2Reference.Service2Client();
svc.DoWork();
}
finally
{
if (svc != null)
{
((IDisposable)svc).Dispose();
}
}
}
}
}