August 2007 - Posts
Earlier this week, I posted about a bug that I had encountered in WCF 3.0 regarding the content-type header. As promised, this post breaks down a solution that I put together to workaround the problem. Keep in mind this problem has been addressed when I last tested it on the WCF bits for 3.5 Beta 2.
I will stress that this wasn't what I would consider to be an ideal solution, but it saves the Apache Axis developer that wrote the service from having to write a custom handler to reorder the parameters in the content-type header. I also don't guarantee my specific Band-Aid will work for every situation. However, the same principle should apply. You may just have to tweak a bit of the logic. At any rate, let's take a look at the problem and how I get around it.
The fundamental problem has to do with the parsing logic in the text encoder. To be specific, it resides in the GetEncodingFromContentType method of the class System.ServiceModel.Channels.TextMessageEncoderFactory. Well, I really didn't want to write a completely new text encoder implementation simply for the sake of changing some parsing logic related to the encoding in the content-type header. So, I thought it would be ideal to simply override it. Unfortunately, the TextMessageEncoderFactory isn't even publicly accessible. It is an internal class within the System.ServiceModel assembly. Furthermore, this particular method is static and gets called from the TextMessageEncoder class, which is coupled to the TextMessageEncoderFactory. Oh yeah, TextMessageEncoder is a private class that is nested within TextMessageEncoderFactory.
After quite a bit of digging through the internals with Reflector, I noticed both TextMessageEncoderFactory and TextMessageEncoder inherit from publicly accessible base classes that are used for rolling custom implementations: MessageEncoderFactory and MessageEncoder. I was extremely fortunate to discover that the problematic parsing method gets invoked from a virtual method in TextMessageEncoder. As soon as I saw that, I knew that I had found a hack an alternative solution to writing my own custom implementation of a text encoder via the power of reflection.
I wrote two classes: MessageEncoderFactoryWrapper and MessageEncoderWrapper. These were simple classes that inherited from MessageEncoderFactory and MessageEncoder respectively. The implementation simply accepts an instance of the corresponding base class in the constructor. Each virtual method is overridden and just executes the same method in the wrapped instance. If you have ever used the decorator pattern, this is the same principle.
Next, I wrote two more classes: AxisTextMessageEncoderFactory and AxisTextMessageEncoder. These classes inherited from MessageEncoderFactoryWrapper and MessageEncoderWrapper respectively. When AxisTextMessageEncoderFactory is instantiated, I use reflection to create an instance of the private class TextMessageEncoderFactory and it becomes "wrapped". As I mentioned earlier, TextMessageEncoder is tightly coupled to TextMessageEncoderFactory. So, I also wrap the instanced returned by the Encoder property of TextMessageEncoderFactory and wrap it in an instance of AxisTextMessageEncoder. In the implementation of the class, I override the ReadMessage method. This makes it possible to intercept the execution of ReadMessage and manipulate the contentType parameter that will eventually get passed to the flawed parsing logic.
You can think of it similarly to the decorator pattern. I am essentially adding some additional behavior to the existing implementation. :) Again, keep in mind this was a very specific fix that I put in place for my particular needs. This isn't guaranteed to work in all cases. For instance, if you are using streamed messages rather than buffered messages, you will need to override a different method. This also will not work for binary encoding or MTOM encoding. However, you can probably apply the same approach for those encoders as well.
Finally, I created an AxisTextMessageEncodingBindingElement class. This taps into the necessary extensibility points to allow the encoder to be added to a binding. You could easily create a class to enable configuration file support as well, but I am currently setting up my binding programmatically.
At any rate, here is the source code. I hope that someone out there finds it to be useful.
Just an FYI to those that are interested...
A Silverlight contest has been announced for the upcoming Alabama Code Camp. The general idea is to create a simple game using Silverlight. You have until midnight on October 2, 2007 to submit your game. The entries will be reviewed and judged during the week leading up to code camp, and the winner(s) will be announced at the actual code camp event on October 6th. The grand prize is a Zune.
For complete details regarding the rules, refer to the contest page.
Recently, I have been using WCF as the consumer of a Java web service that is running in the Apache Axis environment. Initially, I thought this project would be extremely simple. Well, I guess that it is what I get for thinking!
Shortly after I finished the initial implementation, I fired up the debugger to test the interaction with the web service. As soon as the request was submitted, I received an unusual error indicating that a substring operation failed due to an invalid length. As I researched the cause of the exception, I discovered that it was being thrown by TextMessageEncoderFactory.GetEncodingFromContentType. This was occurring when the response from the web service was being processed by the text encoder.
Naturally, I fired up Reflector to get a closer look at exactly what this method was doing.
Well, it turns out that WCF has very specific expectations regarding how the content-type parameters should be ordered. Typically, the content-type header appears as follows:
Content-Type: application/soap+xml; charset=utf-8
Unfortunately, the Apache Axis environment inserts an optional action parameter between content type and charset as follows:
Content Type: application/soap+xml; action="urn: myMethod"; charset=utf-8
Based on the applicable W3C specs, there is no requirement for the parameters to be listed in a specific order. However, WCF's current parsing logic doesn't account for this possibility. It ultimately results in an invalid substring operation due to a negative length.
I did some more searching around the web and stumbled onto a couple of posts in the MSDN forum where someone had complained about this exact problem. Surprisingly, it has received extremely little attention and I have been unable to find any references about the problem elsewhere on the web. In the MSDN posts, it was mentioned that this issue would probably be addressed in WCF 3.5. Well, I am happy to verify that it has been resolved as of Beta 2...at least for my specific scenario.
While it is great to see the problem is being addressed for the next release of WCF, I'm sure there are quite a few people out there who are in the same boat as me and need a solution immediately. From what little information I have seen regarding this problem, it appears as though it is passed back over to the Apache environment to deal with it by reordering the parameters in the content-type header. If this isn't an option for you, I have written a quick solution that can be used as a workaround on the .NET side of things. Admittedly, it isn't the most elegant solution that I have ever developed, but it should be sufficient when you are in a bind.
Later today or tonight, I will post the solution and source code.
In some previous posts, I highlighted some of the major functionality for UriTemplate and UriTemplateMatch. Before I move on to the new functionality that really begins to consume these building blocks, it only seemed fair to also point out another useful new class related to working with uris. As you could probably judge by the title of the post, I am referring to the UriTemplateTable.
So, what exactly does UriTemplateTable do for you? You can essentially think of it as UriTemplateMatch on steroids. The name really gives it away. The UriTemplateTable provides support for storing a set of related UriTemplates. A candidate uri can be run against the UriTemplate objects within the table to determine the most appropriate match or matches.
Let's look at some code to clarify what I am talking about. Here is an example using Keith Elder's Flickr archive.
// Setup a template table for the base address.
UriTemplateTable table = new UriTemplateTable(new Uri("http://www.flickr.com/photos/keithelder/archives"));
// Add the templates to the table.
table.KeyValuePairs.Add(
new KeyValuePair<UriTemplate, object>(
new UriTemplate("{takenOrPosted}/{year}/calendar/"),
"some info about the template"));
table.KeyValuePairs.Add(
new KeyValuePair<UriTemplate, object>(
new UriTemplate("takenOrPosted}/{year}/{month}/calendar/"),
"more info about the template"));
table.KeyValuePairs.Add(
new KeyValuePair<UriTemplate, object>(
new UriTemplate("takenOrPosted}/{year}/{month}/{day}/"),
"yet even more info about the template"));
So far, all we have done is setup a UriTemplateTable that contains a set of related UriTemplates. If you look closely, you can see there are some similarities between the UriTemplates. Each one adds an extra level of detail to the possible date. This could have been taken a step further and the user made into a parameter as well, but we are keeping this example specific to Zorka. :)
You may be wondering what is this KeyValuePair business all about? This is one of the other nice features in UriTemplateTable. The UriTemplates are stored as an ILIst of KeyValuePairs. The key is the UriTemplate and the value is an object of your choosing. Unfortunately, you are forced to use the Object type rather than supplying a type parameter. Regardless, this could potentially be quite useful. You can essentially store any information that you deem to be relevant with each instance of UriTemplate.
Now that a UriTemplateTable is setup with our UriTemplates, it's time to unleash its matching capabilities.
// Create a candidate uri for a match.
Uri candidateUri = new Uri("http://www.flickr.com/photos/keithelder/archives/date-posted/2007/01/calendar/");
// Tell the table to match against the uri.
Collection<UriTemplateMatch> matchResults = table.Match(candidateUri);
// Check if a match was found.
if ((matchResults != null) && (matchResults.Count > 0))
{
// Write out each result.
foreach (UriTemplateMatch match in matchResults)
{
Console.WriteLine();
Console.WriteLine("Template: " + match.Template.ToString());
Console.WriteLine("Parameters");
foreach (string key in match.BoundVariables.Keys)
{
Console.WriteLine(" Name: {0} | Value: {1}", key, match.BoundVariables[key]);
}
}
}
Output:
Template: {takenOrPosted}/{year}/{month}/calendar/
Parameters
Name: TAKENORPOSTED | Value: date-posted
Name: YEAR | Value: 2007
Name: MONTH | Value: 01
Notice the Match method returns a Collection of UriTemplateMatch objects. This is a result of the possibility that more than one template could match against the candidate uri. It may be necessary to do some additional work to narrow down your results, but it's better than the alternative of manually writing the code to support this behavior. There is also a MatchSingle method that will attempt to return only one match. However, it will result in a UriTemplateMatchException if more than one match is found. So, proceed with caution.
As a final note, there is another method that I haven't included in the sample code named MakeReadOnly. As the name suggests, it prevents any additional changes from being made to the UriTemplateTable when true is passed as a parameter. However, an exception will be thrown if you pass true and the UriTemplateTable contains more than one UriTemplate that is structurally equivalent.
In the next WCF 3.5 post, I will begin getting into how these new Uri support classes are leveraged by WCF's new features.
It's that time again.
The next Alabama Code Camp will be hosted in Birmingham on Saturday, October 6th. As of today, the call for speakers is officially open. Additional details, such as venue, will be forthcoming in the next week or so. Regardless, be sure to mark your calendars and start making plans to attend. This is always an awesome event with plentiful opportunities to learn a lot about .NET and related technologies.
It is hard to believe the first code camp in the state was held nearly two years ago. We have finally come full circle back to where it all started in Birmingham. If you or anyone you know would be interested in delivering a presentation, go to the site to obtain the speaker document and email it to codecampspeakers@nxtdimension.com. In case you don't have Silverlight installed (shame on you), here is a direct link to the speaker form.
For the October code camp, I intend to deliver a presentation about the new features in WCF 3.5. If we determine there there are still enough WCF newcomers, I will likely do another round of "Introduction to WCF". Otherwise, am giving some serious thought about pulling together an overview of grid computing. It should be some good stuff!
I will see you at the event!
Earlier this week, I posted about the new UriTemplate class that will be available in .NET 3.5. In that post, I mentioned that UriTemplate can be used to to generate a Uri based on a set of parameters. However, it can also be used to match against an existing Uri and parse the Uri into the parameters defined within the UriTemplate.
Here is an example:
// Setup a template based on the format of archived posts on my blog.
UriTemplate template = new UriTemplate("portal/blogs/jeff_barnes/archive/{year}/{month}/{day}/*");
// Setup the base address for my blog.
Uri baseAddress = new Uri("http://jeffbarnes.net");
// Create a candidate uri and match against it using the template.
Uri candidateUri = new Uri("http://jeffbarnes.net/portal/blogs/jeff_barnes/archive/2007/08/14/wcf-3-5-uri-templates.aspx");
UriTemplateMatch match = template.Match(baseAddress, candidateUri);
// Check whether the match was successful.
// Match will be null is the operation failed.
if (match != null)
{
// Values within the matched uri can be extracted as the
// named parameters in the template via the BoundVariables property.
DateTime postDate = new DateTime(
Convert.ToInt32(match.BoundVariables["year"]),
Convert.ToInt32(match.BoundVariables["month"]),
Convert.ToInt32(match.BoundVariables["day"]));
}
In this example, a UriTemplate is setup based on the format of the uri for archived posts on my blog. In the template, the year, month, and day values of the uri have been defined as parameters. A uri from one of my previous posts is then matched against the template. This makes it possible to easily extract the named parameters in the template from the actual uri, which is much cleaner than trying to write code that counts the number of slashes, or something similar, in order to manually parse the values.
To get any real usefulness from UriTemplate, you will quickly come to appreciate UriTemplateMatch.
Yesterday, I ran across a really cool SDK for WCF. For whatever reason, I hadn't heard anything about this until now. It is known as the WCF Line-of-Business (LOB) Adapter SDK. This is a really cool SDK that could potentially be quite useful. For example, I'm sure a lot of you have heard about the forthcoming WCF adapter for BizTalk. It turns out that the WCF adapter for BizTalk was developed using the new SDK. After wrapping my head around the concept of this SDK, I can envision quite a few scenarios where it could be useful.
Based on my understanding, here is the general idea. Rather than everyone rolling their own solution when it becomes necessary to integrate WCF with a LOB system, the SDK provides a consistent pattern to ensure some uniformity in this type of development. The added bonus is that it will take care of some of the work for you as well. I really like the way this has been designed to fit into the WCF channel model. All of this resides quite nicely within your binding, which is exactly where these type of communication details belong.
It is yet another testament to the fact that WCF truly is extensible and flexible.
Here is a great blog post that has organized all of the links with pertinent information into a nice table of contents format.
On a side note, I have been swamped a bit over the last couple of days, but I will be catching up on my WCF 3.5 posts tonight.
This is the first post in a long series about WCF 3.5. Originally, I had intended to start with a different topic. However, I gave it some thought and decided it would be a good idea to begin by covering some material that will appear throughout several of the new features. You can think of these first few posts as building blocks toward future posts.
As you could probably guess from the title of the post, I am going to cover Uri Templates.
Before you start pulling your hair out trying to find the UriTemplate class, it requires a reference to the new library System.ServiceModel.Web. However, the UriTemplate class logically resides in the System namespace. Just keep in mind the physical assembly is System.ServiceModel.Web.
So, what exactly is a Uri Template? At the end of the day, a Uri Template is nothing more than a parameterized uri. It is simply a mechanism that allows a uri to be defined with placeholders rather than literal values. Let's take a look at a couple of examples based on the .NET Framework documentation from MSDN Online:
{culture}/library/*
{culture}/library/{typeInfo}
In case you didn't know, the MSDN site is structured so that you can enter the write the uri as the namespace, type, and method or property to immediately access the corresponding documentation. If you pull out the values that could potentially change, this can be "parameterized" into an Uri Template.
Now, you may have noticed the template doesn't contain a scheme, such as http, or a hostname. This type of information is abstracted from the template and will vary depending upon the base address that is applied to the template at runtime.
Now, let's take a look at a few code examples of putting uri templates into action. Here is an example that uses a template to create a uri to access the online documentation for the String.IsInterned method.:
// Setup a template.
UriTemplate template = new UriTemplate("{culture}/library/{typeInformation}");
// Define the base address.
Uri baseAddress = new Uri("http://msdn2.microsoft.com/");
// Define the parameters by name.
NameValueCollection parameters = new NameValueCollection();
parameters.Add("culture", "en-US");
parameters.Add("typeInformation", "system.string.isinterned");
// Create the formatted uri.
Uri formattedUri = template.BindByName(baseAddress, parameters);
// Output: http://msdn2.microsoft.com/en-US/library/system.string.isinterned
This particular example relies on the matches based on the name of the parameters, but the same thing could be done by ordinal position as well. Consider the following:
UriTemplate template = new UriTemplate("{culture}/library/{typeInformation}");
// Define the base address.
Uri baseAddress = new Uri("http://msdn2.microsoft.com/");
// Create the formatted uri.
Uri formattedUri = template.BindByPosition(
baseAddress,
"en-US",
"system.string.isinterned");
// Output: http://msdn2.microsoft.com/en-US/library/system.string.isinterned
There is also the ability to perform matching between templates and an existing uri, but I will dive into the specifics of that in the next post.
While none of this is really groundbreaking in terms of functionality, there is one key thing to keep in mind. The logic is now consolidated into the framework. Otherwise, everyone would end up writing their own library of functions that essentially does the same thing, but the implementation would vary from system to system.
Although Uri Templates may not seem that interesting in isolation, they play a major role for enabling some of the new features that will be discussed in upcoming posts.
I just thought that I would pass this along for those that are interested. On Thursday, September 27th, there will be an MSDN Event in the Birmingham, AL area. It is scheduled from 1PM to 5PM. There will three sessions that cover LINQ, WCF, and Silverlight.
I would like to encourage any .NET professional in the area to register and attend the event. Keep in mind these MSDN events are completely free! In order to ensure we continue to receive these events in the future, it is critical that we have a solid attendance. Apart from learning a few things about some of the latest and great technologies, these events are always an excellent opportunity to talk with other professionals in the area as well.
Here is the link to the event.
Last week, I mentioned that I am about to begin a posting blitz about the goodness of WCF 3.5. I will be starting that series of posts tomorrow. Before I start drilling down into the details, I thought that I would post a general overview of the upcoming topics.
These are listed in no particular order:
- ASP.NET AJAX Support for Consuming WCF Services
- Support for REST Style Services
- More Love Between Workflow and WCF
- Various New Tools
- More WS-* Protocols
- Create RSS & ATOM Feeds for Services
- Better Support for WCF in a Partial Trust Environment
This is not intended to be a comprehensive list. It's merely some of the major new features that I will be drilling into on my blog over the next couple of months. It may not sound like much, but these are an exciting addition to WCF. The framework is becoming a lot more polished in the 3.5 release.
More Posts
Next page »
Disclaimer:The opinions and views expressed within this blog are solely my own and do not represent those of my employer or anyone else.