WCF: Can I expose a class of an external assembly? - wcf

I have given reference to a dll in my WCF service application. My WCF operation requires input of type class (let's say XYZ) which is present in that dll.
Now, is it possible to expose that class to the clients so that they can call the exposed wcf method?
If yes then can you please explain the idea or with some pesudo code/references ?
Thanks in advance !

Contract:
[OperationContract]
void Add(XYZ item);
Server:
public void Add(XYZ item){}
[DataContract]
class XYZ{}
Client:
var item = new XYZ();
client.Add(item);
Dll containing 'XYZ' should be referenced by both Server and Client.
Class 'XYZ' should have 'DataContract' attribute.
Implementation is more or less similar to FaultContracts in WCF.

Related

Can I expose two methods in my Server with NServiceBus?

I was looking an answer for this but I couln't find it. As you know, the NServiceBus library came with a sample that's call WCF Integration. It has an interface that the Server exposes as a WCF service, right? This interface has only one method inside. My idea is to have more than one method inside that interface, is this possible?
I have my own project, in which I have my interface with more than one method and my idea is that this WCF Service to have a method similar to "Process" from the sample, that publish messages.
Code:
[ServiceContract]
public interface ICancelOrderService
{
[OperationContract(Action = "http://tempuri.org/IWcfServiceOf_CancelOrder_ErrorCodes/Process", ReplyAction = "http://tempuri.org/IWcfServiceOf_CancelOrder_ErrorCodes/ProcessResponse")]
ErrorCodes Process(CancelOrder request);
[OperationContract]
ErrorCodes HelloWorld(CancelOrder request);
}
public class CancelOrderService : WcfService<CancelOrder, ErrorCodes>{}
I trie to inherit from ICancelOrderService, but didn't work.
So, any suggestions? Thanks people...
Regards, Matias.
thanks for your soon response. Maybe my explanation wasn't clear enough. I have my Server that inherits from WcfService, but my idea is to have more than one OperationContract, one similar to Process, and the others ones commons Wcf OperationContract, that they won't interact with NSB.
[ServiceContract]
public interface ICancelOrderService
{
[OperationContract(Action = "http://tempuri.org/IWcfServiceOf_CancelOrder_ErrorCodes/Process", ReplyAction = "http://tempuri.org/IWcfServiceOf_CancelOrder_ErrorCodes/ProcessResponse")]
ErrorCodes Process(CancelOrder request);
[OperationContract]
void HelloWorld(int var);
}
My code will be something like that. With your response I realize that the code of the first post was wrong.
So, is this possible, or I have to look other way to implement this?
Thanks, Matias
The WCF service that is exposed is only to get messages onto the bus. Once the messages is on the bus it will be dispatched to the appropriate message handler. You can then Publish from your handler. NSB will expose methods for each message handler that inherits the WcfService<T,K> class. Just keep using that class to expose more methods.

Business Logic Layer expose in WCF Service

We have already Business logic layer available in our application. It has lots of classes. and this is in separate library(.Dll). Now we want to use this in to our WCF Service. For that We create new project and gave reference to that .Dll. But we are not able to see our class .. I verify that class is public..
Could you please let me know what should I do?
Here I am attaching my code what I need to do
My Business Layer class
namespace BusinessLayer
{
public class MessageContext : Dictionary<string, object>
{ ....}
}
Now I am reference this Project to my WCF project and tried to expose this class into WCF client. So I Create one MessageContextHelper class which inherit from MessageContext the code is following
namespace WCFService
{
public class MessageContextHelper : MessageContext
{ ...... }
}
On client I am not able to get MessageContextHelper class.
Thanks
JK
WCF doesn't send business logic classes to the client. If you're using the SOAP version of WCF (BasicHttpBinding for example) then what WCF will expose is methods that are in your service contract. Your client can call those.
So if you have methods in a business logic class that you want exposed, create methods in your WCF service that will in turn call the business layer methods.
A very rudimentary (and not complete) version would look something like this:
namespace WCFService
{
public class MyService: IMyService
[OperationContract]
public String DoSomeStuff() {
return MessageContext.DoSomething();
}
}
You absolutely cannot (and should not) use your business layer from your client code. As the previous reply message, WCF does not send your business class to the client. Think about how long it will take to send. The business layer (your dll) should be used on the server only. Your WCF should only accept modified/new data from the client, pass the data to the business layer, and then return the results to the client.

WCF - DataContract that inherits from an interface

I have a datacontract as part of my WCF Interface that inherits from IIdentity:
[DataContract]
public class AuthenticationIdentity : IIdentity
{
//implements IIdentity...
}
The service returns my AuthenticationIdentity objects just fine. However, when I try and do the obvious cast on the client:
AuthenticationIdentity aId = client.GetID();
IIdentity id = aId;
I get a complaint that AuthenticationIdentity cannot be cast to IIdentity. I've tried adding the ServiceKnownTypes to the interface:
[ServiceKnownType(typeof(AuthenticationIdentity))]
[ServiceKnownType(typeof(IIdentity))]
but still no luck. Any ideas?
If you control both sides of the wire (which it looks like you do since you want to cast to IIdentity), you can reference your DataContract from a shared assembly. Then you can use svcutil to share the DataContracts between the service and the consumer. Or, if you wanted to cut out svcutil altogether, you could write your own proxy to use the shared assembly.

How do I pass a service to another plugin?

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.

wcf exposing generics

I have an application where client and server share types, and interoperability is not one of our concerns. I am planning to have a single repository for all web enabled objects, and i was thinking of a generic interface for my exposed service.
something like T GetObject(int id)
but wcf doesnt like it since its trying to expose its schema (which i dont really care about)
is it possible to do such a thing with WCF ?, i can use any type of binding doesnt have to be httpbinding or wsbinding...
No, you can't. Whether or not you want or need interoperability, the most basic foundation of WCF is message exchange.
The client send the server a message and gets back a response. That message is all that passes between client and server, and needs to be serializable into a XML or binary format. That's why any data being passed around must be atomic (like int, string) or a DataContract - a description for the WCF service stack about how to serialize and deserialize such objects.
You cannot pass any interfaces, or other "trickery" - all that goes between client and server must be expressable in XML schema, basically.
So I'm afraid what you're trying to achieve is quite contrary to what WCF offers. The world and paradigms of SOA (Service-Oriented Apps) are quite different and not always 100% in sync with the idea and mechanisms of OOP.
Marc
I suppose this is possible, though I'm not sure you'd want this. I'd take the following approach (untested, not sure if it works). First create the following project structure in your solution:
ServiceInterfaces
ServiceImplementations (references ServiceInterfaces and ModelClasses)
ModelClasses
Host (references ServiceInterfaces and ServiceImplementations)
Client (references ServiceInterfaces and ModelClasses)
In ServiceInterfaces you have an interface like this (I skipped the namespaces, etc to make the example shorter):
[ServiceContract]
public interface IMyService<T>
{
T GetObject(int id);
}
In ServiceImplementations you have a class that implements IMyService<T>:
public class MyService<T> : IMyService<T>
{
T GetObject(int id)
{
// Create something of type T and return it. Rather difficult
// since you only know the type at runtime.
}
}
In Host you have the correct configuration for your service in an App.config (or Web.config) file and the following code to host your service (given that it is a stand-alone app):
ServiceHost host = new ServiceHost(typeof(MessageManager.MessageManagerService))
host.Open();
And finally in Client you use a ChannelFactory<TChannel> class to define a proxy:
Binding binding = new BasicHttpBinding(); // For the example, could be another binding.
EndpointAddress address = new EndpointAddress("http://localhost:8000/......");
IMyService<string> myService =
ChannelFactory<IMyService<string>>.CreateChannel(binding, address);
string myObject = myService.GetObject(42);
Again, I'm not sure if this works. The trick is to share your service interfaces (in ServiceInterfaces) and domain model objects (in ModelClasses) between the host and the client. In my example I use a string to return from the service method but it could be any data contract type from the ModelClasses project.
You CAN DO that if you use ServiceKnownTypesDiscovery.
For example:
[ServiceKnownType("GetKnownTypes", typeof(ServiceKnownTypesDiscovery))]
public interface ISomeService
{
[OperationContract]
object Request(IRequestBase parameters);
}
where GetKnownTypes could be declared like so:
public static class ServiceKnownTypesDiscovery
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new List<Type>();
foreach (var asmFile in Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, "*.dll"))
{
Assembly asm = Assembly.LoadFrom(asmFile);
types.AddRange(asm.GetTypes().Where(p=> Attribute.IsDefined(p,typeof(DataContractAttribute))));
}
return types;
}
}
In this case everything declared with [DataContract] (as long as they are discoverable on the server AND the client side) can be serialized.
I hope this helped!
Following the previous example, you could declare a DataContract with an object as DataMember. Then you could add an extension method to get and set a generic type on the object data member. You could also make this internal, this way you would be obliged to use the extension methods to get and set the value.
Of course, it only works if you generate the client using svcutil (or Visual Studio) and you reference the assembly containing the data contract and the class with the extensions methods.
Hope this helps...