I have a big MVC solution with multiple projects. I am planning to create a separate solution with WCF services and move some highly resource hungry projects. Idea is that the MVC application will communicate with WCF for any computational requirements.
The problem is I dont know how do I call the existing class and interfaces which already have interfaces to services. My class/interface:
public interface IHelloWorld
{
string SayHello(string name);
}
public class HelloWorld : IHelloWorld
{
public string SayHello(string name)
{
return string.Format("Hello, {0}", name);
}
}
There are 100s of methods in the class. Not all will be exposed to WCF only a few of them.
Now I have to call this class in newly created WCF service. I am not sure:
Do I have modify the existing classes to convert to svc.cs (service) or I can create a separate service file and call the existing methods there?
The service class also needs an interface which will be defined in web.config (endpoint contract). Do I have to create a separate interface with only methods I need to expose OR I have to use the existing interface in the class library? If I use the class interface, then I have to mention the same in web.config.
I am bit confused what should be the best way to doing it. I dont want to modify the existing class but want to add a new service which I can just hook up and call from there. new svc.cs files are:
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
private IHelloWorld helloWorld = new HelloWorld();
public string SayHello(string name)
{
return helloWorld.SayHello(name);
}
}
This current design seems I am repeating the existing class/interface. Not sure if this is the correct way. Please help.
Do I have modify the existing classes to convert to svc.cs (service) or I can create a separate service file and call the existing methods there?
No, because you say that not all methods need to be exposed.
This current design seems I am repeating the existing class/interface. Not sure if this is the correct way. Please help.
Yes, it's repeating if you are doing like the code you show in the question.
You can write the code of your service like this;
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
private IHelloWorld helloWorld = new HelloWorld();
public string SayHello(string name)
{
return helloWorld.SayHello(name);
}
}
By using the IHelloWorld contract on your service, you are not duplicating logics and only needed method will be exposed through HelloWorldService contracts.
Related
In my solution there's a few WCF services, each of them implementing it's own callback interface. Let's say they are called: Subscribe1, with ISubscribe1 and ICallback1, etc.
It happens there are a few methods shared among ICallbacks, so I made a following interface:
interface ICallback
{
[OperationContract]
void CommonlyUsedMethod();
}
and i inherited it in all: ICallback1 : ICallback, ICallback2 : ICallback, etc. And deleted the CommonlyUsedMethod() from all callback interfaces.
Now, on the service-side code, everything compiles fine and services can start working as usual. But, when I updated the service references for the client, CommonlyUsedMethod() dissapeared from the reference.cs file (the ISubscribeCallback part), and could no longer be used to send data to back to the client.
try to set the ServiceContract attribute on the base interface also.
Ok, this is the exact code, I condensed it as much as I can. Just start a new console application and copy/paste it. Start it and add a service reference to it. CommonlyUsedMethod() is not present in the reference, while the other methods are. Could it be framework 4?
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace TestService
{
class Program
{
static void Main()
{
var serviceHost=new ServiceHost(typeof(Subscribe1), new Uri("net.tcp://localhost:8888"));
serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior());
serviceHost.AddServiceEndpoint(typeof(ISubscribe1), new NetTcpBinding(SecurityMode.None), string.Empty);
serviceHost.AddServiceEndpoint("IMetadataExchange", MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
serviceHost.Open();
Console.WriteLine("Working!");
while(Console.ReadKey(true).Key!=ConsoleKey.Escape) { }
}
}
[ServiceContract]
interface ICallbackBase
{
[OperationContract]
void CommonlyUsedMethod();
}
[ServiceContract]
interface ICallback1 : ICallbackBase
{
[OperationContract]
void SpecificMethod();
}
[ServiceContract(CallbackContract=typeof(ICallback1))]
interface ISubscribe1
{
[OperationContract]
void TestMethod();
}
[ServiceBehavior]
class Subscribe1 : ISubscribe1
{
[OperationBehavior]
public void TestMethod()
{
}
}
}
Does this reflect what you have in your code?
[ServiceContract]
public interface ICallbackBase
{
[OperationContract]
void CommonlyUsedMethod();
}
[ServiceContract]
public interface ICallback1 : ICallbackBase
{
[OperationContract]
void SpecificMethod();
}
This is essentially the structure I have in my production solution, and then I use the proxies that are generated when I add a Service Reference to access my methods from the client.
For reference, the generated interface then looks like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="MyNamespace.ICallback1")]
public interface ICallback1 {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICallbackBase/CommonlyUsedMethod", ReplyAction="http://tempuri.org/ICallbackBase/CommonlyUsedMethodResponse")]
void CommonlyUsedMethod();
}
Note the "ICallbackBase" in the OperationContractAttribute - it really does know where the method came from.
I'm not sure that what you are trying to do using WCF is possible. When you use inheritance in WCF you need to apply the KnownType attribute to the DataContract so that the DataContractSerializer will know to serialize it and make it available on the other end. Since you cannot put the KnownType attribute on interfaces, there is no way to tell the serializer that this is needed on the other end. Thus is does not show up when you implement it on the client.
This question already has answers here:
How to mock non virtual methods?
(8 answers)
Closed last year.
I have a C# class that gets generated using the wsdl.exe tool that looks something like this:
public partial class SoapApi : System.Web.Services.Protocols.SoapHttpClientProtocol
{
public SOAPTypeEnum AskServerQuestion()
{
object[] results = return this.Invoke("AskServerQuestion");
return (SOAPTypeEnum) results[0];
}
}
I have some thin wrapper code around this that keeps track of the result, etc. Is it possible to use any of the object mocking frameworks to make a fake SoapApi class and return predictable results for each of the calls to the thin wrapper functions?
I can't make the AskServerQuestion() function virtual because it's auto-generated by the wsdl.exe tool.
The way I've accomplished this was to inject an ISoapApi instead, where the ISoapApi interface mimics the automatically generated SOAP API.
For your case:
public interface ISoapApi
{
SOAPTypeEnum AskServerQuestion ();
}
Then, take advantage of the fact that the generated SoapApi class is partial, and add this in another file:
public partial class SoapApi : ISoapApi
{
}
Then, consumers should just take an ISoapApi dependency that can be mocked by any of the mocking frameworks.
One downside is, of course, when the SOAP api changes, you need to update your interface definition as well.
The class is partial so you could make the class implement an interface in the partial class part you write.
You can then mock the interface.
I worked out a technique that will work for the case where the class is non-partial. Suppose this is the original class:
// Generated class, can't modify.
public class SomeClass
{
// Non-virtual function, can't mock.
public void SomeFunc() { //... }
}
First, extract the interface from that class:
public interface ISomeClass
{
void SomeFunc();
}
Now make a new class that inherits from both of the above:
public SomeClass2 : SomeClass, ISomeClass
{
// The body of this class is empty.
}
Now you can use SomeClass2 in your program. It will behave the same as SomeClass. And you can mock ISomeClass.
I am currently designing a class library that will provide data to a web application graph rendering engine in C#. I am currently defining the interfaces of this library.
I have a IGraphData interface which I would like to cache using a service that accesses the cache, this is called IGraphDataCacheService and has set and get methods to add and retrieve IGraphData objects to and from the cache. the cache service will be a singleton.
I am confused about the correct way to implement this, so that there is only one cache service that can get and set generic IgraphData objects.
I came up with this:
interface IGraphDataCacheService {
IGraphData<object> Get(string identifier);
void Set(IGraphData<object> graphData);}
or this:
T Get<T, P>(string identifier) where T : IGraphData<P>;
void Set<T,P>(T graphData) where T : IGraphData<P>;
Can any one offer any advice help?
Thanks
Why don't you just make the interface generic instead?
interface ICacheService<T> {
T Get(string identifier);
void Set(T graphData);
}
if you wanted, you could type-constrain T to be of type IGraphData, or you could write it as:
interface IGraphDataCacheService<T> {
IGraphData<T> Get(string identifier);
void Set(IGraphData<T> graphData);
}
A few points:
I'd probably rename the interface methods to be more emblematic of a caching service. For example, Fetch and Store instead of Get and Set, which makes it sound like you're getting or setting the provider rather than the data to be cached.
Ensuring that there is only one cache is an implementation detail, not an interface one.
To implement a singleton, try something like:
public class SingletonCacheService : IGraphDataCacheService {
private static Singleton instance;
private Singleton() {}
// snip implementation of IGraphDataCacheService methods ...
public static Singleton Instance {
get {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
Note that this simple version isn't threadsafe.
Both alternatives seem plausible at a glance; my hunch is that you need to write some 'typical' client code to decide. e.g. Does the typical client 'know' the type of data associated with the identifier it's looking up? Good API design requires identifying the main use scenarios and using that to inform the design.
If I understand your question correctly you are wanting to treat the generic types like they are the same, but in current .NET implementation you can't do this.
IGraphData<string> can't be passed as a IGraphData<object> they are actually different types even though string is an object, the generic types are not related and can't be cast or passed like they are the same.
If you control the IGraphData interface you can create a IGraphData interface and derive IGraphData from it and use IGraphData to access the cache. It just depends on how you are using it and what you have the control over.
You can do what you want in C# 4.0. There is an article about it here
You can't ensure there's only a single instance implementing an interface. However, you can make a class (e.g. GraphDataCacheServiceImpl) implementing the interface a singleton by sealing it and providing only a getter property, with the object created as a static variable from a private constructor. See the below. As far as generics, it's not exactly clear what you're seeking to accomplish. But I would guess the below is close to what you want.
interface IGraphDataCacheService<T> {
IGraphData<T> Get(string identifier);
void Set(IGraphData<T> graphData);
}
public sealed class GraphDataCacheServiceImpl<T> : IGraphDataCacheService<T>
{
private GraphDataCacheServiceImpl()
{
// ..
}
static GraphDataCacheServiceImpl()
{
Instance = new GraphDataCacheServiceImpl<T>();
}
public IGraphData<T> Get(string id)
{
return new GraphDataImpl<T>();
}
public void Set(IGraphData<T> graphData)
{
}
public static GraphDataCacheServiceImpl<T> Instance {get; private set;}
}
I'm experimenting with WCF Services, and have come across a problem with passing Interfaces.
This works:
[ServiceContract]
public interface IHomeService
{
[OperationContract]
string GetString();
}
but this doesn't:
[ServiceContract]
public interface IHomeService
{
[OperationContract]
IDevice GetInterface();
}
When I try to compile the client it fails on the GetInterface method. I get an Exception saying that it can't convert Object to IDevice.
On the clientside the IHomeService class correctly implements GetString with a string as it's returntype, but the GetInterface has a returntype of object. Why isn't it IDevice?
You need to tell the WCF serializer which class to use to serialize the interface
[ServiceKnownType(typeof(ConcreteDeviceType)]
Thanks, it works when I changed it like this:
[ServiceContract]
[ServiceKnownType(typeof(PhotoCamera))]
[ServiceKnownType(typeof(TemperatureSensor))]
[ServiceKnownType(typeof(DeviceBase))]
public interface IHomeService
{
[OperationContract]
IDevice GetInterface();
}
I also got help from this site: http://www.thoughtshapes.com/WCF/UsingInterfacesAsParameters.htm
I initially tried to pass an interface to a WCF method but couldn't get the code to work using the answers provided on this thread. In the end I refactored my code and passed an abstract class over to the method rather than an interface. I got this to work by using the KnownType attribute on the base class e.g.
[DataContract]
[KnownType(typeof(LoadTypeData))]
[KnownType(typeof(PlanReviewStatusData))]
public abstract class RefEntityData : EntityData, IRefEntityData
i have a library with some entities that share the same interface. clients and service share this assembly. now i wonder if there is a way to have this Interface-type as Parameter in my service contracts so that i can use the same method for all classes implementing the interface.
the entities themselve are all decorated with datacontract-attribute and its members with datamember attributes.
is it possible at all? probably with the NetDataContractSerializer?
i know that i can do it with a base class (some abstract class e.g.) and the knowntype-attribute but i´d definitely prefer the Interface as identificator of the objects cause it is used widely in the client app and would ease development.
thanks
I solved the problem using the ServiceKnownType attribute at the implementations of the OperationContracts.
When telling your classes that implement the interface as ServiceKnownType's, you can use the interface as parameter and therefore are able to use all classes implementing your interface as long as they are serializable. (look at "Programming WCF Services" from Juval Löwy, page 100)
It certainly isn't possible under regular "mex". It might be possible with assembly sharing, but I really wouldn't recommend it - you are fighting WCF: it will be brittle, etc. Of course, you can always mask this in your object model - i.e. rather than calling the [OperationContract] method directly, abstract this away into a wrapper method that hides the WCF details (perhaps using different objects for the data transfer than it actually returns).
[I just read your answer and realized that you were asking specifically about parameters to service methods. I'll leave my comments here in case they're still helpful.]
What I've done on projects where I know I have WCF on both sides of the wire, is something like:
A library of only the shared interfaces, eg:
namespace SharedInterfaces {
public interface ICompositeType {
bool BoolValue { get; set; }
string StringValue { get; set; }
}
}
The WCF service library, where the [DataContract]s (POCOs) implement the shared interfaces.
[DataContract]
public class CompositeType : ICompositeType {
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue {
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue {
get { return stringValue; }
set { stringValue = value; }
}
}
In the service client, each proxy POCO can be "compelled" to implement the shared, deployed, interface using a partial class (it will anyway if svcutil did it's job correctly), and you'll be able to program to the interface in the rest of your client code:
namespace ServiceClient.ServiceReference1 {
public partial class CompositeType : ICompositeType {
}
}
This partial is also useful if you want to add some additional properties or methods that the client can make use of (eg. Presenter or ViewModel concepts in MVP or MVVM patterns).