Wednesday, September 29, 2010

MSDeploy with Declare and Set parameter files

One of the most undocumented parts of MSDeploy is the declare and set parameter xml files you can use to encapsulate the parameters declaration and setting rather than having them clogging up the command line call to MSDeploy.

So firstly, here is how to include them when packaging and deploying:

msdeploy.exe" -verb:sync -source:apphostconfig="default web site/application” -dest:archivedir="C:\packages\application" -declareParamFile="C:\source\application\deployment\declareParamsFile.xml"

msdeploy.exe" -verb:sync -dest:apphostconfig="default web site/application” -source:archivedir="C:\packages\application" -setParamFile="C:\source\application\deployment\setParamsFile.xml"

You can verify that the parameters were correctly generated when the package was generated by examining the parameters file in the package folder.

The format of the declareParamFile is exactly the same as the parameter file that is generated in the package when you specify them manually in the command line – e.g. below is the content of the declareParamsFile.xml file.

<parameters>
<parameter name="enabledProtocols" defaultValue="http,net.pipe">
<parameterEntry kind="DeploymentObjectAttribute" scope="application" match="application/@enabledProtocols" />
</parameter>
<parameter name="applicationPool" defaultValue="synctest">
<parameterEntry kind="DeploymentObjectAttribute" scope="application" match="application/@applicationPool" />
</parameter>
<parameter name="providerServiceAddress" >
<parameterEntry kind="XmlFile" scope="web.config" match="//configuration/system.serviceModel/client/endpoint[@name='NetNamedPipeBinding_ProviderCustomerDetails']/@address" />
</parameter>
<parameter name="physicalPathLocation" description="Physical path where files for this Web application will be deployed." defaultValue="E:\Install\Services\ExampleService\" tags="PhysicalPath">
<parameterEntry kind="DestinationVirtualDirectory" scope="Default\ Web\ Site/iag\.application\.services\.exampleservice/" match="" />
</parameter>


Parameters are defined using various kind types. The common type is DeploymentObjectAttribute which allows you to configure the values within the archive.xml file using an XPath expression to determine where the update should be made. The archive.xml file is generated when the package is created and defines configuration for the deployment – e.g. if a website was packaged using the AppHostConfig provider, then it will contain the setting for which AppPool to use when the site is deployed. Create a deployment package, then open the archive.xml to better understand what this means. For a list of parameter kinds available see here http://64.4.11.252/en-us/library/dd569084(WS.10).aspx.

Once the deployment package is created, the parameter file generated within the package will contain the parameters specified in the declareParamFile.

Below is an example of the setParamfile and the format that should be used. Note that the name of the setParameter elements is the same name as their corresponding declaration in the declareParamFile example above.

<parameters>
<setParameter name="enabledProtocols" value="http, net.pipe"/>
<setParameter name="applicationPool" value="ServiceNameAppPool"/>
<setParameter name="providerServiceAddress" value="net.pipe://server/servicename/endpoint.svc"/>
<setParameter name="physicalPathLocation" value="C:\Services\ServiceName\"/>
</parameters>


When performing the deployment to the destination web server, to include the setParamFile file use the –setParamFile switch in the command line – e.g. setParamFile="C:\source\application\deployment\setParamsFile.xml"

Probably my favourite parameter kind is XmlFile (providerServiceAddress) which allows you to specify a xml file (which would typically be the web.config when deploying web applications) to be updated when the deployment is executed. You specifiy a XPath expression to indicate where you want to update the file. This is great when moving through different environments as the web.config usually contains environment specific settings.

Wednesday, September 22, 2010

Rhino Mocks and constraints on Object Parameters

The Is.Matching Rhino Mocks constraint is really nice way to setup expectation constraints on object parameters.

Is.Matching expects a predicate delegate which means the constraint can be very flexible - which is needed since the expectations on the object can be complex due to the possibility of several properties that require certain values.

Below is an example of setting up the expectation using an annoymous delegate. In this test we are expecting the Query object that is passed in the call to the GetCustomer method having an Id of 10 and BusinessGroup of "Finance". The declarations of request and response has been omitted to keep the code snippet concise.

MockRepository repo = new MockRepository;
IProvider mockProvider = repo.DynamicMock();
mockProvider.Expect( x => x.GetCustomer(request)).Constraints(Is.Matching(delegate(Query qry){ return (qry.Id == 10 && qry.BusinessGroup == "Finance"); })).Return(response);


As an aside, using the DynamicMock factory method rather than StrictMock means the call to the mockProvider in the code under test with the parameter expectations incorrect won't throw an exception, where using StrickMock will. However, using DynamicMock with the incorrect parameter passed in, mockProvider.GetCustomer will return null - so unless you have a check in your code under test for a null being return then an exception will be thrown anyway. So with this in mind, personally I believe that the StrictMock factory should be used when there is a Return object required.

Wednesday, August 18, 2010

WCF Client performance improvement

Recently I had to try various methods to overcome performance problems due to a large schema which represented the canonical model that is to be used in our SOA layer.

The biggest bottleneck was the initial call made to the service which used the model in its service contract. WCF generates serialization code on the fly when the first service request is sent – and due to the size and structure of the schema – the amount of generated code was large – 20mb!

The reason why the structure was an issue is because the model dictates that you use a generic message wrapper type which contains an element which allows you to specify the request and response type (basically in the XSD definition, this element contains several hundred choices that it could be – so when it’s deserialized – this is of type object – with several hundred XmlElementAttribute attributes above it as it could be any of these types specified in the XmlElementAttribute attributes. A truncated example of the deserialized code is below.

[System.Xml.Serialization.XmlElementAttribute("exampleRequest1", typeof(ExampleRequest1))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse1", typeof(ExampleResponse1))]

[System.Xml.Serialization.XmlElementAttribute("exampleRequest200", typeof(ExampleRequest200))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse200", typeof(ExampleResponse200))]
… you get the idea
public object Item {…


So the generated serialization code needs to handle every possible combination that could possibly be thrown at it (so it can handle the all the possible types that are declared in the XmlElement attributes). So in other words, a lot of if statements

To overcome the cost of generating the serialization code, I used the steps described in this MSDN article - http://msdn.microsoft.com/en-us/library/aa751883.aspx. I went with option 3: “Compile the generated serialization code into your application assembly and add the XmlSerializerAssemblyAttribute to the service contract that uses the XmlSerializerFormatAttribute. Do not set the AssemblyName or CodeBase properties. The default serialization assembly is assumed to be the current assembly”.

I used the following method to generate my assembly with the serialization code:

  • Add the XmlSerializerAssembly attribute and XmlSerializerFormat to my service contract (example below).

[ServiceContract(Name = "ITest", Namespace = "http://testnamespace"), XmlSerializerFormat]
[XmlSerializerAssemblyAttribute()]
public interface ITest
{

  • Compile my assembly
  • Run svcutil against my assembly – an example of the command line: svcutil C:\Source\Project\TestServiceContract \bin\TestServiceContract.dll /t:xmlserializer.
  • Copy the generated file that was produced in step 3 to the project folder of the assembly and include the generated file in the project.
  • Rebuild the assembly.
  • Done.
In the above example TestServiceContract.dll only contains the service contract definition, not the implementation. Using this approach to resolve the serialization cost means you have to share the service contract assembly with the client and service (meaning, the client must use the ChannelFactory) – so the service definition should live in its own assembly. Sharing the assembly means both the client and the service has access to the serialization code.

One option I looked at was the ServiceKnownType attribute – which is specific to the DataContractSerializer. The positives with the DataContractSerializer is it really is fast. So even with the below

[System.Xml.Serialization.XmlElementAttribute("exampleRequest1", typeof(ExampleRequest1))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse1", typeof(ExampleResponse1))]

[System.Xml.Serialization.XmlElementAttribute("exampleRequest200", typeof(ExampleRequest200))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse200", typeof(ExampleResponse200))]
you get the idea
public object Item {…


If I update my service contract to the following:
[ServiceContract(Name = "ITest", Namespace = "http://testnamespace"), DataContractFormat]
[ServiceKnownType(typeof(ExampleRequest1))]
[ServiceKnownType(typeof(ExampleResponse1))]
public interface ITest
{


The service performance is amazingly faster. In fact, even though I am still using the ChannelFactory, so the channel isn’t cached (I’ll get onto that later) – the cost of generating the channel is very cheap (I’m assuming since the amount of types that need to be reflected when creating the channel is considerably low since we have specified the types the Service is interested in by using ServiceKnownType).

However, since we build our services using the Contract First pattern – the DataContract serializer is not an option since the payload that is produced across the wire doesn’t resemble at all the original XSD – in other words you have no control on how the XML will look.

So the next bottleneck in performance was the generation of the channel. Since the ChannelFactory is being used, the channel is not cached; however if you are using a generated proxy class by svcutil, ClientBase caches its internal ChannelFactory. More details are here: http://blogs.msdn.com/b/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx.

Again an assumption on my part for why the channel generation is costly in this example: in the client improvement article by Wenlong Dong, when the channel is created, all of the required CLR types are reflected, and because of the Item property in the example and all of the possible types it could be – there are a lot of the types that are reflected (which is where I believe ServiceKnownType mention before resolves this issue since the channel generation is fast, ServiceKnownType must supress the unneeded types that are not used by the service). I needed a solution like this using the XmlSerializer. And I worked it out using the below process

  1. Generate the XmlSerializer file against the service dll with all the required XmlElement attributes (i.e. many XmlElement attributes above the Item property).
  2. Copy the generated serialization file to the service folder; add it to the project etc…
  3. Remove all the XmlElement attributes for the Item property – and add [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
  4. Rebuild the project that contains the CLR schema definitions.
  5. Latency is very low.
So the key with the above is the XmlSerializer code must be generated with the expected types for the Item property (Item property decorated with multiple XmlElement attributes). Doing so means you can remove all the expected types since the XmlSerializer can still handle serializing since it’s an expected type in the serialization code (since we generated the code with the required types in step 1).

So using the assumption for why the channel generation is so costly - the cost of generating the channel is now reduced as it doesn’t have to worry about reflecting as many types (which according to Wenlong, is the biggest cost) – however serialization is successful as I said before since we generated the serialization code is aware of these types.

Monday, August 9, 2010

Serializing with CDATA as the content of an element

Recently I came across the problem where I needed to serialize a property of type string whose content contained a CDATA element section - the content of the property/element was HTML markup. If you serialize the property using the XmlSerializer out of the box, you get the following example:

&lt ;![CDATA[&lt ;h3&gt ;Service Job 1561245&lt ;/h3&gt ;

The solution is to update the property type from string to XmlCDataSection. You can leave the field type to string (so that's descriptionField in the below example), but the get and set of the property needs to look something like this:


get
{
XmlDocument xmlDocument = new XmlDocument();
return xmlDocument.CreateCDataSection(descriptionField);
}
set
{
descriptionField = value.Value;
}

Sunday, August 8, 2010

Building blocks of SOA article

The following SOA Mag article uses a great analogy (Lego blocks) to describe the principles of SOA - http://www.soamag.com/I36/0210-1.php

Thursday, August 5, 2010

Great Provider model article

Had to implement the Provider model recently, this is a great article on how to do so using the .Net framework - http://dotnetslackers.com/articles/designpatterns/HowToWriteAProviderModel.aspx

Wednesday, July 28, 2010

WCF and FitNesse - how to load the client's config file

Firstly, here is a great post on how to get started with FitNesse - http://schuchert.wikispaces.com/Acceptance+Testing.UsingSlimDotNetInFitNesse. This is what I used to get started. What I wanted to do was use FitNesse to perform integration tests for my web services - which means the assembly that the fitsharp runner loads, must also load the config file for that assembly (as it contains the service model configuration which is required when we create the client proxy within the loaded assembly).

Under the Create a page with necessary configuration heading in the above link, it defines how to setup your test fixtures to use the .Net test runner. The line we're interested in the one below.


!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\tools\nslim\fitsharp.dll %p}

We need to update this line to include a reference to the our test project's config file. So an example would be:


!define COMMAND_PATTERN {%m -a c:\projects\someapplication\acceptancetests\acceptancetests.dll.config -r fitSharp.Slim.Service.Runner,c:\tools\nslim\fitsharp.dll %p}

This allows you to load the config where your acceptancetests.dll makes a call through a WCF proxy (i.e. acceptancetests.dll contains the type which Runner.exe will call - and this type calls the service)