Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

The CLR team takes a look inside the System.Globalization namespace to explain how to handle data formats for proper localization and globalization.

Melitta Andersen

MSDN Magazine November 2008

...

Read more!

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

With Windows Presentation Foundation (WPF) you can lay out text on a path, then animate the individual points defining the path and watch the characters bounce around in response.

Charles Petzold

MSDN Magazine December 2008

...

Read more!

Ken Getz shows how the CollectionChanged event lets you reflect changes to your underlying data source in your bound data controls.

Ken Getz

MSDN Magazine December 2008

...

Read more!

Here we describe some of the more common challenges to concurrent programming and present advice for coping with them in your software.

Joe Duffy

MSDN Magazine October 2008

...

Read more!

Also by this Author

The next version of COM+, COM+ 1.5, offers many improvements over COM+ 1.0. A comprehensive user interface that displays more data for each application as well as complete support for legacy components make the management of existing applications easier and more efficient. Enhanced queueing support provides more flexibility for managing queued calls, and pooling and recycling means better application lifetime management. Application partitioning in COM+ 1.5 surpasses that offered in COM+ 1.0, and transaction isolation can be configured for safer ...

Read more!

This month Juval Lowy tackles questions such as when to keep proxies and services in memory for better state management in long-running workflows.

Juval Lowy

MSDN Magazine October 2008

...

Read more!

The .NET Framework 2.0 provides custom credentials management to ASP.NET apps out of the box. Using it, you can easily authenticate users without using Windows accounts. In this article the author presents a set of helper classes that let a Windows Forms application use the ASP.NET credentials management infrastructure as easily as if it were an ASP.NET application.

Juval Lowy

MSDN Magazine April 2005

...

Read more!

With queued calls in Windows Communication Foundation you can perform work in a disconnected manner by sending messages through Microsoft Message Queuing. Juval Lowy explains.

Juval Lowy

MSDN Magazine February 2007

...

Read more!

While .NET offers adequate support for the simple serialization cases, issues arise when you're attempting to support delegates and subscribers, versioning, and class hierarchies. . In addition, the introduction of generics in The .NET Framework breaks new ground in the complexity of the serialization task and the power of serialization tools. This article discusses these issues and related pitfalls, suggests techniques and workarounds that address them, and recommends when and how to best use the new serialization abilities.

Juval Lowy

Read more!

Popular Articles

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

Ray Djajadinata

MSDN Magazine May 2007

...

Read more!

When incorporating the ASP.NET DataGrid control into your Web apps, common operations such as paging, sorting, editing, and deleting data require more effort than you might like to expend. But all that is about to change. The GridView control--the successor to the DataGrid-- extends the DataGrid's functionality it in a number of ways. First, it fully supports data source components and can automatically handle data operations, such as paging, sorting, and editing, as long as its bound data source object supports these capabilities. In addition, ...

Read more!

Chris Tavares explains how the ASP.NET MVC Framework's Model View Controller pattern helps you build flexible, easily tested Web applications.

Chris Tavares

MSDN Magazine March 2008

...

Read more!

Jeff Prosise explains when it's better to use UpdatePanel and when it's better to use asynchronous calls to WebMethods or page methods instead.

Jeff Prosise

MSDN Magazine June 2007

...

Read more!

Our Blog

Silverlight provides a browser interoperability layer that allows managed code to access the document object model (DOM) of the underlying page. At the same time, JavaScript code running in the page can access the XAML content of the plug-in and even make modifications.

In the November 2008 issue of MSDN Magazine, Dino Esposito discusses the ...

Read more!

We're currently in the process of stepping back and taking a critical look at our Web site to see how you all are using it - and how we can redesign parts of it (big or small) to make that experience better.  We are continuously receiving your feedback on existing frustrations and we are working hard to remedy those (as a general fyi, most of the frustrations have to do with navigation).  However, in order to get a sense of whether we need to look at some of the more fundamental ...

Read more!

It’s helpful to think about secure design from a more holistic perspective by using threat models to drive your security engineering process.

In the November 2008 issue of MSDN Magazine, Michael Howard proposes using the threat model to help drive other SDL security requirements, primarily code review priority, fuzz testing priority, ...

Read more!

Choosing the best alternative is a common task in software development and testing. A group of beta users may need to choose the best user interface from a set of prototypes. Or imagine the members of an open source project voting for a policy.

In the November 2008 issue of MSDN Magazine, Dr. James McCaffrey describes five of the ...

Read more!

Windows Workflow Foundation (WF) imposes some restrictions on the developer authoring programs that target it. But in return WF offers a powerful, flexible, and extensible set of runtime services such as support for long-running code.

In the December 2008 issue of MSDN Magazine, Josh Lane provides some best practices to consider ...

Read more!

Foundations
What's New for WCF in Visual Studio 2008
Juval Lowy

Code download available at: Foundations2008_02.exe (329 KB)
Browse the Code Online
Visual Studio® 2008 and the underlying Microsoft® .NET Framework 3.5 offer new tools and support for Windows® Communication Foundation (WCF). They don't change the basic capabilities of WCF 1.0 (released with the .NET Framework 3.0); rather, they extend and complete it.
Visual Studio 2008 automates manual WCF tasks, which includes updating proxy references, and eliminates repetitive tasks such as creating simple host projects. Visual Studio also addresses some tough problems such as cross-targeting and data contract type sharing. In this column I'll walk through the new features, point out their advantages, and explain any pitfalls and workarounds. Although I'll use C# project settings here, everything applies to Visual Basic® as well unless I state otherwise.

.NET Framework Cross-Targeting
Previous Visual Studio releases always targeted the version of the .NET Framework they shipped with. For example, Visual Studio 2005 can only generate assemblies that target the .NET Framework 2.0. This practice did not reflect the reality most developers face. Typically, developers need to maintain old versions of their applications written for previous versions of .NET while at the same time using the new version of Visual Studio on the application's next version.
Moreover, this practice meant that developers who were maintaining applications written for previous .NET Framework versions could not benefit from productivity enhancements, such as the code refactoring support introduced in Visual Studio 2005.
The problem was that there was no cross-targeting of .NET Framework versions. You either had to have multiple versions of Visual Studio installed or compensate with separate testing and deployment builds. Visual Studio 2008 tries to address this by providing adequate (albeit imperfect) support for targeting multiple versions of the .NET Framework. Since the .NET Framework 3.0 and the .NET Framework 3.5 actually use the same CLR version as the .NET Framework 2.0, and the only differences are in new referenced assemblies, Visual Studio can still target the same runtime yet provide cross-targeting for the .NET Framework versions 2.0, 3.0, and 3.5 (where the .NET Framework version number corresponds to release numbers, not runtime versions—that is still the CLR 2.0).
In Visual Studio 2008, the Application pane of the project Properties contains a new combobox called Target Framework that allows you to target the .NET Framework versions 2.0, 3.0, and 3.5 (see Figure 1).
Figure 1 Target Framework Property in Visual Studio 2008 (Click the image for a larger view)
The Target Framework value is only in effect at development time; it has no effect at run time (your assembly still targets the .NET 2.0 CLR). The value you choose represents the oldest version of the .NET Framework your assembly can be built against. New projects are configured by default to target .NET Framework 3.5. It gets a bit more complicated when adding references; if you downgrade the Target Framework version while referencing higher-version assemblies, Visual Studio 2008 will prompt you, fault the reference, and fail the build. Visual Studio 2008 will not allow you to add a reference to a .NET Framework assembly that requires a higher version of the Framework than your project. If you add a reference to another project in the same solution that is of a higher version, Visual Studio 2008 will alert you as to the possible conflict. If you add a reference by browsing to an assembly, Visual Studio 2008 will not intervene to stop you.
With respect to languages and cross-targeting, note that in C# (but not Visual Basic), you can restrict use of features such as anonymous types and extension methods in a .NET Framework 2.0 or 3.0 project by restricting the compiler version. You can do this by going to the Build pane, clicking the Advanced button, and selecting ISO-2 (C# 2.0) for the language version (instead of the default, which has not been standardized as of yet).
When opening a Visual Studio 2005 WCF project in Visual Studio 2008, the upgrade process will keep the framework version at 2.0. While this will actually work (remember, the underlying runtime version is unchanged), I recommend manually setting it to version 3.0 or 3.5, as required.
The Target Framework version matters the most when taking advantage of new project templates. WCF workflow and syndication projects must be built targeting the .NET Framework 3.5; the Service Library project requires targeting the .NET Framework 3.0 or 3.5. The Add Service Reference feature (described later in this column) is only available when selecting Framework version 3.0 or 3.5 for the project.

WCF-Provided Host
Visual Studio 2008 ships with a ready-made, general-purpose service host called WcfSvcHost.exe. It's found under C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE. For ease of use, I recommend adding that location to the system's Path variable. WcfSvcHost is a simple command-line utility, accepting two parameters: the file path to a .NET assembly containing the service class or classes, and a file path to the host .config file. For example:
WcfSvcHost.exe /service:MyService.dll  /config:App.config
The specified service assembly can be a class library assembly (DLL) or an application assembly (EXE). WcfSvcHost will launch a new process that will automatically host all the service classes listed in the services section of the specified .config file. Note that these service classes, along with their service contracts and data contracts, need not be public types—they can be internal. In addition, auto-hosted services need not provide any metadata, but they can publish metadata if they choose to.
WcfSvcHost is a Windows Forms application that resides as a desktop tray icon. To close the host, simply select Exit from the tray icon context menu. Terminating the host this way is an ungraceful exit—WcfSvcHost will abort all calls currently in progress, and clients are likely to receive an exception. If you click on the WcfSvcHost tray icon, it will bring up a dialog listing all the hosted services (see Figure 2).
Figure 2 WcfSvcHost Services List  (Click the image for a larger view)
The dialog also shows the status of the service and its metadata address, which you can copy to the clipboard, perhaps for use later when adding a reference to the service. Closing the WcfSvcHost UI merely collapses it back to the tray.
WcfSvcHost is designed to eliminate the need during development for a separate host assembly to accompany your service library. Developing such host projects is a repetitive task; these hosts typically contain the same lines of code over and over again, and they tend to bloat the solution when you have multiple service libraries. For development and testing purposes, you can integrate WcfSvcHost directly into your Visual Studio 2008 service library projects. In the Debug pane of the project properties, specify WcfSvcHost.exe as the external program to start, and then specify your class library name and its .config file (the one auto-generated and auto-copied to the bin folder) as arguments.
With that done, when you run the class library (something you could not do before), it will be automatically hosted by WcfSvcHost with the debugger attached to that process. When you stop debugging, Visual Studio 2008 will abort the host ungracefully.
You can even use WcfSvcHost in your .NET Framework 3.0 applications and with Visual Studio 2005 projects, since all WcfSvcHost requires is the .NET Framework 3.0. Simply copy WcfSvcHost from a machine where Visual Studio 2008 is installed. To make things easier, I recommend adding WcfSvcHost to the Global Assembly Cache (GAC) on your .NET Framework 3.0 machine.
The last feature of WcfSvcHost is its ability to automatically launch a client application and even provide the client with optional parameters specific for that application:
WcfSvcHost.exe /service:MyService.dll  /config:App.config                  
               /client:MyClient.exe    /clientArgs:123,ABC
This is useful in automated testing and even simple deployment scenarios to launch both the host and the client.
The biggest drawback of WcfSvcHost is that it is only suitable for simple scenarios where you do not require programmatic access to the host instance before opening it or programmatic access to its event model once opened. Unlike hosting with IIS or the Windows Activation Service (WAS), there is no equivalent service host factory support. Consequently, there is no ability to dynamically add base addresses, configure endpoints, throttle calls, configure custom behaviors at the host level, and so on. My experience with WCF is that in all but the simplest cases, eventually you will need programmatic access to the host instance, so I do not view WcfSvcHost as a full-fledged production-worthy host, as I do the WAS or a dedicated self host.

WCF-Provided Test Client
In addition to the service host, Visual Studio 2008 ships with a simple, general-purpose test client for rudimentary testing that you can use to invoke operations on most services. The test client, WcfTestClient.exe, is found after normal installation at C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE. You must provide WcfTestClient with a single command-line argument containing the metadata address of the service to test:
WcfTestClient.exe http://localhost:9000/
You can specify any metadata address, such as HTTP-GET, or metadata endpoint over HTTP, TCP, or IPC (named pipes). You can also specify multiple metadata addresses:
WcfTestClient.exe http://localhost:8000/ net.tcp://localhost:9000/MEX
WcfTestClient is a Windows Forms 3.5 application (see Figure 3). In this figure, the tree control on the left contains the tested services and their endpoints. You can drill into an endpoint's contract and select an operation. The information specific to that invocation will be displayed in a tab on the right pane. An example is the simple contract and implementation in Figure 4.
[ServiceContract]
interface IMyContract
{
   [OperationContract]
   string MyMethod(int someNumber,string someText);
}
class MyService : IMyContract
{
   public string MyMethod(int someNumber,string someText)
   {
      return "Hello";
   }
}
Figure 3 Using WcfTestClient (Click the image for a larger view)
The method tab will let you provide an integer and a string as operation parameters in the Request section, as in Figure 3. When you click the Invoke button, it will dispatch the call to the service and display the returned value or out-parameters in the Response. If the operation is one-way, WcfTestClient will notify you in a message box upon the operation's successful dispatch. In case of an exception, WcfTestClient will display the exception information in a message box and let you issue additional calls.
WcfTestClient does not maintain a transport-level session (or any other session) with the tested service. All calls are made on new proxy instances. In addition, all calls are made asynchronously so that the UI is kept responsive. However, while the calls are asynchronous, WcfTestClient will only let you dispatch one call at a time.
WcfTestClient functions by silently creating an assembly from a proxy file, complete with a .config file, and then loading it from a temporary location. If you click on the Config File item in the tree, you can actually grab that .config file (the same one generated when adding a service reference), and you can display it in its own tab.
Unlike the old Visual Studio ASMX Web services test page, WcfTestClient allows you to invoke operations with enumerations, composite parameters such as classes or structures (each being a composite of other classes or structures), and even collections and arrays of parameters. Simply expand the items in the Request section, set their values from dropdown lists (such as enum values), and invoke the call. If the operation accepts a collection or an array, you will also need to set the length. For example, for the following operation, Figure 5 shows the resulting request and response:
Figure 5 Specifying an Array Length and Values (Click the image for a larger view)
[OperationContract]
bool ProcessNumbers(int[] numbers]
Much the same way, the Response pane will contain any returned composite value or out parameters. This brings us to a drawback of WcfTestClient, which is that in order to specify different services to test, you have to shut it down, change the command-line arguments, and relaunch it. It would have been better had it been possible to provide the service addresses in the GUI as well.
You can integrate WcfTestClient directly into your Visual Studio 2008 solution. First, add a class library project to the solution and delete all references, folders, and source files, as you have no need for them. Next, set WcfTestClient.exe as the external start program and provide the metadata address (or addresses) of the tested service (or services), such as the .svc address of an IIS or WAS hosted project, or, for that matter, any other metadata address of a host project, inside or outside your solution.
Note that you cannot use WcfTestClient on machines with only .NET Framework 3.0, since it makes use of an internal .NET Framework 3.5 tree grid control (the one used to represent composite parameters).
Of course, you can combine both WcfTestClient and WcfSvcHost in a single step to automatically host a service in a service library and test it:
WcfSvcHost.exe /service:MyService.dll    /config:App.config 
               /client:WcfTestClient.exe 
               /clientArgs:http://localhost:9000/
However, with WcfSvcHost, specifying the metadata arguments is optional. By default WcfSvcHost will pipe in to the specified client application the metadata addresses it found in the service .config file. You should specify the metadata address explicitly only if the service or services do not provide their own metadata or if you would like the test client to use different addresses. Also, if the service .config file contains multiple metadata endpoints for a given service, they will be provided in this order of precedence: HTTP, TCP, IPC, HTTP-GET. You can incorporate these steps in Visual Studio 2008 for a seamless hosting and testing experience. Specify WcfSvcHost.exe as the start-up program along with the .config file and WcfTestClient.exe as the client.

WCF Service Libraries
As a function of the Target Framework, Visual Studio 2008 offers several new WCF project templates. The New Project dialog offers a combobox that lets you specify the Target Framework version (2.0, 3.0, or 3.5), as shown in Figure 6.
Figure 6 WCF Project Templates (Click the image for a larger view)
If you select Framework 2.0, then no new templates are available. With Framework 3.0 there is a new project template called the WCF Service Library. This project type is merely the pre-built usage of WcfSvcHost and WcfTestClient, and it is very similar to the technique that I mentioned previously (combining the two). Note that with the WCF Service Library template there is no need to specify WcfSvcHost.exe as the start-up program or the .config file because the project file contains a new ProjectTypeGuids element for a WCF service library.
An unfortunate side effect of the template is that stopping the debugger does not terminate the test client; over time, your desktop becomes littered with orphaned clients. To fix this, simply revert to the manual explicit steps described earlier.
The WCF Service Library also provides a simple template for a service contract, its implementation, and the matching .config file.
The Syndication Service Library allows you to implement an RSS feed over a WCF endpoint, and it starts you off with a simple service contract that returns a feed, its implementation, and a matching .config file. You can host and expose your feed like any other service. The syndicated endpoints make use of the new WebHttpBinding binding. This new binding is designed to receive Web requests and cannot be used for normal service invocations.
The Sequential Workflow Service Library template allows you to implement an endpoint's contract operations as workflow activities or, for that matter, to expose a workflow as a service. The project will contain a single sequential activity that implements a simple contract and a matching .config file. The client still interacts with what looks like a traditional endpoint, and yet the implementation is purely workflow-driven.
The State Machine Workflow Service Library template uses a state machine instead of a sequential workflow to implement its operations (trigger state transitions). The workflow project templates make use of WcfSvcHost and WcfTestClient, just as the plain WCF Service Library does. The workflow templates also make use of the new context bindings to manage passing the workflow instance ID to support durable workflows. I will address these binding in detail in a future column.

Adding Service References
The Visual Studio 2005 extensions for .NET Framework 3.0 provided a rudimentary ability to add a reference to a WCF service, without many of the advanced features of SvcUtil. Visual Studio 2008 features a new service reference dialog, as shown in Figure 7.
Figure 7 Add Service Reference Dialog (Click the image for a larger view)
You can bring up the new dialog in any project by right-clicking anywhere inside the project in the Solution Explorer and selecting Add Service Reference from the context menu. Note that the project must be configured to target .NET Framework 3.0 and above to enable this option.
In the Add Service Reference dialog, you first need to specify the service metadata address (not the service URL, as the dialog states) and click Go to view the available service endpoints (not Services, as labeled). You must specify a namespace (such as MyService) to contain the generated proxy and click OK to generate the proxy and update the .config file. Note that, in most cases, Visual Studio 2008 is not smart enough to infer the cleanest binding values, and it will therefore butcher the .config file by declaring all the default values for the bindings. This issue will be addressed in a future release of Visual Studio. If you care about maintaining the .config file, before adding the reference, open the .config file, add the reference, then perform a single Undo (Ctrl+Z), and manually add the .config file entries in the client section.
The Discover button lets you discover WCF services in your own solution as long as they are either hosted in a Web site project or in one of the new WCF service libraries. In the case of a Web site project, Visual Studio 2008 will either retrieve the metadata from IIS or will launch the ASP.NET file-system-based development server. In the case of a WCF service library, WCF will auto-launch its host (WcfSvcHost) to get the metadata.
The Advanced button brings up the settings dialog that lets you tweak the proxy generation almost as if you were using SvcUtil (see Figure 8). The more intuitive options let you configure the visibility of the generated proxy and contracts (public or internal); you can generate message contracts for your data types for advanced interoperability scenarios in which you have to comply with an existing, typically custom, message format, and you can click the Add Web Reference button to convert the reference to an old ASMX Web service reference.
Figure 8 Service Reference Advanced Options (Click the image for a larger view)
The Generate asynchronous operations checkbox adds for each operation in the imported contract a matching pair of Begin<operation> and End<operation> elements that allows the client to issue the call asynchronously on a worker thread and later sync up with the completion of the operation by either providing a completion callback method or by blocking for completion. For example, given this contract definition
[ServiceContract]
interface ICalculator
{
   [OperationContract]
   int Add(int number1,int number2);
}
the imported contract will look like Figure 9.
[ServiceContract]
interface ICalculator
{
   [OperationContract]
   int Add(int number1,int number2);

   [OperationContract(AsyncPattern = true)]
   IAsyncResult BeginAdd(int number1,int number2,
                         AsyncCallback callback,object asyncState);
   int EndAdd(IAsyncResult result);

   //Rest of the methods
}
The matching client code for asynchronous invocation will look like the following:
CalculatorClient proxy = new CalculatorClient();
int sum;
AsyncCallback completion = (result)=>
                           {
                              sum = proxy.EndAdd(result);
                              Debug.Assert(sum == 5);
                              proxy.Close(); 
                           };
proxy.BeginAdd(2,3,completion,null);
While you could use these methods as-is, the completion callback provided to Begin<operation> is called on a thread from the thread pool. This presents a serious problem if the callback is used to access some resources that have affinity to a particular thread or threads. The classic example is a Windows Forms (or WPF) application that dispatches a lengthy service call asynchronously (to avoid blocking the UI) and then wishes to update the UI with the result of the invocation. Using the raw Begin<operation> is disallowed since only the UI thread is allowed to update it. To better handle this situation, the ClientBase<T> base class has been extended with a protected InvokeAsync method that picks up the synchronization context of the client and will use it to invoke the completion callback, as shown in Figure 10.
public abstract class ClientBase<T> : ...
{
   protected delegate IAsyncResult BeginOperationDelegate(
             object[] inValues,AsyncCallback asyncCallback,object state);

   protected delegate object[] EndOperationDelegate(IAsyncResult result);
   
   //Picks up sync context used for completion callback 
   protected void InvokeAsync(BeginOperationDelegate beginOpDelegate,
                              object[] inValues,
                              EndOperationDelegate endOpDelegate,
                              SendOrPostCallback opCompletedCallback,
                              object userState)
   {}
   //More members
}
ClientBase<T> also provides an event arguments helper class and two dedicated delegates used to begin and end the asynchronous call. The generated proxy class that derives from ClientBase<T> makes use of the base functionality. The proxy will have a public event called <operation>Completed that uses a strongly typed event argument class specific to the results of the asynchronous method, and two methods called <operation>Async used to dispatch the call asynchronously:
partial class AddCompletedEventArgs : AsyncCompletedEventArgs
{
   public int Result
   {get;}
}

class CalculatorClient : ClientBase<ICalculator>,ICalculator
{
   public event EventHandler<AddCompletedEventArgs> AddCompleted;

   public void AddAsync(int number1,int number2,object userState);
   public void AddAsync(int number1,int number2);

   //Rest of the proxy 
}
The client can also subscribe an event handler to the <operation>Completed event, to have that handler called upon completion. The big difference using <operation>Async as opposed to Begin<operation> is that the <operation>Async methods will pick up the synchronization context of the client and will fire the <operation>Completed event on that synchronization context, as shown in Figure 11.
partial class CalculatorForm : Form
{
   CalculatorClient m_Proxy;
 
   public MyClient()
   {
      InitializeComponent();

      m_Proxy = new CalculatorClient();
      m_Proxy.AddCompleted += OnAddCompleted;
   }
   void CallAsync(object sender,EventArgs args)
   {
      m_Proxy.AddAsync(2,3); //Sync context picked up here
   }
   //Called on the UI thread
   void OnAddCompleted(object sender,AddCompletedEventArgs args)
   {     
      Text = "Sum = " + args.Result;
   }
}
The Collection type combobox lets you specify how to represent to the client certain kinds of collections and arrays found in the service metadata. For example, if the service operation returns one of the IEnumerable<T>, IList<T>, or ICollection<T> collections, then by default the proxy will present it as an array. For example, the following service-side operation
[OperationContract]
IEnumerable<int> GetNumbers();
will be expressed on the proxy as:
[OperationContract]
int[] GetNumbers();
However, you can request that Visual Studio 2008 use another collection such as BindingList for data binding, a List<T>, Collection, LinkedList<T>, and so on. If a conversion is possible, the proxy will use the requested collection type instead of an array, like so:
[OperationContract]
List<int> GetNumbers();
A similar feature is available for dictionaries. Normally, if the service operation returns a serializable dictionary such as this
[Serializable]
class MyDictionary<K,T> : IDictionary<K,T> 
{...}

[OperationContract]
MyDictionary<int,string> GetDictionary();
then the proxy class will express that dictionary as a Dictionary<T,K>, which is the default value of the following Dictionary collection type combobox:
[OperationContract]
Dictionary<int,string> GetDictionary();
However, you can request other dictionary types, such as the SortedDictionary<T,K>, HashTable, or the ListDictionary, and the proxy will use that dictionary instead if possible:
[OperationContract]
SortedDictionary<int,string> GetDictionary();
By far, the most important feature of the new service reference feature is its ability to share data contract types across assemblies. With Visual Studio 2005, if a client added a service reference to two independent services that supported the same data contract, the client would get two distinct yet identical types representing the same data contract. With Visual Studio 2008, by default, if any of the assemblies referenced by the client already has a data contract type matching a data contract type exposed in the metadata of the referenced service, Visual Studio 2008 will not import that type again. It is worth emphasizing again that the existing data contract reference must be in another referenced assembly, not in the client project itself. This limitation may be addressed in a future release of Visual Studio. For now, the workaround and best practice is obvious: factor all of your shared data contracts to a designated class library and have all clients reference that assembly.
The advanced settings dialog of the service reference lets you configure data contract sharing. The "Reuse types in the referenced assemblies" checkbox is checked by default, but you can turn this feature off. Despite its name, it will only share data contracts, not service contracts. Using the radio buttons underneath it (see Figure 8), you can also instruct Visual Studio 2008 to reuse data contracts across all referenced assemblies, or restrict the sharing to specific assemblies by placing a check mark next to them in the list.
Once a reference is added, your project will have a new folder called Service References, inside of which is a service reference item for each referenced service (see Figure 12).
Figure 12 Service References Folder 
You can always right-click on the reference and select Update Service Reference to regenerate the proxy and update the client's .config file. This is possible because the service reference item also contains a file that records the original metadata address used.
You can also select Configure Service Reference to bring up a dialog similar to the advanced settings dialog used when adding the reference. The configure service reference dialog lets you change the service metadata address as well as the rest of the advanced proxy settings.

Send your questions and comments to mmnet30@microsoft.com.


Juval Lowy is a software architect with IDesign providing WCF training and architecture consulting. He is also the Microsoft Regional Director for the Silicon Valley. Juval's recent book is Programming WCF Services (O'Reilly, 2007), and he can be contacted at www.idesign.net.

Page view tracker