Reputation: 1962
I'm trying learn and use WCF but I'm confused on whether or not it is possible to pass parameters by reference. I struggled for a while trying to call an operation contract from my client that was passing a parameter by reference (it would timeout every time, even with both the service and client on my local machine). However the test client that Visual Studio provides could invoke the operation contract without problem (even with the reference parameter). My client succeeds when calling operation contracts that only contain value parameters however.
I came across this article on MSDN but I must not be understanding it correctly because it seems to contradict itself (at least that's how I interpreted it): http://msdn.microsoft.com/en-us/library/ms733070(v=vs.100).aspx
under the heading "Parameters and Return Values" it states:
Each operation has a return value and a parameter, even if these are void. However, unlike a local method, in which you can pass references to objects from one object to another, service operations do not pass references to objects. Instead, they pass copies of the objects.
Yet further down under the heading "Out and Ref Parameters" it states:
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.
I'm using netTcpBinding with a .net client and (at least at this point) just trying to pass by reference a string. What am I missing? Is this possible?
UPDATE: It seems that if my operation contracts do not return a type (void/sub in c#/vb) then I can successfully pass parameters by reference (even multiple parameters). I'm guessing this is how it is designed as the reference parameters take the place of the return value in a request/reply operation.
Upvotes: 1
Views: 6248
Reputation:
It's not possible without creating copies.
If you want a client to directly manipulate an object in the server or vice versa use .NET Remoting This generally works irrespective of whether:
Refer to MarshalByRefObject . Unlike WCF, Remoting creates proxies behind the scenes that hides all the messaging.
.NET Remoting is still useful because one must use it to communicate with objects in different AppDomains.
Upvotes: 0
Reputation: 558
Yes. You are right. Reference parameters are passed by value like the documentation says. They make copies of them. And you are right, the model used is Request\Reply. The reason being that the reference is really an address at the end of the day correct? Therefore the address on one machine is not going to get you the same result on another machine (see my point?). The way the data gets sent and received is different. I would like to encourage you to take a look at the proxy class that gets created when you add the service reference. The name of this file is usually Reference.cs and you can double click your reference and get through your Object Browser to it.
Let's say your contract method is int GetMyData(ref string modifyMe);
If you look at the ServiceClient class (assume your service is called Service) you will see that the GetMyDataRequest object has one member of type string and the GetMyDataResponse object that gets returned has two members of type integer and string. This is what happens in the wrapper method inside your ServiceClient class
C#:
public int GetMyData(ref string value) {
WCFServiceClientApp.ServiceReference1.GetMyDataRequest inValue = new WCFServiceClientApp.ServiceReference1.GetMyDataRequest();
inValue.value = value;
WCFServiceClientApp.ServiceReference1.GetMyDataResponse retVal = ((WCFServiceClientApp.ServiceReference1.IService1)(this)).GetMyData(inValue);
value = retVal.value;
return retVal.GetMyDataResult;
}
VB:
Public Function GetMyData(ByRef value As String) As Integer
Dim inValue As ServiceReference1.GetMyDataRequest = New ServiceReference1.GetMyDataRequest()
inValue.value = value
Dim retVal As ServiceReference1.GetMyDataResponse = CType(Me,ServiceReference1.IService1).GetMyData(inValue)
value = retVal.value
Return retVal.GetMyDataResult
End Function
So for you as the client, your string is being passed by reference, but under the hood, the modified value gets assigned back to the string variable you passed in. Hope this helps.
Upvotes: 3
Reputation: 4292
It is possible to use by ref parameter but keep in mind
In addition, using out or ref parameters requires that the operation have an underlying response message to carry back the modified object. If your operation is a one-way operation, an InvalidOperationException exception is thrown at runtime.
Upvotes: 0