Hotfix for some BizTalk 2009 issues in Visual Studio

Hotfix for some BizTalk 2009 issues in Visual Studio

For some time now, I’ve been working with BizTalk Server 2009.  One of the major frustrations has been with the VS 2008 integration.  Project references between BizTalk projects wreaked havoc if you were working on a single developer machine with BTS installed.  Fortunately, Microsoft has released a hotfix for many of these issues [1].  If you are having issues within Visual Studio, you may want to try this hotfix.  Look for the link near the top of the document to request the hotfix.  I got an email with the link within minutes when I tried. 

Thanks to Bryan Corazza of Avanade for pointing out this support document. 

 

[1] http://support.microsoft.com/kb/977428/en-us

Bookmarked Activities in WF4

Bookmarked Activities in WF4

Note: This blog post is written using the .NET framework 4.0 Beta 2

Windows Workflow Foundation 4 introduces the concept of bookmarks to temporarily pause activities. A bookmark is basically a named pause point in an activity. The result is that the workflow runtime doesn’t consider an activity to be finished until all its bookmarks are either resumed or removed.

 

That last statement isn’t completely true though as it is only the case when the optional BookmarkOptions aren’t specified or specified as None. With BookmarkOptions.MultipleResume a bookmark can be resumed multiple times, de default is just once, so just resuming a bookmark isn’t enough it actually needs to be removed. The other option is BookmarkOptions.NonBlocking which means that the activity is finished even if the bookmark was never resumed. This last option is useful when you want to be able to receive messages while child activities are executing but you don’t need to receive the message per se. The BookmarkOptions enum is a flag so you can combine both NonBlocking  and MultipleResume if you so desire.

One annoying thing with using bookmarks is that you need to use a NativeActivity and you have to override the CanInduceIdle property and return True as the default of False doesn’t permit bookmarks to be created, even when the NonBlocking option is used.

public class MyBookmarkedActivity : NativeActivity
{
    protected override bool CanInduceIdle
    {
        get { return true; }
    }
 
    protected override void Execute(NativeActivityContext context)
    {
        var bookmark = context.CreateBookmark("MyBookmark", BookmarkResumed);
 
    }
 
    private void BookmarkResumed(NativeActivityContext context, Bookmark bookmark, object value)
    {
        Console.WriteLine("Bookmark resumed with '{0}'.", value);
    }
}

 

Running the workflow and resuming a bookmark is easy when using a WorkflowApplication as seen below.

var wa = new WorkflowApplication(new MyBookmarkedActivity());
 
wa.Run();
 
var data = Console.ReadLine();
wa.ResumeBookmark("MyBookmark", data);
 
Console.ReadLine();

 

Nice and easy right?

Well yes except we also have WorkflowInvoker and WorkflowServiceHost to host our activity and neither contains a ResumeBookmark function. More about that later.

 

Enjoy!

www.TheProblemSolver.nl

Wiki.WindowsWorkflowFoundation.eu

BizTalk Server Performance Benchmark Wizard

BizTalk Server Performance Benchmark Wizard

In case you have missed it, about two weeks ago a few members of the BizTalk Server and the SQL Server Customer Advisory Teams (CAT) have released to Codeplex, a vey useful BizTalk performance benchmarking tool.clip_image002

The BizTalk Benchmark Wizard checks the performance of your BizTalk Server installation using pre-existing scenarios and validates it against some known results. Essentially it provides an answer to the question:” Are you getting the most throughput performance out of of your BizTalk Server installation?”
If the answer is no – you better follow the BizTalk Server 2009 Performance Optimization Guide.

The idea for the tool was conceived by BizTalk MVP Mikael Hakansson and the actual project involved a few Microsoft employees: Ewan Fairweather from the BizTalk Server CAT and  other members from the SQL Server CAT.

For a full description of the project check out these blog posts:

For more information:clip_image002[5]
Benchmark your BizTalk Server (Part 1)

How to install:
Benchmark your BizTalk Server (Part 2)

Drill Down on the Wizard:
Benchmark your BizTalk Server (Part 3)

The Wizard is very simple to install and use.

So start using the it and make sure you get the most out of your BizTalk Server!

Ofer 

Bubble up searching within a BizTalk map

Bubble up searching within a BizTalk map

A recent client had a high profile issue that took some interesting mapping to get working. I thought that I would write about it, as it is the second client that I have come across that has needed it. Since it has happened twice, it warrants a blog entry.

Requirement: I don’t know where a particular number is going to show up, but I need to find it and place it in this particular column in the output.

Specifically: I know that the Medicaid or Medicare number is going to show up in 1 of 4 places, I need to look for it and where ever it is, I need to place it in these two places in the output.

It is going to show up in the REF02 where the REF01 is 1C (Medicare) and 1D (Medicaid) in the following locations: 2420A, 2310B, 2010BA, 2010AA. I want to look first in the 2420A level, if it is not there, then I want to search the 2310B level, 2010BA, and finally the 2010AA and since there might (most likely) be multiple REF segments, I need it to search all of the REF segments (not just the first one).

Here is a few snippets of the xml where the data can reside:

              <ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A>
                <REF01__ReferenceIdentificationQualifier>1D</REF01__ReferenceIdentificationQualifier>
                <REF02__RenderingProviderSecondaryIdentifier>2420A Medicaid</REF02__RenderingProviderSecondaryIdentifier>
              </ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A>
              <ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A>
                <REF01__ReferenceIdentificationQualifier>1C</REF01__ReferenceIdentificationQualifier>
                <REF02__RenderingProviderSecondaryIdentifier>2420A Medicare</REF02__RenderingProviderSecondaryIdentifier>
              </ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A>

and

            <ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B>
              <REF01__ReferenceIdentificationQualifier>1D</REF01__ReferenceIdentificationQualifier>
              <REF02__RenderingProviderSecondaryIdentifier>2310B Medicaid</REF02__RenderingProviderSecondaryIdentifier>
            </ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B>
            <ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B>
              <REF01__ReferenceIdentificationQualifier>1C</REF01__ReferenceIdentificationQualifier>
              <REF02__RenderingProviderSecondaryIdentifier>2310B Medicare</REF02__RenderingProviderSecondaryIdentifier>
            </ns0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B>

and

        <ns0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB>
          <REF01__ReferenceIdentificationQualifier>1D</REF01__ReferenceIdentificationQualifier>
          <REF02__PaytoProviderIdentifier>2010AB Medicaid</REF02__PaytoProviderIdentifier>
        </ns0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB>
        <ns0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB>
          <REF01__ReferenceIdentificationQualifier>1C</REF01__ReferenceIdentificationQualifier>
          <REF02__PaytoProviderIdentifier>2010AB Medicare</REF02__PaytoProviderIdentifier>
        </ns0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB>

and

          <ns0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop>
            <ns0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA>
              <REF01__ReferenceIdentificationQualifier>1D</REF01__ReferenceIdentificationQualifier>
              <REF02__BillingProviderAdditionalIdentifier>2010AA Medicaid</REF02__BillingProviderAdditionalIdentifier>
            </ns0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA>
            <ns0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA>
              <REF01__ReferenceIdentificationQualifier>1C</REF01__ReferenceIdentificationQualifier>
              <REF02__BillingProviderAdditionalIdentifier>2010AA Medicare</REF02__BillingProviderAdditionalIdentifier>
            </ns0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA>
          </ns0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop>

So for the purposes of this blog entry I have created an output schema that creates an output row for each service line:

SampleOutputSchema

I first create some mapping so we can ensure that the map is creating the output correctly.

xsltmap1

Which creates this (so far so good):

<ns0:Root xmlns:ns0="http://BubbleUp.Output">
  <ServiceLine ChargeAmt="914"></ServiceLine>
  <ServiceLine ChargeAmt="5299"></ServiceLine>
</ns0:Root>

Now we get into the ’real work’

What we need to do is make the map query various portions of the xml document and because I am lazy, lets have the mapper do the heavy lifting for us:

Lets drag the REF02 from the 2420A loop into the MedicaidId and lets look at the XSL:

xsltmap2

and the resulting xsl is:

<xsl:attribute name="MedicaidId">
  <xsl:value-of select="s0:TS837Q2_2420_SubLoop/s0:TS837Q2_2420A_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A/REF02__RenderingProviderSecondaryIdentifier/text()" />
</xsl:attribute>

and since we are going to want it from the other loops, let’s get the other REF segments in xsl:

<xsl:attribute name="MedicaidId">
  <xsl:value-of select="../s0:TS837Q2_2310_SubLoop/s0:TS837Q2_2310B_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B/REF02__RenderingProviderSecondaryIdentifier/text()" />
</xsl:attribute>

<xsl:attribute name="MedicaidId">
  <xsl:value-of select="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AB_Loop/s0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB/REF02__PaytoProviderIdentifier/text()" />
</xsl:attribute>

<xsl:attribute name="MedicaidId">
  <xsl:value-of select="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AA_Loop/s0:REF_TS837Q2_2010AA_SubLoop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA/REF02__BillingProviderAdditionalIdentifier/text()" />
</xsl:attribute>

Now we need to write the ’bubble up’ logic:

The first thing is we need to query the correct REF01 qualifier

<xsl:value-of select="s0:TS837Q2_2420_SubLoop/s0:TS837Q2_2420A_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A[REF01__ReferenceIdentificationQualifier/text()='1D']/REF02__RenderingProviderSecondaryIdentifier/text()" />

and the other values in the other segments the same logic.

After that we merge all of these queries into a variable in a choose function:

<!--Lets create the Mediciad ID variable-->
<xsl:variable name="medicaidID">
  <xsl:choose>
    <xsl:when test="s0:TS837Q2_2420_SubLoop/s0:TS837Q2_2420A_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A/REF01__ReferenceIdentificationQualifier/text()='1D'">
      <xsl:value-of select="s0:TS837Q2_2420_SubLoop/s0:TS837Q2_2420A_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A[REF01__ReferenceIdentificationQualifier/text()='1D']/REF02__RenderingProviderSecondaryIdentifier/text()" />
    </xsl:when>
    <xsl:when test="../s0:TS837Q2_2310_SubLoop/s0:TS837Q2_2310B_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B/REF01__ReferenceIdentificationQualifier/text()='1D'">
      <xsl:value-of select="../s0:TS837Q2_2310_SubLoop/s0:TS837Q2_2310B_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B[REF01__ReferenceIdentificationQualifier/text()='1D']/REF02__RenderingProviderSecondaryIdentifier/text()" />
    </xsl:when>
    <xsl:when test="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AB_Loop/s0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB/REF01__ReferenceIdentificationQualifier/text()='1D'">
      <xsl:value-of select="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AB_Loop/s0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB[REF01__ReferenceIdentificationQualifier/text()='1D']/REF02__PaytoProviderIdentifier/text()" />
    </xsl:when>
    <xsl:when test="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AA_Loop/s0:REF_TS837Q2_2010AA_SubLoop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA/REF01__ReferenceIdentificationQualifier/text()='1D'">
      <xsl:value-of select="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AA_Loop/s0:REF_TS837Q2_2010AA_SubLoop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA[REF01__ReferenceIdentificationQualifier/text()='1D']/REF02__BillingProviderAdditionalIdentifier/text()" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="'Mediciad Id Not found'" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

Now lets take the result of the result of the choose function and populate the attribute:

<!--Now that we have found it, lets put the value as the attribute-->
<xsl:attribute name="MedicaidId">
  <xsl:value-of select="$medicaidID" />
</xsl:attribute>

So the last step in this is to implement the code in the map, because like all of the maps I have ever worked in, I already have logic I have created, I just need to enhance what I already have there. I copy the above xsl into a scripting (inline xslt) functiod and attach it to the MediaidId attribute:

xsltmap3

Now I need to find the MedicareId, so I simply replace the ID with 1C and change the variable name and attribute name I would have the following code:

<xsl:variable name="medicareID">
  <xsl:choose>
    <xsl:when test="s0:TS837Q2_2420_SubLoop/s0:TS837Q2_2420A_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A/REF01__ReferenceIdentificationQualifier/text()='1C'">
      <xsl:value-of select="s0:TS837Q2_2420_SubLoop/s0:TS837Q2_2420A_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2420A[REF01__ReferenceIdentificationQualifier/text()='1C']/REF02__RenderingProviderSecondaryIdentifier/text()" />
    </xsl:when>
    <xsl:when test="../s0:TS837Q2_2310_SubLoop/s0:TS837Q2_2310B_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B/REF01__ReferenceIdentificationQualifier/text()='1C'">
      <xsl:value-of select="../s0:TS837Q2_2310_SubLoop/s0:TS837Q2_2310B_Loop/s0:REF_RenderingProviderSecondaryIdentification_TS837Q2_2310B[REF01__ReferenceIdentificationQualifier/text()='1C']/REF02__RenderingProviderSecondaryIdentifier/text()" />
    </xsl:when>
    <xsl:when test="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AB_Loop/s0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB/REF01__ReferenceIdentificationQualifier/text()='1C'">
      <xsl:value-of select="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AB_Loop/s0:REF_PaytoProviderSecondaryIdentificationNumber_TS837Q2_2010AB[REF01__ReferenceIdentificationQualifier/text()='1C']/REF02__PaytoProviderIdentifier/text()" />
    </xsl:when>
    <xsl:when test="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AA_Loop/s0:REF_TS837Q2_2010AA_SubLoop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA/REF01__ReferenceIdentificationQualifier/text()='1C'">
      <xsl:value-of select="../../../s0:TS837Q2_2010A_SubLoop/s0:TS837Q2_2010AA_Loop/s0:REF_TS837Q2_2010AA_SubLoop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA_Loop/s0:REF_BillingProviderSecondaryIdentificationNumber_TS837Q2_2010AA[REF01__ReferenceIdentificationQualifier/text()='1C']/REF02__BillingProviderAdditionalIdentifier/text()" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="'Medicare Id Not found'" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:attribute name="MedicareId">
  <xsl:value-of select="$medicareID" />
</xsl:attribute>

Put it into a scripting functiod and you would have the following map:

xsltmap4

The output looks like this:

<ns0:Root xmlns:ns0="http://BubbleUp.Output">
  <ServiceLine ChargeAmt="914" MedicaidId="2420A Medicaid" MedicareId="2420A Medicare"></ServiceLine>
  <ServiceLine ChargeAmt="5299" MedicaidId="2310B Medicaid" MedicareId="2010AB Medicare"></ServiceLine>
</ns0:Root>

As a bonus: the client wanted to sum up Deductible and CoInsurance amounts from the CAS segment where the qualifier was 1 and 2 respectively, so the following example has that xsl included in it.

Here is the solution (BizTalk 2009 solution only: please don’t ask for 2006, as I don’t have time to make a version for that!)

Azure Integration Part 3 – Sending a Message from an ESB off-ramp to Azure AppFabric ServiceBus

Azure Integration Part 3 – Sending a Message from an ESB off-ramp to Azure AppFabric ServiceBus

This is the third post in this series. So far, we have seen:

In this third post, we will see how to use an ESB off-ramp to send a message to the Windows Azure AppFabric ServiceBus. We will actually be doing the same thing as we did in the second post, however, we’ll be doing it in a different way.

There is an accompanying video for this post (as I did with the others too), which you can find here.

The sequence used here is:

  1. Message is picked up from a file drop (because that’s how most BizTalk demos start:))
  2. An itinerary is retrieved from the itinerary repository and applied to the message
  3. The itinerary processing steps are performed, and the message is sent to the ServiceBus
  4. The message is retrieved by the receive location I wrote about in my previous post
  5. A send port has a filter set to pick up messages received by that receive port, and persists the file to disk

The last two steps are not covered here, but are shown in the video.

In this case, we’re not using an orchestration at all, we’ve specified in the itinerary that all processing happens at a messaging level.

The first part of this is the itinerary selection, which is as shown below. As you can see, I’ve “hard-wired” this receive location, and anything coming through it will get the “ServiceBusTest.OrderRelayNetTcp” itinerary applied to it.

image

The itinerary itself is also quite simple (this one is slightly different than the one shown in the video, but they are functionally equivalent).

image

All of the magic happens in the “SetProperties” resolver. In this case I am using a STATIC resolver, however, that just means I have statically specified the values. The settings are being applied dynamically by the itinerary processing components. Note that I have specified we are using the WCF-Custom adapter provider. As was the case with the first two posts in this series, I have installed the Windows Azure platform AppFabric SDK, which gave me some additional bindings that let me relay messages through the ServiceBus. In the second post, we used one of those bindings along with the WCF-Custom adapter by setting some values on a dynamic send port. In this one, we will set the same properties, but do so using the out-of-the-box ESB Toolkit WCF-Custom adapter provider. Each adapter provider registered with the ESB has a UI that can be associated with it, and you get there by clicking the Endpoint Configuration ellipses:

image

If you compare the values above to what I set in the second post in this series, you’ll see they are pretty much the same.

And. THAT’S IT!!!!! That is all we have to do in order for BizTalk to send a message to the Azure platform AppFabric ServiceBus using an ESB off-ramp. As you can see from the behavior specified, this is a secured channel (in this case I am using “shared secret”). The actual security part of this is provided with the Windows Azure platform AppFabric Access Control Service, which is tightly integrated with the ServiceBus.

Note also that in this example I used the netTcpRlayBinding, which is a high performance .NET-to-.NET, but also requires TCP/IP ports be open, which could be an issue depending on how locked down your network is.

For my demo purposes, I use the ws2007HttpRelayBinding (also provided with the Azure AppFabric SDK), as that’s over port 80.

image

In this series of posts I have shown you how to bridge the gap between on-premise and Windows Azure AppFabric ServiceBus using out-of-the-box BizTalk and/or ESB Toolkit components. There is much more that can be done, this is only the beginning. We are entering a really interesting time, and I think that “hybrid” applications, with some part on-premise, other parts off-premise, will become increasingly common. As that happens, having a clean integration solution becomes very important so that we don’t create “Point-to-point Spaghetti 2.0”, a more modern version of the chaos that many experienced integration developers have seen all too frequently.

I hope you’ve enjoyed these posts and videos, and that they help you as you explore the new and exciting world of Windows Azure.

Using Routes to Compose WCF WebHttp Services

Using Routes to Compose WCF WebHttp Services

This is part six of a twelve part series that introduces the features of WCF WebHttp Services in .NET 4.  In this post we will cover:



  • Composing multiple WCF WebHttp Services into a single web service

  • Using ASP.NET routes with WCF WebHttp Services

Over the course of this blog post series, we are building a web service called TeamTask.  TeamTask allows a team to track tasks assigned to members of the team.  Because the code in a given blog post builds upon the code from the previous posts, the posts are intended to be read in-order.


Downloading the TeamTask Code


At the end of this blog post, you’ll find a link that will allow you to download the code for the current TeamTask Service as a compressed file.  After extracting, you’ll find that it contains “Before” and “After” versions of the TeamTask solution.  If you would like to follow along with the steps outlined in this post, download the code and open the “Before” solution in Visual Studio 2010.  If you aren’t sure about a step, refer to the “After” version of the TeamTask solution.


Note:  If you try running the sample code and see a Visual Studio Project Sample Loading Error that begins with “Assembly could not be loaded and will be ignored”, see here for troubleshooting.


Getting Visual Studio 2010


To follow along with this blog post series, you will need to have Microsoft Visual Studio 2010 and the full .NET 4 Framework installed on your machine.  (The client profile of the .NET 4 Framework is not sufficient.)  At the time of this posting, the Microsoft Visual Studio 2010 Ultimate Beta 2 is available for free download and there are numerous resources available regarding how to download and install, including this Channel 9 video.


Step 1: Refactoring the TeamTask Service into Resources


So far the TeamTask service that we’ve been implementing over the past five blog posts has had a manageable number of operations.  The service exposes an operation for retrieving a list of tasks, another for updating a single user and a third for updating a single task.  All of these operations are implemented within a single class-the TeamTaskService class. 


There is nothing necessarily wrong with this single service class design.  However, as we add more operations, our TeamTaskService class will continue to grow and we’ll end up with one large monolithic class.  As has been shown time and time again, monolithic entities tend to be difficult to maintain and they make code reuse problematic.  If we intend to continue adding functionality to the TeamTask service (and we do), we would be well served to start thinking of our service as a collection of resources and refactor our code to reflect this new mentality.  


A resource is technically anything with an addressable state.  In HTTP, a given resource is addressable because it has an associated URI and its current state is represented in the response from an HTTP GET request. 


However, using a more informal mental model of a resource as just a “thing” can be helpful.  It’s pretty easy to divide our TeamTask service into “things”.  Our “things” happen to be tasks and users.  We’ll start by refactoring our single TeamTaskService class into two separate service classes that will better represent our resources: a TaskService and a UserService.




  1. If you haven’t already done so, download and open the “Before” solution of the code attached to this blog post.



  2. Rename the TeamTaskService.cs file to “TaskService.cs” by right-clicking on it in the “Solution Explorer” window (Ctrl + W, S) and selecting “Rename” from the context menu.  A dialog box should appear asking if you want to rename all references in the project to the code element “TeamTaskService”.  Select “Yes”.



  3. In the “Solution Explorer” window select the newly renamed TaskService.cs file and press Ctrl+C, Ctrl+V to create a copy of the TaskService.cs file in the TeamTask.Service project.  The new file should be named “Copy of TaskService.cs”.



  4. Rename the “Copy of TaskService.cs” file to “UserService.cs” by right-clicking on it in the “Solution Explorer” window and selecting “Rename” from the context menu.



  5. Open the UserService.cs file in the code editor.  Because this file is actually a copy of the TaskService.cs file, it will contain a second definition of the TaskService class.  Rename the class to “UserService”, making sure NOT to update references throughout the project.



  6. In the UserService.cs file, delete the GetTasks() and UpdateTask() operations since they apply to tasks.



  7. Likewise, in the TaskService.cs file, delete the GetUser() operation as it applies to users and not tasks.      






Helpful Tip: The concept of a resource is central to the set of architectural constraints that make up REST.  We won’t be discussing the theory behind REST but there are plenty of articles, wiki entries, and books that discuss REST in depth.  That said, the remainder of the posts in this blog series will demonstrate how to build web services that are more RESTful in nature with WCF WebHttp Services in .NET 4.


 


Step 2: Adding Routes for our Task and User Services


We now have two separate service classes: a TaskService class that contains all of the task related operations and a UserService class that contains all of the user related operations.  Having two separate service classes means that we now need a mechanism to indicate which service class should handle a given incoming request.  Routes happen to be this mechanism.


Routes provide a mapping from a base address path to a service class. Originally an ASP.NET feature, routes can be used with WCF WebHttp Services when ASP.NET compatibility mode is enabled.  We’ve actually been using routes all along.  We just weren’t using the feature in an interesting way since we only had a single route that mapped an empty string path to the now-defunct TeamTaskService class.


For the TaskService class, we will register the route path “Tasks”.  This means that only requests with a URI base address of the form “http://<baseAddress>/Tasks” will be handled by the TaskService.  Likewise, we will map the route path “Users” to the UserService class.


A benefit of using routes is that we can now simplify the UriTemplates associated with our service operations.  If you look at the UriTemplates used with the TaskService operations, you’ll notice that they both begin with a “Tasks” path segment.  Likewise, the single operation on the UserService class begins with a “Users” path segment.  We’ll cut these first path segments from our UriTemplates since our routes will now have this “routing” information. 


Before the refactoring we had really collapsed the “routing” information in our URIs into the “operation” information of the UriTemplates.  With the refactoring, we rectify this issue.  The diagram below shows the improved scheme for mapping from request URIs to service operations:


UriRoutingFigure     


Routes are registered in the Global.asax file.  If you’ve worked with ASP.NET before, you may be familiar with the Global.asax file.  It provides the capability to respond to application-level events.  In this case, we want to respond to the application start event, which will occur when IIS receives the very first request to the TeamTask service.  It is in the handler for the application start event that we will register our routes for the TaskService and UserService classes.




  1. Open the Global.asax file in the code editor.  You should find that the RegisterRoutes() method has a single route registered like so:


        private void RegisterRoutes()
        {
            RouteTable.Routes.Add(new ServiceRoute(“”,
                new WebServiceHostFactory(), typeof(TaskService)));
        }


    Note: If the service type being registered in your code is of type TeamTaskService, then the references to TeamTaskService were not correctly updated when the class was renamed to “TaskService” in step one.



  2. Replace the the RegisterRoutes() method with the following implementation:


        private void RegisterRoutes()
        {
            WebServiceHostFactory factory = new WebServiceHostFactory();
            RouteTable.Routes.Add(new ServiceRoute(“Tasks”, factory,
                typeof(TaskService)));
            RouteTable.Routes.Add(new ServiceRoute(“Users”, factory,
                typeof(UserService)));
        }


    This new implementation adds two ServiceRoute instances to the Routes collection of the static RouteTable.  The first ServiceRoute instance provides a mapping from the route path “Tasks” to the TaskService class and the second instance provides a mapping from the route path “Users” to the UserService class.



  3. Open the TaskService.cs file in the code editor and remove the “Task” path segments from the UriTemplate values on the GetTasks() and UpdateTask() operations like so:


        [WebGet(UriTemplate =
            “?skip={skip}&top={top}&owner={userName}&format={format}”)]
        public List<Task> GetTasks(int skip, int top, string userName, string format)


    and,


        [Description(“Allows the details of a single task to be updated.”)]
        [WebInvoke(UriTemplate = “{id}”, Method = “PUT”)]
        public Task UpdateTask(string id, Task task)



  4. Open the UserService.cs file in the code editor and remove the “User” path segments from the UriTemplate values on the GetUser() operation like so:


        [WebGet(UriTemplate = “{userName}”)]
        public User GetUser(string userName)






Helpful Tip: Routes in ASP.NET can actually include variables much like UriTemplates.  However, be aware that in WCF WebHttp Services in .NET 4 only literal route paths are supported, as UriTemplates already provide URI variable support.


 


Step 3: Adding the GetTask() Operation


With the refactoring complete, let’s add some new operations to round out the functionality provided by the TeamTask service.  We already have the GetUser() operation for retrieving the details of a single user, but we don’t have a similar operation for retrieving the details of a single task.  So let’s add a GetTask() operation that will perform this function.


The GetTask() operation will use some of the same logic that the UpdateTask() uses. So we’ll first refactor some of the UpdateTask() method’s logic into private methods and then we’ll implement the GetTask() operation to use these private methods.




  1. Open the TaskService.cs file in the code editor.



  2. In the UpdateTask() method, select the entire “if” block in which the task id is parsed and right-click.  In the context menu that appears, select “Refactor”->”Extract Method”.  In the “Extract Method” dialog box that appears, enter “ParseTaskId” as the name for the new method and press enter.  The new ParseTaskId() method should look like the following:


        private static int ParseTaskId(string id)
        {
            int parsedId;
            if (!int.TryParse(id, out parsedId))
            {
                throw new WebFaultException<string>(
                   string.Format(
                       “The value ‘{0}’ is not a valid task id. The id must be an integer.”
                       id), HttpStatusCode.BadRequest);
            }
            return parsedId;
        }



  3. Also in the UpdateTask() method, select the code within the “catch” block and right-click.  In the context menu that appears, select “Refactor”->”Extract Method”.  In the “Extract Method” dialog box that appears, enter “ThrowNoSuchTaskId” as the name for the new method and press enter.  The new ThrowNoSuchTaskId() method should look like the following:


        private static void ThrowNoSuchTaskId(int parsedId)
        {
            throw new WebFaultException<string>(
               string.Format(“There is no task with the id ‘{0}’.”, parsedId),
               HttpStatusCode.NotFound);
        }


    Note: Both of these new private methods throw a WebFaultException.  The WebFaultException class is new in WCF WebHttp Services in .NET 4.  It was discussed in part five of this blog post series.



  4. With the new ParseTaskId() and ThrowNoSuchTaskId() methods, the implementation of the GetTask() operation is straightforward.  Copy the following code into the TaskService class:


        [Description(“Returns the details of a single task.”)]
        [WebGet(UriTemplate = “{id}”)]
        public Task GetTask(string id)
        {
            int parsedId = ParseTaskId(id);
            using (TeamTaskObjectContext objectContext =
                      new TeamTaskObjectContext())
            {
                var task = objectContext.Tasks.FirstOrDefault(t => t.Id == parsedId);
                if (task == null)
                {
                    ThrowNoSuchTaskId(parsedId);
                }
                return task;
            }
        }



  5. You may notice that the GetTask() operation uses the same UriTemplate as the UpdateTask() operation.  The difference between the two operations is the associated HTTP method: the UpdateTask() operation uses a [WebInvoke] attribute with the method set to “PUT” while the GetTask() operation uses a [WebGet] attribute, which is always for HTTP GET requests.



  6. Start without debugging (Ctrl+F5) and use the browser of your choice to navigate to http://localhost:8080/TeamTask/Tasks/1.  In Internet Explorer, the single task will be displayed as shown below:


    SingleTaskInBrowser_sansUserNames


Step 4: Adding the GetUsers() Operation


Lastly, for the sake of completeness we’ll also add a GetUsers() operation that will return a list of users just like the GetTasks() operation returns a list of tasks.




  1. Open the UserService.cs file in the code editor and add the following implementation of the GetUsers() operation:


        [Description(“Returns the users on the team.”)]
        [WebGet(UriTemplate = “?skip={skip}&top={top}&manager={userName}”)]
        public List<User> GetUsers(int skip, int top, string userName)
        {
            // Set reasonable defaults for the query string parameters
           
    skip = (skip >= 0) ? skip : 0;
            top = (top > 0) ? top : 25;

            using (TeamTaskObjectContext objectContext =
                      new TeamTaskObjectContext())
            {
                // Include the where clause only if a userName was provided
               
    var userQuery = (string.IsNullOrWhiteSpace(userName)) ?
                    objectContext.Users :
                    objectContext.Users.Where(
                        user => user.ManagerUserName == userName);

                return userQuery.OrderBy(user => user.UserName)
                                       .Skip(skip).Take(top).ToList();
            }
        }


    The GetUsers() operation is very similar to the GetTasks() operation introduced in the first part of this blog post series.  The only difference is that GetUsers() operation provides the ability to filter the list of users by the user’s manager whereas the GetTasks() operation provided the ability to filter by task owner.



  2. Start without debugging (Ctrl+F5) and use the browser of your choice to navigate to http://localhost:8080/TeamTask/Users?manager=user4.  In Internet Explorer, the list of users will be displayed as shown below: 


    ListOfUsersInBrowser_sansUserNames


Next Steps: Integrating ASP.NET Output Caching with WCF WebHttp Services


We performed a lot of code refactoring in this part of the blog post series.  But by starting to think of the TeamTask service in terms of resources, we’re in a much better position to add features and functionality to the service.  Involved in this refactoring was the use of the new ASP.NET routes integration feature introduced with WCF WebHttp Services in .NET 4.


In part seven of this blog post series we’ll take a look at another ASP.NET integration feature introduced with WCF WebHttp Services in .NET 4: declarative output caching.


Randall Tombaugh
Developer, WCF WebHttp Services

Microsoft Hotfix BizTalk Server 2009/VS 2008

Microsoft Hotfix BizTalk Server 2009/VS 2008

I am currently quite active on BizTalk forums and must say it is a great experience for me helping out people in field. It gives me great satisfaction to be able to share some of experience and knowlegde around BizTalk Server and integration. You see some people having difficulties around VS 2008 and BizTalk Server 2009: like broken schema references. There is a hotfix out that will, I quote:

“On a computer that is running Microsoft BizTalk Server 2009, you use Microsoft Visual Studio to develop a BizTalk application. In your BizTalk project, you add a reference to another BizTalk project. In this scenario, you may see the following behavior:

  • The orchestrations in the referenced BizTalk project may show compiler warnings.
  • The changes that are made to the referenced BizTalk project are not propagated on to the referencing project.
  • When you edit the orchestrations of the referenced project, XLANG errors are thrown. These errors may disappear after the orchestrations are saved and recompiled.
  • After you deploy the referencing project, the local copies of the referenced project’s binaries are deleted.
  • After you deploy the referencing project, various errors or warnings occur in Orchestration Designer.”

belong to the past. You will need to send request to Microsoft to download it. Once you have it you can apply it on your machine. Extract hotfix zipfile type in password Microsoft has sent via email (with download link).Apply hotfix

You can check if has applied it by going to file directory of Microsoft.visualstudio.biztalkproject.dll (see screen below).

Apply hotfix 2

Hopefully this hotfix will give BizTalk Developers less pain and make them more productive.

Technorati:

Twin Cities Cloud Computing User Group presentation

Twin Cities Cloud Computing User Group presentation

I had a great time presenting at the TC Cloud Computing User group about a week ago.  The group is still kind of small, but growing rapidly and pulling together good content as well as hands-on opportunities for people to get going on cloud technologies.  This particular presentation was on the Azure platform AppFabric (ServiceBus and Access Control).  For those of you who attended, the demos I used are in the attachments as I mentioned