<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Development</title>
        <link>http://www.garfoot.com/blog/category/2.aspx</link>
        <description>Development</description>
        <language>en-GB</language>
        <copyright>Rob Garfoot</copyright>
        <generator>Subtext Version 2.1.2.2</generator>
        <item>
            <title>Calling WCF services with an invalid SSL certificate</title>
            <link>http://garfoot.com/blog/archive/2009/01/12/calling-wcf-services-with-an-invalid-ssl-certificate.aspx</link>
            <description>&lt;p&gt;A useful little snippet when using WCF with web services that have test SSL certificates.&lt;/p&gt;
&lt;p&gt;When you call a service in WCF it's still using the underlying .NET classes in System.Net so it's actually here that you need to tell to ignore the invalid SSL certificate.&lt;/p&gt;
&lt;p&gt;As it turns out this is very easy, all you need is the snippet below and it's good. Obviously you shouldn't deploy to a live environment with this code since it essentially says all certificates are valid but it's a handy trick to get a service working with any SSL certificate for testing.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =&amp;gt; { return true; };&lt;/code&gt;&lt;/p&gt;&lt;img src="http://garfoot.com/blog/aggbug/9.aspx" width="1" height="1" /&gt;</description>
            <guid>http://garfoot.com/blog/archive/2009/01/12/calling-wcf-services-with-an-invalid-ssl-certificate.aspx</guid>
            <pubDate>Mon, 12 Jan 2009 16:52:00 GMT</pubDate>
            <wfw:comment>http://garfoot.com/blog/comments/9.aspx</wfw:comment>
            <comments>http://garfoot.com/blog/archive/2009/01/12/calling-wcf-services-with-an-invalid-ssl-certificate.aspx#feedback</comments>
            <wfw:commentRss>http://garfoot.com/blog/comments/commentRss/9.aspx</wfw:commentRss>
            <trackback:ping>http://garfoot.com/blog/services/trackbacks/9.aspx</trackback:ping>
        </item>
        <item>
            <title>Transferring large files using WCF</title>
            <link>http://garfoot.com/blog/archive/2008/06/23/transferring-large-files-using-wcf.aspx</link>
            <description>&lt;p&gt;Recently I wanted to send large files (several GB) from a rich desktop client to a web service. The client and service communicate using WCF and I thought that this would be quite easy. As it turns out it is but there are a few gotchas on the way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Streaming&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first gotcha is that you do not want to buffer the message as you send it. Depending on the amount of RAM and the size of the file this may or may not be a problem on the client but it's almost certainly going to be a problem on the server with multiple clients sending files at the same time.&lt;/p&gt;
&lt;p&gt;To solve this you can either write a service contract that accepts the file in chunks or use WCF streaming. In this instance I decided to use streaming.&lt;/p&gt;
&lt;p&gt;Streaming in WCF does have some drawbacks which I'm not going to go into here so it's not suitable for everything but it was fine in this situation.&lt;/p&gt;
&lt;p&gt;To use streaming you simply pass parameters of type 'Stream' and change the config to use streaming. This is a per endpoint setting so I set up a separate endpoint for the upload service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Passing Metadata&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next problem I found was how to pass metadata with streams. Since I'm uploading via HTTP I want to make sure the file gets there intact so I'd like to transfer a checksum with the file (along with other details). WCF will not let you have any other parameters if using streams so how do you pass it.&lt;/p&gt;
&lt;p&gt;Since using sessions with streaming can result in unpredictable behaviour there are a couple of options open. The first is to return a GUID (or other unique ID) after uploading the file and then allow a separate operation to set the metadata for that GUID and then link it to the previous file upload.The other option, and the one I chose, is to explicitly specify the message and send the metadata in the message header.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Max Message Sizes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next issue I faced was the size of the messages, you need to ensure that the maxReceivedMessageSize is set large enough for your largest file. Since headers are always buffered, even when streaming, you want to ensure that this doesn't result in DOS attacks by settings maxBufferSize to something reasonable such as 64K. This will allow large streamed bodies but limits the size of the headers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So that's it, all set up and working now. Well not quite. As I mentioned at the start there are a few gotchas with this.&lt;/p&gt;
&lt;p&gt;First, the VS webdev server (Cassini) cannot handle streaming over HTTP. This is simple to fix, use IIS or self host in a console app or windows service.&lt;/p&gt;
&lt;p&gt;Second, IIS uses the ASP.NET maxRequestLength setting for the max length not the WCF setting. You need to add this to your web config.&lt;/p&gt;
&lt;p&gt;Third, IIS cannot transfer more than 2GB of data. You'll need to self host to get around this if you need to send more data than that.&lt;/p&gt;
&lt;p&gt;Fourth, timeouts can occur so you need to increase the send/receive timeouts in WCF.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So here are samples of the code bits I used.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;web.config&lt;/em&gt; - server&lt;/p&gt;
&lt;div class="code"&gt;
&lt;p&gt;&amp;lt;system.web&amp;gt;&lt;br /&gt;
    &amp;lt;httpRuntime maxRequestLength="2097151" /&amp;gt;&lt;br /&gt;
&amp;lt;/system.web&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;basicHttpBinding&amp;gt;&lt;br /&gt;
    &amp;lt;binding name="FileSenderService.StreamedBinding"&lt;br /&gt;
                 transferMode="StreamedRequest" maxBufferSize="65536"&lt;br /&gt;
                 maxReceivedMessageSize="2000000000" messageEncoding="Mtom"&lt;br /&gt;
                 receiveTimeout="00:10:00"&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/basicHttpBinding&amp;gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;app.config&lt;/em&gt; - client&lt;/p&gt;
&lt;div class="code"&gt;
&lt;p&gt;&amp;lt;basicHttpBinding&amp;gt;&lt;br /&gt;
    &amp;lt;binding name="BasicHttpBinding_IFileTransfer" sendTimeout="00:10:00"&lt;br /&gt;
             messageEncoding="Mtom"transferMode="StreamedRequest" /&amp;gt;&lt;br /&gt;
&amp;lt;/basicHttpBinding&amp;gt; &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Contracts&lt;/em&gt;&lt;/p&gt;
&lt;div class="code"&gt;
&lt;p&gt;[MessageContract]&lt;br /&gt;
public class SendFileRequestMessage&lt;br /&gt;
{&lt;br /&gt;
    [MessageHeader(MustUnderstand = true)]&lt;br /&gt;
    public FileTransferInfo FileInfo;&lt;br /&gt;
&lt;br /&gt;
    [MessageBodyMember(Order = 1)]&lt;br /&gt;
    public Stream FileData;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
[ServiceContract]&lt;br /&gt;
public interface IFileTransfer&lt;br /&gt;
{&lt;br /&gt;
    [OperationContract]&lt;br /&gt;
    void SendFile(SendFileRequestMessage request);&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[DataContract]&lt;br /&gt;
public class FileTransferInfo&lt;br /&gt;
{&lt;br /&gt;
    [DataMember(Order = 1, IsRequired = true)]&lt;br /&gt;
    public string Name { get; set; }&lt;br /&gt;
&lt;br /&gt;
    [DataMember(Order = 2, IsRequired = true)]&lt;br /&gt;
    public byte[] Checksum { get; set; }&lt;br /&gt;
}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The following blogs / articles were useful in sorting this out.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://kjellsj.blogspot.com/2007/02/wcf-streaming-upload-files-over-http.html"&gt;WCF Streaming: Upload files over HTTP&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms733742.aspx"&gt;Large Data and Streaming&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms789010.aspx"&gt;How to: Enable Streaming&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;&lt;img src="http://garfoot.com/blog/aggbug/5.aspx" width="1" height="1" /&gt;</description>
            <guid>http://garfoot.com/blog/archive/2008/06/23/transferring-large-files-using-wcf.aspx</guid>
            <pubDate>Mon, 23 Jun 2008 14:17:00 GMT</pubDate>
            <wfw:comment>http://garfoot.com/blog/comments/5.aspx</wfw:comment>
            <comments>http://garfoot.com/blog/archive/2008/06/23/transferring-large-files-using-wcf.aspx#feedback</comments>
            <slash:comments>7</slash:comments>
            <wfw:commentRss>http://garfoot.com/blog/comments/commentRss/5.aspx</wfw:commentRss>
            <trackback:ping>http://garfoot.com/blog/services/trackbacks/5.aspx</trackback:ping>
        </item>
        <item>
            <title>Web test recorder problems in IE</title>
            <link>http://garfoot.com/blog/archive/2008/06/11/web-test-recorder-problems-in-ie.aspx</link>
            <description>&lt;p&gt;Visual Studio Team System has some nice testing feature, amongst which is the ability to record and playback web browsing as part of a web test. The recorder makes building web tests much easier that writing the test scripts by hand. I went to record a new web test today but the test recorder didn't appear.&lt;/p&gt;
&lt;p&gt;I've recently installed IE8, I don't know if this was the culprit for breaking the recorder or not but fortunately the fix was quite easy. After a bit of searching I came across an entry on Michael Taute's blog at &lt;a href="http://blogs.msdn.com/mtaute/archive/2007/11/09/diagnosing-and-fixing-web-test-recorder-bar-issues.aspx"&gt;blogs.msdn.com/mtaute/archive/2007/11/09/diagnosing-and-fixing-web-test-recorder-bar-issues.aspx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This article contains several possible fixes for these kinds of problems, the one that worked for me was regarding VSTS 2008 and Vista 64 (I'm running on Server 2008 64 bit). I've included that particular fix below but have a look at the original article for others.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VSTS 2008 : Vista (64 bit) : Recorder bar does not appear when recording a new webtest&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fix:  Vista caches the list of explorer bars you have available and the recorder bar was not included in your list.  The fix is to force Windows to rebuild that cache.  To do this, first make sure you have all Internet Explorer instances shut down, then open the 32 bit registry editor and delete the following keys:&lt;/p&gt;
&lt;p&gt;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}&lt;br /&gt;
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000046}&lt;/p&gt;
&lt;p&gt;[Note: by default, the 32 bit registry editor is located in %WINDIR%\SysWow64\RegEdt32.exe]&lt;/p&gt;
&lt;p&gt;The next time you boot Internet Explorer, your explorer bar cache will be rebuilt and the recorder bar should be available.&lt;br /&gt;
 &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;img src="http://garfoot.com/blog/aggbug/3.aspx" width="1" height="1" /&gt;</description>
            <guid>http://garfoot.com/blog/archive/2008/06/11/web-test-recorder-problems-in-ie.aspx</guid>
            <pubDate>Wed, 11 Jun 2008 09:28:00 GMT</pubDate>
            <wfw:comment>http://garfoot.com/blog/comments/3.aspx</wfw:comment>
            <comments>http://garfoot.com/blog/archive/2008/06/11/web-test-recorder-problems-in-ie.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://garfoot.com/blog/comments/commentRss/3.aspx</wfw:commentRss>
            <trackback:ping>http://garfoot.com/blog/services/trackbacks/3.aspx</trackback:ping>
        </item>
    </channel>
</rss>