Udostępnij za pośrednictwem


A walk through WinFx (third of a series) - the joy of WCF endpoints

It's been a while since I posted on this this (does it still qualify as a series?), but I'll continue and in the hope that I'll be able to pick up the frequency. In the first postings in this series, I discussed how I'd like to build a small CRM-ish application to track activity with the ISVs I work with, and in the second I discussed how Dynamics CRM 3.0 could serve as the basis for such an application. I'd like to now discuss how WCF can be used to provide a simple endpoint to serve data entities up to consumers (such as WPF applications.)

This week marked my first forays into WCF programming, and I was impressed by what I found. It wasn't the advanced features that made the impression though, but rather the simple basic things we all have to grapple with as developers and architects. As I mentioned, I'd like to use this application to track things like contacts, events, and locations in MSCRM, but I'd like to surface those entities through a WCF endpoint. That requires the definition of a Service Contract and a Data Contract. As services typically provide one or more operations and data entities typically consist of one or more members, I also had to define a set of Operation Contracts and Data Members to complete the implementation of my end point.

In WCF, this is simply a matter of using the System.Runtime.Serialization and System.ServiceModel namespaces and marking your data entities and service classes appropriately. To retrieve a list of locations for a given ISV from a WCF endpoint, I modeled it using code like the following:

using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.Text;

using System.ServiceModel;

namespace IsvApp.ServicesLayer.Contracts

{

[DataContract]

public class Location

{

[DataMember]

public Guid IsvId;

[DataMember]

public Guid LocationId;

[DataMember]

public string Name;

[DataMember]

public string Description;

[DataMember]

public string Address1;

// plus the usual, then...

[DataMember]

public double Latitude;

[DataMember]

public double Longitude;

// and a couple more, then...

}

[DataContract]

public class LocationFilter

{

// much like Location - you’ll see this in action below...

}

[DataContract]

public class Locations

{

[DataMember]

public int TotalLocationCount;

[DataMember]

public List<Locations> LocationList;

}

[ServiceContract]

public interface ILocationSvc

{

[OperationContract]

Locations GetLocations(LocationFilter filter);

}

public class LocationSvc : ILocationSvc

{

public Locations GetLocations(LocationFilter filter);

}

}

That’s all it took to specify a few non-trivial objects which could be easily transported across a remoting boundary and returned in aggregate, along with a simple interface and a service class to implement it. After running svcutil.exe and adding the proxy and configuration information, I could test my endpoint by building a console application similar to the following:

using System;

using System.Collections.Generic;

using System.Text;

using IsvApp.ServicesLayer.Contracts

;

namespace isvapptest

{

class Program

{

static void Main(string[] args)

{

// create the WCF service proxy

LocationSvcProxy locationSvc = new LocationSvcProxy();

// create the filter object

LocationFilter filter = new LocationFilter();

// set filter parameters to constrain result set

filter.OrderColumnName = "isv_name";

filter.OrderAscending = true;

filter.GetTotalCount = true;

filter.GetTotalCountOnly = true;

filter.StartIndex = 0;

filter.MaxLocationCount = 10;

// use WCF service proxy to fetch data

Locations locations = locationSvc.GetLocations(filter);

Console.WriteLine("locations.TotalLocationCount = {0}",

locations.TotalLocationCount);

// iterate over data

int i = 0;

foreach (Location location in locations.LocationList)

{

Console.WriteLine(string.Format("Location[{0}]: {1}",

filter.StartIndex,

location.ToString()));

}

// rest of code...then

return;

}

}

}

This is a relatively straightforward usage pattern for fetching a set of data from a WCF endpoint which leaves all the transport, authentication, authorization, and even federation cognizance out of both the client and server code. If you’ve backed off of attempting using complex types over web services or lamented about all the type system tricks you had to employ to do so, I highly encourage you to take a look at WCF and give a pattern like this a shot. I think you’ll be impressed as well.

In my next posting, I’ll attempt to illustrate how this could be bound to a ListView in a WPF application.