I've recently seen a WCF service declaring operation contracts with by ref arguments.
I don't know why this design decision was taken (operations are void), but furthermore, I'm not able - from my WCF knowledge - to say if this is a good practice or not. Or if this is not relevant.
What do you think?
However, According to this Microsoft Article a WCF Call behaves exactly like a Remote Procedure Call and ByRef arguments can be used to return data:-
http://msdn.microsoft.com/en-us/library/ms733070.aspx
Refer to the section: Out and Ref Parameters
In most cases, you can use in parameters (ByVal in Visual Basic) and
out and ref parameters (ByRef in Visual Basic). Because both out and
ref parameters indicate that data is returned from an operation, an
operation signature such as the following specifies that a
request/reply operation is required even though the operation
signature returns void.
WCF is not a "remote object call" method or anything - it's pure message-passing. So havnig a "by-ref" parameter might compile, but it's really not going to do anything useful.
On your client, you have a method with parameters which you call. The WCF runtime then intercepts that call, packages up the parameters and any further information needed into a message, serializes that message (into textual or binary XML), and send that message across the wire to the server.
The server then deserializes the messages back into a set of parameters, and the dispatcher component on the server will then instantiate the service class and call the appropriate method on that service class instance with the parameters from the message.
The whole story works backwards for the reply the server sends back.
But again: all you're exchanging between client and server is a serialized message - there's absolutely no point in making a parameter "by ref" - it cannot possibly be a by-ref parameter, in the end. The server and the client are totally separate worlds, totally separate objects and classes - they just look the same on the wire.
So I think whoever wrote that WCF method didn't understand the principles of WCF message passing, but was lured by the way WCF feels - like just a method call. But it's really not just a method call in the end.
i'm with marc_s.
you need to be very careful.
WCF will always assign a new instance of that object, it not just change its contents.
As mars_s already explained wcf is a messaging-framework.
Its nature is to send and receive indipendant messages.
I think a good practice is to always define an in-/ and an out-message.
Your sericve-interface will be easier to understand and maintain.
methods with ref- and out-parameters always tend to be very ugly and harder to understand.
Related
Is it possible to create a "generic" as in "adaptable" routing service, which will NOT have any public methods to call. Instead, you'd be able to call any command, which would then be mapped in the service and will pass it to appropriate end point with simple message transformation where required.
It may be hard to understand and idea might seem a bit crazy (it came from a colleague of mine), but it's clearer if you look at the example:
similar to what's described in this article, only difference is that our service should not have a "SubmitTimeSheet" public method, in fact it should have no public methods to call. We'd have to "intercept" an incoming call on a much lower level before it returns "Method Not Found" error.
Is this at all possible? The reason for this is obvious: possibility of adding new clients without having to change the code. All we'd have to do is to add a new mapping entry in some sort of config file or even database, e.g.
<Client address="newClientAddress" method="DoAnything" transformation="NewClientDoAnything.xslt" endPoint="endPointClientAddress" endPointMethod="endPointClientDoAnything" />
Check out WCF 4 routing - supports content based routing, xpath transforms and much more.
http://blogs.msdn.com/b/routingrules/
They have already done it in Nirvana. But it is very expensive.
This is not possible in WCF unless you define your contract as a very loose, fit-for-all contract which takes a message and returns a message. By doing this, you will los all the goodness (although not huge goodness in WCF) of WCF.
I'm new to WCF, so apologies if I'm missing the boat completely.
It seems like WCF provides plenty of functionality for using the "Channel" layer by itself. For example, to create a server, you can create a channel listener from a binding and call WaitForRequest, Reply, etc. These methods all deal with Message objects, so it is up to you to do something with the message.
My question has to do with what happens once we've already got a message. Suppose I have an object that implements a service, described by a ServiceContract, and a Message object which I know represents a call to a particular operation. What I'd really like to do is something like:
Message requestMessage = GetMessageSomehow();
OperationDescription oc = GetContractForMessage();
Message replyMessage = Invoke(myService, oc, requestMessage);
At the very least, if I could somehow access the IOperationInvoker and IDispatchMessageFormatter objects that get created for a type, it would be pretty simple to chain them together to get the functionality I'm looking for.
In my particular case, I need to implement some simple Soap 1.1 and 1.2 services (with no WS-Addressing). I already have HttpListenerRequest/Response objects, and can route based off of either the SOAPAction or ContentType header.
I think having this functionality would also be pretty useful for unit testing. For example, I need to implement to existing clients. It would be nice to have unit tests where I could test that the Attributes on the service class are correct (i.e. that the message that I know I will be getting gets properly translated into a call on my service interface).
Any suggestions?
Serialization/Deserialization from that Message instance to actual parameters for a call is usually done by an IDispatchMessageFormatter / IClientMessageFormatter.
On the server side, an IDispatchMessageFormatter is injected into the DispatchRuntime by a custom operation behavior that the data contract serializer (or other serializer) inserts.
But... if you're not using ServiceHost, there's no DispatchRuntime. Basically, if you want all of this, you're going to have to do all the hard work yourself :)
That said, if you can get an OperationDescription object, you should be able to instantiate a DataContractSerializerOperationBehavior, but you won't be able to get an IDispatchMessageFormatter out of it... you can get an XmlObjectSerializer, though, which might, or might not, be useful for you.
Notice that an IOperationInvoker wouldn't help all that much, since that presumes you've already done message serialization/deserialization, so it's not really all that useful (and the rest of the functionality is fairly simple for basic use cases if you want to roll it yourself)
I have an idea, but I need help implementing it.
WCF does not support delegates in its contracts.
Instead it has a cumbersome callback contracts mechanism, and I'm looking for a way to overcome this limitation.
I thought about using a IDataContractSurrogate to replace each delegate in the contract with a token that will be serialized to the remote endpoint. There, the token will be deserialized into a generated delegate. This generated delegate will send a generic callback message which encapsulates all the arguments (that the delegate was invoked with).
The generic callback message will reach the first endpoint, and there the original delegate would be invoked with the arguments.
Here is the purposed (simplified) sequence:
A calls B-proxy.Foo(callback)
callback is serialized through a DelegateSurrogate.
The DelegateSurrogate stores the delegate in a dedicated delegate storage and replaces it with a token
The message arrives to B's endpoint
the token is deserialized through a DelegateSurrogate
The DelegateSurrogate constructs a generated delegate
B.Foo(generatedCallback) is invoked
Later, B is invoking generatedCallback(args)
generatedCallback(args) calls a dedicated generic contract on A's endpoint: CallbackContract-proxy.GenericCallback(args)
CallbackContract.GenericCallback(args) is invoked on A's endpoint
The original callback is retrieved from the storage and is invoked: callback(args)
I have already implemented this previously using service bus (NServiceBus), but I want to adapt the idea to WCF and I'm having hard time. I know how to implement steps 3,6,9 and 11. I don't know yet how to wire everything in WCF - especially the surrogate part.
That's it - I hope my question made sense, and that the collective wisdom here will be able to help me build this up.
Here's a sample usage for my desired solution:
// client side
remoteSvc.GetEmployeeById(17, emp =>
{
employees.Add(emp);
logger.log("Result received");
});
// server side
public void GetEmployeeById(int id, Action<Employee> callback)
{
var emp = getEmpFromDb(id);
callback(emp);
}
Actually, in this scenario I would look into the Expression API. Unlike a delegate, an Expression can be deconstructed at runtime. You can't serialize them by default, but a lot of work has been done in that space. It is also a bit like what a lot of LINQ providers do in the background, for example WCF Data Services.
Of course, another approach is simply to use a lambda expression as the hook for RPC, which is what I describe here. The code that implements this is freely available in the protobuf-net tree. You could customize this by using an attribute to associate your token with the method, and obtain the attribute from the MethodInfo.
IMO, the problem with delegates is that they are too tightly coupled to the implementation, so you can't have different implementations at each end (which is a common requirement).
Expressions have the advantage that lambdas still support intellisense etc, so you can do things like:
client.Invoke(svc => svc.Foo(123, "abc"));
and from that obtain Foo (the MethodInfo), 123 and "abc" separately, including captured variables, ref/out, etc. It all works.
I'm looking to use the MsmqIntegrationBinding to integrate with a legacy queue which has a serialized object as the message body. Has anyone come up with a way to obtain the "metadata" of the message body and create a service side class to use within the service?
For example, if I put in a serialized Product object from System A and my service needs to consume it, how do I provide MsmqMessage the type if I do not have the Product class on my side? I was thinking of reading off a message in a separate program, deserializing, and then emitting via the code dom. Ideas?
I wholeheartedly recommend against attempting to emit the deserialized type at runtime in the message destination. Either work with the XML at the destination to obtain the data you desire, or build data contracts that both the source and destination can adhere to.
Hmm... in WCF, you can define service methods which take (and optionally return) an untyped Message type. This seems to fit your bill quite nicely.
Other than with strongly typed messages, you'll have to do all the putting together of the message on the client and the taking apart on the server by means of reading the raw XML - but that seems to be what you're looking for, right?
Find more information and samples here:
WCF - Handling Generic Messages
How to pass a generic object through WCF
Untyped messages on WCF
Untyped messages have some restrictions, e.g. you can only read them once on the server, but you should be able to manage your scenario with this, I think.
Marc
I'm developing a WCF service and if there is an error I want to serialize the incoming parameter from the original method that was called on the service. I am using IErrorHandler to catch all exceptions.
My initial thoughts were that I will store the serialized parameter in OperationContext.IncomingMessageProperties so that I can access it from the HandleError method. However, as this isn't run on the original thread I believe the OperationContext will be null, so I am considering accessing it from the ProvideFault method.
Does this seem feasible? And will it work with OneWay service calls?
Not sure I can really help you much here, but let me try:
on your client, your code basically calls a method and passes it parameters. The WCF stack on the client side then converts that into a SOAP message (typically with an XML body, but could be binary, too) with headers and all and then sends that message across the wire to the server to be processed.
The server then attempts to deserialize that message into an object and attempts to call a message on a server implementation object. That method on the server object will most likely have the same parameters again, as the client - however, there's a possibility that the call will fail before that method even gets called.
So what I'm trying to say is: you can't rely on the fact that your server-side method with its parameters really gets called - there might have been a problem with e.g. authentication, the message format, a missing header or something else, that causes the server side to fail and throw an exception even before the server-side method ever gets called.
In the end, in the IErrorHandler, there's no way I would know of to get a hold of the message and/or the method and its parameters - all you can get are the error that occured on the server, and you can use that to turn it into a SOAP fault.
What you could do - both on the client and the server side - is create a new behavior that plugs into the WCF stack, and that records the methods being called and the parameters being passed into them - by implementing a class that implements the IParameterInspector interface of WCF. But that only will get called if the message on the client and the server will get properly deserialized and the server-side method really gets called.
Check out some of these links for more info on WCF extensibility:
How to: Inspect or Modify Parameters
WCF Extensibility: Parameter Inspectors
IParameterInspector in WCF
Extending WCF with custom behaviors
Hope this helps a bit!
Marc