If you're using BizTalk Server maps, it is about 99.999% likely that you are using logic in them.  Testing this functionality in Visual Studio can be tedious as the only way to change the test document is in the properties of the map.  So if you have quite a few scenarios to test, this method sucks.  BizTalk Server 2000 and 2002 allowed you to select the test document at runtime, which was nice I suppose but it still meant that you had to do it manually all the time.

With the exception of either figuring out how to use BizUnit and actually deploying your solution, there are not too many ways to quickly test multiple scenarios of documents in your maps.  I wanted to create a series of tests for a project that I was working on so that I could very quickly test the outcome of my BizTalk Server maps and essentially 'tick some boxes' before moving in to system testing.  There is nothing worse than a BizTalk Server deploy just to find out you've forgotten something that is key in your map.

Using BizTalk Server Maps in Code

I use Test Projects in Visual Studio to do a majority of my unit tests have recently stopped using NUnit.  What I wanted was a nice way to simply perform multiple BizTalk Server map tests at the click of a button.  Saving me a great deal of time and helping me to ensure my deployments contain maps that fulfil the project requirements.

I'll not go in to how to create the actual test projects, the purpose of this article is to call a BizTalk Server map in code so that we can examine the output.

In order to reference BizTalk Server maps, you must first add a reference to Microsoft.XLANGs.BaseTypes which can be found in C:\Program Files\Microsoft BizTalk Server 2006\Microsoft.XLANGs.BaseTypes.dll or wherever you ended up installing BizTalk Server.  Once you have this, it's actually pretty simple (although it took me a while to figure everything out and I was trying to do stuff manually that was already done for me).

Below is the code I used to execute a map.

// Create an instance of the map from the BizTalk Server project
MyBizTalkProjects.Schemas.MapProduct map = new MyBizTalkProjects.Schemas.MapProduct();

// Create an XPath document based on the XML file that is our source
System.Xml.XPath.XPathDocument source;

// Open the XML document from the file system and load it in to the XPath document
using (
    System.IO.StreamReader sRead = new StreamReader(
        @"D:\BraitrimDotNet\BizTalk\Schemas TestProject\EBizDocuments\DespatchConfirmation.xml"
        )
    )
{
    source = new System.Xml.XPath.XPathDocument(sRead);
}

// This took a while to figure out.  Essentially the map is a fully declared XslTransform.  as such, the
// extension objects (i.e. functiod references) are already referenced and so we can use this reference
// rather than trying to build it ourselves.
System.Xml.Xsl.XsltArgumentList args = map.TransformArgs;

// Set the XmlReader to the transorm.
System.Xml.XmlReader xReader = map.Transform.Transform(source, args);

// Perform the transform and load it in to an XmlDocument for examination
System.Xml.XmlDocument result = new System.Xml.XmlDocument(xReader.NameTable);
result.Load(xReader);

Once I have the XmlDocument, I can simply use XPath queries to check values in the XML match my anticipated output.

In Visual Studio, I essentially create a test method for piece of map logic that I want to test.  That way, when I run my tests from the Test View window, I can quickly see what has worked and what has not.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I tend to spend a lot of time adding assemblies to the GAC (Global Assembly Cache) in order to run unit tests or work with BizTalk Server assemblies.  Usually, I'll do this using the Visual Studio command prompt or the .Net configuration tool. I wanted to find a marginally quicker way to add assemblies to the GAC so I started to look at the 'Send To' menu.

In order to add shortcuts to your 'Send To',  simply navigate to the following folder:

  • C:\Documents and Settings\<User Name>\SendTo

In here you can create simple shortcuts to applications.  So for example you can add a 'Send To Notepad' shortcut.  I'm not going to go in to all of the detail of creating a shortcut here though.

What I wanted to do was add shortcut to gacutil.exe.  The first thing to think about is where Microsoft decided to put the thing in your particular version of .Net.  To help you here, I created a little list of places that you are likely to find gacutil.exe for different versions of the framework

Framework Version Possible Locations
1.0 C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705
1.1 C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322
2.0 C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\
3.0 C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin  (not too sure about this one)
3.5 C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin

Once you've located your gacutil.exe, create a shortcut to it in the SendTo folder mentioned above.  In order to get it to work, simply modify the target of the shortcut so that there is a '/i' at the end of the target (outside of the quotes) as in the following diagram:

SendToGAC

That should do it, from now on you should get the following in your context menu:

SendToGAC_inuse


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I ran in to this problem recently while developing a solution for a client.  For me it took a little while to figure out what was happening and the error was reported to be coming from a send shape that sent a message of type System.Xml.XmlDocument.

While this is the correct place for the error to be raised, it was not strictly related to them message that I was trying to send.

The actual cause of the problem is that I have a class that is used to return information back from a series of helper methods in a library that I have built.  The class has 3 public properties:

  • Result: An inumeration indicatign the level of success
  • Document: when successful, this is an XML document otherwise, it is null.
  • Exception: this is null if the call was successful, otherwise it contains all relevant information to describe the failure.

Document is a System.Xml.XmlDocument and it is this that is causing the error.  Essentially, BizTalk Server seems to be trying to serialize this class, either for dehydration, analyst reporting or some other reason.  All we need to do to avoid this error is simply mark the property as nonserializable, I.e:

/// <summary>
/// Contains the result of a receipt processing attempt.
/// </summary>
[Serializable()]
public class ReceiptResult
{
    private ReceiptSuccessResult _result;
    [NonSerialized()]
    private XmlDocument _document;
    private ReceiptException _exception;

    /// <summary>
    /// Gets the overall result of the validation attempt.
    /// </summary>
    public ReceiptSuccessResult Result
    {
        get { return this._result; }
    }

    /// <summary>
    /// Gets any XML document that may have been returned from the validation attempt.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode")]
    public XmlDocument Document
    {
        get { return this._document; }
    }

    /// <summary>
    /// Gets any exception that was returned from the validation attempt.
    /// </summary>
    public ReceiptException Exception
    {
        get { return this._exception; }
    }

    public ReceiptResult(ReceiptSuccessResult result)
    {
        this._result = result;
    }

    public ReceiptResult(ReceiptSuccessResult result, XmlDocument document)
    {
        this._result = result;
        this._document = document;
    }

    public ReceiptResult(ReceiptSuccessResult result, ReceiptException exception)
    {
        this._result = result;
        this._exception = exception;
    }
}

After that (for me at least) the error goes away.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

Overview

The above message can be quite frustrating if you don't know why you are getting it.  Microsoft's take on this particular error message when you try to compile you BizTalk Server project is pretty much detailed in the article:

One of the times I have come across this problem is when I want to create a message in an orchestration that is not the result of a transform.  At first I was confused by this error, but it does sort of make sense.  To resolve the issue I figured that, if Visual Studio can create a document instance, then so can I.

The Problem

Consider the following scenario:

An orchestration wants to call a web service to save some data away to a third-party service.  Should this web service raise an exception for any reason, I want to create an instance of a message that contains an error report and then send it off to another orchestration for processing.  For this purpose I have create a schema for my error report message.  I don't have ownership of the web service, so I will make my call to it in a Scope shape and to that scope shape, I will add an exception handler to contain my error reporting.

All I want to do is set four properties in my error message; sender email, recipient email, subject and body.  If I just use a Message Assignment shape inside a Construct Message shape and try to set these properties, we get the error.

Solution

Using a couple of the less-than-well documented assemblies, we can create an empty XML instance of our document schema.  To do this, I added a helper class to my solution that would contain a series of helpers that could create an instance of a specified document schema.  These can be found in the following location on your BizTalk Server:

C:\Program Files\Microsoft BizTalk Server 2006\Microsoft.BizTalk.Pipeline.dll

C:\Program Files\Microsoft BizTalk Server 2006\Microsoft.XLANGs.BaseTypes.dll

using Microsoft.BizTalk.Component.Interop;
using Microsoft.XLANGs.BaseTypes;

Following that, I simply need to create a method for each message I need to create.  So for my error message type, I created the following:

/// <summary>
/// Creates an empty instance of the Error Message schema.
/// </summary>
/// <remarks>
/// Error handling has been left out in the hope that BizTalk Server might be able to raise the error message.
/// </remarks>
/// <returns>XmlDocument instance of the EBiz ErrorMessage schema</returns>
public static XmlDocument ConstructEBizErrorMessage()
{
    Type MessageSchemaType = typeof(TestProject.BizTalk.EBiz.ErrorMessage);

    DocumentSpec DocumentSpecification = new DocumentSpec(
        MessageSchemaType.FullName,
        MessageSchemaType.Assembly.FullName
        );

    XmlDocument SchemaInstance = new XmlDocument();
    using (StreamReader InstanceStreamReader = new StreamReader(DocumentSpecification.GetDocSchema().CreateXmlInstance()))
    {
        SchemaInstance.Load(InstanceStreamReader);
    }
    
    return SchemaInstance;
}

The class library with this method is then referenced by my BizTalk Server project that contains the orchestration and can be called from within a Message Assignment shape to effectively initialize the instance of the message so that the properties can be set.

The nice thing is, when I update my schema in the BizTalk Server project, this helper class needs no updating and will just work.

Lovely - time for a cup of tea. :)

Versions Metadata

Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I found these two great articles on MSDN about performance and scaling of ASP.Net applications.  They're well worth a read in my opinion.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist