Introduction
One option in WCF I find very valuable is the ability to share types between the service and the client proxy. The /reference option of the SvcUtil allows the generated client proxy to reuse some types defined in a shared assembly.
Background
When a client proxy for a web service is generated, a definition for all complex types is generated as well. This creates two problems:
- If you use the same type in more than one service, the generated client code may have multiple definitions for the same type
- Any useful properties, constructors and collections used in the server type definition are lost
While the second problem is simply an annoyance, the first one may create a lot of headaches.
Let's assume the SharedType
class is defined in the code used by the service like this:
[DataContract(Namespace = "http://mycode.com/types")]
public class SharedType
{
private string name;
[DataMember]
public string Name
{
get { return name; }
set
{
if (value == null || value.Length < 3)
throw new ApplicationException();
name = value;
}
}
[DataMember(Name = "Attributes")]
private List<string> attributes = new List<string>();
public ICollection<string> Attributes
{
get { return attributes; }
}
public SharedType()
{
}
public SharedType(string name)
{
this.Name = name;
}
}
If the client proxy is generated without reference to the assembly with the data types, the SharedType
class is generated like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute
(Namespace="http://mycode.com/types")]
public partial class SharedType : object,
System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject
extensionDataField;
private string[] AttributesField;
private string NameField;
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get { return this.extensionDataField; }
set { this.extensionDataField = value; }
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string[] Attributes
{
get { return this.AttributesField; }
set { this.AttributesField = value; }
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string Name
{
get { return this.NameField; }
set { this.NameField = value; }
}
}
It is easy to notice that this type does not have the constructor with argument name
and the Attributes
property is implemented as Array
instead of List
.
To generate client proxy that refers to the original type use the following options of the ServiceModel
Metadata Utility Tool (Svcutil.exe):
"c:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\SvcUtil"
/l:cs
/out:SharedTypeService.cs
/config:..\App.config
/n:*,MyClient.Proxy
<b>/r:..\..\MyTypes\bin\MyTypes.dll</b>
http://localhost/MyService/SharedTypeService.svc?wsdl
Now the client proxy refers to the assembly with the data contracts and the client may take advantage of all accessors and useful methods coded in it.
Using the code
The code is a sample that demonstrates how a client proxy can be generated by referring to the data contracts used in the service.
History
References