| By Michael Ruminer | Article Rating: |
|
| November 11, 2003 12:00 AM EST | Reads: |
12,948 |
In the early days of .NET Web services, using a Web service to accept binary data required converting the data to something that could be represented in XML. Surely you remember those days - back before December 2002. With the release of Web Service Enhancements (WSE) 1.0, followed shortly by WSE 1.0 SP1 in March 2003, and now with WSE 2.0 on the horizon, we can at last quickly and easily send binary attachments via Web services by utilizing WSAttachments.
The support of the proposed WSAttachments standard in WSE is of particular interest to any programmer who has ever used a Web service in a production environment. You quickly realize how much you rely on data that doesn't lend itself to some sort of XML serialization. You may want your Web service to accept a word processing document, an image, or any of a number of binary data types. In the past, you might have encoded this binary data as Base64 and sent it over the wire as XML, reconstituting the data on the other side. While the process works well, it is in many cases clunky, and it is not useful in all situations.
The SOAP attachments may be binary data, other SOAP messages, or any other data type you wish to send. WS-Attachments, as defined in the WSE and as submitted as a draft Web services standard, relies on Direct Internet Message Encapsulation (DIME). DIME is used much like MIME (Multipurpose Internet Mail Extensions) to encapsulate a message, and in fact uses the MIMEtypes to indicate the type of attachment it carries. An important thing to remember is that DIME encapsulates (as the name suggests) the SOAP message and its attachments - not the other way around.
For the purposes of this article, we'll look at the practical application of the WSE classes in order to send a SOAP message with an attachment to a Web service that in turn responds with a different attachment. The demonstration code builds a Web service named CodeWidgetServices with a Web method Image2Jpg that accepts a SOAP message with an image file attachment. The Web service converts the attached image file to a JPEG image and returns the converted file's name in the SOAP message and the new JPEG as an attachment.
If you don't need cookbook examples of implementing WSAttachments in your own projects, the quick checklist accompanying this article will keep you headed in the right direction as you go off on your own. If you prefer to read the article and code samples, the checklist will let you know where we are headed and is useful for quick referral.
Building the DIME Web Service
To begin building a DIME-compatible
Web service, WSE 1.0 SP1
must be downloaded from
http://msdn.microsoft.com/webservices and installed. This will
install Microsoft.Web.Services.dll,
which contains the WSE classes and
the filters necessary for ASP.NET to
handle DIME. Once WSE 1.0 SP1 is
installed, you can begin a DIME-
enabled Web service project.
You'll also need to add a reference to Microsoft.Web.Services.dll to your Web service project. In addition, you will need to check the web.config file for the Web service, ensuring that it has the soapExtensionTypes elements (see Listing 1). Ensure that if you are manually adding the soapExtension Types elements that the type attribute has no breaks or extra spaces in it despite how it may appear in the listing. If you have line breaks in the attribute value when you run the service, the .asmx page will indicate an invalid type.
Add aliases for the namespaces
you will use; otherwise you will
need to provide fully qualified
names in the code. The following
are the namespaces you will need to
reference in order to support DIME.
Setting Up a Web Method
Listing 2 shows the classic Web
service method format for Image2Jpg.
What may seem odd is that nowhere
does this method seem to indicate
that it relies on a SOAP attachment.
The method has the typical
(WebMethod) attribute and it accepts
a string and returns a string. Where's
the indicator for passed attachments?
At first glance, you would have no way
of knowing that this method relies on
an attachment. You could review the
code carefully, but this entry point
method may call other methods in the
class that deal with the attachment,
making it increasingly hard to recognize
that this Web method uses
attachments. And let's not even talk
about the possibility that one of the
called methods from the entry Web
method uses an inherited class with a
delegate that handles the attachments.
Good luck realizing an attachment
is used in that case!
A person looking at the classically defined Web method would have to investigate carefully to discover that attachments are being utilized. Not only is this currently acceptable - I have failed to find any reference from Microsoft on best practices to avoid this sort of ambiguity. Later in this article I will show you how to avoid this ambiguity by using a recommended way to indicate that attachments are handled by a Web method.
What about the WSDL? Can we look at the WSDL to discover that the method uses DIME? Yes and no. Using WSE 1.0 SP1 the WSDL is not automatically modified to indicate DIME. There is a proposed WSDL Extension for SOAP in the DIME specification. Nevertheless, WSE 1.0 SP1 does not implement this. Oddly enough, the SOAP Toolkit 3.0 does. Thus, if you wish the WSDL to indicate that you are using DIME, you will need to modify the WSDL file manually. It's not required that you do this if you are using WSE on the client consuming the Web service, but if you plan to use the SOAP Toolkit 3.0 with the client it needs the DIME information in the WSDL. For the scope of this article, the WSDL is not modified.
As a programmer I don't want to have to look at the WSDL to see if a Web method utilizes attachments, and as we have learned, there is no guarantee that doing so will tell you whether or not the method utilizes attachments. Furthermore, the SOAP message could have an indefinite number of attachments. You may want to build code to ensure the message sent only what was expected. Or you may wish to have code validate that the attachment is the proper data type, e.g., not an image when the method was expecting an XML document.
The best way to indicate the type and number of attachments expected - and that the method uses DIME - is to create a custom attribute. Listing 3 shows the class definition for a custom attribute named DimeCompliant Attribute. Listing 4 is the complete Web method code for Image2Jpg utilizing the DimeCompliant attribute. You will notice in the Web method that I have not checked the message against those attributes (because it is outside the scope of this article), but by utilizing reflection, you could validate that the message meets the expected message format. If nothing else, the attribute is a strong flag to the programmer that this Web method uses attachments and what sort of attachment it expects.
In the case of the sample code, it indicates it expects one attachment of type Bitmap (which is any of a number of image types under .NET, e.g., JPEG, BMP, GIF, etc.). I hope that in the future such attributes will be required for members to receive DIME information. It only makes sense that a strongly typed language such as C# should not allow a message to be sent that can't be validated systematically against an expected signature. What do you need to do to set up a Web method to handle SOAP attachments? In short, you aren't required do anything special to the method itself; you can simply check the SOAP message for attachments. However, I can recommend better practices that use custom attributes.
Building the Web Method
Listing 4 shows how the
RequestContext of the SOAP message
sent to the Web method can be
accessed and the attachments associated
with it handled. The first six
lines of code deal with accessing the
SOAP message's attachments and
streaming it into a Bitmap object.
All that is required to access the
attachments is to call HttpSoapCon
text.RequestContext.Attachments[ind
ex], which returns an object,
Microsoft.Web.Services. Dime.Dime
Attachment. The attachments can be
referenced by the index number of the
collection or by the DimeAttachment. id. In its most pure
form, a DimeAttch ment.id
should be a URI. In reality, it does
not have to be an URI but does
have to be unique to the collection
of attachments. You may prefer
to use a friendlier indicator
than a URI for the ID.
In the sample code, once the sent image has been converted to a JPEG we are now ready to create a new DimeAttachment made up of that JPEG image for the response SOAP message. This is done simply by creating a new DimeAttachment instance indicating the attachment's MIME type, TypeFormatEnum, and the stream that represents the actual attachment data.
new DimeAttachment("image/jpeg", TypeFormatEnum.MediaType, myJpgStream)
After assigning the DimeAttachment a friendly IDvalue, the attachment is added to the ResponseContext.Attachments collection. The Web method returns the new filename or the error text if any of a number of conditions occurs to prevent the Web method from returning a JPEG file. A DIME message containing the SOAP message and attachment will be returned to the client.
Setting Up a Client
In the sample code for the client
a simple form is built that presents
a Windows BMP file. When the user
clicks the "convert" button it sends
the BMP file to the Web service, gets
back the JPG file, and displays the
returned JPEG on the form. Not all
of the form coding is listed in the
sample code - only the two methods
that handle the outgoing and
incoming SOAP attachments and
DIME are shown. The client project
needs to reference the Microsoft.
Web.Services.dll as well as the Web
service you wish to utilize.
In the sample, the Web reference is named CodeWidget. There is one very important change on the client side that must be made in order to send and receive SOAP attachments in conjunction with a Web service. When using VS.NET and adding a Web reference, a proxy class named Reference.cs is created for the Web service. This file can usually be found under Project Folder/Web References/web reference name/Reference.cs, and will contain a class that is a proxy for the Web service referenced. This class typically inherits from System.Web.Services.Protocols. SoapHttpClientProtocol. In order to utilize DIME, the class needs to be changed to inherit from Microsoft.Web.Services.WebServicesClientProtocol.
Note: If you have installed WSE 1.0, Reference.cs likely already contains an additional class that inherits from WebServicesClientProtocol. This additional class will have a class name ending in "Wse". Use this class to create the Web service instance in your code.
A very useful aspect of the architecture of Web services built with WSE is that a client can communicate with the Web service method designed for attachments - without DIME - and the service will not throw an exception. It will see the SOAP message with zero attachments because of how the ASP.NET filters work with DIME. By the time the actual Web method sees the message, it is simply a SOAP message like any other with zero or more attachments.
Coding the Client
At this point coding the client
application is no different than coding
the Web service method. See Listing 5
for the sample code, which creates an
instance of the appropriate Web service
proxy class, creates a
DimeAttachment, adds the
DimeAttachment to the SOAP message,
calls the Web method, receives
the response, and processes the
returned DimeAttachment.
Using WSE 2.0
As I write this the WSE 2.0
Technology Preview is available.
It's unsupported and not authorized
for redistribution. Under the
tech preview, one of the major differences
you should be aware of is
that the Microsoft.Web.Services.
HttpSoapContext class has been
made obsolete and a new means
of accessing the SoapContext
exists. Look carefully at the
readme associated with WSE 2.0
to see the reasons for obsolescence,
and for how you will need
to tweak your code.
Conclusion
The implementation of WSAttachments
via WSE is not complicated,
but there are a few
tricky spots. In addition, there
are more changes to come under
WSE 2.0, and as I have pointed
out, there are issues that have not
yet been fully considered.
However, WS-Attachments via
WSE takes a large leap forward
for Web services and the ability to
easily send attachments. Despite
the various weak points and stillevolving
implementation, I recommend
implementing DIME
with SOAP in your Web services
now and further utilizing the
power as it evolves.
References
Published November 11, 2003 Reads 12,948
Copyright © 2003 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Michael Ruminer
Michael Ruminer is the President and Founder of CodeWidget, a company specializing in .NET development and consulting. He has an extensive background in supply chain operations and currently heads up building new “Widgets” in .NET for clients and developers. He spends time both in Boston, MA and Helena, MT.
- iPad3 vs Windows 8 - and the Winner Is...Cloud
- Eleven Reasons Why Windows Phone Will Overtake Android
- Windows Azure Overview Part 4: Security
- Agile Development & Enterprise Architecture Practice – Can They Coexist?
- Eleven Tips for Successful Cloud Computing Adoption
- GM to Pull Facebook Advertising: WSJ
- System Center Virtual Machine Manager 2012 as Private Cloud Enabler
- Apply Agile When Deploying Apps
- The Web – Changing the Way We Work
- EE Times and EDN Announce the 2012 UBM Electronics ACE Award Winners
- Closer Look at One NoSQL Database – MongoDB
- Why Is Scrum So Widely Adopted and So Very Dangerously Deceptive
- iPad3 vs Windows 8 - and the Winner Is...Cloud
- Cisco Unveils Visual Collaboration Solutions in the Post-PC Era, Extending the Reach of TelePresence With New Mobile-to-Immersive Offerings
- Eleven Reasons Why Windows Phone Will Overtake Android
- Windows Azure Overview Part 4: Security
- Agile Development & Enterprise Architecture Practice – Can They Coexist?
- Eleven Tips for Successful Cloud Computing Adoption
- GM to Pull Facebook Advertising: WSJ
- System Center Virtual Machine Manager 2012 as Private Cloud Enabler
- Apply Agile When Deploying Apps
- The Web – Changing the Way We Work
- Book Review: Decision Management Systems
- User Group Malaise?
- Google Maps and ASP.NET
- Converting VB6 to VB.NET, Part I
- How to Write High-Performance C# Code
- Crystal Reports XI & How It Has Changed
- Creating Controls for.NET Compact Framework in Visual Studio 2005
- Where Are RIA Technologies Headed in 2008?
- Programmatically Posting Data to ASP .NET Web Applications
- Implementing Tab Navigation with ASP.NET 2.0
- AJAX World RIA Conference & Expo Kicks Off in New York City
- i-Technology Viewpoint: "SOA Sucks"
- .NET Archives: Getting Reacquainted with the Father of C#
- i-Technology Photo Exclusive: Bill Gates & Steve Jobs In "Nerds"





















