Navigation

Search

Categories

 
 

On this page

How to change the IncludeExceptionDetailInFaults property value
Managing exceptions in WCF
CS2007 Starter Site CTP available
Error - "Identifier expected" when the pipeline is compiling
Biztalk AddIn for Reflector
New version of BizTalkGenerateStrongName tool
Get the connection string to BizTalkMgmtDb
BizTalk Server 2006 project properties
Custom GetContextProperty Functoid

Archive

Blogroll

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 21
This Year: 0
This Month: 0
This Week: 0
Comments: 29

Sign In
Pick a theme:

 Friday, May 04, 2007
Friday, May 04, 2007 3:20:34 PM (GMT Standard Time, UTC+00:00) ( WCF )

In WCF service, one service can send managed exception information in the detail SOAP faults from service to client using the IncludeExceptionDetailInFaults property.  By default its value is false, but you can chage it; in this post I'll show the possible ways to change this value using different techniques.

Using config file

This is the most common way, to do it you must specify in the config file of the WCF service the includeExceptionDetailFaults attribute to true.  With this action every endpoint associated to WCF service will send managed exception information. 

<system.serviceModel>
    <services>
        <service name="devdeo.WCF.DebugService"
                         behaviorConfiguration="DebugServiceConfiguration">
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="DebugServiceConfiguration">
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

Using code

One way is setting the IncludeExceptionDatailInFaults property to true using the ServiceBehaviorAttribute. 

[ServiceContract(Namespace="http://wcf.devdeo.com/debug/")]
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class DebugService
{ }

Also, you can get the behaviors associated to WCF service using the Behaviors property and search the behavior that is related with the ServiceDebugBehavior object and set its property to true.

[ServiceContract(Namespace=http://wcf.devdeo.com/debug/)] 
public class DebugService { } using (ServiceHost host = new ServiceHost(typeof(DebugService))) { ServiceDescription svcDesc = host.Description.Behaviors; ServiceDebugBehavior svcDebug = svcDesc.Behaviors.Find<ServiceDebugBehavior>(); svcDebug.IncludeExceptionDetailInFaults = true; host.Open(); }

Enable the property partially

Supose that you have a WCF service with two endpoint: debubep1 and debugep2  (see below the config file that represent the configuration), now you need that only the endpoint called debugep1 sends managed exception information. 

<system.serviceModel>
    <services>
        <service name="devdeo.WCF.DebugService"
            behaviorConfiguration="DebugServiceConfiguration"> 
            <endpoint address="net.tcp://localhost:8009/wcf/debugep1"
                binding="netTcpBinding"
                bindingName="debugep1"
                bindingNamespace="http://wcf.devdeo.com/binding/"
                contract="devdeo.WCF.DebugService" />
            <endpoint address="net.tcp://localhost:8009/wcf/debugep2"
                binding="netTcpBinding"
                bindingName="debugep2"
                bindingNamespace="http://wcf.devdeo.com/binding/"
                contract="devdeo.WCF.DebugService" />
        </service>
        <behaviors>
            <serviceBehaviors>
                <behavior name="DebugServiceConfiguration">
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
        </behaviors> 
    </services>
</system.serviceModel>

To implement this, you must create a custom service class that derives from Attribute class and IServiceBehavior interface.  After it, override the ApplyDispatcherBehavior method to evaluate each endpoint reprensted by the ChannelDispatcher class and change the IncludeExceptionDetailInFaults to true.

The ApplyDispatcherBehavior method allows to change run-time property values or insert custom extension objects such as error handlers, message or parameter interceptors, security extensions, and other custom extension objects. 

[ServiceContract(Namespace = "http://wcf.devdeo.com/debug/")]
[CustomDebugBehavior]
public class DebugService
{ }

public class CustomDebugBehaviorAttribute : Attribute, IServiceBehavior
{
    #region IServiceBehavior Members
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, 
        System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, 
        System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
        // to-do...
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            if (cd.BindingName.Equals("http://wcf.devdeo.com/binding/:debugep1"))
                cd.IncludeExceptionDetailInFaults = true;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        // to-do...
    }
    #endregion
}

At the end, start the WCF service normally. 

using (ServiceHost host = new ServiceHost(typeof(DebugService))) {
    host.Open();
    ...
}

 

Remember that returning managed exception information to services can be a security risk.  This is because exception details expose information about the internal client implementation that could be used by unauthorized services.

NOTE: you can read the spanish version of this post at Propiedad IncludeExceptionDetailInFaults en WCF

 Monday, April 30, 2007
Monday, April 30, 2007 12:33:08 PM (GMT Standard Time, UTC+00:00) ( WCF )

WCF uses SOAP fault objects to transmit exceptions from a service to a client and, in the duplex case, from a client to a service in an interoperable way. Inside this scope, there are two types of SOAP faults that can be sent, declared and undeclared SOAP faults.  Declared SOAP faults are those in which an operation has a System.ServiceModel.FaultContractAttribute that specifies a custom SOAP fault type.  Undeclared SOAP faults are those that are not specified in the contract for an operation.

This post shows the implementation of declared SOAP fault objects using both scenarios: one-way and duplex.

One-way scenario

This example shows a simple code that use a WCF service to publish a post.  To do it, one interface called IBlogs defines a CreatePost(string post) method and, to support declared SOAP faults, this method specifies the FaultContractAttribute to transmit BlogsFault exceptions.

[ServiceContract(Namespace="http://wcf.devdeo.com/excepciones")]
interface IBlogs
{
    [OperationContract]
    [FaultContract(typeof(BlogsFault))]
    void CrearPost(string post);
}

[DataContract(Namespace="http://schemas.devdeo.com/excepciones")]
class BlogsFault
{
    [DataMember]
    public string CustomError;

    public BlogsFault(string error)
    {
        CustomError = error;
    }
}

class BlogsService : IBlogs
{
    public void CreatePost(string post)
    {
        if (post == null || post.Length == 0)
        {
            Console.WriteLine("Error trying to read the post");
            throw new FaultException<BlogsFault>(new BlogsFault("The post was incorrect"));
        }
        Console.WriteLine(string.Format("The post: \"{0}\" was published", post));
    }
}

 

The client invokes the WCF service two times; the first time the client try to publish the post "First post", and the WCF service doesn't generate any error.  The second time the client try to publish an empty post, but at this time the WCF service generates an error and sent it as a SOAP fault object represented by the BlogsFault class.  At this time, the client capture the error using a try..catch... block with the FaultException<> class.

class Program
{
    static void Main(string[] args)
    {
        BlogsClient client = new BlogsClient();
        client.CreatePost("First post");

        try
        {
            client.CreatePost("");
        }
        catch (FaultException<BlogsFault> e)
        {
            Console.WriteLine(string.Format("Error: {0}", e.Detail.CustomError));
        }
    }
}

Duplex scenario

Now, to simulate a duplex scenario, the WCF service will need a confirmation from client before to publish the post.  In this case, a new interface called IBlogsCallback is implemented and specifyed as a CallbackContract property in the service.

If the client doesn't confirm the post, a BlogsFault exception is generated and sent to service as a SOAP fault object.

[ServiceContract(Namespace="http://wcf.devdeo.com/excepciones",CallbackContract=typeof(IBlogsCallback))]
interface IBlogs
{
    [OperationContract]
    [FaultContract(typeof(BlogsFault))]
    void CreatePost(string post);
}

interface IBlogsCallback
{
    [OperationContract]
    [FaultContract(typeof(BlogsFault))]
    void ConfirmPost(string post);
}

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
class BlogsService : IBlogs
{
    public void CreatePost(string post)
    {        
        if (post == null || post.Length == 0)
        {
            Console.WriteLine("Error trying to read the post");
            throw new FaultException<BlogsFault>(new BlogsFault("The post was incorrect"));
        }

        try
        {
            Callback.ConfirmarPost(post);
        }
        catch(FaultException<BlogsFault> e)
        {
            Console.WriteLine(string.Format("The post: \"{0}\" cannot be published", e.Detail.CustomError));
            return;
        }

        Console.WriteLine(string.Format("The post: \"{0}\" was published", post));
    }

    public IBlogsCallback Callback
    {
        get
        {
            return OperationContext.Current.GetCallbackChannel<IBlogsCallback>();
        }
    }
}

[DataContract(Namespace="http://schemas.devdeo.com/excepciones")]
class BlogsFault
{
    [DataMember]
    public string CustomError;

    public BlogsFault(string error)
    {
        CustomError = error;
    }
}

At last, the client must implement the ConfirmPost(string post) method to confirm the post.

public class Blogs : IBlogsCallback
{
    public void ConfirmPost(string post)
    {
        Console.WriteLine(string.Format("Do you really want publish the post: \"{0}\" ? Y/N", post));
        string result = Console.ReadLine();

        if (result == "N")
        {
            BlogsFault fault = new BlogsFault();
            fault.CustomError = "The user doesn't publish the post";
            throw new FaultException<BlogsFault>(fault);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Blogs confirm = new Blogs();
        InstanceContext ctx = new InstanceContext(confirm);
        BlogsClient client = new BlogsClient(ctx);
        client.CreatePost("First post");

        try
        {
            cliente.CreatePost("");
        }
        catch (FaultException<BlogsFault> e)
        {
            Console.WriteLine(string.Format("Error: {0}", e.Detail.CustomError));
        }
    }
}

 

NOTE: you can read the spanish version of this post at Manejando excepciones en WCF

 Friday, August 25, 2006
Friday, August 25, 2006 9:05:12 PM (GMT Standard Time, UTC+00:00) ( )

The Commerce Server team has announced that a Technology Preview of the Commerce Server 2007 Starter Site is now available.   This CS2007 Starter Site CTP will NOT FOR PRODUCTION USAGE, and will NOT supported by Microsoft.

If you are an existing beta tester from the CS2007 beta progam, in Connect: CS2007 Starter Site CTP you can find more information and download the product.

If you have not participated in the CS2007 beta program, go to http://connect.microsoft.com and sign-in using your Passport Account.  After it, you will need to choose CS2007Starter Site CTP from the list of available programs by clicking the link for "Available Connections" in the menu on the left side of the page. From the list of available programs, click on the link to "Apply" next to the CS2007 Starter Site CTP. After completing registration, you will be automatically given access to the Connect site to download the starter site. From the CS2007 Starter Site CTP home page you can click on the "Downloads" link on the left side of the page, which will load a page showing all downloads currently available on the site for Commerce Server.

 Thursday, August 24, 2006
Thursday, August 24, 2006 1:19:15 AM (GMT Standard Time, UTC+00:00) ( biztalk )

Explanation

The execution mode value defined for some stage in the policy file is None. The value None is not available for execution mode, the available values are FirstMatch or All only.

User Action

All pipeline templates have an associated policy file that determines pipeline’s stages, the number of components allowed per stage, and the execution mode of each stage, among others. To specify that one stage can not execute components, use minimum and maximum occurs instead of execution mode.

To resolve this problem is necessary to edit the pipeline’s policy file. The file name can be found in pipeline’s properties windows in Visual Studio 2005 (see figure below), this policy file is stored in <Biztalk Server Installation Directory>\Developer Tools\Pipeline Policy Files directory.

After the file is opened, you must change the value for execution mode in policy file to All or FirstMatch.

Changing the execution mode value

The execution mode is represented in the policy file by the execMethod attribute; it is in the node /Document/Stages/Stage. Open the pipeline’s policy file and identify where this attribute is with value equals to None and replace it by All or FirstMatch as we shown:

Before:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns:xsd="" xmlns:xsi="" CategoryId="" FriendlyName="">
  <Stages>
    <Stage Name="Decode" minOccurs="0" maxOccurs="-1" execMethod="None"></Stage>
  </Stages>
</Document>

After:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns:xsd="" xmlns:xsi="" CategoryId="" FriendlyName="">
  <Stages>
    <Stage Name="Decode" minOccurs="0" maxOccurs="-1" execMethod="All"></Stage>
  </Stages>
</Document>

At last, close and open the pipeline file in Visual Studio 2005 to see these changes replicated. The following is the explanation step by step.

One way, but not the right way

If you want that one stage can not execute any component, you must setting the minimum and maximum occurs to 0 for the specific stage or simply delete it from the policy file. 

CAUTION: if you change any of the following values, the next pipelines files that you create based on the current policy files will be affected.

Delete the stage tag

Identify the specific tag, and delete the complete <Stage /> tag from the policy file.

Setting the minOccurs and maxOccurs to 0

Identify the specific stage and set new values for the minOccurs and maxOccurs attributes to 0:

Before:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns:xsd="" xmlns:xsi="" CategoryId="" FriendlyName="">
  <Stages>
    <Stage Name="Decode" minOccurs="0" maxOccurs="-1" execMethod="All"></Stage>
  </Stages>
</Document>

After:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns:xsd="" xmlns:xsi="" CategoryId="" FriendlyName="">
  <Stages>
    <Stage Name="Decode" minOccurs="0" maxOccurs="0" execMethod="All"></Stage>
  </Stages>
</Document>

ps.  this post was published using Windows Live Writer Beta.

 Saturday, June 10, 2006
Saturday, June 10, 2006 8:03:17 PM (GMT Standard Time, UTC+00:00) ( biztalk )

Gilles has developer an addin for Reflector that allows you to list all BizTalk artifacts contained in an assembly and extract them.

Read more in BizTalk AddIn for Reflector

 Monday, April 24, 2006
Monday, April 24, 2006 3:24:39 AM (GMT Standard Time, UTC+00:00) ( )

I have made some modifications to the BizTalkGenerateStrongName tool developed by Jon Flanders, for more info about this tool please visit his post "Another BizTalk development tool".

The principal change is set the new property value to all BizTalk projects in your solution, additionally include:

.- Copy the existent values of one BizTalk project to all BizTalk projects in the same solution

.- Override the property values in all BizTalk projects

.- Besides to edit the Assembly Key property, you could set a new value to Application Name property in BizTalk projects

You can download the project from BiztalkGenerateStrongName: Workspace site.  This tool works with VS 2005 and BTS 2006.

Thanks to Jon Flander to let me publish these modifications. 

 Tuesday, April 04, 2006
Tuesday, April 04, 2006 3:24:03 AM (GMT Standard Time, UTC+00:00) ( )

When Microsoft.BizTalk.ExplorerOM namespace is used to set/get the artifacts of BTS, the first property that you need to set is BtsCatalogExplorer.ConnectionStringBtsCatalogExplorer uses this property to connect to bts configuration database (BizTalkMgmtDb).

Many people save this connection string in a configuration file (.config) or directly in the code.  For example:

BtsCatalogExplorer catalog = new BtsCatalogExplorer();
catalog.ConnectionString = System.Configuration.Settings.AppSettings["BtsCofigDatabase"];
- or -
catalog.ConnectionString = "server=SQLServer;database=BizTalkMgmtDb;integrated security=true";

This code is not reusable or may be it'll need administration to set the value in the config file when the solution is installed in another bts server.

You can get the connection string dynamically using WMI or Windows Registry to delete this issue.  I developed a little helper class (see code below) with one static method that return the connection string of the configuration database (BizTalkMgmtDb).  Now, you don't need use any config file and your code'll be reusable.  For example:

BtsCatalogExplorer catalog = new BtsCatalogExplorer();
catalog.ConnectionString = BtsHelper.BtsConfigurationDatabase.GetConnectionString();

Code: BtsHelper Class

using System;
using System.Data.SqlClient;
using System.Management;
using Microsoft.Win32;

namespace BtsHelper
{
public class BtsConfigurationDatabase
{
private string _database;
private string _server;
private static BtsConfigurationDatabase _btsConfig = null;

private BtsConfigurationDatabase()
{
this._server = string.Empty;
this._database = string.Empty;
}

private bool GetUsingWMI()
{
bool regFounded = false;
this._server = string.Empty;
this._database = string.Empty;
try
{
using (ManagementObjectSearcher searcherGroupSetting = new ManagementObjectSearcher())
{
searcherGroupSetting.Scope = new ManagementScope(@"root\MicrosoftBizTalkServer");
searcherGroupSetting.Query = new SelectQuery("select * from MSBTS_GroupSetting");
using (ManagementObjectCollection.ManagementObjectEnumerator enumGroupSetting = searcherGroupSetting.Get().GetEnumerator())
{
while (enumGroupSetting.MoveNext())
{
ManagementObject groupSetting = (ManagementObject)enumGroupSetting.Current;
this._server = groupSetting["MgmtDbServerName"] as string;
this._database = groupSetting["MgmtDbName"] as string;
regFounded = true;
break;
}
return regFounded;
}
}
}
catch (Exception) { }
return regFounded;
}

private bool GetUsingRegistry()
{
bool regFounded = false;
this._server = string.Empty;
this._database = string.Empty;
using (RegistryKey keyBts = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\BizTalk Server\3.0\Administration"))
{
if (keyBts == null)
return regFounded;

this._server = keyBts.GetValue("MgmtDBServer") as string;
if (this._server == null)
this._server = string.Empty;

this._database = keyBts.GetValue("MgmtDBName") as string;
if (this._database == null)
this._database = string.Empty;

regFounded = true;
}
return regFounded;
}

public static string GetConnectionString()
{
if (_btsConfig == null)
_btsConfig = new BtsConfigurationDatabase();

if (!_btsConfig.GetUsingWMI())
_btsConfig.GetUsingRegistry();

if ((_btsConfig._server == string.Empty) || (_btsConfig._database == string.Empty))
throw new ApplicationException("Error when get the connection string!");

SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder();
sb.DataSource = _btsConfig._server;
sb.InitialCatalog = _btsConfig._database;
sb.IntegratedSecurity = true;
return sb.ToString();
}

}
}
 

** Don't forget reference the System.Management.dll assembly to build the class.

Tuesday, April 04, 2006 3:20:52 AM (GMT Standard Time, UTC+00:00) ( )

Using the EnvDTE.Project class you can access the BizTalk Server 2006 project properties to get/set its value.  A bts-project uses two collections to store the properties; I’ll explain where you can find each property.

Configuration Properties

To access the configuration properties, you need to get the item ConfigProperties from the active configuration.  This item gets a value that represents the dictionary that contains the properties. (See code below)

 

Property configProperties = project.ConfigurationManager.ActiveConfiguration.Properties.Item("ConfigProperties");
IDictionary dicConfigProps = configProperties.Value as IDictionary;
string outputPath = dicConfigProps[DictionaryTags.OutputPath].ToString();

In the code, the type of project variable is EnvDTE.Project and represents the BizTalk Server 2006 project.  This object has a dictionary with each property related to configuration, to access each property you must use the DictionaryTags.

In the example, I get the location of the output files for the current project using the DictionaryTags.OutputPath key.  This is the list that you can access in this dictionary.

 

Configuration Properties

Enumeration

Section: Build

Restart Host Instances: specifies whether to restart all BizTalk in-process host instances on local machine.

DictionaryTags.RestartHostInstances

Register: specifies whether to register the assembly in the Global Assembly Cache.

DictionaryTags.Register

Redeploy: specifies whether to delete existing configuration and recreate it every time the assembly is deployed.

DictionaryTags.Redeploy

Application Name: specifies the BizTalk Application in which to deploy the assembly.

DictionaryTags.ApplicationName

Configuration Database: configuration Database to deploy.

DictionaryTags.ConfigurationDatabase

Server: specifies the server when the BizTalk Configuration Database resides.

DictionaryTags.Server

Section: Deployment

BPEL Compliance: specifies whether to generate Business Process Execution Language (BPEL) compliance output.

DictionaryTags.BpelCompliance

Generate Debugging Information: specifies whether generate debug symbols.

DictionaryTags.GenerateDebuggingInformation

Embed Tracking Information: specifies whether to embed tracking information in the assembly.

DictionaryTags.EmbedTrackingInformation

Treat Warnings As Errors: specifies whether to treat warning as errors during the build.

DictionaryTags.TreatWarningsAsErrors

Warning Level: specifies the warning level.

DictionaryTags.WarningLevel

Output Path: specifies the location of the output files for this project configuration.

DictionaryTags.OutputPath

 

Common Properties

To access the configuration properties, you need to get the item CommonProperties from the project.  This item gets a value that represents the dictionary that contains the properties. (See code below)

Property commmonProperties = project.Properties.Item("CommonProperties");
IDictionary dicCommonProps = commmonProperties.Value as IDictionary;
string projKeyFileName = dicCommonProps[DictionaryTags.AssemblyKeyFile].ToString();

In the example, I get the name of the file that contains either the public key using the DictionaryTags.AssemblyKeyFile enumeration.  This is the list that you can access in this dictionary.

 

Common Properties

Enumeration

Section: Assembly

Assembly Key Name: indicates the key container that contains the key pair passed as a parameter to the constructor of this attribute.

DictionaryTags.AssemblyKeyName

Assembly Key File: specifies the name of the file that contains either the public key or both the public and private keys passed as parameter to the constructor of this attribute.

DictionaryTags.AssemblyKeyFile

Assembly Delay Sign: value indicating that delay signing is being used.

DictionaryTags.AssemblyDelaySign

Assembly Title: specifies the title of the assembly.

DictionaryTags.AssemblyTitle

Assembly Description: specifies a short description that summarizes the nature and purpose of the assembly.

DictionaryTags.AssemblyDescription

Assembly Default Alias: specifies the default alias to be used by referencing assemblies.

DictionaryTags.AssemblyDefaultAlias

Assembly Configuration: specifies the configuration of the assembly, such as Development or Deployment.

DictionaryTags.AssemblyConfiguration

Assembly Trademark: specifies the trademark information.

DictionaryTags.AssemblyTrademark

Assembly Product: specifies the product information.

DictionaryTags.AssemblyProduct

Assembly Informational Version: specifies the version information.

DictionaryTags.AssemblyInformationalVersion

Assembly File Version: specifies the Win32 file version.

DictionaryTags.AssemblyFileVersion

Assembly Copyright: specifies the copyright information.

DictionaryTags.AssemblyCopyright

Assembly Company: specifies the name of the company.

DictionaryTags.AssemblyCompany

Assembly Version: number that represent the version of the assembly.

DictionaryTags.AssemblyVersion

Assembly Culture: indicate the culture that the assembly supports.

DictionaryTags.AssemblyCulture

Section: References Path

References Path: Lists the directories to search when the project is loaded for assemblies referenced by the project. This setting is specific to the project, computer, and user for which it is set. A relative path specification will be converted to, and stored as a fully-qualified path. Relative paths are assumed to be relative to the project directory.

DictionaryTags.ReferencesPath

Section: General

Project Folder: the full path to the project directory.

DictionaryTags.ProjectFolder

Project File: the name of the file containing build, configuration, and the information about the project.

DictionaryTags.ProjectFile

Default Namespace: specifies the default namespace for added items, such as classes, that are added via the Add New Item Dialog Box.

DictionaryTags.DefaultNamespace

Assembly Name: the name of the output file that will hold assembly metadata.

DictionaryTags.AssemblyName

 

 

DictionaryTags Enumeration 

The DictrionaryTags enumeration class is use to access each property, this class can be found in Microsoft.BizTalk.Studio.Extensibility.dll assembly.  See the structure below.

public enum DictionaryTags{
OutputPath,
WarningLevel,
TreatWarningsAsErrors,
EmbedTrackingInformation,
GenerateDebuggingInformation,
BpelCompliance,
Server,
ConfigurationDatabase,
ApplicationName,
Redeploy, Register,
RestartHostInstances,
AssemblyName,
DefaultNamespace,
ProjectFile,
ProjectFolder,
ReferencesPath,
AssemblyCulture,
AssemblyVersion,
AssemblyCompany,
AssemblyCopyright,
AssemblyFileVersion,
AssemblyInformationalVersion,
AssemblyProduct,
AssemblyTrademark,
AssemblyConfiguration,
AssemblyDefaultAlias,
AssemblyDescription,
AssemblyTitle,
AssemblyDelaySign,
AssemblyKeyFile,
AssemblyKeyName, None
}

 Friday, March 24, 2006
Friday, March 24, 2006 4:17:47 AM (GMT Standard Time, UTC+00:00) ( )

I have listened many times, how can I get a message context property from a map?  Well, while I was playing with the framework of BizTalk Server 2006 RC I found the way to do a functoid that implements this functionality.  I’ll try to explain how I do it below.

First, I have to know three values:

Message Name: the name of the message that have the context property
Property Name: the name of the context property
Property Namespace: the namespace of the context property

Second, I need to get the segments of the service (orchestration) and check in each segment if the message that I’m looking for is there.  The messages aren’t stored directly in the service; the messages are stored in the segments that exist inside the orchestration.  Normally one orchestration has two segments and one more segment when the orchestration implements compensation; the message normally is stored in the second segment (I really don’t know why the segments exist, this is an internal architecture from Microsoft and there isn’t information about that).

Third, when I find the particular message I check the context property (formed by Property Name and Property Namespace) inside the message and return its value.

This is the code that I have used:

// set the property
string property = "";
// get the service
Microsoft.XLANGs.Core.Service s = Microsoft.XLANGs.Core.Service.RootService;
foreach (Microsoft.XLANGs.Core.Segment seg in s._segments)
{
// find the real name of the message
foreach (DictionaryEntry de in Microsoft.XLANGs.Core.Context.FindFields(typeof(Microsoft.XLANGs.BaseTypes.XLANGMessage), seg.ExceptionContext))
{
// check that the key ends with the name of the message
if (de.Key.ToString().EndsWith(val1))
{
// get the message as a XLANGMessage
Microsoft.XLANGs.Core.XMessage msg = de.Value as Microsoft.XLANGs.Core.XMessage;
// if the message was found, then I get the value of the property
if (msg != null)
{
// create a XmlQName instance
Microsoft.XLANGs.BaseTypes.XmlQName qName = new Microsoft.XLANGs.BaseTypes.XmlQName(val2, val3);
// find the message property in the message
if (msg.GetContextProperties().ContainsKey(qName))
{
// get the property from GetContextProperties
property = msg.GetContextProperties()[qName].ToString();
}
else if (msg.GetContentProperties().ContainsKey(qName))
{
// get the property from GetContentProperties
property = msg.GetContentProperties()[qName].ToString();
}
}
break;
}
}
if (property.Length > 0)
break;
}
// return the property value
return property;

Exception :(

Unfortunately this functoid ONLY works if it is invoked from an orchestration… I mean a map inside an orchestration.  The reason is simple, to access to Message I have to get the current context of the service and this service is represented by the orchestration, if the orchestration doesn’t exist I cann’t get the context.

You can download the functoid assembly from GetContextProperty Functoid Workspace

This functoid was developed with the framework of Microsoft BizTalk 2006 RC using the Microsoft.XLANGs.Engine.dll and Microsoft.XLANGs.BasTypes.dll assemblies.  I hope that this functionality exists in the RTM version.