The Simple Way to Generate One File MSDN Style Documentation for Your .NET Projects
I was recently tasked with generating code documentation. The last time I had to do that I used NDoc and the XML Comments that the C# compiler (csc.exe) spits out. Turns out that NDoc is no longer, or at least it’s not being maintained. Instead the new kid on the block is Sandcastle.
It might be my memory failing, but I seem to remember that setting up NDoc to generate MSDN style documentation was pretty easy. My initial foray into using Sandcastle was not. This post describes a super simple way to generate MSDN style documentation that’s contained in a single CHM file.
We’ll need some software. So go ahead and download and install the following:
- Sandcastle – http://sandcastle.codeplex.com
- Sandcastle Help File Builder – http://shfb.codeplex.com
This includes a guide that installs and sets up the required software. It’s important to download and set up HTML Help Workshop v.1 as part of this process.
Optional:
- GhostDoc – http://submain.com/products/ghostdoc.aspx
Not required, but it makes it super easy to generate XML documentation from within Visual Studio. It’ll even auto generate some of the text. The free version is fine, but obviously the paid version includes more features.
With all of the software installed and in place, it’s time to generate some documentation.
- Open Sandcastle Help File Builder GUI and start a new project.
- Right click Documentation Sources on the right and select “Add Documentation Source”.
- Find and select your solution file (*.sln).
- Select “HtmlHelp1″ under HelpFileFormat under the “Build”-category.
- Fill out whatever other properties you want. HelpTitle and HtmlHelpName are obviously good for putting in the name of your project. The “Show Missing Tags”-category is good for fine tuning what’s added if you haven’t explicityly documented everything.
- Hit CTRL+SHIFT+B or select “Build Project” from the “Documentation”-menu.
- Wait.
- You should now have a .chm file in your output folder.
Remember if your distribute the CHM file by putting it on the internet and allowing people to download that they need to Unblock the file first, before opening it. Otherwise all of the links inside will fail. You can see my post on X.509 Certificates and Downloads Via Internet Explorer for a description of the troubles that can occur when downloading files and they’re marked as being unsafe.
If you like my writing you should subscribe to my RSS feed.
Dates With a Sencha Touch Data Model and a WCF JSON Service
I’ve been developing a Sencha Touch Mobile app recently, that interface with a WCF REST service exposing data via JSON. One of the issues I faced was parsing the dates returned from the service into a date type in the Sencha Touch Data Model. This post explains one way to do that.
Say we have a simple model that only holds an id and a date:
Ext.regModel("MyModel", {
fields : [
'id',
{name : 'MyDate', type : 'date'},
]
});
When data is read into this model using a Proxy from a WCF REST JSON service, the MyDate column will just hold the string representation of the data such as “/Date(1238606590509+0800)/”, ie. it won’t be parsed. The trick to overcome this is to utilize the “convert” property that you can set on a field. This allows you to call out to a helper function every time a value will be set on the model for that field.
Now our model looks like this:
Ext.regModel("MyModel", {
fields : [
'id',
{name : 'MyDate', type : 'date', convert : toDateFromJSON},
]
});
We need to define our converter function;
function toDateFromJSON(v, record) {
return Date.parseDate(v, "M$");
}
In this converter function we utilize the built in Date object. When giving it the format string “M$” it will parse Microsoft Serialized AJAX dates which is what’s used with WCF, REST and the JSON formatter OOB.
Now our model will have the correct datatype for the MyDate property, which will allow us to call useful functions on it such as format.
If you like my writing you should subscribe to my RSS feed.
Installing Azure Tools for Visual Studio 2010 Fails On IIS CGI Dependency
I was trying to install the Azure Tools for Visual Studio 2010 via the Web Platform Installer, but it kept on failing on me. I complained on Twitter and @wadewegner helped out.
Error message I got from the installer (TwitPic)
So to make the error message I received a bit more google-able I’m writing this blog post with the error I received and how I got it to work.
Problem was with the CGI feature of IIS. It failed on installation. I got an obscure error line and code in my Web Platform Installer Log:
Error: 0 : Unattended setup returned ‘-2146498529′
Googling that and “-2146498529 IIS CGI” didn’t help me. I tried installing just the IIS: CGI dependency via WPI, but that didn’t help. In the end the solution for me was to install CGI for IIS using “Programs and Features” and Windows Components. Then start WPI with the Azure Tools. That got it all working.
Edited April 19th: Link to image of observed error
If you like my writing you should subscribe to my RSS feed.
Comparing Two Nullable Values In a Workflow Using Visual Basic
I needed to compare two Nullable date values in a workflow service. The way it was organized was as a parameter to a method call (using the InvokeMethod Activity), namely the Sort call on a collection of POCOs. The parameter is of type Comparison
At first the dates couldn’t be null, and hence there wasn’t a problem. I’d just use CompareTo:
Function(d1, d2) d1.MyDate.CompareTo(d2.MyDate)
Once the values are Nullable though it’s a different game. I had an exception because now values in my collection could have null on the MyDate property.
System.InvalidOperationException: Failed to compare two elements in the array.
—> System.InvalidOperationException: Nullable object must have a value.
My solution was to rewrite the function delegate I pass in, and use Nullable.Compare
Function(d1, d2) Nullable.Compare(d1.MyDate, d2.MyDate)
If you like my writing you should subscribe to my RSS feed.
X.509 Certificates and Downloads Via Internet Explorer
Re-installing my computer I moved some X.509 certificates and suddenly experienced some very weird behavior. I got the error:
The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected.
from WCF, when I tried to call an X.509 protected service. This had all worked before, my binding in WCF hadn’t changed, neither had the server side. One thing was strange though, the thumbprint of the X.509 certificated had changed. It wasn’t a problem loading it into Certificate Manager in MMC, even when importing a certificate that had a password.
Turns out that during my move of the file Windows Explorer had labeled the source from where I moved it as belonging to the Internet Zone. This means that the file is blocked. Much the same way as when you download a zip file via Internet Explorer, unzip it and nothing works. You have to right-click the file and select “Unblock” for it to unzip properly. After deleting my certificated, unblocking them, and then re-importing everything worked like a charm again.
There’s a very cool utility from NirSoft called AlternateStreamView that can look at a file or directory and display any alternate streams on that file. The alternate stream is where Windows adds the download source (zone info). This tool will let you scan a directory and remove all alternate streams on files. I found it very useful in removing the errornous zone info that had been added to my files as I’d copied them over.
If you like my writing you should subscribe to my RSS feed.
Hosting Workflow Foundation in Appfabric, 64-bit DLLs or EXEs
I got a funky error when I tried to host my workflow services in AppFabric on my developer machine. I run Windows 7 64-bit. As I deployed my web application to AppFabric I got this error:
Cannot create unknown type ‘{clr-namespace:your -namespace}’
Turned out my update was to use some types (Workflow Activites) from another assembly that happened to be an Exe file. However, that wasn’t the main problem. The underlying problem turned out to be that my Exe platform target was set to x86. The project had been created when I ran Windows 7 32-bit and I hadn’t updated it after reinstalling.
Chris Crowe has a good explanation with screenshots about it, Could not load file or assembly ‘name’ or one of its dependencies .
Bottom line: You need to either change your platform target to “Any CPU” or x64, or if that’s not an option allow the application pool to use 32 bit applications (configurable from the IIS Manager’s Advanced Settings on the AppPool).
If you like my writing you should subscribe to my RSS feed.
Removing the SOAP mustUnderstand attribute from a WCF message
I’ve been working on an integration to an endpoint that’s been under development. Furthermore the service is special in that the endpoint I hit acts as a forwarding gateway to an internal endpoint. This had implications for the security configuration of the service. A new release meant that my configured UsernameToken WS-Security binding stopped working. I suspect it was denied by the gateway but I’m not entirely sure. Either way the error message suggested that it had something to do with a SOAP mustUnderstand attribute not being understood. This blog post details how you can apply a fix that’ll allow you to get through.
The SOAP mustUnderstand attribute says that the recipient must understand and obey the semantics of the SOAP header to which it is applied, or fail processing the message.
Investigating the messages going across the wire I found that the mustUnderstand attribute was only applied to the WS-Security header. It makes sense that you want the security configuration to be obeyed by the recipient, otherwise there wouldn’t be any point in sending it over. The service though failed to process it. I had an equivalent call working through SoapUI, the reason being that SoapUI can be configured to omit the mustUnderstand attribute. Hence I knew that if I could remove the mustUnderstand attribute from my WCF call I’d have end-to-end connection.
However, removing that is not so easy! Out of the box WCF doesn’t allow you to remove this by simply flipping a switch. It makes a lot of sense, but doesn’t really help me much.
WCF is very extensible. Actually to the point where it’s so extensible that it can be tough to figure out where to hook in. To remove the mustUnderstand attribute from the Security header you need to hook into the pipeline where the header is about to be applied or just after it’s been applied. One place to do that is with a Custom Message Encoder. Microsoft has a sample Message Encoder that adds character set and media type to a text encoder. Based on this sample I wrote some code that looks at the message before it’s being written on the wire and alters the XML.
You want to hook into the WriteMessage method of the Message Encoder. In here you can read the message into XLINQ and manipulate it.
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream, this.writerSettings);
message.WriteMessage(writer);
writer.Close();
stream.Position = 0;
//Interesting part
XNamespace soapEnvelope = "http://schemas.xmlsoap.org/soap/envelope/";
Namespace sec = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
var securityHeader = xmlMessage.Descendants(sec + "Security");
var attribute = securityHeader.Attributes(soapEnvelope + "mustUnderstand").First();
if (attribute != null)
attribute.Remove();
//End Interesting part
stream.Position = 0;
xmlMessage.Save(stream);
byte[] messageBytes = stream.GetBuffer();
int messageLength = (int)stream.Position;
stream.Close();
int totalLength = messageLength + messageOffset;
byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
Array.Copy(messageBytes, 0, totalBytes, messageOffset, messageLength);
ArraySegment<byte> byteArray = new ArraySegment<byte>(totalBytes, messageOffset, messageLength);
return byteArray;
I’ve included the full method for reference, but the main thing is between the “Interesting part” comments. First we define some namespaces that we’ll use to locate the Security header and mustUnderstand attribute. Then we extract the Security header element and look for the XML mustUnderstand attribute identified in the SOAP envelope namespace. We remove the attribute. The full code base then continues by writing the modified XML message to the stream being returned by WCF.
If you’re using the sample from Microsoft there’s an error in the app.config that adds the Custom Message Encoder. The full element needs to look like this:
<extensions>
<bindingElementExtensions>
<add name="customTextMessageEncoding" type="Microsoft.Samples.CustomTextMessageEncoder.CustomTextMessageEncodingElement, TestApplication"/>
</bindingElementExtensions>
</extensions>
In the sample documentation the class in the type-attribute is wrongly put down as CustomTextMessageEncodingBindingSection and it needs to be CustomTextMessageEncodingElement as shown above.
You exchange the Text Message Encoder with this new Custom Encoder and it’ll remove the mustUnderstand attribute from the SOAP header. Setting this up on a custom binding is seen below:
<customTextMessageEncoding messageVersion="Soap11" mediaType="text/xml" />
instead of
<textMessageEncoding messageVersion="Soap11" />
With this in place my WCF client could now talk to the service endpoint again. Later the gateway service was fixed so it didn’t break when a Security-header with mustUnderstand was sent to it. However this example serves to show that you can modify the message going across the wire in a lot of ways. You have access to the full XML, and hence can do whatever is required. Be careful though when dealing with the Security aspects of WCF, especially when you have timestamps, signatures, and encryption involved. It only takes a single character to invalidate a signature, and hence you want to be careful where and what you change.
If you like my writing you should subscribe to my RSS feed.
Setting UserNameToken Client Credentials on a Send Activity in WF4
With .NET 4.0 we also got a new release of Windows Workflow Foundation. It’s a complete rewrite of the Workflow framework that was part of .NET 3.0/3.5. One of the strong points of the new release is in the integration between WF and WCF. Part of this is being able to call web services easily from inside Workflows. This is accomplished using the built in Send Activity. Depending on your integration scenario you might need to have some pretty elaborate service configurations and hence bindings. Once you’ve configured your WCF binding, which is what WF uses to actually call the web service, you should be able to go.
I had to call a service that required a UserNameToken configured. Setting this up in WCF is easy. Configuring WF to call using the WCF binding is moderately easy as well. But specifying the UserName ClientCredentials is not so easy. In regular code calling WCF you could write:
client.ClientCredentials.UserName.UserName = USERNAME; client.ClientCredentials.UserName.Password = PASSWORD;
Doing this in WF is not so easy since you don’t have access to the client proxy. The next thought might be to specify it in WCF configuration, however unlike other Client Credentials the Username and password is not externally configurable. Obviously because that would put the two in clear text in a configuration file. In an MSDN Forum post a developer from Micrsoft acknowledges that this feature isn’t supported in the initial release. So how do you accomplish this scenario?
One solution is described here Setting UserName ClientCredentials in WF SendActivity. With this in place you attach to the processing pipeline in WCF and can hence set the Client Credentials as you please. Obviously you can retrieve the username and password from where ever you want. When the Send Activity does the call to the web service via WCF this custom extension will be called and you’re set to go.
If you like my writing you should subscribe to my RSS feed.
Getting WCF to talk to a Java AXIS 1.X and WSS4J Web Service – Part 3 of 3
This is the third post in a series on my woes in integrating to a Java AXIS 1.X and WSS4J web service. Read Part 1, Part 2, Part 3.
Setting up the second type of service calls with its separate security configuration also had its quirks. The service semantics require Usernames with a password, but it specifically does not want WS-Security timestamps. Via MSDN forums I found this post by Kjell-Sverre Jerijærvi in which he details how to turn off the inclusion of the timestamp. His approach required code however, and I prefer to be able to do it all in the configuration. The problem with that is that the “includeTimestamp” attribute is not available on the Basic HTTP binding. Therefore I needed to convert the default out of the box Basic HTTP binding into a Custom Binding upon which I can control the “includeTimestamp” attribute. This post details the BasicHttpBinding equivalent CustomBinding. Based on that I devised the following custom binding.
<customBinding>
<binding name="SkatUserNameToken">
<security authenticationMode="UserNameOverTransport" includeTimestamp="false">
<secureConversationBootstrap />
</security>
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport />
</binding>
</customBinding>
The client endpoint that connects the binding is seen below. It’s completely standard and out of the box.
<endpoint address="https://the-external-service-url.dk"
binding="customBinding" bindingConfiguration="SkatUserNameToken"
contract="IContract"
name="BestillingHent" />
When calling the service you need to set the Username and Password on the client in ClientCredentials property. This is used by WCF when it includes the username and password in the WS Security header elements.
client.ClientCredentials.UserName.UserName = USERNAME; client.ClientCredentials.UserName.Password = PASSWORD;
This completes my little series on getting WCF to talk to a Java AXIS 1.X and WSS4J web service exposed by a public institution in Denmark (Skat eIndkomst).
Let me know if you have any comments or questions.
If you like my writing you should subscribe to my RSS feed.
Getting WCF to talk to a Java AXIS 1.X and WSS4J Web Service – Part 2 of 3
This is the second post in a series on my woes in integrating to a Java AXIS 1.X and WSS4J web service. Read Part 1, Part 2, Part 3.
The first service interaction requires signing the message, timestamping it and include the certificate that the request should be signed with in a BinarySecurityToken. The key discovery was in this forum thread that lead me to using the mutualCertificate option for the authentication method as well as where to tweak the timestamp inclusion. With this in place I could call my service and get to the next step. This was a policy error on the WCF side meaning my client that the order of the returned security elements didn’t line up. This was a major breakthrough because it meant that I was now calling the service from WCF. Via Fiddler I could also see what was going over the wire and that the returned data was in fact valid! Solving the exception I received on my WCF side proved to be fairly easy. WCF is strict in enforcing the order that the WS-Security elements appear in the response, but OOB an attribute (“securityHeaderLayout”) is provided that relaxes this requirement (Incorrect order of security elements “lax”).
The full binding configuration is seen below.
<customBinding>
<binding name="SkatSignatureTimestamp">
<textMessageEncoding messageVersion="Soap11" />
<security allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificate"
requireDerivedKeys="false" securityHeaderLayout="Lax" includeTimestamp="true"
keyEntropyMode="ClientEntropy" messageProtectionOrder="SignBeforeEncrypt" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSecurityContextCancellation="false">
<secureConversationBootstrap />
</security>
<httpsTransport />
</binding>
</customBinding>
To configure the certificates used to sign an endpoint behavior needs to be applied. I’ve been given a test certificate that I can use by the service vendor and I imported it to my computers certificate store. Then configuring the certificates used was fairly easy. The behavior is seen below.
<behaviors>
<endpointBehaviors>
<behavior name="SkatCertificates">
<clientCredentials>
<clientCertificate findValue="xx xx xx xx" x509FindType="FindByThumbprint" />
<serviceCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certificate authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<defaultCertificate findValue="xx xx xx" x509FindType="FindByThumbprint" />
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
Setting up the client section is a matter of coupling the binding configuration with the behavior configuration. The thing to remember is the “identity” element that needs to match up with the identity in the certificate used, ie. the certificate alias. You can find this name by opening the certificate in Certificate Manager in Windows and look for the value of “Issued To”.
<client>
<endpoint address="https://the-external-service-url.dk"
behaviorConfiguration="SkatCertificates" binding="customBinding"
bindingConfiguration="SkatSignatureTimestamp" contract="IContract"
name="Service">
<identity>
<dns value="certificate identity" />
</identity>
</endpoint>
</client>
Calling the service now will result in an error. The problem was that the SOAP body is being encrypted and the service expects the message to only be signed. Fixing this is done by adding an attribute to the ServicePortType interface automatically generated by the “Add Service Reference” in Visual Studio. The attribute that needs to be set is the ProtectionLevel attribute:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://rep.oio.dk/skat.dk/eindkomst/",
ConfigurationName = "Service_IServicePortType",
ProtectionLevel = ProtectionLevel.Sign
]
public interface IndkomstOplysningKlassiskAbonnentHent_IServicePortType {
//interface implementation
}
This instructs WCF to only Sign the message. Other values of ProtectionLevel are None, and EncryptAndSign. Issuing the service call now results in a correct message to be sent over the wire.
The next part deals with the second type of service call I had to make, which had its own set of security requirements.
If you like my writing you should subscribe to my RSS feed.
I am a self employed independent software development consultant at