If you point XSD.exe at one of the ESB itinerary on-ramps, it will produce some ugly DTO classes for the itinerary, services and resolvers, and a proxy for the on-ramp service. You can use the DTO classes directly to build the itinerary object graph, but it's not intuitive and the results aren't pretty. It also ties you in to using the ESB Guidance solution, whereas it would be nice to abstract that away and construct a generic itinerary.
In the set of simple samples - which I'll put on CodePlex when I've tidied them up - I have a variety of helper classes which make building an itinerary much easier. The simple itinerary from the previous post is built in code like this:
public override ItineraryRequest PrepareRequest()
{
//we have three services - map input, route map output, process routed messages:
ItineraryService mapService = new ItineraryService(ServiceName.Transform, ServiceType.Messaging);
ResolverConnection mapResolver = new ResolverConnection(ResolverType.STATIC);
mapResolver.TransformType = "ESBSimpleSamples.BizTalk.Maps.Parameters_GetASCIICodeRequest,ESBSimpleSamples.BizTalk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a9e52fd7be56a687";
mapService.Resolvers.Add(mapResolver);
ItineraryService routingService = new ItineraryService(ServiceName.Routing, ServiceType.Messaging);
ResolverConnection routingResolver = new ResolverConnection(ResolverType.STATIC);
routingResolver.TransportLocation = "http://localhost/ESBSimpleSamples/EncodingService.asmx";
routingResolver.Action = "http://ESBSimpleSamples.BizTalk.Schemas/1.0/GetASCIICode";
routingResolver.TargetNamespace = "http://ESBSimpleSamples.BizTalk.Schemas/1.0/";
routingService.Resolvers.Add(routingResolver);
ItineraryService sendService = new ItineraryService("DynamicResolutionSolicitResp", ServiceType.Messaging);
//the send has an empty resolver:
sendService.Resolvers.Add(new ResolverConnection());
//build this into an itinerary request:
ItineraryBuilder builder = new ItineraryBuilder();
builder.AddService(mapService);
builder.AddService(routingService);
builder.AddService(sendService);
To submit the itinerary to the on-ramp, you add the message body, specify the credentials and submit (in this case, using default credentials and submitting to the two-way on-ramp):
ItineraryRequest request = new ItineraryRequest();
request.Header = builder.GetItinerary();
request.Body = this.GetXmlParameters();
…
XmlNode body = request.Body;
using (esb.Process proxy = new esb.Process())
{
proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
proxy.ItineraryValue = request.Header;
proxy.SubmitRequestResponse(ref body);
}
Two things to note in the samples. Firstly I'm using a generic schema for the request – a simple name/value list of parameters. The map specified in the itinerary takes this and transforms to the service's expected request schema. This decouples the consumer from the service and means the message bus presents a standard interface for all service requests. The exact request schema and the map are deployed to BizTalk so we still have the advantages of typesafe messages.
Secondly I've abstracted away from ESB Guidance – the only direct usage is of the Process class (generated from XSD), which is wrapped inside ESBServiceBroker. This implements IServiceBroker and clients will use that interface, so the actual message bus implementation can change. All the classes representing itineraries, services, resolvers etc. are custom wrappers.
Again, the resolver connections are all STATIC here, which is brittle but quick to set up. The problems I've had in setting up and consuming services have all been around schemas – messages being lost if they don't conform to the expected schema, or arriving empty at the service or the consumer. To get around this, the process I've been using so far is:
- Publish the service
- Run a sample request/response through WebServiceStudio
- Extrapolate schemas from the sample messages, and publish them in BizTalk
- Write the itinerary XML by hand and test it using the Itinerary Test Client from the ESB Samples
- When it works, use the service and resolver config from the XML to build the itinerary in code
Steps 2 and 3 will depend on the approach you're taking to schemas. Step 4 is a useful one, as it gives you an XML itinerary which you know works through ESB. You can use this artifact in unit tests, or for automating step 5 using codegen.
Next, UDDI.