I have a WCF application that have a bunch of domain entities (mapped by NHibernate) and service contracts. Currently I'm exposing entities directly via service contracts to WCF clients. But this causes me to encounter many limitations of WCF data contracts specially those related to serialization. For example circular graph limitation, KnownTypes etc.
It seems a better way is to use entities just in server side and using DTOs to transfer objects between WCF server and client. Am I right? Is it a must to be?
WCF is a message-based system - it connects clients and servers basically via XML serialized data messages. Therefore, WCF can only send back and forth static data - it's not a "remote procedure call" or "remote object" system where you'd have functionality transferred from cilent to server and back.
Since anything WCF transfers must be XML serializable, it's really just about data - and so yes - WCF is best suited to just send back and forth DTO style data objects.
Related
I am hoping this is a simple question.
I want to create a cluster of services that process dynamic reports that involve any number of several thousand fields. From what I can tell, I can't use a stream as a return type from a reliable actor or service. Are my only options to return serialised byte arrays or to write the results elsewhere and direct clients to query that resource instead, or am I missing something?
Thanks
It depends on the communication stack you use in your services. Services themselves are agnostic to communication protocols. Implementations of services can plug in any communication stack: Web API, WCF, sockets, doesn't matter.
Reliable Actors is a special implementation of a service, and as a service implementation it specifies a communication stack. In that communication stack, request/response payloads have to be DataContract serializable, so no you can't return a stream there.
Otherwise, if you're using WCF to communicate with your services, then you're limited by what WCF can do.
If you're using service remoting (where your service implements IService and you use a ServiceProxy to call methods on it remotely), then no you can't return a stream for a service method. You need to return something that is DataContract serializable.
If you're using Web API in your service, you can grab the HTTP response stream in a controller action method and stream your data back without allocating a byte buffer for it.
Or you can implement your own communicaton protocol and do whatever you want.
I am struggling to understand answer for one question.
.net standard types are first converted to standard messages. This we call Serialization and will be done by one of the WCF serializer.
Those standard messages are converted to stream of bytes . Its called encoding and done by Encoders and which encoder will do that is decided by binding we choose.
My Question is why this serialization is kept in between, Why.net objects are converted to steams of bytes directly by WCF run-time engine and transferred across.
The only thing that connects a client and a server in WCF is the contract and the serialized XML format to exchange messages between the two parties.
WCF is an interoperable messaging service - it cannot rely on anything for the other party. WCF is NOT a ".NET object remoting" system or anything like that. WCF cannot rely on the other side of the communication being a .NET application, so therefore it cannot just exchange .NET objects.
WCF can talk to and serve data for anything - Ruby, Java - whatever. The smallest common denominator for this are serialized XML messages. Therefore, WCF will serialize your messages into a XML format (text or binary) and send them across the wire.
So I've created a series of objects that interact with a piece of hardware over a serial port. There is a thread running monitoring the serial port, and if the state of the hardware changes it updates properties in my objects. I'm using observable collections, and INotifyPropertyChanged.
I've built a UI in WPF and it works great, showing me real time updating when the hardware changes and allows me to send changes to the hardware as well by changing these properties using bindings.
What I'm hoping is that I can run the UI on a different machine than what the hardware is hooked up to without a lot of wiring up of events. Possibly even allow multiple UI's to connect to the same service and interact with this hardware.
So far I understand I'm going to need to create a WCF service. I'm trying to figure out if I'll be able to pass a reference to an object created at the service to the client leaving events intact. So that the UI will really just be bound to a remote object.
Am I moving the right direction with WCF?
Also I see tons of examples for WCF in C#, are there any good practical use examples in VB that might be along the lines of what I'm trying to do?
No, WCF is a message based system - you pass around serialized (text/xml) messages. There's no "object references" that you can pass around.
The client has a proxy, which gives you the ability to "call" the service method. The WCF runtime then captures the parameters to that call, packages them up in a serialized message, and sends that message across the wire.
There is no direct connection between the client and the server - the client can't "reach over" to the service to get a remote object, nor can the service go back to the client to find out who called it or anything like that.
All that you want to send to the service must be part of either the message itself, or the headers that accompany the message.
Those messages must conform to the XML schema standard, which again means: only concrete non-generic types. You can't pass around interfaces, you cannot pass references - only concrete types made up of basic types such a string, int, datetime etc.
Update: maybe you need to check out the publish/subscribe (pub/sub for short) pattern - which you can also build using WCF. This would allow you data collection machine to publish its data on a regular basis or whenver it changes, and any number of subscribers could be notified of those changes.
Check out some of those articles - googling or binging for "WCF pub sub" will definitely turn out quite a few more!
Tom Hollander: Building a Pub/Sub Message Bus with WCF and MSMQ
Pub/sub sample with WCF net.tcp protocol in Silverlight 4
Pub/sub sample using HTTP polling duplex WCF channel in Microsoft Silverlight 3
WCF Router and Publish/Subscribe Sample Implementation
I have WCF Per-Call service which provides data for clients and at the same time is integrated with NServiceBus.
All stateful objects are stored in UnityContainer which is integrated into custom service host.
NServiceBus is configured in service host and uses same container as service instances.
Every client has its own instance context(described by Juval Lowy in his book in chapter about Durable Services).
If I need to send request over bus I just use some kind of dispatcher and wait response using Thread.Sleep().Since services are per-call this is ok afaik.
But I am confused a bit about messages from bus, that service must handle and provide them to clients. For some data like stock quotes I just update some kind of stateful object and and then, when clients invoke GetQuotesData() just provide data from this object.
But there are numerous service messages like new quote added and etc.
At this moment I have an idea to implement something like "Postman daemon" =)) and store this type of messages in instance context. Then client will invoke "GetMail()", receive those messages and parse them. Problem is that NServiceBus messages are "Interface based" and I cant pass them over WCF, so I need to convert them to types derived from some abstract class.
I Don't know what is best way to handle this situation.
Have you considered a "pure" NServiceBus solution for communicating back to clients? NServiceBus already has that "Postman daemon" capability. NServiceBus messages don't have to be interfaces - you can use regular classes as well.
Hope that helps.
I have found myself responsible for carrying on the development of a system which I did not originally design and can't ask the original designers why certain design decisions were taken, as they are no longer here. I am a junior developer on design issues so didn't really know what to ask when I started on the project which was my first SOA / WCF project.
The system has 7 WCF services, will grow to 9, each self-hosted in a seperate console app/windows service. All of them are single instance and single threaded. All services have the same OperationContract: they expose a Register() and Send() method. When client services want to connect to another service, they first call Register(), then if successful they do all the rest of their communication with Send(). We have a DataContract that has an enum MessageType and a Content propety which can contain other DataContract "payloads." What the service does with the message is determined by the enum MessageType...everything comes through the Send() method and then gets routed to a switch statement...I suspect this is unusual
Register() and Send() are actually OneWay and Async...ALL results from services are returned to client services by a WCF CallbackContract. I believe that the reson for using CallbackContracts is to facilitate the Publish-Subscribe model we are using. The problem is not all of our communication fits publish-subscribe and using CallbackContracts means we have to include source details in returned result messages so clients can work out what the returned results were originally for...again clients have a switch statements to work out what to do with messages arriving from services based on the MessageType (and other embedded details).
In terms of topology: the services form "nodes" in a graph. Each service has hardcoded a list of other services it must connect to when it starts, and wont allow client services to "Register" with it until is has made all of the connections it needs. As an example, we have a LoggingService and a DataAccessService. The DataAccessSevice is a client of the LoggingService and so the DataAccess service will attempt to Register with the LoggingService when it starts. Until it can successfully Register the DataAccess service will not allow any clients to Register with it. The result is that when the system is fired up as a whole the services start up in a cascadeing manner. I don't see this as an issue, but is this unusual?
To make matters more complex, one of the systems requirements is that services or "nodes" do not need to be directly registered with one another in order to send messages to one another, but can communicate via indirect links. For example, say we have 3 services A, B and C connected in a chain, A can send a message to C via B...using 2 hops.
I was actually tasked with this and wrote the routing system, it was fun, but the lead left before I could ask why it was really needed. As far as I can see, there is no reason why services cannot just connect direct to the other services they need. Whats more I had to write a reliability system on top of everything as the requirement was to have reliable messaging across nodes in the system, wheras with simple point-to-point links WCF reliabily does the job.
Prior to this project I had only worked on winforms desktop apps for 3 years, do didn't know any better. My suspicions are things are overcomplicated with this project: I guess to summarise, my questions are:
1) Is this idea of a graph topology with messages hopping over indirect links unusual? Why not just connect services directly to the services that they need to access (which in reality is what we do anyway...I dont think we have any messages hopping)?
2) Is exposing just 2 methods in the OperationContract and using the a MessageType enum to determine what the message is for/what to do with it unusual? Shouldnt a WCF service expose lots of methods with specific purposes instead and the client chooses what methods it wants to call?
3) Is doing all communication back to a client via CallbackContracts unusual. Surely sync or asyc request-response is simpler.
4) Is the idea of a service not allowing client services to connect to it (Register) until it has connected to all of its services (to which it is a client) a sound design? I think this is the only design aspect I agree with, I mean the DataAccessService should not accept clients until it has a connection with the logging service.
I have so many WCF questions, more will come in later threads. Thanks in advance.
Well, the whole things seems a bit odd, agreed.
All of them are single instance and
single threaded.
That's definitely going to come back and cause massive performance headaches - guaranteed. I don't understand why anyone would want to write a singleton WCF service to begin with (except for a few edge cases, where it does make sense), and if you do have a singleton WCF service, to get any decent performance, it must be multi-threaded (which is tricky programming, and is why I almost always advise against it).
All services have the same
OperationContract: they expose a
Register() and Send() method.
That's rather odd, too. So anyone calling will first .Register(), and then call .Send() with different parameters several times?? Funny design, really.... The SOA assumption is that you design your services to be the model of a set of functionality you want to expose to the outside world, e.g. your CustomerService might have methods like GetCustomerByID, GetAllCustomersByCountry, etc. methods - depending on what you need.
Having just a single Send() method with parameters which define what is being done seems a bit.... unusual and not very intuitive / clear.
Is this idea of a graph topology with
messages hopping over indirect links
unusual?
Not necessarily. It can make sense to expose just a single interface to the outside world, and then use some internal backend services to do the actual work. .NET 4 will actually introduce a RoutingService in WCF which makes these kind of scenarios easier. I don't think this is a big no-no.
Is doing all communication back to a
client via CallbackContracts unusual.
Yes, unusual, fragile, messy - if you can ever do without it - go for it. If you have mostly simple calls, like GetCustomerByID - make those a standard Request/Response call - the client requests something (by supplying a Customer ID) and gets back a Customer object as a return value. Much much simpler!
If you do have long-running service calls, that might take minutes or more to complete - then you might consider One-Way calls which just deposit a request into a queue, and that request gets handled later on. Typically, here, you can either deposit the answer into a response queue which the client then checks, or you can have two additional service methods which give you the status of a request (is it done yet?) and a second method to retrieve the result(s) of that request.
Hope that helps to get you started !
All services have the same OperationContract: they expose a Register() and Send() method.
Your design seems unusual at some parts specially exposing only two operations. I haven't worked with WCF, we use Java. But based on my understanding the whole purpose of Web Services is to expose Operations that your partners can utilise.
Having only two Operations looks like odd design to me. You generally expose your API using WSDL. In this case the WSDL would add nothing of value to the partners, unless you have lot of documentation. Generally the operation name should be self-explanatory. Right now your system cannot be used by partners without having internal knowledge.
Is doing all communication back to a client via CallbackContracts unusual. Surely sync or asyc request-response is simpler.
Agree with you. Async should only be used for long running processes. Async adds the overhead of correlation.