Microsoft KB Archive/904846

= How to implement a receipt URL for reliable messaging that requires a user name and a password in BizTalk Server =

Article ID: 904846

Article Last Modified on 11/14/2006

-

APPLIES TO


 * Microsoft BizTalk Server 2006 Standard Edition
 * Microsoft BizTalk Server 2006 Enterprise Edition
 * Microsoft BizTalk Server 2006 Developer Edition
 * Microsoft BizTalk Server 2004 Enterprise Edition
 * Microsoft BizTalk Server 2004 Standard Edition
 * Microsoft BizTalk Server 2004 Partner Edition
 * Microsoft BizTalk Server 2004 Developer Edition

-



INTRODUCTION
This article describes how to implement a receipt URL for reliable messaging that requires a user name and a password in Microsoft BizTalk Server 2006 and in Microsoft BizTalk Server 2004.



MORE INFORMATION
In Microsoft BizTalk Server 2002, a BizTalk Framework message can contain a receipt URL for reliable messaging that uses one of the following formats:
 * http:// : @ /
 * https:// : @ /

BizTalk Server 2002 can use this information to deliver the receipt to a URL that requires user name and password authentication.

BizTalk Server 2006 and BizTalk Server 2004 cannot send receipts to a URL that requires a user name and a password unless you create a custom pipeline component. This custom pipeline component extracts the user name and the password from the URL. To create this custom pipeline component, use code that is similar to the following Microsoft Visual C# code example. using System; using System.Runtime.InteropServices;

namespace Microsoft.Samples.BizTalk.Pipelines.CustomComponent {   ///     /// This helper class parses the HTTP URL that contains the user name and the password. ///    class UrlHelper {       [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] private struct URL_COMPONENTS {           public uint     dwStructSize; public string  szScheme; public uint    dwSchemeLength; public int     nScheme; public string  szHostName; public uint    dwHostNameLength; public uint    nPort; public string  szUserName; public uint    dwUserNameLength; public string  szPassword; public uint    dwPasswordLength; public string  szUrlPath; public uint    dwUrlPathLength; public string  szExtraInfo; public uint    dwExtraInfoLength; }

const int INTERNET_SCHEME_HTTP = 3; const int INTERNET_SCHEME_HTTPS = 4;

const int INTERNET_MAX_HOST_NAME_LENGTH = 256; const int INTERNET_MAX_USER_NAME_LENGTH = 128; const int INTERNET_MAX_PASSWORD_LENGTH = 128; const int INTERNET_MAX_PATH_LENGTH = 2048; const int INTERNET_MAX_SCHEME_LENGTH = 32;     // This value is the longest protocol name length. const int INTERNET_MAX_URL_LENGTH = INTERNET_MAX_SCHEME_LENGTH + 3 + INTERNET_MAX_PATH_LENGTH;

[DllImport(&quot;Wininet.dll&quot;, SetLastError=true, CharSet=CharSet.Unicode)] static private extern bool InternetCrackUrl (string url, int urlLength, int flags, ref URL_COMPONENTS urlComponents);

///        /// This function tries to parse the user name and the password from the HTTP or HTTPS URL string. ///        /// [in] Original URL /// [out] If the function returns true, this parameter contains the URL that has the user name and the password removed. /// [out] param. If the function returns true, this parameter contains the user name from the URL. /// [out] param. If the function returns true, this parameter contains the password from the URL. ///        ///     true if the user name and the password were successfully parsed from the input URL. ///    false if the URL is not an HTTP URL or does not contain the user name and password. ///        static public bool ParseUserPasswordFromHttpUrl(string originalUrl,             out string resultUrl,             out string userName,             out string password) {           bool    ContainAuthInfo = false; URL_COMPONENTS Result = new URL_COMPONENTS; // Initialize the parameters. resultUrl = string.Empty; userName = string.Empty; password = string.Empty;

// Preallocate the buffer. Result.dwStructSize = (uint) Marshal.SizeOf(typeof(URL_COMPONENTS)); Result.szScheme = new string(' ', INTERNET_MAX_SCHEME_LENGTH); Result.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH; Result.szHostName = new string(' ', INTERNET_MAX_HOST_NAME_LENGTH); Result.dwHostNameLength=INTERNET_MAX_HOST_NAME_LENGTH; Result.szUserName= new string(' ', INTERNET_MAX_USER_NAME_LENGTH); Result.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH; Result.szPassword= new string(' ', INTERNET_MAX_PASSWORD_LENGTH); Result.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH; Result.szUrlPath= new string(' ', INTERNET_MAX_PATH_LENGTH); Result.dwUrlPathLength =INTERNET_MAX_PATH_LENGTH; Result.szExtraInfo= new string(' ', INTERNET_MAX_URL_LENGTH); Result.dwExtraInfoLength = INTERNET_MAX_URL_LENGTH;

// Call the InternetCrackUrl function to parse the URL. // If the InternetCrackURL function does not parse the URL, the function returns False. if (InternetCrackUrl(originalUrl, originalUrl.Length, 0, ref Result)) {               // Only process the URL if the URL is HTTP or HTTPS. if (Result.nScheme == INTERNET_SCHEME_HTTP ||                    Result.nScheme == INTERNET_SCHEME_HTTPS) {                   // Run this code if the URL includes a user name and a password. if (Result.szUserName.Length > 0 || Result.szPassword.Length > 0) {                       if (Result.nPort == 80) {                           resultUrl = String.Format(&quot;{0}://{1}{2}{3}&quot;,                                 Result.szScheme,                                 Result.szHostName,                                 Result.szUrlPath,                                 Result.szExtraInfo); }                       else {                           resultUrl = String.Format(&quot;{0}://{1}:{2}{3}{4}&quot;,                                 Result.szScheme,                                 Result.szHostName,                                 Result.nPort,                                 Result.szUrlPath,                                 Result.szExtraInfo); }                       userName = Result.szUserName; password = Result.szPassword; ContainAuthInfo = true; }               }            }

return ContainAuthInfo; }   } } After you extract the user name and the password from the URL, set the authentication method, the user name, and the password in the message context. To do this, use code that is similar to the following Visual C# code example. namespace Microsoft.Samples.BizTalk.Pipelines.CustomComponent {   using System; using System.Resources; using System.Drawing; using System.Collections; using System.Reflection; using System.ComponentModel; using System.Text; using System.IO; using Microsoft.BizTalk.Message.Interop; using Microsoft.BizTalk.Component.Interop; using Microsoft.XLANGs.BaseTypes;

///    /// This code uses a custom pipeline component to extract the user name and the password from /// the HTTP URL in deprecated format. Then, the code sets the user name and the password in the message context. ///    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)] [ComponentCategory(CategoryTypes.CATID_Any)] [ComponentCategory(CategoryTypes.CATID_Validate)] [System.Runtime.InteropServices.Guid(&quot;041F4BBB-E37F-437f-9352-D761096CCF7A&quot;)] public class FixBTFHttp : IBaseComponent, Microsoft.BizTalk.Component.Interop.IComponent, Microsoft.BizTalk.Component.Interop.IPersistPropertyBag {       private static PropertyBase PropOutboundUrl = new BTS.OutboundTransportLocation; private static PropertyBase PropMessageType = new BTS.MessageType;

private static PropertyBase PropHttpAuthType = new HTTP.AuthenticationScheme; private static PropertyBase PropHttpUsername = new HTTP.Username; private static PropertyBase PropHttpPassword = new HTTP.Password;

///        ///         public FixBTFHttp {       }

#region IBaseComponent ///        /// This code names the component. ///        [Browsable(false)] public string Name {           get {   return &quot;FixBTFHttp Component&quot;;  } }       ///         /// This code sets the version of the component. ///        [Browsable(false)] public string Version {           get {   return &quot;1.0&quot;;   } }       ///         /// This code sets the description of the component. ///        [Browsable(false)] public string Description {           get {   return &quot;FixBTFHttp Pipeline Component&quot;; } }       #endregion #region IComponent

///        /// This code implements the IComponent.Execute method. ///        /// Pipeline context /// Input message /// Processed input message together with appended or prepended data. ///        /// The IComponent.Execute method is used to initiate /// the processing of the message in the pipeline component. ///        public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg) {           IBaseMessageContext MsgContext      = null; object             PropertyValue   = null;

string             OriginalUrl     = string.Empty; string             NewUrl          = string.Empty; string             Username        = string.Empty; string             Password        = string.Empty; MsgContext = inmsg.Context;

// Verify that the message is a BizTalk Framework acknowledgement message. PropertyValue = MsgContext.Read(PropMessageType.Name.Name, PropMessageType.Name.Namespace); if (PropertyValue != null && (PropertyValue is string) && ((string)PropertyValue == &quot;BTF2DeliveryReceipt&quot;)) {               // Extract the outbound URL. PropertyValue = MsgContext.Read(PropOutboundUrl.Name.Name, PropOutboundUrl.Name.Namespace); if (PropertyValue != null && PropertyValue is string) {                   OriginalUrl = ((string) PropertyValue).Trim; // Verify that the URL is HTTP or HTTPS. if (OriginalUrl.ToLower(System.Globalization.CultureInfo.InvariantCulture).StartsWith(&quot;http&quot;)) {                       // Verify that the URL contains the user name and the password. if (UrlHelper.ParseUserPasswordFromHttpUrl (OriginalUrl, out NewUrl, out Username, out Password)) {                           // Update the new outbound URL. MsgContext.Promote(PropOutboundUrl.Name.Name, PropOutboundUrl.Name.Namespace, NewUrl); // Set up HTTP basic authentication with the user name and the password. MsgContext.Write(PropHttpAuthType.Name.Name, PropHttpAuthType.Name.Namespace, &quot;Basic&quot;); MsgContext.Write(PropHttpUsername.Name.Name, PropHttpUsername.Name.Namespace, Username); MsgContext.Write(PropHttpPassword.Name.Name, PropHttpPassword.Name.Namespace, Password); }                   }                }            }

return inmsg; }       #endregion

#region IPersistPropertyBag ///        /// This code obtains the class ID of the component that will be used. The code obtains the class ID from unmanaged code. ///        /// Class ID of the component public void GetClassID(out Guid classid) {           classid = new System.Guid(&quot;041F4BBB-E37F-437f-9352-D761096CCF7A&quot;); }       ///         /// The InitNew method is not implemented. ///        public void InitNew {       }        ///         /// This code loads the configuration property for the component. ///        /// Configuration property bag /// Error status. (This parameter is not used in this code.) public void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, Int32 errlog) {       }        ///         /// This code saves the current component configuration in the property bag. ///        /// Configuration property bag /// Not used /// Not used public void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, Boolean fClearDirty, Boolean fSaveAllProperties) {       }

#endregion } }

Additional query words: BTS2006 BTS2004 BTS2002 BTS BTF

Keywords: kbbiztalk2004-2006swept kbbtsmessaging kbhowto kbinfo KB904846

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.