Archive

Archive for the ‘Development’ Category

Automated testing of Azure Biztalk Services maps

March 4, 2016 LeandroDG No comments

Azure BizTalk Services (also known as WABS: Windows Azure Biztalk Services and MABS: Microsoft Azure Biztalk Services) enables Biztalk-like services that run on the cloud.

Like BizTalk Server, Azure BizTalk Services include a mapping/transform services is included. This service can be invoked to perform XML mapping in Azure Logic Apps.

Unlike regular BizTalk, there’s nothing included in the SDK to perform automated map testing.

After playing around with Reflection and the Visual Studio Extension assemblies included in the Biztalk Services SDK, we are now able to programatically test Biztalk Services maps (maps with trfm extension).

I created a simple helper class that can be used to test the map.

All you need to do is call the static MapTester.TestMap method with the map file path and the input file path. Here’s a sample test call:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BizTalkServicesTesting.Helpers;
using System.IO;

namespace BizTalkServicesTesting.Tests
{
    [TestClass]
    public class MapUnitTests
    {
        [TestMethod]
        public void SampleMapTest()
        {
            var mapFilePath = @"..\..\..\BiztalkServicesTesting.Artifacts\Map.trfm";
            var inputFilePath = @"SampleInput.xml";
            var testMapResult = MapTester.TestMap(mapFilePath, inputFilePath);

            Assert.AreEqual(true, testMapResult.Success);
            Assert.AreEqual(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<ns1:Root xmlns:ns0=""http://tempuri.org/Schema1.xsd"" xmlns:ns1=""http://tempuri.org/Schema2.xsd"">
  <ns1:Target1>Source1_0</ns1:Target1>
  <ns1:Target2>Source2_0</ns1:Target2>
</ns1:Root>", testMapResult.OutputText);
        }
    }
}

In order to be able to use this library, we need to reference several Azure BizTalk Services SDK assemblies. To avoid licensing issues I haven’t provided included them in the post, you can download the SDK from here: https://www.microsoft.com/en-us/download/details.aspx?id=39087

These are the libraries you need to add them to the Lib folder in the downloaded source code, or add as references in your unit test projects if you download the compiled version. Once the SDK is installed, they can be found in the following path “C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\Windows Azure BizTalk Services SDK”.

  • Microsoft.ApplicationServer.Integration.Common.Core.dll
  • Microsoft.ApplicationServer.Integration.Common.dll
  • Microsoft.ApplicationServer.Integration.Pipeline.dll
  • Microsoft.ApplicationServer.Integration.Services.Pipeline.Tracing.dll
  • Microsoft.ApplicationServer.Integration.Transforms.BaseFunctoids.dll
  • Microsoft.ApplicationServer.Integration.Transforms.Common.dll
  • Microsoft.ApplicationServer.Integration.Transforms.Compiler.Common.dll
  • Microsoft.ApplicationServer.Integration.Transforms.Compiler.XamlGenerator.dll
  • Microsoft.ApplicationServer.Integration.Transforms.MapCompiler.dll
  • Microsoft.ApplicationServer.Integration.Transforms.MapOM.dll
  • Microsoft.ApplicationServer.Integration.Transforms.Mapper.OM.dll
  • Microsoft.ApplicationServer.Integration.Transforms.Runtime.BuiltInFunctions.dll
  • Microsoft.ApplicationServer.Integration.Transforms.Runtime.dll
  • Microsoft.ApplicationServer.Integration.Transforms.TOM.dll

This is how it works:

// Create output temp file name
var outputFilePath = Path.GetTempFileName();

// Get MapCompiler type and methods
var mapCompilerType = Type.GetType("Microsoft.ApplicationServer.Integration.Transforms.MapCompiler.MapCompiler, Microsoft.ApplicationServer.Integration.Transforms.MapCompiler");
var mapCompilerTestMapMethod = mapCompilerType.GetMethod("TestMap");

// Get TestMapConfiguration type and create instance
var testMapConfigurationType = Type.GetType("Microsoft.ApplicationServer.Integration.Transforms.MapCompiler.TestMapConfiguration, Microsoft.ApplicationServer.Integration.Transforms.MapCompiler");
var testMapConfigurationInstance = testMapConfigurationType.GetConstructor(new Type[] { typeof(Dictionary<String, Object>) }).Invoke(new object[] { new Dictionary<String, Object>() });

// Get TestMapResult type and properties
var testMapResultType = Type.GetType("Microsoft.ApplicationServer.Integration.Transforms.MapCompiler.TestMapResult, Microsoft.ApplicationServer.Integration.Transforms.MapCompiler");
var testMapResultOutputFileWrittenProperty = testMapResultType.GetProperty("OutputFileWritten");
var testMapResultErrorsProperty = testMapResultType.GetProperty("Errors");
var testMapResultWarningsProperty = testMapResultType.GetProperty("Warnings");

// Get MapError type and properties
var mapErrorType = Type.GetType("Microsoft.ApplicationServer.Integration.Transforms.Common.MapError, Microsoft.ApplicationServer.Integration.Transforms.Common");
var mapErrorErrorMessageProperty = mapErrorType.GetProperty("ErrorMessage");

// Invoke MapCompiler TestMap method
dynamic testMapResult = mapCompilerTestMapMethod.Invoke(null, new object[] { mapFilePath, inputFilePath, outputFilePath, testMapConfigurationInstance });

// Process TestMap results
var result = new ExecutionResult();
result.Errors = ((IEnumerable<dynamic>)testMapResultErrorsProperty.GetValue(testMapResult)).Select(e => mapErrorErrorMessageProperty.GetValue(e)).Cast<string>().ToArray();
result.Warnings = ((IEnumerable<dynamic>)testMapResultWarningsProperty.GetValue(testMapResult)).Select(e => mapErrorErrorMessageProperty.GetValue(e)).Cast<string>().ToArray();
var outputMessageWritten = (bool)testMapResultOutputFileWrittenProperty.GetValue(testMapResult);

if (outputMessageWritten)
{
    result.OutputText = File.ReadAllText(outputFilePath);

    if (result.Errors.Length == 0)
        result.Success = true;
}

Downloads:
BizTalk Services Testing Source Code (42)
BizTalk Services Testing Binaries (30)

VN:F [1.9.11_1134]
Rating: 5.0/5 (2 votes cast)

Call REST services from BizTalk Server 2010

March 14, 2011 LeandroDG 7 comments

I was having some trouble consuming REST services from Biztalk Server 2010.

The first and easy thing to try is creating a Send Port with WCF-Custom adapter and configuring webHttpBinding as the binding and webHttpBehavior as the behavior.

But it doesn’t work inmediately, when you send a message with this configuration, you’ll get the following error:

The adapter failed to transmit message going to send port "SampleSendPort" with URL "http://localhost/SampleSite". It will be retransmitted after the retry interval specified for this Send Port. Details:"System.InvalidOperationException: Manual addressing is enabled on this factory, so all messages sent must be pre-addressed."

So, I tried another solution that I read around, use webHttpBehavior but instead of webHttpBinding, use a custom binding just like webHttpBinding but with manual addressing turned off. This looks like this:

The problem is that webHttpBehavior expects ManualAddressing to be turned on, so it throws this error:

The adapter failed to transmit message going to send port "SampleSendPort" with URL "http://localhost/SampleSite". It will be retransmitted after the retry interval specified for this Send Port. Details:"System.InvalidOperationException: In the endpoint at 'http://localhost/SampleSite', in order to use 'System.ServiceModel.Description.WebHttpBehavior', the 'HttpTransportBindingElement' of the binding must have ManualAddressing set to true."

So, I got rid of webHttpBehavior, and the messages were being sent without issues. If the endpoint couldn’t be reached, it would throw an error correctly in Biztalk and the message instance would get suspended. But when the server threw a 500 error (Internal Server Error), the message would dissappear and no error would show up.

Finally I decided to use webHttpBinding, webHttpBehavior but also add a custom behavior that configures the address and the method for the call. I took the code for this from here: http://social.msdn.microsoft.com/Forums/eu/biztalkesb/thread/c19d7486-0705-433f-8e1a-a9088d076ed7. And it ends up looking like this:

WebManualAddressingBehavior.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.Configuration;

namespace Logue.Library.WebManualAddressingBehavior
{
    public class WebManualAddressingBehavior : IEndpointBehavior, IClientMessageInspector
    {
        public string Method { get; set; }
        public Uri ManualAddress { get; set; }

        public WebManualAddressingBehavior()
        {
        }

        public WebManualAddressingBehavior(string _method, Uri manualAddress)
        {
            Method = _method;
            ManualAddress = manualAddress;
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(this);
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            request.Headers.To = ManualAddress;
            HttpRequestMessageProperty property = new HttpRequestMessageProperty();
            property.Method = Method;
            property.SuppressEntityBody = true;
            request.Properties.Add(HttpRequestMessageProperty.Name, property);

            return request;
        }
    }
}

WebManualAddressingBehaviorExtensionElement.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.Configuration;

namespace Logue.Library.WebManualAddressingBehavior
{
    public class WebManualAddressingBehaviorExtensionElement : BehaviorExtensionElement
    {
        //Constructor to create instance of endpoint behavior and initialize with two property values.
        protected override object CreateBehavior()
        {
            return new WebManualAddressingBehavior(Method, ManualAddress);
        }

        public override Type BehaviorType
        {
            //Return configuration element type to be used in the behavior.
            get
            {
                return typeof(WebManualAddressingBehavior);
            }
        }

        [ConfigurationProperty("Method", DefaultValue = "GET", IsRequired = true)]
        public string Method
        {
            get
            {
                return (string)base["Method"];
            }
            set { base["Method"] = value; }
        }

        [ConfigurationProperty("ManualAddress", DefaultValue = "", IsRequired = true)]
        public Uri ManualAddress
        {
            get
            {
                return (Uri)base["ManualAddress"];
            }
            set { base["ManualAddress"] = value; }
        }

        //Copies the content of the specified configuration element to this configuration element
        public override void CopyFrom(ServiceModelExtensionElement extFrom)
        {
            base.CopyFrom(extFrom);
            WebManualAddressingBehaviorExtensionElement element = (WebManualAddressingBehaviorExtensionElement)extFrom;
            Method = element.Method;
        }

        //Represents a collection of configuration-element properties
        private ConfigurationPropertyCollection _properties;

        /// Both properties are returned as a collection.
        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                if (_properties == null)
                {
                    _properties = new ConfigurationPropertyCollection();
                    _properties.Add(new ConfigurationProperty("Method", typeof(string), "", ConfigurationPropertyOptions.IsRequired));
                    _properties.Add(new ConfigurationProperty("ManualAddress", typeof(Uri), "", ConfigurationPropertyOptions.IsRequired));
                }
                return _properties;
            }
        }
    }
}

You need to GAC this behavior assembly and modify both 32-bit and 64-bit machine.configs, in the following paths: “%WINDIR%Microsoft.NETFrameworkv4.0.30319Configmachine.config” and “%WINDIR%Microsoft.NETFramework64v4.0.30319Configmachine.config”.

In the system.serviceModel/extensions/behaviorExtensions section, add the following line:

<add name="webManualAddressingBehavior" type="Logue.Library.WebManualAddressingBehavior.WebManualAddressingBehaviorExtensionElement, Logue.Library.WebManualAddressingBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=be30eb01119b89a8" />

It should look like this:

And then, you should be able to add it to the send port configuration, so you can set the method and the address:

When configured like this, an error on server side will generate an exception on Biztalk send port as expected, like this:

The adapter failed to transmit message going to send port "SampleSendPort" with URL "http://localhost/SampleSite". It will be retransmitted after the retry interval specified for this Send Port. Details:"System.ServiceModel.CommunicationException: Internal Server Error

Downloads:
WebManualAddressingBehavior Source Code (311)
WebManualAddressingBehavior Binaries (228)

VN:F [1.9.11_1134]
Rating: 3.8/5 (5 votes cast)
Categories: Development Tags: , ,

Tellago Studios SO-Aware at Microsoft TechReady!

February 15, 2011 adglopez No comments

Tellago Studios’ Chief Architect Jesus Rodriguez will be presenting a session about SOA Governance on the Microsoft platform using SO-Aware at Microsoft TechReady.

This week Microsoft is hosting the first edition of their annual TechReady conference. Even though TechReady is an internal conference, Microsoft invited us to present a session about how to enable Agile SOA Governance on the Microsoft platform using our recently release product: SO-Aware.

As part of our session, we will take a look at the current challenges that organizations face when enabling SOA governance capabilities on the Microsoft platform and how organizations can benefit from  more agile, lightweight and modern SOA governance models.

The session will provide a practical view to the role of Tellago Studios’ SO-Aware as an essential technology to enable native SOA governance on the Microsoft platform. We will explore in detail important capabilities of SO-Aware such as

  • Centralized service repository
  • Centralized configuration management
  • Service testing
  • Monitoring
  • Transparent integration with technologies such as Visual Studio, BizTalk Server, Windows Server & Azure AppFabric among many others

But the fun doesn’t stop there…..

As part of this session, we will showcase for the first time our upcoming SO-Aware Test Workbench product which enables load and functional web service testing capabilities on the Microsoft technology stack.

SO-Aware Test Workbench provides developers with a visually rich environment to model and control the execution of load and functional tests in a SOA infrastructure. This tool includes the first native WCF load testing engine allowing developers to transparently load test applications built on Microsoft’s service oriented technologies such as WCF, BizTalk Server or the Windows Server or Azure AppFabric.

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)

SO-Aware at TechReady!

I’m happy to announce that Tellago will be presenting a session on Techready on SOA governance using our product SO-Aware!

And for the first time we will be presenting SO-Aware Test Workbench, an environment that allows modelling and controlling execution of load and functional tests in a SOA infrastructure.

More information at: http://www.tellagostudios.com/blog/so-aware-highlighted-microsoft-techready

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)
Categories: Development Tags: ,

Windows Azure AppFabric Labs September release: announcement and scheduled maintenance

September 15, 2010 adglopez No comments

For those of you that have been playing with AppFabric Labs, take into account the following announcement.

If you’ve been doing tests, they are letting us know that after the scheduled tasks, current configurations will not be maintained and you’ll need to backup and restore them manually.

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)