WCF

WCF: NetMsmqBinding and Non-Transactional Queues

Recently we had a situation where we needed to remove transactions from the equation in a WCF service because we were calling a downstream component that could not support transactions.  The new transaction infrastructure in .NET 2.0 and the use of ambient transactions makes it easy to leverage transactional functionality in your service calls with no real coding required on your part.  By default, using the NetMsmqBinding enables Durable and Exactly once on the binding which implies the use of transactions in the background, and those transactions are applied to any transactional call made including sending to other message queues, database connections, etc.

The new transaction infrastructure leveraged by WCF is great, except when you need to opt out, because the key to getting the result you want is understanding how the different "knobs and switches" (as coined by Juval Lowy) or configuration options on the binding affect each other.  In the case of Durable and Exactly Once you may be lead to believe disabling exactly once will remove transactions if you go solely by the descriptions of each option.  However, you will quickly be notified by the WCF runtime that enabling Durable and disabling ExactlyOnce on the NetMsmqBinding is not supported.

Disabling both Durable and ExactlyOnce on the NetMsmqBinding ultimately removed transactions from the equation and produced the result we expected once we did this on both the client and the service.

The other key is how we ultimately found the correct way to do this.  Once we changed the queue to non-transactional the symptom we saw was that our message we were sending kept ending up in the system wide Transactional Dead-Letter queue.  There was no error message or exception logged by our service because the message never got there.  A little research and a couple tests and we arrived at our solution.  We could have handled this with an IErrorHandler implementation but at the time we knew what direction to look (transactions were the issue) so we took the manual route.

Streaming in WCF: Knowing is Half the Battle

WCF provides the ability to stream data from service to client which can aid greatly in transferring large files and improve performance.  But as with all things WCF there are a few things you should know before you turn on the streams.

In order to activate streaming in WCF you must supply a service method that accepts or returns the type System.IO.Stream, edit your binding to use the streamed transfer mode (default is buffered), and let the streaming begin.  Be sure to consider the following advice from Large Data and Streaming on MSDN: "You should not be using System.IO.Stream derived types inside of data contracts. Stream data should be communicated using the streaming model, explained in the following "Streaming Data" section."  This post on MSDN forums explains in more detail how you can handle the stream on the receiving end as you do not have a guarantee that the type of stream you send is how it is received.  For example, if you send a MemoryStream, the receiver will receive it as the System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream class (any stream you send is received as this).  The data is there, it’s just not the type of stream you sent it as.

Here are a few bullets to keep in mind when streaming with WCF:

  • Your contract should accept or return the type System.IO.Stream and not any of the derived types.
  • On the receiving end the simplest way to deal with the stream is to treat is as the base System.IO.Stream class.
  • Callers of the service will have to understand the format of the stream through a mechanism provided out of band – the WSDL cannot show them what will potentially be in the stream.
  • Set the buffer sizes to appropriate values in configuration: MaxBufferSize, MaxReceivedMessageSize, and MaxStringContentLength
  • Streaming is only available on BasicHttpBinding, NetTcpBinding, and NetNamedPipeBinding.
  • WCF is still Xml based so your stream will be serialized as an xs:base64Binary as evidenced by this WSDL output:
      <?xml version="1.0" encoding="utf-8" ?>
      <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/Message" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/Message">
        <xs:simpleType name="StreamBody">
          <xs:restriction base="xs:base64Binary" />
        </xs:simpleType>
      </xs:schema>

Now you know, and for those of us who spent the 80’s watching cartoons we know what knowing is.

Beware Writing to the ‘Bin’ Folder in IIS Hosted Services

The other day we had a issue occur where one of our WCF web services hosted in IIS 6 was getting a ThreadAbortException while processing the first few requests.  We had made a change to the service to perform some diagnostic logging and the data was being written to a subfolder in ‘bin’.  This turned out to be the cause of our problem.  Because of how IIS 6 works in conjunction with .NET, when the ‘bin’ folder is touched it initiated a recycle of the application pool because it thought files had changes.  We moved the logging to save to App_Data and our troubles went away.

Buyer beware, if you write to ‘bin’ you might become the victim of a mysterious, but explainable, application pool recycle!

WSCF.Blue Support For WCF and a Few Tips on WCF + XmlSerializer

Over a week ago the Web Services Contract First (WSCF) project announced the "blue" version which supports WCF.  WSCF is a great tool that saved my butt on a large integration project with one of our fine 3-letter agencies a few years back.  The tool boasts the ability to take a WSDL and Schema files and turn them into C# or VB code.  When I saw the new release I had to give it a try.

My first run went smooth but I noted the WSCF tool generated the service contract interface type without the "I" prefix.  I reported this to the team and they promptly fixed it and even tried it against the DOJ LEXS WSDLs that I was working on.  Many thanks to Christian Weyer and Alex Meyer-Gleaves for responding so quickly.

In the government data sharing space there is a lot of contract first development happening.  The NIEM IEPD process encourages developing both the business need and data schemas before you begin coding the exchange.  I think this is a great approach to take and helps everyone from the business analysts to the technical analysts understand the exchange, the data to be exchanged, and the overall process. 

Having an open source tool like WSCF is a great addition to your toolbox when interop is key.

As I migrated a soon-to-be-released open source project to it’s new solution I used WSCF to generate all the classes and service stub.  The following are some tips I have when you are using WCF + XmlSerializer; these really have nothing to do with WSCF, you will get the same if you use SvcUtil directly.  That said I think WSCF generates the classes from the schemas with a lot less effort and actually better than Svcutil directly.

Tips for WCF + XmlSerializer

Tip 1: For types that are marked with a MessageContractAttribute and IsWrapped=True, if you inherit from a base class that exposes a public XmlSerializerNamespaces property the namespaces are not properly serialized.  XmlSerializerNamespaces are used when you want to control the namespace prefixing and output during serialization.  This is accomplished by creating a public field with the name "xmlns" and marking it up with the XmlNamespaceDeclarationAttribute.  The XmlSerializer uses the presence of this field to output the Xml Namespaces and the associated prefixes within the element from the object in the object graph where the attribute was applied.

Tip 2: If you have a class marked with the MessageContractAttribute and you inherit from a base class within that class then the base class must also be marked with the MessageContract attribute.  WCF gives you a nice error message explaining this because it is unable to start the service.

Tip 3: In some cases both SvcUtil and WSCF generate ReplyAction="*" on the WSDL.  This could potentially make it fail in an interop scenario.  Not exactly sure what causes that but in any case, if you have trouble then remove that from the service contract.  A tell tale sign is that when you view the WSDL page for your service you do not see any of the operations listed.

WCF InstanceContextMode.Single, Default Constructors, and Unity

During a refactoring of a WCF solution I was converting all the various services in the solution to use dependency injection with constructors.  One of the services was configured as a singleton using the ServiceBehavior InstanceContextMode.Single.  This particular service controls a resource that is best left for a singleton because it has an open socket listener that receives responses from our mainframe systems.  The service was also configured for transactions and has the ReleaseServiceInstanceOnTransactionComplete explicitly set to false.

When the other developer on the project fired up the test harness for the services he was receiving the message “The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host. “.  After testing a few theories I noticed that the service was marked up with the InstanceContextMode behavior.  I removed the attribute and tested the service and it worked just fine which lead me to draw a conclusion about how WCF handles the InstanceContextMode attribute.

Because you are telling WCF to manage that service instances lifetime it makes sense that it would require a default constructor because WCF is going to be instantiating and disposing of the service instance.  When I refactored the service with no default constructor that was a breaking change for the WCF infrastructure.  So the question remains, can Unity handle a singleton service instance?

To test Unity with a Singleton service I followed the steps in my previous article on Unity and WCF and created an IInstanceProvider, IServiceBehavior, and a custom ServiceHost.  The results were what I expected.  Each call to the service was handled by the singleton instance of the service whose lifetime was being managed by the Unity container.

using System;

namespace Service
{
    //[System.ServiceModel.ServiceBehavior(InstanceContextMode=System.ServiceModel.InstanceContextMode.Single)]
    public class PersonService : Contracts.IPersonService
    {
        private Guid _instanceId;

        /// <summary>
        /// Initializes a new instance of the PersonService class.
        /// </summary>
        public PersonService()
        {
            _instanceId = Guid.NewGuid();
        }

        #region IPersonService Members

        public Contracts.PersonResponse SavePersonRecord(Contracts.PersonRequest request)
        {
            return new Contracts.PersonResponse(_instanceId.ToString(),                     String.Format("Added Person - {0}", request.Person.Name));
        }

        public Contracts.PersonResponse DeletePersonRecord(Contracts.PersonRequest request)
        {
            return new Contracts.PersonResponse(_instanceId.ToString(),                    String.Format("Deleted Person - {0}", request.Person.Name));
        }

        #endregion
    }
}

Unity_Singleton_Output

The client calls the SavePersonRecord method then subsequently the delete person method.  As you can see the Instance Id returned by the service is the same for both calls.  Removing the lifetime element from the Unity configuration results in two different instance Id’s returning from the service because the default behavior for WCF is to create a new instance per call to the service.

I ran one final test and that was to remove the default constructor and require the Instance Id to be passed to the constructor:

using System;

namespace Service
{
    //[System.ServiceModel.ServiceBehavior(InstanceContextMode=System.ServiceModel.InstanceContextMode.Single)]
    public class PersonService : Contracts.IPersonService
    {
        private Guid _instanceId;

        /// <summary>
        /// Initializes a new instance of the PersonService class.
        /// </summary>
        /// <param name="instanceId"></param>
        public PersonService(string instanceId)
        {
            _instanceId = new Guid(instanceId);
        }

        #region IPersonService Members

        public Contracts.PersonResponse SavePersonRecord(Contracts.PersonRequest request)
        {
            return new Contracts.PersonResponse(_instanceId.ToString(),               String.Format("Added Person - {0}", request.Person.Name));
        }

        public Contracts.PersonResponse DeletePersonRecord(Contracts.PersonRequest request)
        {
            return new Contracts.PersonResponse(_instanceId.ToString(),                String.Format("Deleted Person - {0}", request.Person.Name));
        }

        #endregion
    }
}

The Unity configuration now looks like so:

<unity>
  <typeAliases>
    <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,         Microsoft.Practices.Unity" />
    <typeAlias alias="IPersonService" type="Contracts.IPersonService, Contracts" />
  </typeAliases>
  <containers>
    <container>
      <types>
        <type type="IPersonService" mapTo="Service.PersonService, Service">
          <lifetime type="singleton" />
          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,              Microsoft.Practices.Unity.Configuration">
            <constructor>
              <param name="instanceId" parameterType="System.String, mscorlib">
                <value value="2423f423-a4da-4306-9ba1-452214c517d6"/>
              </param>
            </constructor>
          </typeConfig>
        </type>
      </types>
    </container>
  </containers>
</unity>

Hopefully it is no surprise that the results of calling the service are the same as the screenshot posted above.

I still need to test this with transactions but I believe using the right set of options will prevent WCF from disposing your singleton and allow your custom Unity service host to handle that.

Dude, where’s my message? WCF and Bringing Messages Back From The Dead (-Letter Queue)

Last week while researching an issue with one of our systems I discovered that six days worth of messages were missing from a queue.  After the initial panic we started researching.  One of my colleagues discovered the Transactional Dead-Letter queue had a large amount of messages piled up in it.  I had read some about that queue but never really dug into it.  This gem of an article got me started on a path that would ultimately lead to a best of breed type solution.

The solution from Billy Dunlop’s article has you change the ServiceBehavior AddressFilterMode to "Any".  What this does is allows your queued service to receive messages destined for any endpoint, so long as the message body is what it expects.  I have used this in the past for poison queues and it made perfect sense here.  However, we had one other problem.  Some of the messages in the dead-letter queue were for other queued services and simply changing one of our services to use the dead letter queue as it’s endpoint would not work right.  The solution is to use a more generic contract similar to the WCF Message Router covered in this MSDN article.

I took the router approach and created a router service and console application to host it.  For work I did all this in VB.NET.  As a tribute to my very good friend David Risko I spent the weekend rewriting the whole thing in C#.  This was my first shot at writing something from scratch in C#, so if you see something that could be condensed or written in a more clear manner please do let me know.

The default Time-to-live on the NetMsmqBinding is 1 day.  This can be adjusted in configuration or through code when you create the binding.  As a simple test you can create a NetMsmq service client and set your binding time-to-live to something ridiculous like 30 seconds (it’s a time span so you can do this with TimeSpan.FromSeconds(int)).  Watch the message hit your transactional queue and refresh and after 30 seconds, *poof*, message gone and you can now find it in your Transactional Dead-Letter queue.

Feel free to follow the code below or download the .ZIP file with the solution.  The solution was created in Visual Studio 2008 SP1.

On to the code!

The contracts – included are the Service Contract  which will be used by the router service and the Channel contract which will be used by the MessageRouter class to resend the message to it’s intended destination.  The service contract uses System.ServiceModel.Channels.Message as it’s input message.  This allows the router to receive any WCF message for any service without having to understand the body.  This is a hugely powerful ability that should be used with great care.

namespace CD.ServiceModel.NetMsmqRouter.Contracts
{
   
/// <summary>
    ///
Service contract interface for the message router service.
  
/// </summary>
   
[System.ServiceModel.ServiceContract]
    public interface
IMessageRouterService
   
{
        [System.ServiceModel.OperationContract(IsOneWay=true,Action="*")]
        void Route(System.ServiceModel.Channels.Message message);
    }

    public interface IMessageRouterChannel : System.ServiceModel.IClientChannel,IMessageRouterService
   
{

    }
}

The biggest piece I had to get my head around when learning WCF was the notion of the contract.  The same interface will be implemented by both the service and client but each one implements it differently.  The service implements it from the perspective of receiving the message and the client implements it from the perspective of sending the message.

Next up is the service implementation.  Pretty straight forward and it does two things – uses the MessageWriter class to save the message to disk (in case something really bad happens) and then uses the MessageRouter class to send the message to it’s original intended destination.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CD.ServiceModel.NetMsmqRouter.Service
{
    [System.ServiceModel.ServiceBehavior(AddressFilterMode = System.ServiceModel.AddressFilterMode.Any,        ValidateMustUnderstand = false)]
    public class RouterService : Contracts.IMessageRouterService
    {
        private MessageWriter _writer;
        private MessageRouter _router;

        /// <summary>
        /// Initializes a new instance of the RouterService class.
        /// </summary>
        public RouterService()
        {
            _writer = new MessageWriter(Properties.Settings.Default.MessageWriterPath);
            _router = new MessageRouter(Properties.Settings.Default.NetMsmqBindingConfigurationName);
        }

        #region IMessageRouterService Members

        [System.ServiceModel.OperationBehavior(TransactionAutoComplete = true, TransactionScopeRequired = true)]
        public void Route(System.ServiceModel.Channels.Message message)
        {
            try
            {
                System.Diagnostics.Trace.WriteLine("----- Message Received -----");
                System.ServiceModel.Channels.MessageBuffer messageCopyToWrite = message.CreateBufferedCopy(Int32.MaxValue);
                _writer.Write(messageCopyToWrite);
                _router.RouteMessage(messageCopyToWrite.CreateMessage());
                System.Diagnostics.Trace.WriteLine("----- Message Processing Complete -----");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.ToString());
                throw;
            }
        }

        #endregion
    }
}

The service is geared to work with the Transactional Dead-Letter queue which is why the Route method is marked up with the TransactionAutoComplete and TransactionScopeRequired attributes.  Within the try/catch block the service does not handle the exception in order to facilitate the aborting of the transaction scope the message is received under and this is the recommended pattern when you use TransactionAutoComplete = true.  If we did not throw here the scope would complete and the message would be lost if it was not routed to it’s original queue.

The message writer class has one responsibility – write the message to the path supplied in it’s constructor.  The message router class is the one we’ll focus on next as it is responsible for taking the original message and routing it to the messages original destination:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Transactions;

namespace CD.ServiceModel.NetMsmqRouter.Service
{
    /// <summary>
    /// Routes a message to its original destination
    /// </summary>
    internal class MessageRouter
    {
        private string _bindingConfigurationName;

        /// <summary>
        /// Creates a new instance of the message router class.
        /// </summary>
        /// <param name="bindingConfigurationName"></param>
        public MessageRouter(string bindingConfigurationName)
        {
            _bindingConfigurationName = bindingConfigurationName;
        }

        /// <summary>
        /// Gets an instance of the NetMsmqBinding
        /// </summary>
        /// <returns></returns>
        /// <remarks>Returns the default binding if no configuration name was specified.</remarks>
        private NetMsmqBinding GetBinding()
        {
            if (!string.IsNullOrEmpty(_bindingConfigurationName))
            {
                return new NetMsmqBinding(_bindingConfigurationName);
            }
            else
            {
                return new NetMsmqBinding();
            }
        }

        /// <summary>
        /// Returns an instance of a Contracts.IMessageRouterChannel
        /// </summary>
        /// <param name="binding"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        private Contracts.IMessageRouterChannel GetChannel(NetMsmqBinding binding, string address)
        {
            return new ChannelFactory<Contracts.IMessageRouterChannel>(binding, address).CreateChannel();
        }

        /// <summary>
        /// Routes the message to its destination uri.
        /// </summary>
        /// <param name="message">The message to send</param>
        public void RouteMessage(System.ServiceModel.Channels.Message message)
        {
            System.Diagnostics.Trace.WriteLine(String.Format("Message destination: {0}", message.Headers.To.ToString()));
            Uri destinationUri = message.Headers.To;
            System.ServiceModel.NetMsmqBinding binding = GetBinding();
            using (Contracts.IMessageRouterChannel channel = GetChannel(binding, destinationUri.ToString()))
            {
                using (System.Transactions.TransactionScope scope =                    new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    try
                    {
                        channel.Route(message);
                        scope.Complete();
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine(String.Format("**** Error ****\n{0}", ex.ToString()));
                        channel.Abort();
                        throw;
                    }
                }
            }
        }

    }
}

All that is left is to wire up the service in the console host and then add the proper configuration elements.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using CD.ServiceModel.NetMsmqRouter;

namespace RouterServiceConsoleHost
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out));
            System.Diagnostics.Trace.AutoFlush = true;
            System.Diagnostics.Trace.WriteLine("Starting service.");
            StartServiceHost(typeof(CD.ServiceModel.NetMsmqRouter.Service.RouterService));
        }

        public static void StartServiceHost(Type serviceType)
        {
            using (System.ServiceModel.ServiceHost serviceHost = new System.ServiceModel.ServiceHost(serviceType))
            {
                serviceHost.Open();

                Trace.WriteLine("Service started...press <Enter> to exit");
                Trace.WriteLine("");
                Trace.WriteLine("");

                Console.ReadLine();
                if (serviceHost.State == System.ServiceModel.CommunicationState.Faulted)
                {
                    serviceHost.Abort();
                }
                serviceHost.Close();
            }

        }
    }
}

And the configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="CD.ServiceModel.NetMsmqRouter.Service.Properties.Settings"  type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <applicationSettings>
    <CD.ServiceModel.NetMsmqRouter.Service.Properties.Settings>
      <setting name="MessageWriterPath" serializeAs="String">
        <value>C:\Users\Chris\Desktop\RecoveryRouter\</value>
      </setting>
      <setting name="NetMsmqBindingConfigurationName" serializeAs="String">
        <value>RecoveryRouterNetMsmqBinding</value>
      </setting>
    </CD.ServiceModel.NetMsmqRouter.Service.Properties.Settings>
  </applicationSettings>
  <system.serviceModel>
    <bindings>
      <netMsmqBinding>
        <binding name="RecoveryRouterNetMsmqBinding" maxReceivedMessageSize="4194304" maxRetryCycles="2" receiveRetryCount="1" timeToLive="1">
          <readerQuotas maxStringContentLength="4194304"/>
          <security mode="None">
            <transport msmqProtectionLevel="None"/>
          </security>
        </binding>
      </netMsmqBinding>
    </bindings>
    <services>
      <service name="CD.ServiceModel.NetMsmqRouter.Service.RouterService">
        <endpoint address="net.msmq://localhost/system$;DeadXact" binding="netMsmqBinding" bindingConfiguration="RecoveryRouterNetMsmqBinding" name="RecoveryRouterService" contract="CD.ServiceModel.NetMsmqRouter.Contracts.IMessageRouterService"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>
Technorati Tags: ,

Modularizing WCF with Unity

For a new project at work I thought it best to use dependency injection to deal with some complexities we were facing.  I also wanted to get in and do some mocking in our unit tests to get a good feel for that.  Since we use the Enterprise Library I decided it would be easiest to roll with using Unity.  I have previously blogged about using Unity but this would go even further, because we would be injecting a dependency into the constructor of the service as well as injecting dependencies into the service’s core library.

I did quite a bit of homework and reached the conclusion that in order to do this you would need to hook into WCF’s pipeline and override several key areas during the service host creation and service instance creation.  The best article I found to get me started was this one by Steve Moseley.  Steve broke it down into 6 steps:

  1. Creating a custom instance provider that resolves the service
  2. Creating a custom service behavior to plug in the new instance provider
  3. Creating a custom service host that will add the new behavior
  4. Creating a custom service host factory (which configures your Unity Container)
  5. Changing the service host factory in the .svc file
  6. Inject your objects (through configuration)

His instructions were fantastic for steps 1-5 but step 6 left me to think on my own a bit.  The constructor of the new service we were working on needed an instance of its “core” library which will be the real work horse for the service.  Typically our services only provide a gateway into some other functionality so the service layer handles messaging and translation then delegates the work to a core library which can do whatever it needs to. 

This service would also be a little different than most because we would be relying on both internal and external “suppliers” to provide data to our core library.  These suppliers could be in the form of remote web services, local services, or shared assemblies.  Our core library itself will also need it’s dependencies injected at runtime.

Step 6 involved a bit more detailed study of Unity in which I did the following:

  • Defined typeAliases for each of the dependencies I would be injecting
  • Defined type mappings for the simple dependencies which had only a default constructor
  • Defined typeConfigs for the complex dependencies which required other dependencies passed to their constructor

I chose the constructor injection route because the service should not be created without a core library and the core library should not be created without its supplier dependencies and data access layer.  I believe I could have accomplished something similar had I used default constructors and exposed read/write properties for the dependencies.  This would have removed the constructor requirements but potentially caused issues if someone were using this class without supplying the dependencies to the read/write properties.  So, constructor injection wins for now.

In the end the config looked something like this:

<configSections>
  <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<unity>
  <typeAliases>
    <!-- Lifetime manager types -->
    <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    <typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    <!-- User-defined type aliases -->
    <typeAlias alias="ISupplier" type="MyService.Contracts.ISupplier, MyService.Contracts"/>
    <typeAlias alias="MyService" type="MyService.Service.MyService, MyService.Service"/>
    <typeAlias alias="ICore" type="MyService.Contracts.ICore, MyService.Contracts"/>
  </typeAliases>
  <containers>
    <container>
      <types>
        <type type="ISupplier" mapTo="MyService.Suppliers.ExternalSupplier, MyService.Suppliers" name="ExternalSupplier"/>
        <type type="ISupplier" mapTo="MyService.Suppliers.InternalSupplier, MyService.Suppliers" name="InternalSupplier"/>

        <type type="ICore" mapTo="MyService.Core.MyCore, MyService.Core" name="MyCore">
          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <constructor>
              <param name="externalSupplier" parameterType="ISupplier">
                <dependency name="ExternalSupplier"/>
              </param>
              <param name="internalSupplier" parameterType="ISupplier">
                <dependency name="InternalSupplier"/>
              </param>
            </constructor>
          </typeConfig>
        </type>

        <type type="MyService" mapTo="MyService.Service.MyService, MyService.Service">
          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <constructor>
              <param name="myCore" parameterType="ICore">
                <dependency name="MyCore"/>
              </param>
            </constructor>
          </typeConfig>
        </type>
      </types>
    </container>
  </containers>
</unity>  

Once this was working successfully I took a step back to the unit tests project to do some mocking.  I know someone out there is thinking “why would he try that before unit tests?   Couple reasons: 1) This was an entirely new endeavor and its easier for me to get the final concept working 2) The first 5 steps from Steve’s article required some low-level work to hook into WCF.  Rather than unit testing that I decided to flush it out by actually firing up a sample service to work out the kinks.  Next time the unit tests will be done first…

WCF: InstanceContextMode.Single and ReleaseServiceInstanceOnTransactionComplete

WCF was designed with a lot of options for you to tweak so your services run the way you need them to.  This flexibility is probably my favorite feature of WCF because you have a lot of power to choose things like instancing mode, transactional support, and so on.  The drawback is "discovering" how these things work together.

I have a transactional queued service that needs to behave like a singleton.  This service holds onto a resource that must always be available and there should not be many instances of it running (it’s a TCP socket listener so I don’t want a new one for every message I process).  During testing I discovered that though I had the InstanceContextMode set to Single WCF was still creating a new instance for each message received.  After some research I decided to tweak a few knobs starting with ReleaseServiceInstanceOnTransactionComplete.

While that name is probably longer than what Mcconnell might suggest it sure does make it clear what behavior to expect.  The property is a boolean but I went ahead and set it specifically to false and voilà, problem solved.  My service now behaves as a singleton.  For good measure I also set the ConcurrencyMode to Multiple to ensure that my service can be accessed by multiple threads.  Because I’m doing a lot of asynchronous work it will perform better under these settings.

Technorati Tags: ,,,

Recipe: WCF and Interpreting xs:any in a SOAP Message Body

I recently ran into a situation where the WSDL was altered to allow for xs:any in part of the expected SOAP body for a WCF service I am implementing in support of the project.  I have handled this situation before in WSE 3.0 and ASMX web services and was anxious to find out how WCF would handle it. 

When working with large XML models such as the National Information Exchange Model (NIEM) it is becoming common to use xs:any for parts of messages because the schemas that support the message structure are too complex to include in the WSDL.  For the large data sharing projects I work on at the state and federal level this is pretty much the standard.  Just about everyone has a "Payload" element that is of type xs:any.

With WSE 3.0 and ASMX web services .NET would convert the xs:any part of the SOAP body to a System.Array containing a single item of type System.Xml.XmlText.  I was only able to discover this because I was provided a Java based client to send requests to our service so that I could debug and see what types were coming across.  Somehow when I sent the same requests from .NET the xs:any was interpreted as a System.String and I did not have to do any further work to get the data I needed from that part of the message.

When I learned I would be in that same situation with WCF I started searching to find any documentation on what might possibly happen.  To my dismay I could not locate any via searches on MSDN, Google, etc. 

I ran some tests using a .NET WCF client and used message tracing to capture the raw soap message.  Upon inspection I noticed that the .NET client was appending xsi:type="xsd:string" on the element that was of type xs:any per the WSDL.  Also the first item in that tag was the XML declaration tag.  When my WCF service received that request it treated that element as a string and capture the raw string XML.

After searching I decided to use SoapUI to run the tests.  I installed SoapUI and began a test project.  I took the raw SOAP message captured in my .NET test and pasted that into the body of the test data window in SoapUI.  While testing I discovered that in SoapUI you need to remove the <soap:Header> element if one is included in the trace data you are using (it was causing errors with the ws-addressing headers).  Once I did that I was able to get some messages to hit the service. 

Test cases:

Soap Body included: <Payload xsi:type="xsd:string"><?xml version="1.0" encoding="UTF-8"?> … xml content …</Payload>
Result: InvalidOperationException – Error in XML document at Line {N} Position {N}

Soap Body included: <Payload xsi:type="xsd:string"> … xml content …</Payload>
Result: InvalidOperationException – Error in XML document at Line {N} Position {N}

Soap Body included: <Payload> … xml content …</Payload>
Result: Payload property on incoming message received as a System.Array containing one item that was of type System.Xml.XmlElement

What I found was very interesting was that when I used the exact trace output from the message created by my .NET client it received an exception when I sent it with SoapUI.  I tried a few variations of escaping characters to no avail.  There must be some type of escaping that .NET does in order to facilitate sending the xs:any portion of the message as a string, I just couldn’t guess them.

I’m still curious as to how the .NET WCF Client is encoding the content in the xs:any element to get it to pass those deserialization checks.  If anyone has any thoughts, leave me a comment.

Technorati Tags: ,,