Nick's Blog

Biztalk gotcha!

Assembly * references the following assemblies that must be deployed before deploying this assembly:

leave a comment »

Recently I came across this error in visual studio when I try to deploy the BizTalk components.

Normally this error would go away after putting all the missing assemblies into the GAC, but this time it didn’t.

I did a little digging around and found this useful forum thread :
http://www.eggheadcafe.com/microsoft/BizTalk/30337132/assembly-x-references-the-following-assemblies-that-must-be.aspx

Basically, if the referenced assembly contains schemas, it not only needs to be in the GAC, it also needs to be added to the BizTalk application.

So all I needed to do is go to the biztalk application’s resources tab (If the application hasn’t been created, just create an empty one with the same name). And add those assemblies that were missing.

Written by stormdweller

September 22, 2011 at 10:45 PM

Posted in Uncategorized

Incorrect schemalocation in WCF wsdl generated by the WCF publishing wizard

leave a comment »

A few days ago a client of mine asked me a question about schemalocations in the wsdl generated by the WCF publishing wizard. Their WCF service is exposed to an external URL but the schemalocation in the wsdl is the internal URL generated by the WCF publishing wizard.

When an outside party tries to consume the webservice, an error similar to the following is returned:

Metadata contains a reference that cannot be resolved : <The internal schemalocation URL>

Since the publishing wizard has no way of knowing the actual external url that is going to be used for this
service, we will have to create a custom wsdl for this. Here’s a summary of what I did to get around this issue:

–          Run publishing wizard

–          Expose the wcf service on an external URL (e.g. http://externalURL/WCF.svc)

–          Browse to the new web service WSDL and save it to the web service folder

–          Move the xsd (schema) file from App_Data to the web service folder. (This step is required because we cannot get direct access to the schema file if it’s inside the App_Data folder. If we use a custom wsdl file, the old reference ‘xsd=xsd*’ won’t work)

–          Modify the WSDL file to change all reference of the internal URL to the external URL

–          Modify the WSDL file to change schemaLocation to the location of the schema in the web service folder (e.g. http://externalURL/schema.xsd)

–          Modify the web.config to add externalMetadataLocation attribute to <serviceMetadata> and point it to the WSDL file in the web service folder (externalMetadataLocation: http://msdn.microsoft.com/en-us/library/ms731317.aspx)

–          IISRESET

 

Now if you browse to your WCF service, the wsdl link on the top of the page should be something like “http://externalURL/WCF.wsdl&#8221; instead of “http://externalURL/WCF.svc?wsdl&#8221;

 

 

Written by stormdweller

August 2, 2011 at 12:44 AM

Posted in Guides, WCF Adapter

BizTalk flatfile schema

leave a comment »

The flat file sample looks like this:

<A> blah

<B> blah

<C>blah

 

I fired up the flatfile wizard and created a schema for it.

First issue I encountered is the whitespace after the tag identifier (<A>,<B> and <C>). There is random whitespaces after the tag and at the end of the record. Justification on the node seems to work for scenarios where there are whitespaces on one side of the record, but I couldn’t get it to work for random spaces on both sides.

The simple solution for this is to make all your element fields attributes. It turns out that if you create attributes in the flatfile schema they ignore the whitespaces in the record.

 

Second issue is that <B> can be optional. But it keep complaining about “Unexpected data found while looking for: <B>” even when I set Min Occurs of this record to be “0”.

The flatfile schema I created is not a positional structured schema so it should be able to cope with optional fields quite well even though the record has a tag identifier.

Then I found this page “http://geekswithblogs.net/ErwinAI/archive/2006/07/26/86318.aspx&#8221;

The solution is, on the schema node, set Parser Optimization to “Complexity”. Apparently with the default “Speed” optimization, the mapper can’t cope with optional records that have a tag identifier.

Written by stormdweller

October 13, 2010 at 9:16 PM

Biztalk Mapper mapping white space and LF CR characters

leave a comment »

By default, biztalk mapper maps all the whitespaces and even LF CR over to the destination schema. But what if we don’t want it to happen?

A project I am currently working on requires me to map an xml document to a flatfile document, and I had an issue where the outgoing CSV file has all these random LFCR characters in it. So I did some digging and realized that biztalk has mapped them across from the source document.

To stop biztalk from doing this, we just need to add a registry key “LegacyWhitespace”  into the registry location:

HKEY_LOCAL_MACHINE\Software\Microsoft\BizTalk Server\3.0\Administration
,
setting it to 1, and restart the host instances

Piece of cake huh?

More about this at:

http://social.msdn.microsoft.com/Forums/en-US/biztalkgeneral/thread/7dd28a9b-16b5-4c0e-90db-843caf4689ee

Written by stormdweller

April 16, 2010 at 2:57 AM

Visual studio 2008, Biztalk 2009, Friends?

with one comment

Lately I’ve been working on a project which involves migrating an existing Biztalk 2002 server to Biztalk 2009. What I want to talk about here is not the migration bit but the Biztalk 2009 development bit.

Visual Studio 2008 just hates biztalk 2009.

Frustration #1:

 Unable to copy file “obj\Debug\schemas.dll” to “bin\Debug\schemas.dll”. The process cannot access the file ‘bin\Debug\schemas.dll’ because it is being used by another process.

Visual Studio gets a lock on the dlls after it builds them. This happens everytime I re-build my schemas project, some times it happens to the custom pipeline components projects too. So I had to restart visual studio again and again just to release that lock from the dll.

Frustration #2 (Visual Studio 2008 and Biztalk 2009 reference issues) :

#error: “The expression that you have entered is not valid.”

Visual Studio 2008 does a good job at confusing the orchestrations and messing with the references. You will find out soon enough that the referenced projects/dlls in your orchestrations break easily. Visual studio 2008 doesn’t require any help for the users to mess up your orchestrations project. If you are lucky, a simple refresh of the referenced project (Change the Copy Local property for the reference and change it back) will make the error go away.

If a refresh of the reference can get rip of the warning signs on the expression shapes but when you build the project, they come back again and the build fails with the same error. Double check the expression and make sure it’s a reference issue and there’s nothing wrong with the statements. Here’s what you can do to fix it.

First, you refresh the references again to make the warning signs go away. Now, drag the shape which triggers the first occurance of the error to somewhere else, doesnt matter where, just move it. Save the orchestration. And drag the same shape back to where it was and save the orchestration again. Now the orchestration should build without raising any errors……unless you just built your schemas project and rebuilding your orchestration project brings back frustration #1…

Written by stormdweller

September 1, 2009 at 11:55 PM

dateTime format conversion using XSLT

leave a comment »

We all like last minute requirement changes, it could turn a boring task into an exciting time attack game.

This time, the client wanted to change the dateTime format from 2009-11-26T01:02:03 to 01:02:03 26 November 2009.

The datetime is presented in a email request which is sent by biztalk’s SMTP adapter. The adapter uses a XSLT transformer to transform a piece of xml into a nice look html page.

The conversion details are easy……to find on google, I’m gonna post it here for my future reference

Here’s the post I found:

http://geekswithblogs.net/workdog/archive/2007/02/08/105858.aspx

Here’s my code

<xsl:template name=”FormatDate”>
<xsl:param name=”DateTime” />

<xsl:variable name=”year”>
<xsl:value-of select=”substring($DateTime,1,4)” />
</xsl:variable>

<xsl:variable name=”month-temp”>
<xsl:value-of select=”substring-after($DateTime,’-‘)” />
</xsl:variable>

<xsl:variable name=”month”>
<xsl:value-of select=”substring-before($month-temp,’-‘)” />
</xsl:variable>

<xsl:variable name=”day-temp”>
<xsl:value-of select=”substring-after($month-temp,’-‘)” />
</xsl:variable>

<xsl:variable name=”day”>
<xsl:value-of select=”substring($month-temp,1,2)” />
</xsl:variable>

<xsl:variable name=”time”>
<xsl:value-of select=”substring-after($DateTime,’T’)” />
</xsl:variable>

<xsl:variable name=”hh”>
<xsl:value-of select=”substring($time,1,2)” />
</xsl:variable>

<xsl:variable name=”mm”>
<xsl:value-of select=”substring($time,4,2)” />
</xsl:variable>

<xsl:variable name=”ss”>
<xsl:value-of select=”substring($time,7,2)” />
</xsl:variable>

<xsl:value-of select=”$hh”/>
<xsl:value-of select=”‘:'”/> <!–13:–>
<xsl:value-of select=”$mm”/>
<xsl:value-of select=”‘:'”/> <!–13:24 –>
<xsl:value-of select=”$ss”/> <!–13:24:55 –>
<xsl:value-of select=”‘ ‘”/>
<xsl:value-of select=”$day”/>
<xsl:value-of select=”‘ ‘”/>
<xsl:choose>
<xsl:when test=”$month = ’01′”>January</xsl:when>
<xsl:when test=”$month = ’02′”>February</xsl:when>
<xsl:when test=”$month = ’03′”>March</xsl:when>
<xsl:when test=”$month = ’04′”>April</xsl:when>
<xsl:when test=”$month = ’05′”>May</xsl:when>
<xsl:when test=”$month = ’06′”>June</xsl:when>
<xsl:when test=”$month = ’07′”>July</xsl:when>
<xsl:when test=”$month = ’08′”>August</xsl:when>
<xsl:when test=”$month = ’09′”>September</xsl:when>
<xsl:when test=”$month = ’10′”>October</xsl:when>
<xsl:when test=”$month = ’11′”>November</xsl:when>
<xsl:when test=”$month = ’12′”>December</xsl:when>
</xsl:choose>
<xsl:value-of select=”‘ ‘”/>
<xsl:value-of select=”$year”/>

</xsl:template>

Written by stormdweller

May 26, 2009 at 4:09 AM

Posted in XSLT

Biztalk WCF adapter Security – part 2

leave a comment »

In Part 1, I have created my own behavior class and added it to the receive location. But after that, the test client always gets “access is denied” exception no matter what credentials I used. Then after another hour of head scratching…. I found out that in order for authorization to work, I need to set up all the authentication settings to match it.

First, fire up IIS, and uncheck the anonymous access in Directory Security/Authentication and access control. That handles the corresponding IIS setting for authentication.

Secondly, in biztalk administration console, configure the WCF-CustomIsolated adapter and set the basichttpbindings to use TransportCredentialOnly and windows as the clientCredentialType. That takes care of biztalk’s authentication settings.

Finally, open up the test client again and we should see……………..WHAT THE ****???? RED WORDS!!!!!!

“Security settings for this service require ‘Anonymous’ Authentication but it is not enabled for the IIS application that hosts this service.”

ok..this is because when we created the webservice, the meta data endpoint is the only endpoint exists in the web.config, and meta data endpoint’s mexhttpbinding only supports anonymous authentication.

To solve this, add a binding to the web.config, and modified the HttpMexEndpoint so that it uses the binding which is using Windows authentication. And everything should work……if you are as lucky as me..

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name=”CustomBasicBinding”>
<security mode=”TransportCredentialOnly”>
<transport clientCredentialType=”Windows” />
</security>
</binding>
</basicHttpBinding>
</bindings>

</system.serviceModel>

<endpoint name=”HttpMexEndpoint” address=”mex” binding=”basicHttpBinding” bindingConfiguration=”CustomBasicBinding” contract=”IMetadataExchange” />

Note: If everything is not working as you would expect it to, you can try the following

1. make sure the dll in the GAC is using the most up to date version. Sometimes biztalk holds the dll in memory and you might need to uninstall it, close biztalk administration console, install it and do it over again.

2. IISreset

Biztalk WCF adapter Security – part 1

leave a comment »

I’ve spent days to try to set up a simple windows authorisation in a WCF webservice published by Biztalk. I will share how I managed to do it here and hope that it might save others sometime when they are trying to do the same thing.

Initially, I knew nothing about webservices when I started this problem, after reading some articles on WCF security, I believe that I could set up the authorization and anthentication in the web.config. And after a frustrating day, I gave up believing that.

The following guide shows how I achieved the goal, even though I don’t fully understand some of the things here and there, this configuration worked for me.

I believe that to add authorization, I have add it in biztalk but not the webservice side.

Firstly, I published the web service through the biztalk WCF publishing wizard, it’s published to use WCF-BasicHttp adapter.

Then I followed the post from

http://www.topxml.com/code/cod-429_15089_biztalk-and-wcf-part-vi-publishing-advanced-services.aspx

And created my own behavior class, I’ve also included a copy of my behavior class at the end of this post because of the code is not properly “codeBlock’d” in that post.

Then, after I have the class built and put into the GAC (Global assembly cache), I set the receive location to use WCF-CustomIsolated adapter as the basichttp doesn’t allow extended behaviors to be added.

So I added my custom behavior class and started my testing client. Then I got this error message which had me scratching my head for nearly 3 hours….

Receive location for address  ‘yourWCFservice.svc’ not found. (BizTalk receive location may be disabled)

The receive location is clearly visible in the Biztalk administration console…what the **** happened here???

Then I found out that I’ve set the adapter to be basichttp at the beginning, so it’s looking for “yourWCFservice.svc” using the WCF-customIsolated adapter, and ofcourse it won’t be able to find it since the “yourWCFservice.svc” recerive port is using WCF-basicHttp.

Not knowing a better way to change it…I simply republished my WCF webservice and my behavior class started to work fine after that :D!!

WcfServiceBehaviors.cs

using System;

using System.Collections.Generic;

using System.Text;

using System.ServiceModel;

using System.ServiceModel.Channels;

using System.ServiceModel.Description;

using System.ServiceModel.Configuration;

using System.IdentityModel.Policy;

using System.IdentityModel.Claims;

using System.Security.Principal;
using System.Configuration;

namespace WcfServiceBehaviors
{

public class MyCustomServiceAuthorizationManager : ServiceAuthorizationManager
{
private string m_windowsgroup;

public MyCustomServiceAuthorizationManager(string windowsgroup)
{
this.m_windowsgroup = windowsgroup;
}

protected override bool CheckAccessCore(OperationContext operationContext)
{

if (!base.CheckAccessCore(operationContext))
{

return false;

}

AuthorizationContext authCtx = operationContext.ServiceSecurityContext.AuthorizationContext;

//print out inbound identities recorded by WCF
System.Diagnostics.Trace.WriteLine(“Primary Identity is ” +
operationContext.ServiceSecurityContext.PrimaryIdentity.Name);
System.Diagnostics.Trace.WriteLine(“Windows Identity is ” +
operationContext.ServiceSecurityContext.WindowsIdentity.Name);
//create Windows principal object from inbound Windows identity
WindowsPrincipal p = new WindowsPrincipal(operationContext.ServiceSecurityContext.WindowsIdentity);
//check user in role
//System.Diagnostics.Trace.WriteLine(“Windows Group is ” + this.m_windowsgroup);

bool isAdmin = p.IsInRole(this.m_windowsgroup);
if (!isAdmin)
{
//System.Diagnostics.Trace.WriteLine(“Windows user ” + operationContext.ServiceSecurityContext.WindowsIdentity.Name + ” not in group ” + this.m_windowsgroup + ” so denying access.”);
return false;
}
return true;

}

}

public class MyCustomBehaviorElement : BehaviorExtensionElement
{
///
/// Want custom config property to show up in the BizTalk receive location
///
[ConfigurationProperty(“windowsgroup”, IsRequired = false, DefaultValue = “”)]
public string WindowsGroup
{
get { return (string)base[“windowsgroup”]; }
set { base[“windowsgroup”] = value; }
}

protected override object CreateBehavior()
{

return new MyCustomServiceBehavior(WindowsGroup);

}

public override Type BehaviorType
{

get { return typeof(MyCustomServiceBehavior); }

}

}

public class MyCustomServiceBehavior : IServiceBehavior
{
private string m_windowsgroup;

public MyCustomServiceBehavior(string windowsgroup) { this.m_windowsgroup = windowsgroup; }

#region IServiceBehavior Members

public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{

}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{

ServiceAuthorizationBehavior authBehavior = serviceDescription.Behaviors.Find<ServiceAuthorizationBehavior>();

authBehavior.ServiceAuthorizationManager = new MyCustomServiceAuthorizationManager(this.m_windowsgroup);

((IServiceBehavior)authBehavior).ApplyDispatchBehavior(serviceDescription, serviceHostBase);

}

public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{

}

#endregion

}

}

Using a orchestration to subscribe to schemas which have been published as a web service

leave a comment »

I came across this gotcha a few days ago, I wanna document it very badly before I forget.

So you published your schemas as a web service, built a orchestration and a C# program to test your web service. And then BAAAMM, you got the following error.

A message received by adapter “SOAP” on receive location “<YourReceiveLocation>” with URI “<YourWebServiceURI>” is suspended.
Error details: The published message could not be routed because no subscribers were found. This error occurs if the subscribing orchestration or send port has not been enlisted, or if some of the message properties necessary for subscription evaluation have not been promoted.

You checked your orchestration and the web service and failed to identify the problem. Now it’s the time to blame biztalk, as it gives no help for resolving this issue.

As a general note, you can view your subscriptions from Biztalk Administration Console -> Biztalk Group -> New Query -> Search for subscriptions -> Double click on the orchestration.

Ok, in the expressions tab, there is a method Name row. This method name row has to be the same as the operation name of the webservice you are using. For example, if you are calling an operation in a web service called “calculate”, the orchestration port subscribing to this web service must use the name “calculate” as it’s “Operation” not the default value “Operation_1”. SO next time don’t forget to set your operation name when subscribing to a web service. 🙂

I will post a guide on how to publish a web service and write a C# windows application to test the web service when I have time.

Written by stormdweller

March 31, 2009 at 3:33 AM

How to call a stored procedure with parameters and retrieve the response

leave a comment »

One of the tasks given to me last week was to build a biztalk solution to communicate with a stored procedure on a SQL server DB. I’ve played around the SQL adapter in biztalk for a bit and I’m going write a step-by-step guide to show you how I built my solution. It might not be the only way nor the correct way to do it, but it worked for me, please do tell me if I made any stupid mistakes.

First, Click the Add Generated item to bring up the “Add Adapter Wizard”. This wizard will generate a schema to use for the SQL interactions. In this case, it will generate 2 schemas, one for sending the request and one for retrieving the response.

Here, you set up your SQL related information including Server name, Login, Target DB.

And in the following window,

Add Generated Item wizard

Add Generated Item wizard

Select Send port as we are sending a request first and then receive a response.

Type in the corresponding namespace and root names in the fields.

(Note: The namespace and root names here is the namespace and root names of the generated schemas.)

In the next window, select Stored Procedure.

In the “Statement information” window, select the stored procedure you want to call and click generate (make sure the value column is un-checked).

(Note: Here, the SQL adapter communicates with the SQL database and retrieves the format of the return value of the stored procedure you want to call and it constructs the response schema by looking at the return value’s format. Hence, to generate a schema, the return value must be in XML format. If you get a incorrect syntax error, refer to the “SQL Adapter – Add generated item” entry)

Click Finish on the next window.

Now, the SQL adapter is set. If you look at your project folder, there are 2 new items, the SQL service and an empty orchestration.

Expand SQLSerive schema, confirm that the request and response schemas are set correctly. Notice that the request schema contains the stored procedure as a child record and it’s child field elements are the parameters for that stored procedure.

Now we need to set up the orchestration to use the SQL adapter.

Create 2 messages in orchestration for the request and response schemas.

Drag a Send shape to the orchestration where you want the SQL stored procedure call to be made.

Drag a Receive shape to the orchestration where you want the stored procedure response to be returned.

Create a Request-Response port for sending and receiving messages from the SQL stored procedure and click Next.

Config port wizard

Config port wizard

In the next window, select “I will be send request and receiving response.” Click Next and click Finish to close the wizard

The request message must be constructed before going into the Send shape. We can use a map to assign values for the fields in the request schema. As mentioned before, the fields in the request schema are the parameters of the stored procedure.

Now we can deploy the solution and continue the configuration in the Biztalk administration console.

In the Biztalk console, create a 2-way send port for your application. Select “SQL” for the transport type and click configure.

SQL send port

SQL send port

Set up the connection string and type in the namespace and response root element name.

(Note: The namespace is the namespace of your SQLSerive schema and the root element name is the root name of the response schema in SQLService.)

From the drop-down menus, select XMLTransmit and XMLReceive from the pipeline options and click OK.

AND WE ARE DONE!

Written by stormdweller

March 24, 2009 at 2:34 AM