Tuesday, May 14, 2013
Two things I learned about direct bound ports
When you directly bind to the message box, your messages will get picked up by subscribing orchestrations and send ports and then returned (see diagram below which I got from http://www.c-sharpcorner.com/UploadFile/john_charles/Introduction_to_Biztalk_Server09072007152846PM/Introduction_to_Biztalk_Server.aspx). One thing I learned is that if you have two orchestrations subscribing to a message they will both get it. Another thing you might notice from the diagram is that if your orchestration recieves and sends back the same message then it will pick it up again(and again, and again...). This infinite loop is a rather common peril of message box use.
Thursday, March 14, 2013
Enterprise SSO problem
So I was having an issue after creating a local user on my box with all kinds of privledges. The issue was that this user couldnt access the secret on the master secret server(ESSO was running as this local user);
Error Code: 0xC0002A1F, Cannot perform encryption or decryption because the secret is not available from the master secret server. See the event log for related errors.
The consensus online is to restore the master secret. This means going to the ESSO snap in (or cmd) and right click 'Restore'. Then locate the backup file you want to restore from. The location of your backup files(*.bak) in case you don't already have one you set up or you don't know, is:
C:\Program Files\Common Files\Enterprise Single Sign-On\SSOXXXX.bak
where the XXXX is generated by Biztalk when it creates the backups. I used the most recent backup file. I didnt know the password, then noticed, from the password secret, that the password was an old users password. After using the correct password i successfully restored and everything worked fine. I will say that if you use the wrong password you get an error of 'Bad Data' from ESSO.
Error Code: 0xC0002A1F, Cannot perform encryption or decryption because the secret is not available from the master secret server. See the event log for related errors.
The consensus online is to restore the master secret. This means going to the ESSO snap in (or cmd) and right click 'Restore'. Then locate the backup file you want to restore from. The location of your backup files(*.bak) in case you don't already have one you set up or you don't know, is:
C:\Program Files\Common Files\Enterprise Single Sign-On\SSOXXXX.bak
where the XXXX is generated by Biztalk when it creates the backups. I used the most recent backup file. I didnt know the password, then noticed, from the password secret, that the password was an old users password. After using the correct password i successfully restored and everything worked fine. I will say that if you use the wrong password you get an error of 'Bad Data' from ESSO.
Tuesday, January 29, 2013
xpath in expression shapes
xpath is a notation for returning specific elements found in xml. It is very useful. I will go over a few problems I had getting it to work in Biztalk 2010 and the solutions I came accross.
First of all suppose you have some message in Biztalk,
<ns0:TaskUpdate xmlns:ns0="TaskUpdateTN">
<ns0:Task>
<ns0:CallID>CallID_0</ns0:CallID>
<ns0:Number>125</ns0:Number>
<ns0:Status>
<ns0:Name>Name_0</ns0:Name>
</ns0:Status>
<ns0:Customer>Customer_0</ns0:Customer>
<ns0:WorkOrderNumber>WorkOrderNumber_0</ns0:WorkOrderNumber>
<ns0:RequiredSkills1>Skill</ns0:RequiredSkills1>
</ns0:Task>
</ns0:SXPTaskUpdate>
and you want to extract a certain element of the xml, say the 'Customer' element.
1) Create a couple of strings in the orchestration, tempStr and customerStr.
2) Use the schema properties to grab the xpath of the element you want,
/*[local-name()='TaskUpdate' and namespace-uri()='TaskUpdateTN']/*[local-name()='Task']/*[local-name()='Customer']. Notice you dont need every last namespace in the xpath, just enough so it can safely find what you're looking for.
3) Open up an expression shape and type:
tempStr="string(/*[local-name()='TaskUpdate' and namespace-uri()='TaskUpdateTN']/*[local-name()='Task']/*[local-name()='Customer']/text())";
customerStr = xpath(Message_1, tempStr);
And youre done; 'customerStr=Customer_0'. In some cases the 'string()' is not neccesary. The '/text()' however is, or else you would get 'customerStr=<ns0:Customer>Customer_0</ns0:Customer>' instead of just 'customerStr=Customer_0'. If you have a list of Customer elements in your message and you want the 3rd element in that list then your xpath will be '...[local-name()='Customer'][3]/text()'.
If you want to assign a certain element in the Message to a value, say the 'Customer' element, to "John Doe". Change step 3) above to:
3)Open up an expression shape and type:
tempStr="/*[local-name()='TaskUpdate' and namespace-uri()='TaskUpdateTN']/*[local-name()='Task']/*[local-name()='Customer']";
xpath(Message_1, tempStr)="John Doe";
Here a 'string()' doesnt work. Also an important thing to remember is if Message_1 is from a Message Part then you will have to write 'xpath(Message_1.part1,tempStr)="John Doe"'.
First of all suppose you have some message in Biztalk,
<ns0:TaskUpdate xmlns:ns0="TaskUpdateTN">
<ns0:Task>
<ns0:CallID>CallID_0</ns0:CallID>
<ns0:Number>125</ns0:Number>
<ns0:Status>
<ns0:Name>Name_0</ns0:Name>
</ns0:Status>
<ns0:Customer>Customer_0</ns0:Customer>
<ns0:WorkOrderNumber>WorkOrderNumber_0</ns0:WorkOrderNumber>
<ns0:RequiredSkills1>Skill</ns0:RequiredSkills1>
</ns0:Task>
</ns0:SXPTaskUpdate>
and you want to extract a certain element of the xml, say the 'Customer' element.
1) Create a couple of strings in the orchestration, tempStr and customerStr.
2) Use the schema properties to grab the xpath of the element you want,
/*[local-name()='TaskUpdate' and namespace-uri()='TaskUpdateTN']/*[local-name()='Task']/*[local-name()='Customer']. Notice you dont need every last namespace in the xpath, just enough so it can safely find what you're looking for.
3) Open up an expression shape and type:
tempStr="string(/*[local-name()='TaskUpdate' and namespace-uri()='TaskUpdateTN']/*[local-name()='Task']/*[local-name()='Customer']/text())";
customerStr = xpath(Message_1, tempStr);
And youre done; 'customerStr=Customer_0'. In some cases the 'string()' is not neccesary. The '/text()' however is, or else you would get 'customerStr=<ns0:Customer>Customer_0</ns0:Customer>' instead of just 'customerStr=Customer_0'. If you have a list of Customer elements in your message and you want the 3rd element in that list then your xpath will be '...[local-name()='Customer'][3]/text()'.
If you want to assign a certain element in the Message to a value, say the 'Customer' element, to "John Doe". Change step 3) above to:
3)Open up an expression shape and type:
tempStr="/*[local-name()='TaskUpdate' and namespace-uri()='TaskUpdateTN']/*[local-name()='Task']/*[local-name()='Customer']";
xpath(Message_1, tempStr)="John Doe";
Here a 'string()' doesnt work. Also an important thing to remember is if Message_1 is from a Message Part then you will have to write 'xpath(Message_1.part1,tempStr)="John Doe"'.
Thursday, December 6, 2012
Could not establish trust relationship for the SSL/TLS ...
If you are consuming a web service in Biztalk and calling it through ports, etc you may come across a certificate for a wsdl that's out of date or wrong in some other way. in this case you get the following error;
"Could not establish trust relationship for the SSL/TLS ... "
In code its easy enough to bypass this by trusting all certs.
However in Biztalk its much harder; I tried adding this code in an expression shape but had no luck. After searching around a bunch I found the following server wide solution. Add the following to your BtsNtSvc.exe.config (see bold):
<?xml version="1.0" ?>
<configuration>
<system.net>
<settings>
<servicePointManager checkCertificateName="false" checkCertificateRevocationList="false" />
</settings>
</system.net>
...
Obviously this is really risky security wise; only use it for development.
"Could not establish trust relationship for the SSL/TLS ... "
In code its easy enough to bypass this by trusting all certs.
//Trust all certificates System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
<?xml version="1.0" ?>
<configuration>
<system.net>
<settings>
<servicePointManager checkCertificateName="false" checkCertificateRevocationList="false" />
</settings>
</system.net>
...
Obviously this is really risky security wise; only use it for development.
Thursday, November 15, 2012
UTF and encodings
So there are a number of ways(ha!) to go from bits/bytes of data to human readable glyphs(like 'a' or 'A' or the chinese characters, etc). Each is called an 'encoding'. One way to go from bytes to (english) characters is ASCII encoding. This uses 8 bits, or actually it uses 7 bits and the extra bit is something that doesnt matter too terribly much to me. This means we can encode 2^7=128 different glyphs(or characters, I'm not sure of the technical distinction. Actually we can also include 'beep', space, escape, etc. For my purposes here i will call all the things we represent 'characters')using ASCII encoding. Naturally the ones ASCII includes for encoding are all the english letters(41 to 7A, in hex) some non readable characters(0 through 20 in hex) and numbers (30 through 39 in hex). You can look up the rest.
UTF encoding is a little different, it starts by taking all the writing systems(in the world) and assigning them to code points those code points are then assigned to a hex number which is stored in memory(in binary).
Every platonic letter(but also space, beep, escape, etc) in every alphabet is assigned a magic number by the Unicode consortium which is written like this: U+0639. This magic number is called a code point. The U+ means "Unicode" and the numbers are hexadecimal. U+0639 is the Arabic letter Ain. The English letter A would be U+0041.
So with UTF we go from characters to code points and from code points to bits/bytes in hex (or decimal, but hex is more common). Now how do code points map to actual numbers represented by bytes, equivalently how do we go from a couple of bytes(how many bites do we get? ASCII took 7.) to a code point. Well UTF-8, UTF-16, etc are all different ways of going from a code point to an actual character(or non readable character).
UTF-8 makes some sense to me. as does UTF-16, though it takes up more space. UTF-8 uses between 1 and 6 bytes to store a code point, whereas UTF-16 uses either 2 bytes or 4 bytes to store a code point.
In UTF-8 U+0041 maps to just 41(in hex) in memory which is the character 'A'. Characters above ASCII, meaning above '127' in decimal or above 007F in hex, are stored in 16 bits(2 bytes). So UTF-8 doesnt use 2 bytes until it 'needs' to(the extra bit on the end of that first byte in UTF-8 is just set to 0 I think).
UTF-16 uses at least 2 bytes so U+0041 goes to 0041(in hex) in memory which is the character 'A'. For english characters this is a bit too much wasted memory('Hello' would look like 00 48 00 65 00 6C 00 6C 00 6F vs in UTF-8 it would be just 48 65 6C 6C 6F). So UTF-16 is a little memory heavy because every other byte is often 00, which in UTF-8, 00, would go to just null, since thats what 00 is in ASCII. UTF-8 and ASCII are the same up to 7F(in hex) or 127(in decimal).
There are other UTF encoding but 8 and 16 seem like the big ones to me. Of course the big thing to remember is that you have to have an encoding before you can read anything on a screen. This is why its so important.
Thursday, September 6, 2012
Biztalk App As HTTP Post Receiver
Suppose you want to set up a Biztalk app that handles incoming HTTP recieve Posts. There are a few parts to setting up an HTTP Receeive location and Biztalk App. I outline them in order below:
1)Set up handler:
*Start up IIS and go to the server tab on the left(main root of the tree).
*In the Features View, in the IIS section in the middle, click on Handler Mappings.
*In the upper left click on Add Script Map; fill in as follows
*RequestPath:
BTSHTTPReceive.dll
*Executable:
C:\Program Files\Microsoft BizTalk Server 2010\HttpReceive\BTSHTTPReceive.dll
*Name:
BTSHTTPReceive
*Click on Request Restrictions button:
*In the Verbs tab, click All verbs.
*In the Access tab click Script radio button.
*Click OK, and then click yes to add the ISAPI extension.
2)Set up IIS application:
*Add a new application, with Alias 'HttpReceive' and Physical Path 'C:\Program Files\Microsoft BizTalk Server 2010\HttpReceive' don't bother testing the connection.
*Use an application pool with access to the Biztalk Message Box DB. I dont think the default app pool has sufficent perms for this.
*In the IIS section of this application click on Authentication and disable everything but Anonymous.
3)Set up biz adapter:
*Create a Recieve Port and then a Location along with it, called whatever you like.
*For Transport type click HTTP. I reccomend using pass through receive as the Receive Pipeline since these posts come through not as XML but as plain text. See http://enricoscipio.blogspot.com/2009/02/biztalk-http-adapters-and-get.html. You should not have this recieve location hand off to an orchestration since orchestrations will need xml.
*Click on Configure and fill out as you see:
I reccomend having a simple send adapter just pick anything up from this recieve location and dump it in a folder.
4)Test with post.
*Open Fiddler, set it to POST;
*****
POST http://localhost/HttpReceive/BTSHTTPReceive.dll HTTP/1.1
Host: localhost
Connection: keep-alive
User-Agent: Fiddler
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Content-Length: 10
Name=Jason
*****
that last bit is in the body.
*You can also try GET;
GET http://localhost/HttpReceive/BTSHTTPReceive.dll?Name=Jason HTTP/1.1
Host: localhost
Connection: keep-alive
User-Agent: Fiddler
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Content-Length: 0
A good reference for most everything said here is:
http://allcomputers.us/windows_server/biztalk-2010-recipes---adapters---configuring-http-receives.aspx
Thursday, August 23, 2012
SSIS or scripts that take a runtime parameters at the command line
If you want to run an SSIS package from the command line you use dtexec. If you have a sql script that you want to run from the command line you use sqlcmd. Both of these utilities will allow you to pass through a variable at runtime to the script/package you created. Of course there are other ways to get them to run but the command line is the lowest common denominator for really anything that runs on a Windows computer(and not just Windows, but I digress).
SQL Script called prune.sql:
<SQL CODE HERE>
delete from Table where Column=$(Param)
<SQL CODE HERE>
and the scripting variable Param you would set like so;
C:\>sqlcmd -S "My Server" -v Param=15 -i prune.sql
SSIS package called Package.dtsx:
As an example say you have only one Control Flow object, no Data Flow objects, and the Control flow is a SQL task with variables as you see:
pruneSP is a stored proceedure that takes a parameter called @testval and when you click on Parameter Mapping you see the map from User::days_back to @testval:
Another gotcha, at least it seemed to me, was that your result set menu requires special configuration. Result Name should be set to 0 and then you will need some variable that you have created to to store the result set in. I named mine outputRS and it should be of type Object. For more on variables in SSIS see
http://www.simple-talk.com/sql/ssis/working-with-variables-in-sql-server-integration-services/
and for a walkthrough of how to use them that is very simple try this:
http://sqlfool.com/2009/08/getting-started-with-variables-in-ssis/
Anyway once you are finished with the dtsx file, you can run it like this(from the dir that the dtsx file is in):
C:\>dtexec /FILE Package.dtsx /SET \Package.Variables[User::days_back].Properties[Value];15
Subscribe to:
Posts (Atom)




