AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=738&pId=-1
Windows Communication Foundation: Steroids for your Enterprise Service-Oriented Architecture (Part II)
page
by Tom Fuller
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 28175/ 30

Introduction

In the first part of this article on Windows Communication Foundation, I covered the programming model and end point definition. This second part will describe in detail how contracts are defined in WCF. Following contract definition, I will describe how to invoke a WCF service from a client. Finally, I will give an overview of how you can host WCF services today and how that may change in the future.

Sign Here on the Dotted Line

Contracts are another critical component of the policy that must be agreed upon between clients and services. Contracts up until today were written with either IDL (Interface Definition Language) or WSDL (Web Service Description Language). WSDL is the most recent attempt at answering the what a service is supposed to do. WSDL has the same information you see in IDL plus much more. WSDL is not really changing with the introduction of WCF services; what does change is how we go about defining what our WSDL should look like.

WCF services have defined a variety of contract types that are used to put together the WSDL document that a service exposes. Service contracts, data contracts, and message contracts all help to define the WSDL a service will expose. I will walk us through the different contract types and map them to those elements of WSDL we are already familiar with. This will help to show some of the obvious parallels between WSDL and WCF service definitions.

Service Contracts

Service contracts are the API for your service. These contracts can be defined using interfaces, or they can be defined on the actual class that implements the service behavior. The following is an example of a service contract using a C# interface.

IFamilyGuyGoodies.cs

[ServiceContract(Namespace = "http://familyguyquotes")]

public interface IFamilyGuyGoodies

{

[OperationContract]

string GetQuote(string familyGuyCharacter);

}

As you have probably already realized, this service contract does not specify much. This really just demonstrates the use of an interface instead of a class to define a service. You should take note that the access modifiers have been left off intentionally. The concept of public and private are meaningless when identifying methods on a service contract. If you expose that functionality using the [OperationContract] then it will be capable of being invoked externally. This again goes back to making explicit decisions about the behavior that is exposed.

It is also important to note that within the service contract and operation contract there are a number of declarative settings that can be enforced. For example, if this method was intended to use simplex messaging then you would specify IsOneWay=True. It is also within this service contract definition that I can make explicit assertions about my binding requirements. I would add an attribute [BindingRequirements()] to specify transaction flow requirements or reliable messaging requirements.

The service contract maps to the portType section of the WSDL document. With the current ASMX stack the [webMethods()] that you define are what make up this section. With WCF, you are capable of making specific decisions about how you want consumers to interact with your service by building interfaces first before diving right into implementation. This decision to focus on API first can lead to much better decisions about what is truly required to invoke a service operation.

Data Contracts

WCF gives us a whole new level of control for how we specify the data that is passed back and forth between the client and the service. A data contract allows us to specify what members of a custom type are serialized and how those members are serialized. The data contracts are analogous to the type element in WSDL today. The following is an example of a data contract in WCF.

Quote.cs

[DataContract]

class Quote

{

[DataMember] string quoteText;

[DataMember(VersionAdded=2)]string episodeFound;

}

I have again used a simple type to demonstrate the most obvious advantages of the data contracts with WCF. Notice the [DataMember] attribute; this is the only way to identify to the serializer that this member should be expected as part of the SOAP payload. As with service contracts, the access modifiers are meaningless.

I also used this simple example to showcase the implicit versioning available in the data contract. Notice that the episodeFound member above was added in a later version of the data contract. This in turn allows a client to specify that it is using version 1 of this service and that that portion of the data is not required to communicate successfully with the service.

WCF data contracts give developers their first set of built-in versioning capabilities. Abiding by some very simple rules will allow for the flexibility to add and remove portions of your data being sent back and forth to a service. This reinforces a couple of service tenets. First, you are obviously exchanging contracts and schema, not types. If you understand how this code translates to WSDL, this becomes even more apparent. I also believe that through data contract versioning you are able to remain autonomous. If the services we develop today can supply a variety of versions to a variety of consumers then the service can remain in control of how to handle those various versions and maintain self-governance.

Message Contracts

One of the types of services that we discussed earlier was a typed message service. This type of service uses typed messages to invoke a service and receives typed messages as responses. One of the common needs of these types of services is to manipulate the format of the actual SOAP message that is being passed between the client and the service. In the past this would have to be done with complicated SOAP extensions. With WCF message contracts, we are able to easily specify the portions of a message that should live in the SOAP header and those that should live in the body. Often, these two sections of the message will have different encryption requirements, and the message contract is a good way to provide flexibility in how we structure that message. The message contract maps to the message section of WSDL today. The following is an example of a WCF message contract.

FamilyGuyQuoteRequest.cs

[MessageContract]

public class FamilyGuyQuoteRequest

{

[MessageBody]

public string characterName;

[MessageHeader(MustUnderstand=True)]

public string requestedBy;

}

You will notice a couple of interesting things in the simple message contract defined above. First of all, notice how simple it is to specify where a member would live in a SOAP message. When using the [MessageHeader] attribute, I am telling the serializer to expect this field in the SOAP header. I also have used the MustUnderstand enumeration to tell the serializer that this is a required field in my SOAP header.

Message contracts round out the primary contract types that go into specifying exactly what a service will be passing on the wire. This takes the guesswork out of service definition. As I mentioned above, this is a vast improvement on the implicit approaches today. We really do not have this type of flexibility with ASMX. Our current approaches would require us to plug into the HTTP pipeline and intercept messages using SOAP extensions.

So Am I Truly Contract-First Now?

An interesting ongoing debate amongst those in the industry that are designing, delivering, and teaching service-orientation is whether or not a code-first approach will ever allow us to design and deliver services that are truly loosely coupled, interoperable, and ultimately long-lived. What we just looked at was a very distinct set of technologies that map directly to the WSDL contract that is generated when this service is exposed. Were we actually doing contract-first development with a code-first approach?

The purists would say that contract-first means focusing on schema (XSD) and behavior (interface) before ever writing any code. What I would say is that we do this now by specifying data contracts (schema/XSD), service contract (behavior/interface), and message contracts when necessary. These approaches are still very code-centric and will require some level of governance to avoid developers diving right into implementation before a contract has been agreed upon. However, with the right level of discipline, I think WCF has found an interesting middle ground for contract-first service development.

Consuming a WCF Service

There had to be some significant changes made to how a client consumes a service if Microsoft wanted to preserve the boundaries are explicit tenet. If you look at how an ASMX client works today, you do not make any explicit decisions about how you want to communicate with a service. Of course, I should mention that there were not a variety of options like there are today with WCF services.

Another primary tenet of service orientation is that communication is policy-based. The configuration at the client will specify all of the policy settings that have to match the service features in order for communication to occur. The following is an example of a client configuration file (App.config), a simple command window client (ShowMeTheFunny.cs), and a generated proxy class (FamilyGuyQuotes.cs).

App.config

<system.serviceModel>

<client>

<endpoint configurationName="default" address="http://tomlaptop/Service/FamilyGuyQuotes.svc"

bindingConfiguration="IFamilyGuyGoodies" bindingSectionName="customBinding"

contractType="IFamilyGuyGoodies">

<addressProperties identityData="" identityType="None" isAddressPrivate="false" />

</endpoint>

</client>

<bindings>

<customBinding>

<binding configurationName="IFamilyGuyGoodies">

<contextFlow transactions="Ignore" transactionHeaderFormat="OleTx" logicalThreadId="Ignore" locale="Ignore" />

<httpTransport manualAddressing="false" maxMessageSize="65536"

authenticationScheme="Anonymous" bypassProxyOnLocal="false"

hostnameComparisonMode="StrongWildcard" mapAddressingHeadersToHttpHeaders="true"

proxyAuthenticationScheme="Anonymous" realm="" transferTimeout="00:01:00"

useSystemWebProxy="true" />

<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"

messageVersion="Soap11Addressing1" encoding="utf-8" />

</binding>

</customBinding>

</bindings>

</system.serviceModel>

 

ShowMeTheFunny.cs

using (FamilyGuyGoodiesProxy proxy = new FamilyGuyGoodiesProxy("default"))

{

string s = Console.ReadLine();

string result = proxy.GetQuote(s);

Console.WriteLine("Quote From {0} is: {1}", s, result);

}

 

FamilyGuyQuotes.cs (Generated Proxy)

[System.ServiceModel.ServiceContractAttribute(Namespace="http://familyguyquotes")]

public interface IFamilyGuyGoodies

{ [return:]

string GetQuote(string familyGuyCharacter);

}

 

public partial class FamilyGuyGoodiesProxy : System.ServiceModel.ProxyBase<IFamilyGuyGoodies>, IFamilyGuyGoodies

{

public FamilyGuyGoodiesProxy(string configurationName) :

base(configurationName)

{

}

public string GetQuote(string familyGuyCharacter)

{

return base.InnerProxy.GetQuote(familyGuyCharacter);

}

}

What will probably stand out initially with the code above is the confusing nature of the app.config. Not to worry, this is simply the default that is generated from the SvcUtil.exe that comes with WCF. It is my understanding that this will be simplified in an upcoming release.

Notice that it specifies a custom binding for me and set every property possible. What would be better is if it would have allowed me to specify the Basic Profile binding and set the configuration correctly to reflect that. I am sure this is something the WCF team is looking into.

The code that actually invokes the service is very simple. Notice, we specify the configuration section that will give us all of the detail we need to invoke the actual request to the service. This is, of course, a configuration-based approach. Also notice that the service is wrapped in a using() block. This is because services written with WCF have explicit Close() operations that release the resources being held by the client. Please note, this is a subset of the code sample available for download.

The last code snippet above is the generated proxy class named FamilyGuyQuotes.cs. I have removed many of the attributes in this class to help improve readability. If you want to get the full picture, you will need to look at the code available for download. What you should be able to recognize from this snippet is the utilization of generics for creating the proxy as the same type I defined in the service called IFamilyGuyGoodies. You probably will also notice some other significant differences to the ASMX proxies. Notice there are no Begin and End methods defined by default. These methods are only created if you are explicitly using async communication. Also, youll notice I have only used simple types at this time, so there are no data elements defined. If I had, you would have seen that the existing limitations with proxy type creation have been resolved. The proxy types will not use fields when properties are defined; in previous versions of VS.NET, the proxies would be converted to public fields by default. This issue caused some headaches when attempting to bind those types to server controls in ASP.NET.

Doesnt This Seem a Little Excessive?

On the surface this does appear to be a little overwhelming. The configuration is very explicit, and the proxy is using some very new features found in .NET 2.0. I will add that VS.NET 2005 still has very little support for working with WCF services. What you will find is that youll have to spend a lot of time working with the command window, and youll spend some time mapping file types to VS.NET because it really doesnt understand what a .svc is. Fortunately, in my conversations with the WCF team, they have committed to making these things much easier by the time they RTM. The Add Reference capability will be there at some point, and the configuration detail will be simplified to include only those items that are necessary for communication.

What I do hope is that they do not oversimplify things. This is a huge step toward requiring explicit definition of the communications between clients and services. This helps a client reinforce that it does understand its boundaries at the time it adds a reference and wants to start invoking operations.

WCF Service Runtime Behaviors

Part of the evolution of the ASMX stack and part of the unification of all distributed development technologies is a set of service runtime behaviors that is unprecedented. Here are some of the most interesting additions.

1.      Instancing Control: WCF services can control how they are instanced by specifying Singleton, Private Session, Shared Session, and Per Call. Today we really only have the ability to do Per Call instancing in ASMX. This provides a much greater set of capabilities for designing services.

2.      Concurrency: A service will specify whether the concurrency is Single, Multiple, or Reentrant. Of course, this flexibility comes with some pitfalls. You have to understand some of the limitations of the other settings. For example, if you are setting your instancing to per-call, you cant use anything other than single threading.

3.      Throttling: A service is able to control through configuration the number of incoming threads it will accept. This allows runtime control over how many resources are consumed on a host environment.

4.      Error Handling: WCF services have a configuration switch that specifies whether errors should be sent to the client or not. This is something you would use only for problem diagnosis; when used carefully, this could give important details in the event of a failure.

5.      Transactions: Transaction flow is a capability of WCF services. This is dependent on the binding that is chosen, but there is support for transaction flow across services calls.

6.      Security: The security features available to WCF services vary based on your bindings. There is message level security that enables message encryption. There is also transport level security that depends completely on the specified binding. In some cases, Windows security is your only option; in other scenarios WS-Security will apply.

7.      Metadata: WCF services provide the facility to enable or disable metadata publishing as well. Services can specify whether they want to respond to HTTP GET request with an MEX endpoint and/or WSDL.

So How Do These Features Help Me Build Service-Oriented Systems?

The service behaviors listed above do not all map directly to the needs of a service-oriented developer. Although supporting SO development is a key objective for WCF, it is not the only objective. Another goal would seem to be to provide a unified robust set of features that enable distributed development on the Microsoft platform. Many of the features above are giving administrators more control of how a service behaves after deploying to a production environment. It is probably unfair to look at these service features and pass judgment based on how immediately they might be able to facilitate SO development. The root of most of these features is based on the unification of the disparate technology stacks and the implementation of the lessons learned from ASMX, WSE 1, and WSE 2.

WCF Hosting Options

The hosting options for WCF services are based on the activation model that you want your services to use. You can use the self-hosted approach, or you can host your service in IIS. If you elect to use the self-hosted approach, you have to manually activate the service. If you decide to host the service in IIS, it will be automatically activated the first time it is called.

Self-Hosted vs. IIS-Hosted

Services can be hosted using any number of .NET 2.0 code execution types. A service can be hosted within a console, a Windows forms, or a Windows service application. In these types of hosts, the code to activate and run the service has to be written within your own custom code. This is what classifies this approach as self-hosted. One advantage you have when self-hosting your WCF service is that you have more control as you are explicitly launching the host when you want to. Another advantage is that you have the flexibility to use transports other than HTTP with service development today.

The more popular option for hosting services is within IIS. IIS gives you automatic activation of your WCF service code. There are also a number of other benefits to using IIS for hosting service code. You will get periodic app domain recycling which helps with the stability of the service. IIS also recognizes changes in configuration files; these changes will trigger another app domain refresh, which will pick up those changes. IIS-hosted services can also be tested easily through a standard Web browser.

One point of clarification is that self-hosted services are the only way to use any transports other than HTTP. This is true today but will be remedied in the future. As soon as Windows Activation Services (WAS) is made available as part of the operating system, other transports will be available for invoking IIS hosted-services. The plan, as I understand it, is to deliver WAS with IIS 7 and Windows Vista.

Conclusion

The era of service-orientation has created a need for a robust set of distributed development features that can help to facilitate the delivery of loosely coupled application components. The differences between Web services and services have never been more evident. The need to continually focus on platform independence remains, but the deficiencies of the existing ASMX programming stack are crippling. WCF Beta 1 shows promise as the most flexible programming model for hosting service-oriented application components.

The enterprise strength features available within WCF will allow applications to be built more freely as aggregates. Transaction flow, reliable messaging, and industry standard security will allow systems to be delivered free of the limitations seen in SO development today. WCF provides the design time flexibility to focus on contracts and API definition. What WCF does not do is enforce good SO design. It will take discipline when designing services to see the full benefits of WCF in a service-oriented architecture.

WCF will make delivering and consuming services easier in the near future. This simplification will put the responsibility back on architects to focus on good design practices. It is still very easy to build services that are tightly coupled and will never see the benefits of service-orientation. In a future article, I will focus on the process of defining service boundaries and delivering reusable services through a normal application delivery schedule.

References

1. Programming Indigo The Code Name For The Unified Framework For Building Service-Oriented Applications On The Microsoft Windows Platform By David Pallman, Microsoft Press 2005

 


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-24 6:28:36 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search