Blog of Lee Williams

Blog of Lee Williams

Custom Pipeline Components Not Updating

I’m sure many BizTalk developers who create custom pipeline components will have run into this problem. You create a custom pipeline component, deploy it, and something doesn’t quite work. Back into Visual Studio and make some code fixes, looks good and redeploy. Test your fix only to find your changes don’t appear to have come across. Ok, rebuild everything and try again. Still no joy? You then start ripping out your solution, removing assemblies from the GAC, restarting Visual Studio etc. until it eventually seems to deploy, but you have no idea which step it was that solved the issue.  

The answer to the problem is Visual Studio is trying to be to helpful. When you add your custom pipeline components into the toolbox on the pipeline editor Visual Studio caches that version. Therefore simply restarting Visual Studio will not work no matter how many times you remove the old assemblies from the GAC. You need to remove the custom pipeline component from the toolbar. Restart Visual Studio and add the component back into the toolbar. Alas the component has been updated.

BizTalk – Generating schemas from classes with TargetNamespace

BizTalk provides a us a way of generating schemas from c# classes by using the xsd.exe tool which comes with the BizTalk SDK. The tool also allows us to generate c# classes from a schema and as an option we can specify the runtime namespace for the generated types. What would be nice is if we could specify the target namespace for the schemas when we generate them from our classes. As a BizTalk developer this can cause major headaches as you need to remember to add this manually every time you need to regenerate your schemas. After much investigate it turns out there is a way to get the target namespace into our schemas.

So for example we have our C#’ class which may look something like this:

using System.Xml.Serialization;
 
namespace ServiceBusDemo.Model
{
     public class TodoItem
     {
         public int ID { get; set; }
         public string Title { get; set; }
         public string Description { get; set; }
         public bool IsDone { get; set; }
     } }

We run it though the xsd.exe tool and it generates us a schemas which looks like this:

  <?xml version="1.0" encoding="utf-16" ?>
- <xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="TodoItem" nillable="true" type="TodoItem" />
- <xs:complexType name="TodoItem">
- <xs:sequence>
  <xs:element minOccurs="1" maxOccurs="1" name="ID" type="xs:int" />
  <xs:element minOccurs="0" maxOccurs="1" name="Title" type="xs:string" />
  <xs:element minOccurs="0" maxOccurs="1" name="Description" type="xs:string" />
  <xs:element minOccurs="1" maxOccurs="1" name="IsDone" type="xs:boolean" />
  </xs:sequence>
  </xs:complexType>
  </xs:schema>

So normally at this point I would go in and manually add the targetnamespace, I probably misspell it, deploy my BizTalk solution and spend half a day wondering why my message are not being routed correctly.

The solution to this is to simply add a reference to the System.Xml.Serialization namespace (Notice how on the msdn help page for the xsd.exe tool it states that the tool uses the System.Xml.Serialization.XmlSerializer) and add the XmlType and XmlRoot (for root elements) Attributes

to your c# classes.

using System.Xml.Serialization;
 
namespace ServiceBusDemo.Model
{
     [XmlType(TypeName = "TodoItem", Namespace = "http://schemas.datacontract.org/2004/07/ServiceBusDemo.Model.TodoItem")]
     [
XmlRoot(ElementName = "TodoItem", Namespace = "http://schemas.datacontract.org/2004/07/ServiceBusDemo.Model.TodoItem")]
     public class TodoItem
     {
         public int ID { get; set; }
         public string Title { get; set; }
         public string Description { get; set; }
         public bool IsDone { get; set; }
     } }

Once we have defined the namespace we want to use, rerun the xsd.exe tool and this time all the work is done for us Smile

<?xml version="1.0" encoding="utf-16" ?>
- <xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns:tns="http://schemas.datacontract.org/2004/07/ServiceBusDemo.Model.TodoItem" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/ServiceBusDemo.Model.TodoItem" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="TodoItem" nillable="true" type="tns:TodoItem" />
- <xs:complexType name="TodoItem">
- <xs:sequence>
  <xs:element minOccurs="1" maxOccurs="1" name="ID" type="xs:int" />
  <xs:element minOccurs="0" maxOccurs="1" name="Title" type="xs:string" />
  <xs:element minOccurs="0" maxOccurs="1" name="Description" type="xs:string" />
  <xs:element minOccurs="1" maxOccurs="1" name="IsDone" type="xs:boolean" />
  </xs:sequence>
  </xs:complexType>
  </xs:schema>