I'm developing a service oriented architecture for an application and I would like the services to be exposed both over WCF as well as usable through a simple library. Ideally I would like to reduce duplicated code.
Conceptually, this maps to:
Client => WCF Service => Service Library (actual implementation)
or
Client => Service Library (actual implementation)
based on where the client is located (local or remote).
Here's a simple example:
[ServiceContract]
public interface ICalculator
{
[OperationContract]
int Add(int a, int b);
}
public class Calculator : ICalculator
{
public int Add(int a, int b)
{
return a + b;
}
}
public class CalculatorFactory
{
public static ICalculator CreateCalculator()
{
return new Calculator();
}
}
And my client application did the following
int result = CalculatorFactory.CreateCalculator().Add(1,2);
or
int result = IChannelFactory<ICalculator>().CreateChannel().Add(1,2);
depending on if it were local or remote.
Is it a bad practice to call into WCF annotated code directly (i.e., without using WCF)?
Additional comments:
I realize that I could use WCF in all cases and just host the service using NamedPipes for local connections. I would like to avoid this if I can for simplicity sake.
The alternative to the above is to essentially duplicate the ICalculator interface in the service library and change the WCF service implementation to contain CalculatorFactory.CreateCalculator().Add(1,2). This seems like a lot of overhead given that I want the interface to be the same.
You can create and consume WCF annotated classes localy without any problems unless you start to use some WCF related features like OperationContext etc.
Generally this is useually abstracted in different way:
Client => ServiceAgent => Business Service
or
Client => ServiceAgent => WCF Service => Business service
The client itself doesn't know if the service is local all remote. The service agent is client side component which based on its implementation either creates local service instance or callse remote WCF service which in turn creates business service instance. ServiceAgent can be injected as dependency into client which will make your application pretty good configurable. Also you can expose different interface on the service agent (the same as business service implements) and if you want WCF service and proxy can use different one.
If you decite to use WCF service all the time including local calls don't use NamedPipes. NamedPipes are for inter process communication on the same machince. If you want to use communication in the same process use NullTransport or Local Channel instead. It still has worse performance then direct call.
Related
One guy explained this way but not very clear to how to implement it.
From experience:
Using different binding, for example one BasicHttpBinding for Java clients while using WsHttpBinding for .NET clients. Also HTTPS for some and HTTP for others...
Dividing and exposing different contracts/interfaces. For example you have one interface that exposes many operations and you have a cut down interface which does basic things and you publish the second to outside so internal clients use the endpoint for extended interface but external clients use the other one.
For example
interface IFoo
{
void DoBasic();
}
interface IFooInternal : IFoo
{
void DoMore();
}
Now you have One class implementing both:
public class Foo : IFooInternal
{
....
}
And now you expose only one to outside while implementation is in the same class.
the things which i do not understand how to design my service contract in such a way that few operation i will expose to other client and extended feature i will expose to internal client. so if possible just make me understand giving me a small program & code that how it can be possible through multiple endpoints in WCF service. thanks
So is it that you shouldn't or can't use Interfaces in methods you are exposing or in the DTOs you are exposing to the client in a WCF service? Because if I have this for example:
public class MyCustomDTO
{
public ITransaction Transaction { get; set; }
}
or
IPaymentRequest SendTransaction(PreAuthorizeRequest request);
I notice that when I try to create integration tests to prove that the wsdl can be used and make successful calls, my ITransaction and IPaymentRequest are serialized and exposed through the service client as "object" probably because it doesn't know what kind of object to expose in the contract right?
so is it you can't create methods or DTOs with Interfaces in them as part of the contract you are exposing to the outside world that consumes your WCF service?
If you are using WCF to connect two .NET instances and you share your contracts as a common contract assembly between the two instead of using the auto-generated client from the wsdl, then it works. However, WCF is about interoperability and you may want to add a non-.NET client down the road so you should only use actual types so your service will work well with all the other languages out there.
I'm in the process of writing a duplex WCF service using NetTcpBinding, and I've run into an architecture question that I think I know the answer to, but hope that I'm wrong.
Our service is stateful, and we've selected NetTcpBinding with PerSession InstanceContextMode. For various reasons, this is something that we require. I'm trying to break up our larger interface (where large blocks of the operations would not apply to many clients) into multiple smaller interfaces with the operations logically grouped. While it's simple enough to have a single service implementation implement all of the contracts, I'm not sure if it's possible to have multiple service contracts share a single channel (or, more to my requirement, a single session), and I'd definitely need to be able to do that in order to make this work.
I could, of course, include everything on one contract and throw FaultExceptions when an invalid operation is performed, but I'd really like to be able to break these up and not even add an endpoint for inapplicable contracts. Is what I'm looking for possible?
TL;DR Version:
I need to be able to do this:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
void Foo();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
void Bar();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IServiceA, IServiceB
{
...
}
And be able to establish one session from the client to the service but use both IServiceA and IServiceB.
The default instance provider over a sessionful channel will give you an instance per connection in your case. You can however extend the instance provider to pick up an existing object from your own cache and return the same object.
How you correlate instances will be upto you using some special message header etc. The underlying channel/Connection will be different for each proxy and also use differnt buffers / concurrency models but you can allow service model to use the same instance.
http://msdn.microsoft.com/en-us/magazine/cc163590.aspx
Imagine I have the following, standard WCF, code :
[ServiceContract]
interface ICustomerService {
[OperationContract]
Customer GetCustomer();
}
public ICustomerService {
public Customer GetCustomer()
{
return MyStore.WhatIsNeeded();
}
}
This is working well and allows me to distribute the service and the consuming code.
Is it possible (and is it a good idea) to completely bypass the WCF engine if working in a single box ?
In fact, I want the app to be able to run on farm servers, or on small single box servers.
To reduce WCF messaging cost, I'd like to have something like :
ICustomerService service = null;
if(singlebox)
{
service = new CustomerService(); // Direct instanciation of the service class. No WCF here ...
}
else
{
service = new CustomerServiceClient(); // Wcf client
}
var cust = service.GetCustomer();
If wrapped properly, can this technique reduce server charge ?
That won't work because the client will be attempting to access an endpoint for a service that no longer is exposing one. The WCF plumbing is required for the both the service and the client. For single box scenarios, look at the NetNamedPipeBinding which is the WCF plumbing done through the equivalent of shared memory.
This will surely reduce the overhead of WCF runtime. I'd create a factory class which will check if(singlebox) and new up the right implementation of ICustomerService.
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.