<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" 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:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Tim Mackey's Weblog - .Net Windows Forms</title>
    <link>http://tim.mackey.ie/</link>
    <description>mostly.Net</description>
    <language>en-ie</language>
    <copyright>Tim Mackey</copyright>
    <lastBuildDate>Tue, 24 Apr 2012 19:51:07 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>tim@mackey.ie</managingEditor>
    <webMaster>tim@mackey.ie</webMaster>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=43284f10-90dc-45c9-a8c9-5b6d31be9e10</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,43284f10-90dc-45c9-a8c9-5b6d31be9e10.aspx</pingback:target>
      <dc:creator>Tim Mackey</dc:creator>
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,43284f10-90dc-45c9-a8c9-5b6d31be9e10.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=43284f10-90dc-45c9-a8c9-5b6d31be9e10</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I have a winforms app that ran into trouble with the XStandard XHTML component on
a 64 bit system. I was registering the OCX file from code if it didn't register via
the MSI. found this <a href="http://support.microsoft.com/kb/282747">kb article</a> useful,
and then called the appropriate version of regsvr32.exe based on the platform.
</p>
        <pre>try
{
    // attempt to load the control 
    this.pageEditor = new PageEditor();
}
catch (System.Runtime.InteropServices.COMException)
{
    // control loading failed
    string ocxPath = Path.Combine(Application.StartupPath, "Xstandard.ocx");
    try
    {
        // OCX is not registered, register it now using the Syswow64 version of regsvr32.exe if we are using a 64 bit system
        Process p = new Process();
        p.StartInfo.FileName = @"regsvr32.exe";
        p.StartInfo.WorkingDirectory = (IntPtr.Size == 8) ? @"%SystemRoot%\Syswow64" : @"%SystemRoot%\system32";  // IntPtr is size 8 on a 64 bit system
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.Arguments = String.Format("/s \"{0}\"", ocxPath);
        p.Start();
        p.Close();
        MessageBox.Show("Please restart... (OCX file registered)", "Restart");
        Application.Exit();
        return;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unable to register OCX file: " + ex.Message, "Error");
        Application.Exit();
        return;
    }
}<pre><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=43284f10-90dc-45c9-a8c9-5b6d31be9e10" /></pre></pre>
      </body>
      <title>Using XStandard dll on a Win 64-bit </title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,43284f10-90dc-45c9-a8c9-5b6d31be9e10.aspx</guid>
      <link>http://tim.mackey.ie/UsingXStandardDllOnAWin64bit.aspx</link>
      <pubDate>Tue, 24 Apr 2012 19:51:07 GMT</pubDate>
      <description>&lt;p&gt;
I have a winforms app that ran into trouble with the XStandard XHTML component on
a 64 bit system. I was registering the OCX file from code if it didn't register via
the MSI. found this &lt;a href='http://support.microsoft.com/kb/282747'&gt;kb article&lt;/a&gt; useful,
and then called the appropriate version of regsvr32.exe based on the platform.
&lt;/p&gt;
&lt;pre&gt;try
{
    // attempt to load the control 
    this.pageEditor = new PageEditor();
}
catch (System.Runtime.InteropServices.COMException)
{
    // control loading failed
    string ocxPath = Path.Combine(Application.StartupPath, "Xstandard.ocx");
    try
    {
        // OCX is not registered, register it now using the Syswow64 version of regsvr32.exe if we are using a 64 bit system
        Process p = new Process();
        p.StartInfo.FileName = @"regsvr32.exe";
        p.StartInfo.WorkingDirectory = (IntPtr.Size == 8) ? @"%SystemRoot%\Syswow64" : @"%SystemRoot%\system32";  // IntPtr is size 8 on a 64 bit system
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.Arguments = String.Format("/s \"{0}\"", ocxPath);
        p.Start();
        p.Close();
        MessageBox.Show("Please restart... (OCX file registered)", "Restart");
        Application.Exit();
        return;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unable to register OCX file: " + ex.Message, "Error");
        Application.Exit();
        return;
    }
}&lt;pre&gt;&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=43284f10-90dc-45c9-a8c9-5b6d31be9e10" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,43284f10-90dc-45c9-a8c9-5b6d31be9e10.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=13058183-db6d-4740-8817-0cd1013d9052</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,13058183-db6d-4740-8817-0cd1013d9052.aspx</pingback:target>
      <dc:creator>Tim Mackey</dc:creator>
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,13058183-db6d-4740-8817-0cd1013d9052.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=13058183-db6d-4740-8817-0cd1013d9052</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <title>.Net windows forms Multi-line ComboBox / text-wrapping</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,13058183-db6d-4740-8817-0cd1013d9052.aspx</guid>
      <link>http://tim.mackey.ie/NetWindowsFormsMultilineComboBoxTextwrapping.aspx</link>
      <pubDate>Mon, 16 Jan 2012 10:08:16 GMT</pubDate>
      <description>seems like the most basic requirement for a list control... but there we are.&amp;nbsp; use this as a replacement for the System.Windows.Forms.ComboBox. &lt;br&gt;
&lt;br&gt;
&lt;pre&gt;
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace HortLaptopApp
{
    class ComboBoxWrap : ComboBox
    {
        // ref http://stackoverflow.com/questions/1245530/unable-to-set-the-dropdownheight-of-combobox
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
        }

        public const int SWP_NOZORDER = 0x0004;
        public const int SWP_NOACTIVATE = 0x0010;
        public const int SWP_FRAMECHANGED = 0x0020;
        public const int SWP_NOOWNERZORDER = 0x0200;

        public const int WM_CTLCOLORLISTBOX = 0x0134;

        private int _hwndDropDown = 0;

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_CTLCOLORLISTBOX)
            {
                if (_hwndDropDown == 0)
                {
                    _hwndDropDown = m.LParam.ToInt32();

                    RECT r;
                    GetWindowRect((IntPtr)_hwndDropDown, out r);

                    //int newHeight = 0;
                   // for(int i=0; i&amp;lt;Items.Count &amp;&amp; i &amp;lt; MaxDropDownItems; i++)
                    //    newHeight += this.GetItemHeight(i);

                    int total = 0;
                    for (int i = 0; i &amp;lt; this.Items.Count; i++)
                        total += this.GetItemHeight(i);
                    this.DropDownHeight = total + SystemInformation.BorderSize.Height * (this.Items.Count + 2);
           

                    SetWindowPos((IntPtr)_hwndDropDown, IntPtr.Zero,
                        r.Left,
                                 r.Top,
                                 DropDownWidth,
                                 DropDownHeight,
                                 SWP_FRAMECHANGED |
                                     SWP_NOACTIVATE |
                                     SWP_NOZORDER |
                                     SWP_NOOWNERZORDER);
                }
            }

            base.WndProc(ref m);
        }

        protected override void OnDropDownClosed(EventArgs e)
        {
            _hwndDropDown = 0;
            base.OnDropDownClosed(e);
        }

        public ComboBoxWrap() : base()
        {
            // add event handlers
            this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
            this.DrawItem += new DrawItemEventHandler(ComboBoxWrap_DrawItem);
            this.MeasureItem += new MeasureItemEventHandler(ComboBoxWrap_MeasureItem);
        }

        void ComboBoxWrap_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            // set the height of the item, using MeasureString with the font and control width
            ComboBoxWrap ddl = (ComboBoxWrap)sender;
            string text = ddl.Items[e.Index].ToString();
            SizeF size = e.Graphics.MeasureString(text, this.Font, ddl.DropDownWidth); 
            e.ItemHeight = (int)Math.Ceiling(size.Height) + 1;  // plus one for the border
            e.ItemWidth = ddl.DropDownWidth;
            System.Diagnostics.Trace.WriteLine(String.Format("Height {0}, Text {1}", e.ItemHeight, text));
        }

        void ComboBoxWrap_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index &amp;lt; 0)
                return;

            // draw a lighter blue selected BG colour, the dark blue default has poor contrast with black text on a dark blue background
            if ((e.State &amp; DrawItemState.Selected) == DrawItemState.Selected)
                e.Graphics.FillRectangle(Brushes.PowderBlue, e.Bounds);
            else
                e.Graphics.FillRectangle(Brushes.White, e.Bounds);
            
            // get the text of the item
            ComboBoxWrap ddl = (ComboBoxWrap)sender;
            string text = ddl.Items[e.Index].ToString();

            // don't dispose the brush afterwards
            Brush b = Brushes.Black;
            e.Graphics.DrawString(text, this.Font, b, e.Bounds, StringFormat.GenericDefault);
            
            // draw a light grey border line to separate the items
            Pen p = new Pen(Brushes.Gainsboro, 1);
            e.Graphics.DrawLine(p, new Point(e.Bounds.Left, e.Bounds.Bottom-1), new Point(e.Bounds.Right, e.Bounds.Bottom-1));
            p.Dispose();
            
            e.DrawFocusRectangle();
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=13058183-db6d-4740-8817-0cd1013d9052" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,13058183-db6d-4740-8817-0cd1013d9052.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=844bcd3d-df43-4b3b-9fdc-8f86293f850e</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,844bcd3d-df43-4b3b-9fdc-8f86293f850e.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,844bcd3d-df43-4b3b-9fdc-8f86293f850e.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=844bcd3d-df43-4b3b-9fdc-8f86293f850e</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <h2>Note: this doesn't really work..
</h2>
        <p>
i'm just leaving it here for interest.  the approach will work for the first
invocation of either v2 or v3 client, but after a v2 client has used the web service,
any v3 clients will fail.  MS told me this is not supported because of the 2
soapExtensions interfere with each other in the pipeline etc
</p>
        <hr size="2" width="100%" />
My asp.net CMS has some winforms clients running WSE2, and i'm doing an upgrade to
the client (and server) to use WSE3, but i want to support both versions.  Both
WSE2 and WSE3 clients are using a CustomUsernameTokenManager.  it was a bit tricky
to work out, but here is what i ended up doing. thanks to brian o'keefe for his <a href="http://groups.google.com/group/microsoft.public.dotnet.framework.webservices.enhancements/browse_thread/thread/e1bed90a5b50ed2d/49fb76d46fa81b7d?lnk=gst&amp;q=version+2+3#49fb76d46fa81b7d">newsgroup
post</a> for most of the answer.  Your exact config might vary but hopefully
it will save you some of the hassle of working all this out.<br /><ul><li>
Leave the existing web service in place, e.g. Service_WSE2.asmx<br /></li><li>
Create a new web service for the WSE3 client, essentially copy/paste the ASMX file,
e.g. Service_WSE3.asmx</li><li>
Create a new CustomUsernameTokenManager for the WSE3 service which inherits from Microsoft.Web.Services3.Security.Tokens.UsernameTokenManager. 
In my case it was as easy as copy/paste from the WSE2 token manager and change all
the WSE2 namespaces to WSE3.<br /></li><li>
then in web.config, make sure both WSE config sections are listed:<br /><pre>&lt;configuration&gt;<br />
&lt;configSections&gt;<br />
&lt;section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3,Version=3.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&gt;<br />
&lt;section name="microsoft.web.services2" type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration,
Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&gt;<br />
&lt;/configSections&gt;<br /></pre></li><li><p>
add in references to both the assemblies for the compilation section (not 100% sure
if this is necessary, but at least it means the app will not compile on the production
server if you forget to deploy either of the WSE assemblies, instead of waiting till
one of your clients connects).<br /></p><pre>	&lt;compilation defaultLanguage="c#" debug="true"&gt;<br />
&lt;assemblies&gt;<br />
&lt;add assembly="Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;<br />
&lt;add assembly="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;</pre></li><li><p>
remove the &lt;webServices&gt; section from &lt;system.web&gt;, because each web service
should be configured by location, not global as this interferes.<br /></p><pre>	&lt;location path="Service_WSE2.asmx"&gt;<br />
&lt;system.web&gt;<br />
&lt;webServices&gt;<br />
&lt;soapExtensionTypes&gt;<br />
&lt;add type="Microsoft.Web.Services2.WebServicesExtension, Microsoft.Web.Services2,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" group="0"
/&gt;<br />
&lt;/soapExtensionTypes&gt; 
<br />
&lt;/webServices&gt;<br />
&lt;/system.web&gt;<br />
&lt;/location&gt;<br /><br />
&lt;location path="Service_WSE3.asmx"&gt;<br />
&lt;system.web&gt;<br />
&lt;webServices&gt;<br />
&lt;soapExtensionTypes&gt;<br />
&lt;clear/&gt;<br />
&lt;/soapExtensionTypes&gt;<br />
&lt;soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br />
&lt;soapExtensionImporterTypes&gt;<br />
&lt;add type="Microsoft.Web.Services3.Description.WseExtensionImporter, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br />
&lt;/soapExtensionImporterTypes&gt; 
<br />
&lt;/webServices&gt;<br />
&lt;/system.web&gt;<br />
&lt;/location&gt;</pre></li><li>
my webservice policy are defined in policyCache.config files, so the following web.config
sections point each version of WSE to the right file:<br /><pre>	&lt;microsoft.web.services3&gt;<br />
&lt;policy fileName="policyCache_WSE3.config"/&gt;<br />
&lt;security&gt;<br />
&lt;securityTokenManager&gt;<br />
&lt;add type="Whatever.CustomUsernameTokenManager3" namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
localName="UsernameToken"/&gt;<br />
&lt;/securityTokenManager&gt;<br />
&lt;/security&gt;<br />
&lt;/microsoft.web.services3&gt;<br />
&lt;microsoft.web.services2&gt;<br />
&lt;messaging&gt;<br />
&lt;maxRequestLength&gt;10000&lt;/maxRequestLength&gt;<br />
&lt;/messaging&gt;<br />
&lt;security&gt;<br />
&lt;securityTokenManager type="Whatever.CustomUsernameTokenManager2, MyAssemblyName"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"<br />
qname="wsse:UsernameToken" /&gt;<br />
&lt;defaultTtlInSeconds&gt;86400&lt;/defaultTtlInSeconds&gt;<br />
&lt;timeToleranceInSeconds&gt;86400&lt;/timeToleranceInSeconds&gt;<br />
&lt;/security&gt;<br />
&lt;policy&gt;<br />
&lt;cache name="policyCache_WSE2.config" /&gt;<br />
&lt;/policy&gt;<br />
&lt;/microsoft.web.services2&gt;</pre></li><li>
and lastly, the policy cache files themselves:<br />
WSE 3 version<br /><pre>&lt;?xml version="1.0"?&gt;<br />
&lt;policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy"&gt;<br />
&lt;extensions&gt;<br />
&lt;extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&gt;<br />
&lt;extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&gt;<br />
&lt;/extensions&gt;<br />
&lt;policy name="usernameTokenSecurity"&gt; 
<br />
&lt;usernameOverTransportSecurity /&gt;<br />
&lt;requireActionHeader /&gt;<br />
&lt;/policy&gt;<br />
&lt;/policies&gt;</pre></li><li>
WSE 2 version<br /><pre>&lt;?xml version="1.0"?&gt;<br />
&lt;policyDocument xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy" xmlns="http://schemas.microsoft.com/wse/2003/06/Policy"&gt;<br />
&lt;mappings xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy"&gt;<br /><br />
&lt;endpoint uri="http://localhost/Service_WSE2.asmx"&gt;<br />
&lt;defaultOperation&gt;<br />
&lt;request policy="#username-token-signed" /&gt;<br />
&lt;response policy="" /&gt;<br />
&lt;fault policy="" /&gt;<br />
&lt;/defaultOperation&gt;<br />
&lt;/endpoint&gt;<br /><br />
&lt;defaultEndpoint&gt;<br />
&lt;defaultOperation&gt;<br />
&lt;request policy="" /&gt;<br />
&lt;response policy="" /&gt;<br />
&lt;fault policy="" /&gt;<br />
&lt;/defaultOperation&gt;<br />
&lt;/defaultEndpoint&gt;<br /><br />
&lt;/mappings&gt;<br />
&lt;policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;<br />
&lt;wsp:Policy wsu:Id="username-token-signed" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wssp="http://schemas.xmlsoap.org/ws/2002/12/secext"&gt;<br />
&lt;wsp:MessagePredicate wsp:Usage="wsp:Required" Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part"&gt;<br />
wsp:Body() wsp:Header(wsa:To) wsp:Header(wsa:Action) wsp:Header(wsa:MessageID) wse:Timestamp()<br />
&lt;/wsp:MessagePredicate&gt;<br />
&lt;wssp:Integrity wsp:Usage="wsp:Required"&gt;<br />
&lt;wssp:TokenInfo&gt;<br />
&lt;SecurityToken xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext"&gt;<br />
&lt;wssp:TokenType&gt;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken&lt;/wssp:TokenType&gt;<br />
&lt;wssp:Claims&gt;<br />
&lt;wssp:UsePassword wsp:Usage="wsp:Required" /&gt;<br />
&lt;/wssp:Claims&gt;<br />
&lt;/SecurityToken&gt;<br />
&lt;/wssp:TokenInfo&gt;<br />
&lt;wssp:MessageParts Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part"&gt;<br />
wsp:Body() wsp:Header(wsa:Action) wsp:Header(wsa:FaultTo) wsp:Header(wsa:From) wsp:Header(wsa:MessageID)
wsp:Header(wsa:RelatesTo) wsp:Header(wsa:ReplyTo) wsp:Header(wsa:To) wse:Timestamp()<br />
&lt;/wssp:MessageParts&gt;<br />
&lt;/wssp:Integrity&gt;<br />
&lt;/wsp:Policy&gt;<br />
&lt;/policies&gt;<br />
&lt;/policyDocument&gt;<br /></pre></li></ul><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=844bcd3d-df43-4b3b-9fdc-8f86293f850e" /></body>
      <title>Running WSE 2 and 3 side by side</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,844bcd3d-df43-4b3b-9fdc-8f86293f850e.aspx</guid>
      <link>http://tim.mackey.ie/RunningWSE2And3SideBySide.aspx</link>
      <pubDate>Fri, 16 Nov 2007 12:16:50 GMT</pubDate>
      <description>&lt;h2&gt;Note: this doesn't really work..
&lt;/h2&gt;
&lt;p&gt;
i'm just leaving it here for interest.&amp;nbsp; the approach will work for the first
invocation of either v2 or v3 client, but after a v2 client has used the web service,
any v3 clients will fail.&amp;nbsp; MS told me this is not supported because of the 2
soapExtensions interfere with each other in the pipeline etc
&lt;/p&gt;
&lt;hr size="2" width="100%"&gt;
My asp.net CMS has some winforms clients running WSE2, and i'm doing an upgrade to
the client (and server) to use WSE3, but i want to support both versions.&amp;nbsp; Both
WSE2 and WSE3 clients are using a CustomUsernameTokenManager.&amp;nbsp; it was a bit tricky
to work out, but here is what i ended up doing. thanks to brian o'keefe for his &lt;a href="http://groups.google.com/group/microsoft.public.dotnet.framework.webservices.enhancements/browse_thread/thread/e1bed90a5b50ed2d/49fb76d46fa81b7d?lnk=gst&amp;amp;q=version+2+3#49fb76d46fa81b7d"&gt;newsgroup
post&lt;/a&gt; for most of the answer.&amp;nbsp; Your exact config might vary but hopefully
it will save you some of the hassle of working all this out.&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
Leave the existing web service in place, e.g. Service_WSE2.asmx&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;
Create a new web service for the WSE3 client, essentially copy/paste the ASMX file,
e.g. Service_WSE3.asmx&lt;/li&gt;
&lt;li&gt;
Create a new CustomUsernameTokenManager for the WSE3 service which inherits from Microsoft.Web.Services3.Security.Tokens.UsernameTokenManager.&amp;nbsp;
In my case it was as easy as copy/paste from the WSE2 token manager and change all
the WSE2 namespaces to WSE3.&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;
then in web.config, make sure both WSE config sections are listed:&lt;br&gt;
&lt;pre&gt;&amp;lt;configuration&amp;gt;&lt;br&gt;
&amp;lt;configSections&amp;gt;&lt;br&gt;
&amp;lt;section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,
Microsoft.Web.Services3,Version=3.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&amp;gt;&lt;br&gt;
&amp;lt;section name="microsoft.web.services2" type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration,
Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&amp;gt;&lt;br&gt;
&amp;lt;/configSections&amp;gt;&lt;br&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
add in references to both the assemblies for the compilation section (not 100% sure
if this is necessary, but at least it means the app will not compile on the production
server if you forget to deploy either of the WSE assemblies, instead of waiting till
one of your clients connects).&lt;br&gt;
&lt;/p&gt;
&lt;pre&gt;	&amp;lt;compilation defaultLanguage="c#" debug="true"&amp;gt;&lt;br&gt;
&amp;lt;assemblies&amp;gt;&lt;br&gt;
&amp;lt;add assembly="Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&amp;gt;&lt;br&gt;
&amp;lt;add assembly="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
remove the &amp;lt;webServices&amp;gt; section from &amp;lt;system.web&amp;gt;, because each web service
should be configured by location, not global as this interferes.&lt;br&gt;
&lt;/p&gt;
&lt;pre&gt;	&amp;lt;location path="Service_WSE2.asmx"&amp;gt;&lt;br&gt;
&amp;lt;system.web&amp;gt;&lt;br&gt;
&amp;lt;webServices&amp;gt;&lt;br&gt;
&amp;lt;soapExtensionTypes&amp;gt;&lt;br&gt;
&amp;lt;add type="Microsoft.Web.Services2.WebServicesExtension, Microsoft.Web.Services2,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" group="0"
/&amp;gt;&lt;br&gt;
&amp;lt;/soapExtensionTypes&amp;gt; 
&lt;br&gt;
&amp;lt;/webServices&amp;gt;&lt;br&gt;
&amp;lt;/system.web&amp;gt;&lt;br&gt;
&amp;lt;/location&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;lt;location path="Service_WSE3.asmx"&amp;gt;&lt;br&gt;
&amp;lt;system.web&amp;gt;&lt;br&gt;
&amp;lt;webServices&amp;gt;&lt;br&gt;
&amp;lt;soapExtensionTypes&amp;gt;&lt;br&gt;
&amp;lt;clear/&amp;gt;&lt;br&gt;
&amp;lt;/soapExtensionTypes&amp;gt;&lt;br&gt;
&amp;lt;soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&amp;gt;&lt;br&gt;
&amp;lt;soapExtensionImporterTypes&amp;gt;&lt;br&gt;
&amp;lt;add type="Microsoft.Web.Services3.Description.WseExtensionImporter, Microsoft.Web.Services3,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&amp;gt;&lt;br&gt;
&amp;lt;/soapExtensionImporterTypes&amp;gt; 
&lt;br&gt;
&amp;lt;/webServices&amp;gt;&lt;br&gt;
&amp;lt;/system.web&amp;gt;&lt;br&gt;
&amp;lt;/location&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
my webservice policy are defined in policyCache.config files, so the following web.config
sections point each version of WSE to the right file:&lt;br&gt;
&lt;pre&gt;	&amp;lt;microsoft.web.services3&amp;gt;&lt;br&gt;
&amp;lt;policy fileName="policyCache_WSE3.config"/&amp;gt;&lt;br&gt;
&amp;lt;security&amp;gt;&lt;br&gt;
&amp;lt;securityTokenManager&amp;gt;&lt;br&gt;
&amp;lt;add type="Whatever.CustomUsernameTokenManager3" namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
localName="UsernameToken"/&amp;gt;&lt;br&gt;
&amp;lt;/securityTokenManager&amp;gt;&lt;br&gt;
&amp;lt;/security&amp;gt;&lt;br&gt;
&amp;lt;/microsoft.web.services3&amp;gt;&lt;br&gt;
&amp;lt;microsoft.web.services2&amp;gt;&lt;br&gt;
&amp;lt;messaging&amp;gt;&lt;br&gt;
&amp;lt;maxRequestLength&amp;gt;10000&amp;lt;/maxRequestLength&amp;gt;&lt;br&gt;
&amp;lt;/messaging&amp;gt;&lt;br&gt;
&amp;lt;security&amp;gt;&lt;br&gt;
&amp;lt;securityTokenManager type="Whatever.CustomUsernameTokenManager2, MyAssemblyName"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&lt;br&gt;
qname="wsse:UsernameToken" /&amp;gt;&lt;br&gt;
&amp;lt;defaultTtlInSeconds&amp;gt;86400&amp;lt;/defaultTtlInSeconds&amp;gt;&lt;br&gt;
&amp;lt;timeToleranceInSeconds&amp;gt;86400&amp;lt;/timeToleranceInSeconds&amp;gt;&lt;br&gt;
&amp;lt;/security&amp;gt;&lt;br&gt;
&amp;lt;policy&amp;gt;&lt;br&gt;
&amp;lt;cache name="policyCache_WSE2.config" /&amp;gt;&lt;br&gt;
&amp;lt;/policy&amp;gt;&lt;br&gt;
&amp;lt;/microsoft.web.services2&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
and lastly, the policy cache files themselves:&lt;br&gt;
WSE 3 version&lt;br&gt;
&lt;pre&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br&gt;
&amp;lt;policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy"&amp;gt;&lt;br&gt;
&amp;lt;extensions&amp;gt;&lt;br&gt;
&amp;lt;extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&amp;gt;&lt;br&gt;
&amp;lt;extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/&amp;gt;&lt;br&gt;
&amp;lt;/extensions&amp;gt;&lt;br&gt;
&amp;lt;policy name="usernameTokenSecurity"&amp;gt; 
&lt;br&gt;
&amp;lt;usernameOverTransportSecurity /&amp;gt;&lt;br&gt;
&amp;lt;requireActionHeader /&amp;gt;&lt;br&gt;
&amp;lt;/policy&amp;gt;&lt;br&gt;
&amp;lt;/policies&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
WSE 2 version&lt;br&gt;
&lt;pre&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br&gt;
&amp;lt;policyDocument xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy" xmlns="http://schemas.microsoft.com/wse/2003/06/Policy"&amp;gt;&lt;br&gt;
&amp;lt;mappings xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy"&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;lt;endpoint uri="http://localhost/Service_WSE2.asmx"&amp;gt;&lt;br&gt;
&amp;lt;defaultOperation&amp;gt;&lt;br&gt;
&amp;lt;request policy="#username-token-signed" /&amp;gt;&lt;br&gt;
&amp;lt;response policy="" /&amp;gt;&lt;br&gt;
&amp;lt;fault policy="" /&amp;gt;&lt;br&gt;
&amp;lt;/defaultOperation&amp;gt;&lt;br&gt;
&amp;lt;/endpoint&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;lt;defaultEndpoint&amp;gt;&lt;br&gt;
&amp;lt;defaultOperation&amp;gt;&lt;br&gt;
&amp;lt;request policy="" /&amp;gt;&lt;br&gt;
&amp;lt;response policy="" /&amp;gt;&lt;br&gt;
&amp;lt;fault policy="" /&amp;gt;&lt;br&gt;
&amp;lt;/defaultOperation&amp;gt;&lt;br&gt;
&amp;lt;/defaultEndpoint&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;lt;/mappings&amp;gt;&lt;br&gt;
&amp;lt;policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&amp;gt;&lt;br&gt;
&amp;lt;wsp:Policy wsu:Id="username-token-signed" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wssp="http://schemas.xmlsoap.org/ws/2002/12/secext"&amp;gt;&lt;br&gt;
&amp;lt;wsp:MessagePredicate wsp:Usage="wsp:Required" Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part"&amp;gt;&lt;br&gt;
wsp:Body() wsp:Header(wsa:To) wsp:Header(wsa:Action) wsp:Header(wsa:MessageID) wse:Timestamp()&lt;br&gt;
&amp;lt;/wsp:MessagePredicate&amp;gt;&lt;br&gt;
&amp;lt;wssp:Integrity wsp:Usage="wsp:Required"&amp;gt;&lt;br&gt;
&amp;lt;wssp:TokenInfo&amp;gt;&lt;br&gt;
&amp;lt;SecurityToken xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext"&amp;gt;&lt;br&gt;
&amp;lt;wssp:TokenType&amp;gt;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken&amp;lt;/wssp:TokenType&amp;gt;&lt;br&gt;
&amp;lt;wssp:Claims&amp;gt;&lt;br&gt;
&amp;lt;wssp:UsePassword wsp:Usage="wsp:Required" /&amp;gt;&lt;br&gt;
&amp;lt;/wssp:Claims&amp;gt;&lt;br&gt;
&amp;lt;/SecurityToken&amp;gt;&lt;br&gt;
&amp;lt;/wssp:TokenInfo&amp;gt;&lt;br&gt;
&amp;lt;wssp:MessageParts Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part"&amp;gt;&lt;br&gt;
wsp:Body() wsp:Header(wsa:Action) wsp:Header(wsa:FaultTo) wsp:Header(wsa:From) wsp:Header(wsa:MessageID)
wsp:Header(wsa:RelatesTo) wsp:Header(wsa:ReplyTo) wsp:Header(wsa:To) wse:Timestamp()&lt;br&gt;
&amp;lt;/wssp:MessageParts&amp;gt;&lt;br&gt;
&amp;lt;/wssp:Integrity&amp;gt;&lt;br&gt;
&amp;lt;/wsp:Policy&amp;gt;&lt;br&gt;
&amp;lt;/policies&amp;gt;&lt;br&gt;
&amp;lt;/policyDocument&amp;gt;&lt;br&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=844bcd3d-df43-4b3b-9fdc-8f86293f850e" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,844bcd3d-df43-4b3b-9fdc-8f86293f850e.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=d7c7e858-3da0-4bb2-a12b-aa0cf254462e</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,d7c7e858-3da0-4bb2-a12b-aa0cf254462e.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,d7c7e858-3da0-4bb2-a12b-aa0cf254462e.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=d7c7e858-3da0-4bb2-a12b-aa0cf254462e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">big bug in ComboBox control here: <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;327244">http://support.microsoft.com/default.aspx?scid=kb;en-us;327244</a><br />
you have to set the SelectedIndex to -1 twice in a row if you want it to take effect!<br />
i came across this in a compact framework app, but it looks like it applies to win-forms
as well.<br /><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=d7c7e858-3da0-4bb2-a12b-aa0cf254462e" /></body>
      <title>Bug in ComboBox SelectedIndex</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,d7c7e858-3da0-4bb2-a12b-aa0cf254462e.aspx</guid>
      <link>http://tim.mackey.ie/BugInComboBoxSelectedIndex.aspx</link>
      <pubDate>Tue, 02 Oct 2007 16:17:18 GMT</pubDate>
      <description>big bug in ComboBox control here: &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;327244"&gt;http://support.microsoft.com/default.aspx?scid=kb;en-us;327244&lt;/a&gt;
&lt;br&gt;
you have to set the SelectedIndex to -1 twice in a row if you want it to take effect!&lt;br&gt;
i came across this in a compact framework app, but it looks like it applies to win-forms
as well.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=d7c7e858-3da0-4bb2-a12b-aa0cf254462e" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,d7c7e858-3da0-4bb2-a12b-aa0cf254462e.aspx</comments>
      <category>.Net Compact</category>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=f4d85eae-48dc-4298-9098-d7d365b48d8f</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,f4d85eae-48dc-4298-9098-d7d365b48d8f.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,f4d85eae-48dc-4298-9098-d7d365b48d8f.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=f4d85eae-48dc-4298-9098-d7d365b48d8f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Just got up and running with VS 2008 Beta
2 and converted my Orcas Beta 1 projects over to VS 2008.  have a read of <a href="http://weblogs.asp.net/scottgu/archive/2007/07/26/vs-2008-and-net-3-5-beta-2-released.aspx">Scott
Gu's post</a> on downloading and installing.  whaddya know? VS 2008 hasn't crashed
yet :)  seriously though, this is a major relief to see good stability. 
as a developer it did my head in to have to keep nuking devenv.exe and losing a few
minutes work, driving me quietly insane.  hopefully those days are over now. 
Beta 1 was a thousand times better than VS 2005, but Beta 2 looks even better.  
<br /><br />
in terms of breaking changes with upgrading projects etc., here are some tidbits i
came across<br /><ul><li>
the namespace <font color="#008000" face="Courier New"><b>System.Data.Linq.Expressions</b></font> no
longer exists.  i just deleted this namespace and it worked fine, they must have
moved various classes back into the root Linq namespace or something.</li><li>
if you use SqlMetal, you will have to use the new version of this tool, which i found
at <b><font color="#008000" face="Courier New">C:\Program Files\Microsoft SDKs\Windows\V6.0A\Bin\SqlMetal.exe</font></b>.
The generated code from the new tool is very different to before so you will need
to regenerate in order to use the new LINQ libraries.<br /></li><li><font color="#008000" face="Courier New"><b>web.config</b></font> changes are also
introduced.  the best way to figure out the changes is to open up a blank web
application and compare the standard web.config in the empty project to your own web.config.</li><li>
Crystal Reports assembly version numbers are the same with this release of VS, 10.5.3700.0,
so no changes here since Beta1.</li></ul>
i'll post more next week when i have some real experience using VS 2008.  so
far so good.  great job Scott &amp; Co.<br /><p></p><h5>Update 30 July 2007 - Deployment Issues<br /></h5><ul><li>
To deploy a VS 2008 beta 2 web application to a Server 2003 with .net runtime 2.0,
you need to install 3.5 of the runtime.  i got all sorts of web.config errors
due to the new syntax with beta 2.  A web app compiled against v3.5 in Beta 1
had no trouble running on top of the 2.0 runtime with the various v3.5 DLLs deployed
to the /bin directory, however this doesn't seem to be possible anymore.  it
took me a while to find the correct download for the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=D2F74873-C796-4E60-91C8-F0EF809B09EE&amp;displaylang=en">3.5
beta 2 redistributable</a>, it installed in about 10 mins and required a reboot, and
did not affect any of the v1.1 and v2 web sites running on the server.  
<br /></li></ul><br /><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=f4d85eae-48dc-4298-9098-d7d365b48d8f" /></body>
      <title>VS 2008: First impressions</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,f4d85eae-48dc-4298-9098-d7d365b48d8f.aspx</guid>
      <link>http://tim.mackey.ie/VS2008FirstImpressions.aspx</link>
      <pubDate>Fri, 27 Jul 2007 16:49:16 GMT</pubDate>
      <description>Just got up and running with VS 2008 Beta 2 and converted my Orcas Beta 1 projects over to VS 2008.&amp;nbsp; have a read of &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/07/26/vs-2008-and-net-3-5-beta-2-released.aspx"&gt;Scott
Gu's post&lt;/a&gt; on downloading and installing.&amp;nbsp; whaddya know? VS 2008 hasn't crashed
yet :)&amp;nbsp; seriously though, this is a major relief to see good stability.&amp;nbsp;
as a developer it did my head in to have to keep nuking devenv.exe and losing a few
minutes work, driving me quietly insane.&amp;nbsp; hopefully those days are over now.&amp;nbsp;
Beta 1 was a thousand times better than VS 2005, but Beta 2 looks even better.&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
in terms of breaking changes with upgrading projects etc., here are some tidbits i
came across&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
the namespace &lt;font color="#008000" face="Courier New"&gt;&lt;b&gt;System.Data.Linq.Expressions&lt;/b&gt;&lt;/font&gt; no
longer exists.&amp;nbsp; i just deleted this namespace and it worked fine, they must have
moved various classes back into the root Linq namespace or something.&lt;/li&gt;
&lt;li&gt;
if you use SqlMetal, you will have to use the new version of this tool, which i found
at &lt;b&gt;&lt;font color="#008000" face="Courier New"&gt;C:\Program Files\Microsoft SDKs\Windows\V6.0A\Bin\SqlMetal.exe&lt;/font&gt;&lt;/b&gt;.
The generated code from the new tool is very different to before so you will need
to regenerate in order to use the new LINQ libraries.&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;font color="#008000" face="Courier New"&gt;&lt;b&gt;web.config&lt;/b&gt;&lt;/font&gt; changes are also
introduced.&amp;nbsp; the best way to figure out the changes is to open up a blank web
application and compare the standard web.config in the empty project to your own web.config.&lt;/li&gt;
&lt;li&gt;
Crystal Reports assembly version numbers are the same with this release of VS, 10.5.3700.0,
so no changes here since Beta1.&lt;/li&gt;
&lt;/ul&gt;
i'll post more next week when i have some real experience using VS 2008.&amp;nbsp; so
far so good.&amp;nbsp; great job Scott &amp;amp; Co.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h5&gt;Update 30 July 2007 - Deployment Issues&lt;br&gt;
&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
To deploy a VS 2008 beta 2 web application to a Server 2003 with .net runtime 2.0,
you need to install 3.5 of the runtime.&amp;nbsp; i got all sorts of web.config errors
due to the new syntax with beta 2.&amp;nbsp; A web app compiled against v3.5 in Beta 1
had no trouble running on top of the 2.0 runtime with the various v3.5 DLLs deployed
to the /bin directory, however this doesn't seem to be possible anymore.&amp;nbsp; it
took me a while to find the correct download for the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=D2F74873-C796-4E60-91C8-F0EF809B09EE&amp;amp;displaylang=en"&gt;3.5
beta 2 redistributable&lt;/a&gt;, it installed in about 10 mins and required a reboot, and
did not affect any of the v1.1 and v2 web sites running on the server.&amp;nbsp; 
&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=f4d85eae-48dc-4298-9098-d7d365b48d8f" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,f4d85eae-48dc-4298-9098-d7d365b48d8f.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=9106477d-0d56-4606-947d-733e6bf8f66b</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,9106477d-0d56-4606-947d-733e6bf8f66b.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,9106477d-0d56-4606-947d-733e6bf8f66b.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=9106477d-0d56-4606-947d-733e6bf8f66b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <pre>public static ImageCodecInfo GetEncoderInfo(String mimeType)<br />
{<br />
int j;<br />
ImageCodecInfo[] encoders;<br />
encoders = ImageCodecInfo.GetImageEncoders();<br />
for(j = 0; j &lt; encoders.Length; ++j)<br />
if(encoders[j].MimeType == mimeType)<br />
return encoders[j];<br />
return null;<br />
}<br /><br />
public static Bitmap resizeImage(Bitmap originalImage, int max)<br />
{<br />
// never increase the size of an image from this method because it loses resolution<br />
if(originalImage.Height &lt;= max &amp;&amp; originalImage.Width &lt;= max)<br />
return originalImage;<br /><br />
int height, width;<br />
if(originalImage.Width &gt; originalImage.Height)<br />
{<br />
width = max;<br />
height = (int)(max/((double)originalImage.Width / (double)originalImage.Height));<br />
}<br />
else<br />
{ 
<br />
height = max;<br />
width = (int)(max/((double)originalImage.Height / (double)originalImage.Width));<br />
}<br /><br />
Bitmap thumb = new Bitmap(originalImage as Image, width, height);<br /><font color="#ff0000"> Graphics resizer = Graphics.FromImage(thumb);<br />
resizer.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;<br />
resizer.DrawImage(originalImage, 0, 0, width, height);</font><br />
resizer.Dispose();<br />
return thumb;<br />
}<br /><br />
public static bool ThumbnailCallback()<br />
{<br />
return false;<br />
}<br /><br /></pre>this lovely code highlighted in red solved problems i was having with resizing
JPEGs using .net.   without the code in red, some images would appear very
grainy when reduced in size.  i got this tip from <a href="http://forums.asp.net/p/532033/532033.aspx">http://forums.asp.net/p/532033/532033.aspx</a>.<br /><br /><br /><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=9106477d-0d56-4606-947d-733e6bf8f66b" /></body>
      <title>JPEG Resizing Quality Problems .Net</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,9106477d-0d56-4606-947d-733e6bf8f66b.aspx</guid>
      <link>http://tim.mackey.ie/JPEGResizingQualityProblemsNet.aspx</link>
      <pubDate>Wed, 18 Jul 2007 16:41:41 GMT</pubDate>
      <description>&lt;pre&gt;public static ImageCodecInfo GetEncoderInfo(String mimeType)&lt;br&gt;
{&lt;br&gt;
int j;&lt;br&gt;
ImageCodecInfo[] encoders;&lt;br&gt;
encoders = ImageCodecInfo.GetImageEncoders();&lt;br&gt;
for(j = 0; j &amp;lt; encoders.Length; ++j)&lt;br&gt;
if(encoders[j].MimeType == mimeType)&lt;br&gt;
return encoders[j];&lt;br&gt;
return null;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public static Bitmap resizeImage(Bitmap originalImage, int max)&lt;br&gt;
{&lt;br&gt;
// never increase the size of an image from this method because it loses resolution&lt;br&gt;
if(originalImage.Height &amp;lt;= max &amp;amp;&amp;amp; originalImage.Width &amp;lt;= max)&lt;br&gt;
return originalImage;&lt;br&gt;
&lt;br&gt;
int height, width;&lt;br&gt;
if(originalImage.Width &amp;gt; originalImage.Height)&lt;br&gt;
{&lt;br&gt;
width = max;&lt;br&gt;
height = (int)(max/((double)originalImage.Width / (double)originalImage.Height));&lt;br&gt;
}&lt;br&gt;
else&lt;br&gt;
{ 
&lt;br&gt;
height = max;&lt;br&gt;
width = (int)(max/((double)originalImage.Height / (double)originalImage.Width));&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
Bitmap thumb = new Bitmap(originalImage as Image, width, height);&lt;br&gt;
&lt;font color="#ff0000"&gt; Graphics resizer = Graphics.FromImage(thumb);&lt;br&gt;
resizer.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;&lt;br&gt;
resizer.DrawImage(originalImage, 0, 0, width, height);&lt;/font&gt;
&lt;br&gt;
resizer.Dispose();&lt;br&gt;
return thumb;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public static bool ThumbnailCallback()&lt;br&gt;
{&lt;br&gt;
return false;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;/pre&gt;this lovely code highlighted in red solved problems i was having with resizing
JPEGs using .net.&amp;nbsp;&amp;nbsp; without the code in red, some images would appear very
grainy when reduced in size.&amp;nbsp; i got this tip from &lt;a href="http://forums.asp.net/p/532033/532033.aspx"&gt;http://forums.asp.net/p/532033/532033.aspx&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=9106477d-0d56-4606-947d-733e6bf8f66b" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,9106477d-0d56-4606-947d-733e6bf8f66b.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=56c0211a-9d04-494d-b5ed-3e963011e14f</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,56c0211a-9d04-494d-b5ed-3e963011e14f.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,56c0211a-9d04-494d-b5ed-3e963011e14f.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=56c0211a-9d04-494d-b5ed-3e963011e14f</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">I have a few reports in my web application
that i export in PDF format only.  You would think this would remove any printer
driver complications but apparently not. 
<br />
Crystal Reports have a <a href="http://support.businessobjects.com/communityCS/TechnicalPapers/cr_printer_driver_options.pdf?ref=devzone_reporting_main">surprisingly
good article</a> to help troubleshoot issues with printing or exporting a report. 
<br /><br />
The problem i was finding was that in a Text object or Unbound field, the text would
be truncated at the edge of the box boundary.  Some users have reported strange
mid-word wrapping, but mine was a different problem, actually hacking off the end
of each line.  This didn't happen on my dev machine, but it did happen on the
server (2003).  When i compared them side by side, the Times New Roman font on
the server was stretched by about 5% compared to my dev machine. 
<br />
with the help of the CR article, i tracked it down to the lack of any printer installed
on the server, i had also disabled the Print Spooler service which was preventing
even the Microsoft Office Document Imaging Printer from being available.  So
i started the print spooler service and made sure that the Office Imaging Printer
was marked as the default printer.  Then i went back to Visual Studio and set
all the reports to use the Office Imaging printer.  This solved the problem.  
<br /><br />
You could of course install a PDF only printer such as PrimoPDF if you didn't have
MS office installed on the server. As long as the server has the same printer installed
as the one set in the report design, everything turns out fine.<br /><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=56c0211a-9d04-494d-b5ed-3e963011e14f" /></body>
      <title>Crystal Reports: Export PDF irregularities between server and dev machine</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,56c0211a-9d04-494d-b5ed-3e963011e14f.aspx</guid>
      <link>http://tim.mackey.ie/CrystalReportsExportPDFIrregularitiesBetweenServerAndDevMachine.aspx</link>
      <pubDate>Fri, 11 Aug 2006 12:20:57 GMT</pubDate>
      <description>I have a few reports in my web application that i export in PDF format only.&amp;nbsp; You would think this would remove any printer driver complications but apparently not. &lt;br&gt;
Crystal Reports have a &lt;a href="http://support.businessobjects.com/communityCS/TechnicalPapers/cr_printer_driver_options.pdf?ref=devzone_reporting_main"&gt;surprisingly
good article&lt;/a&gt; to help troubleshoot issues with printing or exporting a report. 
&lt;br&gt;
&lt;br&gt;
The problem i was finding was that in a Text object or Unbound field, the text would
be truncated at the edge of the box boundary.&amp;nbsp; Some users have reported strange
mid-word wrapping, but mine was a different problem, actually hacking off the end
of each line.&amp;nbsp; This didn't happen on my dev machine, but it did happen on the
server (2003).&amp;nbsp; When i compared them side by side, the Times New Roman font on
the server was stretched by about 5% compared to my dev machine. 
&lt;br&gt;
with the help of the CR article, i tracked it down to the lack of any printer installed
on the server, i had also disabled the Print Spooler service which was preventing
even the Microsoft Office Document Imaging Printer from being available.&amp;nbsp; So
i started the print spooler service and made sure that the Office Imaging Printer
was marked as the default printer.&amp;nbsp; Then i went back to Visual Studio and set
all the reports to use the Office Imaging printer.&amp;nbsp; This solved the problem.&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
You could of course install a PDF only printer such as PrimoPDF if you didn't have
MS office installed on the server. As long as the server has the same printer installed
as the one set in the report design, everything turns out fine.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=56c0211a-9d04-494d-b5ed-3e963011e14f" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,56c0211a-9d04-494d-b5ed-3e963011e14f.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">I was getting blank fields in my crystal
report if one of the values in the formula was null. 
<br />
Thanks to <a href="http://groups.google.com/group/microsoft.public.vb.crystal/browse_frm/thread/a3dbce66126297ac/e872132608e048a0?lnk=st&amp;q=&amp;rnum=8#e872132608e048a0">this
post</a> i know better than to trust Crystal's crummy concatenation rules.  Here
is what <span class="msghv"><b><font class="inheritcolor" color="#790619"> Gundula
Wangerin</font></b></span> had to say:<br /><blockquote>A string concatenated with null always gives null. 
<br />
You have to check if the first name is null with 
<br /><pre>     if not IsNull(firstname) then 
<br />
        lastname + " " + firstname 
<br />
    else 
<br />
        lastname </pre></blockquote><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb" /></body>
      <title>Crystal Reports: join / concatenate null strings</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb.aspx</guid>
      <link>http://tim.mackey.ie/CrystalReportsJoinConcatenateNullStrings.aspx</link>
      <pubDate>Thu, 10 Aug 2006 16:31:20 GMT</pubDate>
      <description>I was getting blank fields in my crystal report if one of the values in the formula was null. &lt;br&gt;
Thanks to &lt;a href="http://groups.google.com/group/microsoft.public.vb.crystal/browse_frm/thread/a3dbce66126297ac/e872132608e048a0?lnk=st&amp;amp;q=&amp;amp;rnum=8#e872132608e048a0"&gt;this
post&lt;/a&gt; i know better than to trust Crystal's crummy concatenation rules.&amp;nbsp; Here
is what &lt;span class="msghv"&gt;&lt;b&gt;&lt;font class="inheritcolor" color="#790619"&gt; Gundula
Wangerin&lt;/font&gt;&lt;/b&gt;&lt;/span&gt; had to say:&lt;br&gt;
&lt;blockquote&gt;A string concatenated with null always gives null. 
&lt;br&gt;
You have to check if the first name is null with 
&lt;br&gt;
&lt;pre&gt; &amp;nbsp; &amp;nbsp; if not IsNull(firstname) then 
&lt;br&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; lastname + " " + firstname 
&lt;br&gt;
&amp;nbsp; &amp;nbsp; else 
&lt;br&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; lastname &lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,922f2ec5-bf8a-4517-95a3-1cc8fbd8f2eb.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=c0ac2cfa-3af5-4012-a72b-fd2b411471a4</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,c0ac2cfa-3af5-4012-a72b-fd2b411471a4.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,c0ac2cfa-3af5-4012-a72b-fd2b411471a4.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=c0ac2cfa-3af5-4012-a72b-fd2b411471a4</wfw:commentRss>
      <slash:comments>29</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <img alt="Screenshot of upload operation" src="content/binary/FTP_upload.jpg" align="right" border="0" hspace="10" vspace="10" />hi, 
<br />
i was delighted to see .Net 2.0 has an excellent class for working with FTP. 
looking back i can't believe it wasn't part of 1.1.  
<br /><br />
i noticed there was no built-in support for reporting the progress of an FTP operation
to a user interface.  I needed this functionality in an app i'm working on so
i built a class and i'm posting it here in case anyone is interested. 
<br /><br />
The class FtpProgress inherits from BackgroundWorker, so you just drag an FtpProgress
component onto your form, hook up events for Completed and ProgressChanged, and your
laughing.  There is a mini class called FtpSettings which stores all the connect
info etc to pass in as a paramter to the RunWorkerAsync() method. 
<br /><br />
I have a variable called 'ChunkSize' which determines the size of each buffer written
to the FtpWebRequest output stream.  It is set to 4k by default, and you can
increase this if you want for very fast networks but i don't think it will make much
difference.  I think the overhead is negligible.<br /><br />
Download the <a href="content/binary/FTP_ProgressBar.zip">source code and demo application</a> [30
k].<br /><br />
It only does upload, so if you want download functionality, you can do the mirror-image
of the upload code, i.e. instead of writing buffers to the output stream, read it
from the input stream, or however that would work :)  
<br /><br />
here is all the code you need to start an Upload, and report progress:<br /><pre>private void btnUpload_Click(object sender, EventArgs e)<br />
{<br />
// create a new FtpSettings class to store all the paramaters for the FtpProgress
thread<br />
FtpSettings f = new FtpSettings();<br />
f.Host = this.txtHost.Text;<br />
f.Username = this.txtUsername.Text;<br />
f.Password = this.txtPassword.Text;<br />
f.TargetFolder = this.txtDir.Text;<br />
f.SourceFile = this.txtUploadFile.Text;<br />
f.Passive = this.chkPassive.Checked;<br />
f.Port = Int32.Parse(this.txtPort.Text); 
<br />
this.ftpProgress1.RunWorkerAsync(f);<br />
}<br /><br />
private void ftpProgress1_ProgressChanged(object sender, ProgressChangedEventArgs
e)<br />
{<br />
this.toolStripStatusLabel1.Text = e.UserState.ToString(); // the message will be something
like: 45 Kb / 102.12 Mb<br />
this.toolStripProgressBar1.Value = Math.Min(this.toolStripProgressBar1.Maximum, e.ProgressPercentage); 
<br />
}<br /></pre><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=c0ac2cfa-3af5-4012-a72b-fd2b411471a4" /></body>
      <title>FtpWebRequest with ProgressBar [C# Ftp]</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,c0ac2cfa-3af5-4012-a72b-fd2b411471a4.aspx</guid>
      <link>http://tim.mackey.ie/FtpWebRequestWithProgressBarCFtp.aspx</link>
      <pubDate>Fri, 17 Feb 2006 18:09:05 GMT</pubDate>
      <description>&lt;img alt="Screenshot of upload operation" src="content/binary/FTP_upload.jpg" align="right" border="0" hspace="10" vspace="10"&gt;hi, 
&lt;br&gt;
i was delighted to see .Net 2.0 has an excellent class for working with FTP.&amp;nbsp;
looking back i can't believe it wasn't part of 1.1.&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
i noticed there was no built-in support for reporting the progress of an FTP operation
to a user interface.&amp;nbsp; I needed this functionality in an app i'm working on so
i built a class and i'm posting it here in case anyone is interested. 
&lt;br&gt;
&lt;br&gt;
The class FtpProgress inherits from BackgroundWorker, so you just drag an FtpProgress
component onto your form, hook up events for Completed and ProgressChanged, and your
laughing.&amp;nbsp; There is a mini class called FtpSettings which stores all the connect
info etc to pass in as a paramter to the RunWorkerAsync() method. 
&lt;br&gt;
&lt;br&gt;
I have a variable called 'ChunkSize' which determines the size of each buffer written
to the FtpWebRequest output stream.&amp;nbsp; It is set to 4k by default, and you can
increase this if you want for very fast networks but i don't think it will make much
difference.&amp;nbsp; I think the overhead is negligible.&lt;br&gt;
&lt;br&gt;
Download the &lt;a href="content/binary/FTP_ProgressBar.zip"&gt;source code and demo application&lt;/a&gt; [30
k].&lt;br&gt;
&lt;br&gt;
It only does upload, so if you want download functionality, you can do the mirror-image
of the upload code, i.e. instead of writing buffers to the output stream, read it
from the input stream, or however that would work :)&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
here is all the code you need to start an Upload, and report progress:&lt;br&gt;
&lt;pre&gt;private void btnUpload_Click(object sender, EventArgs e)&lt;br&gt;
{&lt;br&gt;
// create a new FtpSettings class to store all the paramaters for the FtpProgress
thread&lt;br&gt;
FtpSettings f = new FtpSettings();&lt;br&gt;
f.Host = this.txtHost.Text;&lt;br&gt;
f.Username = this.txtUsername.Text;&lt;br&gt;
f.Password = this.txtPassword.Text;&lt;br&gt;
f.TargetFolder = this.txtDir.Text;&lt;br&gt;
f.SourceFile = this.txtUploadFile.Text;&lt;br&gt;
f.Passive = this.chkPassive.Checked;&lt;br&gt;
f.Port = Int32.Parse(this.txtPort.Text); 
&lt;br&gt;
this.ftpProgress1.RunWorkerAsync(f);&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
private void ftpProgress1_ProgressChanged(object sender, ProgressChangedEventArgs
e)&lt;br&gt;
{&lt;br&gt;
this.toolStripStatusLabel1.Text = e.UserState.ToString(); // the message will be something
like: 45 Kb / 102.12 Mb&lt;br&gt;
this.toolStripProgressBar1.Value = Math.Min(this.toolStripProgressBar1.Maximum, e.ProgressPercentage); 
&lt;br&gt;
}&lt;br&gt;
&lt;/pre&gt;&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=c0ac2cfa-3af5-4012-a72b-fd2b411471a4" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,c0ac2cfa-3af5-4012-a72b-fd2b411471a4.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=ef06b347-51a0-4824-b2d7-a831c8620588</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,ef06b347-51a0-4824-b2d7-a831c8620588.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,ef06b347-51a0-4824-b2d7-a831c8620588.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=ef06b347-51a0-4824-b2d7-a831c8620588</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">For some reason i can't get SelectNodes
to work with the IIS 6 MetaBase.xml file.  It just doesn't return any matches. 
I think the structure may be non-standard or too complex, or else i'm not using it
right.  but in any case, I worked around the problem by opening the file with
File.OpenText and using Regex to parse out the nodes i'm interested in, namely the
IISWebServer nodes.<br /><br /><pre>string MetaBase = "";<br />
using(StreamReader sr = File.OpenText(ConfigurationManager.AppSettings["MetaBasePath"].ToString()))<br />
MetaBase = sr.ReadToEnd();<br /><br />
foreach(Match m in new Regex(@"(?x:)&lt;IIsWebServer[^&gt;]*&gt;.*?&lt;/IIsWebServer&gt;",
RegexOptions.IgnoreCase).Matches(MetaBase))<br />
{<br />
XmlDocument doc = new XmlDocument();<br />
string IisCode = "", ServerBindings = "", ServerComment = "";<br />
doc.LoadXml(m.Groups[0].Value);<br />
XmlElement node = doc.DocumentElement;<br />
// now you can access the node attributes<br />
...<br /></pre><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=ef06b347-51a0-4824-b2d7-a831c8620588" /></body>
      <title>Using Xml DOM with MetaBase.xml</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,ef06b347-51a0-4824-b2d7-a831c8620588.aspx</guid>
      <link>http://tim.mackey.ie/UsingXmlDOMWithMetaBasexml.aspx</link>
      <pubDate>Thu, 02 Feb 2006 13:38:34 GMT</pubDate>
      <description>For some reason i can't get SelectNodes to work with the IIS 6 MetaBase.xml file.&amp;nbsp; It just doesn't return any matches.&amp;nbsp; I think the structure may be non-standard or too complex, or else i'm not using it right.&amp;nbsp; but in any case, I worked around the problem by opening the file with File.OpenText and using Regex to parse out the nodes i'm interested in, namely the IISWebServer nodes.&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;string MetaBase = "";&lt;br&gt;
using(StreamReader sr = File.OpenText(ConfigurationManager.AppSettings["MetaBasePath"].ToString()))&lt;br&gt;
MetaBase = sr.ReadToEnd();&lt;br&gt;
&lt;br&gt;
foreach(Match m in new Regex(@"(?x:)&amp;lt;IIsWebServer[^&amp;gt;]*&amp;gt;.*?&amp;lt;/IIsWebServer&amp;gt;",
RegexOptions.IgnoreCase).Matches(MetaBase))&lt;br&gt;
{&lt;br&gt;
XmlDocument doc = new XmlDocument();&lt;br&gt;
string IisCode = "", ServerBindings = "", ServerComment = "";&lt;br&gt;
doc.LoadXml(m.Groups[0].Value);&lt;br&gt;
XmlElement node = doc.DocumentElement;&lt;br&gt;
// now you can access the node attributes&lt;br&gt;
...&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=ef06b347-51a0-4824-b2d7-a831c8620588" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,ef06b347-51a0-4824-b2d7-a831c8620588.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
      <category>Windows Server 2003</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=8a4b7e76-e10d-4063-bbab-ca339701f6a9</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,8a4b7e76-e10d-4063-bbab-ca339701f6a9.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,8a4b7e76-e10d-4063-bbab-ca339701f6a9.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=8a4b7e76-e10d-4063-bbab-ca339701f6a9</wfw:commentRss>
      <slash:comments>16</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">I have a text object in my crystal report,
and i set the value programatically for it, using something like this:<br /><pre>(rpt.Section3.ReportObjects["txtDate"] as TextObject).Text = DateTime.Now.ToShortDateString();</pre>this
works fine, until you put a string with line breaks inside it, specifically \r\n or
the carriage return character.  This is a bug in CR for .Net, you can <a href="http://support.businessobjects.com/library/kbase/articles/c2015089.asp">read
the official blurb here</a>.  the work-around code they post is in VB, and it
made no sense to me when i read it. 
<br />
what they actually do is make you change the TextObject into a FormulaField (you have
to view the 'Field Explorer' tab next to the toolbox, and drag on a Formula Field). 
Then you set 'CanGrow' to true, and then you go back to your code, and do the most
arcane work-around i've ever seen.  you set the formula to your text string,
but you must surround it in single quote characters, and replace \r\n with some inline
managed code as follows: ' + chr(10) + '<br />
when i first read this, i thought they had made a syntax error, but this is the way
to do it, and it works.  the new format for setting the formula field is:<br /><pre>rpt.DataDefinition.FormulaFields[0].Text = "'" + YourString.Replace("\r\n", "' + chr(10) + '") + "'";</pre><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=8a4b7e76-e10d-4063-bbab-ca339701f6a9" /></body>
      <title>Crystal Reports TextObject ignores newline, carriage return, \r\n</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,8a4b7e76-e10d-4063-bbab-ca339701f6a9.aspx</guid>
      <link>http://tim.mackey.ie/CrystalReportsTextObjectIgnoresNewlineCarriageReturnRn.aspx</link>
      <pubDate>Wed, 25 Jan 2006 13:52:05 GMT</pubDate>
      <description>I have a text object in my crystal report, and i set the value programatically for it, using something like this:&lt;br&gt;
&lt;pre&gt;(rpt.Section3.ReportObjects["txtDate"] as TextObject).Text = DateTime.Now.ToShortDateString();&lt;/pre&gt;this
works fine, until you put a string with line breaks inside it, specifically \r\n or
the carriage return character.&amp;nbsp; This is a bug in CR for .Net, you can &lt;a href="http://support.businessobjects.com/library/kbase/articles/c2015089.asp"&gt;read
the official blurb here&lt;/a&gt;.&amp;nbsp; the work-around code they post is in VB, and it
made no sense to me when i read it. 
&lt;br&gt;
what they actually do is make you change the TextObject into a FormulaField (you have
to view the 'Field Explorer' tab next to the toolbox, and drag on a Formula Field).&amp;nbsp;
Then you set 'CanGrow' to true, and then you go back to your code, and do the most
arcane work-around i've ever seen.&amp;nbsp; you set the formula to your text string,
but you must surround it in single quote characters, and replace \r\n with some inline
managed code as follows: ' + chr(10) + '&lt;br&gt;
when i first read this, i thought they had made a syntax error, but this is the way
to do it, and it works.&amp;nbsp; the new format for setting the formula field is:&lt;br&gt;
&lt;pre&gt;rpt.DataDefinition.FormulaFields[0].Text = "'" + YourString.Replace("\r\n", "' + chr(10) + '") + "'";&lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=8a4b7e76-e10d-4063-bbab-ca339701f6a9" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,8a4b7e76-e10d-4063-bbab-ca339701f6a9.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=4796b7f6-d1c8-4f4d-a472-03a482b0de15</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,4796b7f6-d1c8-4f4d-a472-03a482b0de15.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,4796b7f6-d1c8-4f4d-a472-03a482b0de15.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=4796b7f6-d1c8-4f4d-a472-03a482b0de15</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">I ran into a frustrating problem today
where some properties of my objects weren't getting serialized.  I noticed it
was the ones without 'set' accessors.  I didn't want to put set accessors in
because the properties should be read-only, but apparently the xml serializer needs
the set accessor to de-serialize.  
<br />
there is a good discussion on it on <a href="http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/36456d10b2bf53df/">this
thread.</a><br />
Luckily we can use the ReadOnlyAttribute setting on the property to prevent it being
modified by a programmer at design time.<br />
or you can use the Soap serializer instead of xml, whatever that is.<br /><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=4796b7f6-d1c8-4f4d-a472-03a482b0de15" /></body>
      <title>Xml Serialization: Properties left out without 'set' accessor</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,4796b7f6-d1c8-4f4d-a472-03a482b0de15.aspx</guid>
      <link>http://tim.mackey.ie/XmlSerializationPropertiesLeftOutWithoutSetAccessor.aspx</link>
      <pubDate>Mon, 09 Jan 2006 17:57:34 GMT</pubDate>
      <description>I ran into a frustrating problem today where some properties of my objects weren't getting serialized.&amp;nbsp; I noticed it was the ones without 'set' accessors.&amp;nbsp; I didn't want to put set accessors in because the properties should be read-only, but apparently the xml serializer needs the set accessor to de-serialize.&amp;nbsp; &lt;br&gt;
there is a good discussion on it on &lt;a href="http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/36456d10b2bf53df/"&gt;this
thread.&lt;/a&gt;
&lt;br&gt;
Luckily we can use the ReadOnlyAttribute setting on the property to prevent it being
modified by a programmer at design time.&lt;br&gt;
or you can use the Soap serializer instead of xml, whatever that is.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=4796b7f6-d1c8-4f4d-a472-03a482b0de15" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,4796b7f6-d1c8-4f4d-a472-03a482b0de15.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=9603c0e9-a99e-4d6e-bfef-d4abb7ae9501</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,9603c0e9-a99e-4d6e-bfef-d4abb7ae9501.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,9603c0e9-a99e-4d6e-bfef-d4abb7ae9501.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=9603c0e9-a99e-4d6e-bfef-d4abb7ae9501</wfw:commentRss>
      <slash:comments>24</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">just posting my code-project <a href="http://www.codeproject.com/soap/MTOMWebServices.asp">article
on http chunking web services with MTOM</a> here for reference.  by the way it
has been updated on codeproject...<br /><br /><ul class="download"><li><a href="http://www.codeproject.com/soap/MTOMWebServices/Article_source.zip">Download
source for web service + Windows client - 52.1 Kb</a></li></ul><p><img alt="Screenshot of windows forms client, uploading a file" src="http://www.codeproject.com/soap/MTOMWebServices/Article.jpg" /></p><h2>Introduction
</h2><p>
In trying to keep up to speed with .NET 2.0, I decided to do a .NET 2.0 version of
my CodeProject article <a href="http://www.codeproject.com/cs/webservices/DimeBufferedUpload.asp">"DIME
Buffered Upload"</a> which used the DIME standard to transfer binary data over web
services. The DIME approach was reasonably efficient but the code is quite complex
and I was keen to explore what .NET 2.0 has to offer. In this article, I use version
3.0 of the WSE (<a href="http://msdn.microsoft.com/webservices/webservices/building/wse/" target="_blank">Web
Service Enhancements</a>) which is available for .NET 2.0 as an add-in, to provide
a simpler and faster method of sending binary data in small chunks over HTTP web services.
</p><h2>Background
</h2><p>
Just a recap on why you may need to send data in small chunks at all: if you have
a large file and you want to send it across a web service, you must understand the
way it all fits together between IIS, .NET, and the web service call. You send your
file as an array of bytes, as a parameter to a web service call, which is all sent
to the IIS web server as a single request. This is bad if the size of the file is
beyond the configured <code>MaxRequestLength</code> of your application, or if the
request causes an IIS timeout. It is also bad from the point of view of providing
feedback of the file transfer to the user interface because you have no indication
how the transfer is going, until it is either completed or failed. The solution outlined
here is to send chunks of the file one by one, and append them to the file on the
server.
</p><p>
There is an MD5 file hash done on the client and the server to verify that the file
received is identical to the file sent.
</p><p>
Also, there is an upload and download code included in this article.
</p><h2>Adventures with MTOM
</h2><p>
MTOM stands for SOAP "Message Transmission Optimization Mechanism" and it is a <a href="http://www.w3.org/TR/2005/REC-soap12-mtom-20050125/" target="_blank">W3C
standard</a>. To use it (and to run this application), you must download and install <a href="http://msdn.microsoft.com/webservices/webservices/building/wse/" target="_blank">WSE
3.0</a>, which includes MTOM support for the first time. If you look in the <i>app.config</i> and <i>web.config</i> files
in the source code, you will see sections referring to the WSE 3 assembly, and a messaging <code>clientMode</code> or <code>serverMode</code> setting.
These are necessary to run MTOM in the application.
</p><p>
The problem with DIME was that the binary content of the message was sent outside
the <code>SoapEnvelope</code> of the XML message. This meant that although your message
was secure, the Dime Attachment may not be secure. MTOM fully complies with the other
WS-* specifications (like WS-Security) so the entire message is secure.
</p><p>
It took me a while to realise that when MTOM is turned on for the client and the server,
WSE automatically handles the binary encoding of the data in the web service message.
With DIME and WSE 2.0, you had to configure your app for DIME and then use DimeAttachments
in your code. This is no longer necessary, you just send your byte[] as a parameter
or return value, and WSE makes sure that it is sent as binary, and not padded by XML
serialization as it would be in the absence of DIME or MTOM.
</p><h2>How it works
</h2><p>
The web service has two main methods, <code>AppendChunk</code> is for uploading a
file to the server, <code>DownloadChunk</code> is for downloading from the server.
These methods receive parameters for the file name, the offset of the chunk, and the
size of the buffer being sent/received.
</p><p>
The Windows Forms client application can upload a file by sending all the chunks one
after the other using <code>AppendChunk</code>, until the file has been completely
sent. It can do an MD5 hash on the local file, and compare it with the hash on the
file on the server, to make sure the contents of the files are identical. The download
code is very similar, the main difference is that the client must know from the server
how big the file is, so that it can know when to stop requesting chunks.
</p><p>
A simplified version of the <b>upload code is shown below</b> (from the WinForms client).
Have a look in the code for <i>Form1.cs</i> to see the inline comments + the explanation
of the code. Essentially, a file stream is opened on the client for the duration of
the transfer. Then the first chunk is read into the <code>Buffer</code> byte array.
The <code lang="cs"><span class="cs-keyword">while</span></code> loop keeps running
until the <code>FileStream.Read()</code> method returns 0, i.e. the end of the file
has been reached. For each iteration, the buffer is sent directly to the web service
as a <code lang="cs"><span class="cs-keyword">byte</span>[]</code>. The '<code>SentBytes</code>'
variable is used to report progress to the form.
</p><pre>using(FileStream fs = new FileStream(LocalFilePath, FileMode.Open, FileAccess.Read))<br />
{<br />
int BytesRead = fs.Read(Buffer, 0, ChunkSize);<br />
while(BytesRead &gt; 0 &amp;&amp; !worker.CancellationPending)<br />
{<br />
ws.AppendChunk(FileName, Buffer, SentBytes, BytesRead);<br />
SentBytes += BytesRead;<br />
BytesRead = fs.Read(Buffer, 0, ChunkSize); 
<br />
}<br />
}</pre><h2>Example of the BackgroundWorker class in .NET 2.0
</h2><p>
.NET 2.0 has a great new class called '<code>BackgroundWorker</code>' to simplify
running tasks asynchronously. Although this application sends the file in small chunks,
even these small chunks would delay the WinForms application and make it look crashed
during the transfer. So the web service calls still need to be done asynchronously.
The <code>BackgroundWorker</code> class works using an event model, where you have
code sections to run for <code>DoWork</code> (when you start), <code>ProgressChanged</code> (to
update your progress bar / status bar), and <code>Completed</code> (or failed). You
can pass parameters to the <code>DoWork</code> method, which you could not do with
the <code>Thread</code> class in .NET 1.1 (I know you could with delegates, but delegates
aren't great for thread control). You can also access the return value of <code>DoWork</code> in
the <code>Completed</code> event handler. So for once, MS has thought of everything
and made a very clean threading model. Exceptions are handled internally and you can
access them in the <code>Completed</code> method via the <code>RunWorkerCompletedEventArgs.Error</code> property.
</p><p>
The code shown below is an example of the <code>ProgressChanged</code> event handler:
</p><pre>private void workerUpload_ProgressChanged(object sender, ProgressChangedEventArgs e)<br />
{<br />
// update the progress bar and status bar text<br />
this.toolStripProgressBar1.Value = e.ProgressPercentage;<br />
this.statusText.Text = e.UserState.ToString();<br />
// summary text is sent in the UserState parameter<br />
}<br /></pre><p>
I have used four <code>BackgroundWorker</code> objects in the application:
</p><ul><li>
one to manage the upload process, 
</li><li>
one to manage the download process, 
</li><li>
another to calculate the local MD5 file hash in parallel while waiting for the server
result, 
</li><li>
and another to download the list of files in the <i>Upload</i> server folder to allow
the user to select a file to download. 
</li></ul><p>
The reason I use a <code>BackgroundWorker</code> object for each task is because the
code for each task is tied in to the events for that object.
</p><h2>A good example of Thread.Join()
</h2><p>
When the upload or download is complete, the client asks for an MD5 hash of the file
on the server, so it can compare it with the local file to make sure they are identical.
I originally did these in sequence. But it can take a few seconds to calculate the
result for a large file (anything over a few hundred MB), so the application was waiting
five seconds for the server to calculate the hash, and then five more seconds for
the client to calculate its own hash. This made no sense, so I decided to implement
a multi-threaded approach to allow them to run in parallel. While the client is waiting
on the server, it should be calculating its own file hash. This is done with the <code>Thread</code> class,
and the use of the <code>Join()</code> method which blocks execution until the thread
is complete.
</p><p>
The code below shows how this is accomplished:
</p><pre>// start calculating the local hash (stored in class variable)<br />
this.hashThread = new Thread(new ThreadStart(this.CheckFileHash));<br />
this.hashThread.Start();<br /><br />
// request the server hash<br />
string ServerFileHash = ws.CheckFileHash(FileName);<br /><br />
// wait for the local hash to complete<br />
this.hashThread.Join();<br /><br />
if(this.LocalFileHash == ServerFileHash)<br />
e.Result = "Hashes match exactly";<br />
else 
<br />
e.Result = "Hashes do not match";<br /></pre><p>
There is a good chance that the two operations will finish at approximately the same
time, so very little waiting around will actually happen.
</p><h2>Performance compared with DIME
</h2><p>
I found that MTOM was about 10% faster than DIME in my limited testing. This is probably
to do with the need to package up each chunk into a DIME attachment, which is no longer
necessary with MTOM. I was able to upload files of several gigabytes in size without
problems.
</p><p>
Obviously, there is an overhead with all this business of reading file chunks and
appending them, so the larger the chunk size, the more efficient your application
will be. It should be customised based on the network and the expected size of files.
For very small files, it is no harm to use small chunk sizes (e.g., 32 Kb) because
this will give accurate and regular feedback to the user interface. For very large
files on a fast network, consider using 4000 Kb to make good use of the bandwidth
and reduce the File Input/Output overhead. If you want to send chunks larger than
4 MB, you must increase the .NET 2.0 Max Request Size limit in your <i>web.config</i>.
</p><h2>Conclusions
</h2><p>
Feel free to use this code and modify it as you please. Please post a comment for
any bugs, suggestions, or improvements. Enjoy!
</p><p></p><img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=9603c0e9-a99e-4d6e-bfef-d4abb7ae9501" /></body>
      <title>Sending files in chunks with MTOM Web Services and .NET 2.0</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,9603c0e9-a99e-4d6e-bfef-d4abb7ae9501.aspx</guid>
      <link>http://tim.mackey.ie/SendingFilesInChunksWithMTOMWebServicesAndNET20.aspx</link>
      <pubDate>Thu, 29 Dec 2005 20:34:15 GMT</pubDate>
      <description>just posting my code-project &lt;a href="http://www.codeproject.com/soap/MTOMWebServices.asp"&gt;article
on http chunking web services with MTOM&lt;/a&gt; here for reference.&amp;nbsp; by the way it
has been updated on codeproject...&lt;br&gt;
&lt;br&gt;
&lt;ul class="download"&gt;
&lt;li&gt;
&lt;a href="http://www.codeproject.com/soap/MTOMWebServices/Article_source.zip"&gt;Download
source for web service + Windows client - 52.1 Kb&lt;/a&gt; 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;img alt="Screenshot of windows forms client, uploading a file" src="http://www.codeproject.com/soap/MTOMWebServices/Article.jpg"&gt;
&lt;/p&gt;
&lt;h2&gt;Introduction
&lt;/h2&gt;
&lt;p&gt;
In trying to keep up to speed with .NET 2.0, I decided to do a .NET 2.0 version of
my CodeProject article &lt;a href="http://www.codeproject.com/cs/webservices/DimeBufferedUpload.asp"&gt;"DIME
Buffered Upload"&lt;/a&gt; which used the DIME standard to transfer binary data over web
services. The DIME approach was reasonably efficient but the code is quite complex
and I was keen to explore what .NET 2.0 has to offer. In this article, I use version
3.0 of the WSE (&lt;a href="http://msdn.microsoft.com/webservices/webservices/building/wse/" target="_blank"&gt;Web
Service Enhancements&lt;/a&gt;) which is available for .NET 2.0 as an add-in, to provide
a simpler and faster method of sending binary data in small chunks over HTTP web services.
&lt;/p&gt;
&lt;h2&gt;Background
&lt;/h2&gt;
&lt;p&gt;
Just a recap on why you may need to send data in small chunks at all: if you have
a large file and you want to send it across a web service, you must understand the
way it all fits together between IIS, .NET, and the web service call. You send your
file as an array of bytes, as a parameter to a web service call, which is all sent
to the IIS web server as a single request. This is bad if the size of the file is
beyond the configured &lt;code&gt;MaxRequestLength&lt;/code&gt; of your application, or if the
request causes an IIS timeout. It is also bad from the point of view of providing
feedback of the file transfer to the user interface because you have no indication
how the transfer is going, until it is either completed or failed. The solution outlined
here is to send chunks of the file one by one, and append them to the file on the
server.
&lt;/p&gt;
&lt;p&gt;
There is an MD5 file hash done on the client and the server to verify that the file
received is identical to the file sent.
&lt;/p&gt;
&lt;p&gt;
Also, there is an upload and download code included in this article.
&lt;/p&gt;
&lt;h2&gt;Adventures with MTOM
&lt;/h2&gt;
&lt;p&gt;
MTOM stands for SOAP "Message Transmission Optimization Mechanism" and it is a &lt;a href="http://www.w3.org/TR/2005/REC-soap12-mtom-20050125/" target="_blank"&gt;W3C
standard&lt;/a&gt;. To use it (and to run this application), you must download and install &lt;a href="http://msdn.microsoft.com/webservices/webservices/building/wse/" target="_blank"&gt;WSE
3.0&lt;/a&gt;, which includes MTOM support for the first time. If you look in the &lt;i&gt;app.config&lt;/i&gt; and &lt;i&gt;web.config&lt;/i&gt; files
in the source code, you will see sections referring to the WSE 3 assembly, and a messaging &lt;code&gt;clientMode&lt;/code&gt; or &lt;code&gt;serverMode&lt;/code&gt; setting.
These are necessary to run MTOM in the application.
&lt;/p&gt;
&lt;p&gt;
The problem with DIME was that the binary content of the message was sent outside
the &lt;code&gt;SoapEnvelope&lt;/code&gt; of the XML message. This meant that although your message
was secure, the Dime Attachment may not be secure. MTOM fully complies with the other
WS-* specifications (like WS-Security) so the entire message is secure.
&lt;/p&gt;
&lt;p&gt;
It took me a while to realise that when MTOM is turned on for the client and the server,
WSE automatically handles the binary encoding of the data in the web service message.
With DIME and WSE 2.0, you had to configure your app for DIME and then use DimeAttachments
in your code. This is no longer necessary, you just send your byte[] as a parameter
or return value, and WSE makes sure that it is sent as binary, and not padded by XML
serialization as it would be in the absence of DIME or MTOM.
&lt;/p&gt;
&lt;h2&gt;How it works
&lt;/h2&gt;
&lt;p&gt;
The web service has two main methods, &lt;code&gt;AppendChunk&lt;/code&gt; is for uploading a
file to the server, &lt;code&gt;DownloadChunk&lt;/code&gt; is for downloading from the server.
These methods receive parameters for the file name, the offset of the chunk, and the
size of the buffer being sent/received.
&lt;/p&gt;
&lt;p&gt;
The Windows Forms client application can upload a file by sending all the chunks one
after the other using &lt;code&gt;AppendChunk&lt;/code&gt;, until the file has been completely
sent. It can do an MD5 hash on the local file, and compare it with the hash on the
file on the server, to make sure the contents of the files are identical. The download
code is very similar, the main difference is that the client must know from the server
how big the file is, so that it can know when to stop requesting chunks.
&lt;/p&gt;
&lt;p&gt;
A simplified version of the &lt;b&gt;upload code is shown below&lt;/b&gt; (from the WinForms client).
Have a look in the code for &lt;i&gt;Form1.cs&lt;/i&gt; to see the inline comments + the explanation
of the code. Essentially, a file stream is opened on the client for the duration of
the transfer. Then the first chunk is read into the &lt;code&gt;Buffer&lt;/code&gt; byte array.
The &lt;code lang="cs"&gt;&lt;span class="cs-keyword"&gt;while&lt;/span&gt;&lt;/code&gt; loop keeps running
until the &lt;code&gt;FileStream.Read()&lt;/code&gt; method returns 0, i.e. the end of the file
has been reached. For each iteration, the buffer is sent directly to the web service
as a &lt;code lang="cs"&gt;&lt;span class="cs-keyword"&gt;byte&lt;/span&gt;[]&lt;/code&gt;. The '&lt;code&gt;SentBytes&lt;/code&gt;'
variable is used to report progress to the form.
&lt;/p&gt;
&lt;pre&gt;using(FileStream fs = new FileStream(LocalFilePath, FileMode.Open, FileAccess.Read))&lt;br&gt;
{&lt;br&gt;
int BytesRead = fs.Read(Buffer, 0, ChunkSize);&lt;br&gt;
while(BytesRead &amp;gt; 0 &amp;amp;&amp;amp; !worker.CancellationPending)&lt;br&gt;
{&lt;br&gt;
ws.AppendChunk(FileName, Buffer, SentBytes, BytesRead);&lt;br&gt;
SentBytes += BytesRead;&lt;br&gt;
BytesRead = fs.Read(Buffer, 0, ChunkSize); 
&lt;br&gt;
}&lt;br&gt;
}&lt;/pre&gt;
&lt;h2&gt;Example of the BackgroundWorker class in .NET 2.0
&lt;/h2&gt;
&lt;p&gt;
.NET 2.0 has a great new class called '&lt;code&gt;BackgroundWorker&lt;/code&gt;' to simplify
running tasks asynchronously. Although this application sends the file in small chunks,
even these small chunks would delay the WinForms application and make it look crashed
during the transfer. So the web service calls still need to be done asynchronously.
The &lt;code&gt;BackgroundWorker&lt;/code&gt; class works using an event model, where you have
code sections to run for &lt;code&gt;DoWork&lt;/code&gt; (when you start), &lt;code&gt;ProgressChanged&lt;/code&gt; (to
update your progress bar / status bar), and &lt;code&gt;Completed&lt;/code&gt; (or failed). You
can pass parameters to the &lt;code&gt;DoWork&lt;/code&gt; method, which you could not do with
the &lt;code&gt;Thread&lt;/code&gt; class in .NET 1.1 (I know you could with delegates, but delegates
aren't great for thread control). You can also access the return value of &lt;code&gt;DoWork&lt;/code&gt; in
the &lt;code&gt;Completed&lt;/code&gt; event handler. So for once, MS has thought of everything
and made a very clean threading model. Exceptions are handled internally and you can
access them in the &lt;code&gt;Completed&lt;/code&gt; method via the &lt;code&gt;RunWorkerCompletedEventArgs.Error&lt;/code&gt; property.
&lt;/p&gt;
&lt;p&gt;
The code shown below is an example of the &lt;code&gt;ProgressChanged&lt;/code&gt; event handler:
&lt;/p&gt;
&lt;pre&gt;private void workerUpload_ProgressChanged(object sender, ProgressChangedEventArgs e)&lt;br&gt;
{&lt;br&gt;
// update the progress bar and status bar text&lt;br&gt;
this.toolStripProgressBar1.Value = e.ProgressPercentage;&lt;br&gt;
this.statusText.Text = e.UserState.ToString();&lt;br&gt;
// summary text is sent in the UserState parameter&lt;br&gt;
}&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;
I have used four &lt;code&gt;BackgroundWorker&lt;/code&gt; objects in the application:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
one to manage the upload process, 
&lt;/li&gt;
&lt;li&gt;
one to manage the download process, 
&lt;/li&gt;
&lt;li&gt;
another to calculate the local MD5 file hash in parallel while waiting for the server
result, 
&lt;/li&gt;
&lt;li&gt;
and another to download the list of files in the &lt;i&gt;Upload&lt;/i&gt; server folder to allow
the user to select a file to download. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The reason I use a &lt;code&gt;BackgroundWorker&lt;/code&gt; object for each task is because the
code for each task is tied in to the events for that object.
&lt;/p&gt;
&lt;h2&gt;A good example of Thread.Join()
&lt;/h2&gt;
&lt;p&gt;
When the upload or download is complete, the client asks for an MD5 hash of the file
on the server, so it can compare it with the local file to make sure they are identical.
I originally did these in sequence. But it can take a few seconds to calculate the
result for a large file (anything over a few hundred MB), so the application was waiting
five seconds for the server to calculate the hash, and then five more seconds for
the client to calculate its own hash. This made no sense, so I decided to implement
a multi-threaded approach to allow them to run in parallel. While the client is waiting
on the server, it should be calculating its own file hash. This is done with the &lt;code&gt;Thread&lt;/code&gt; class,
and the use of the &lt;code&gt;Join()&lt;/code&gt; method which blocks execution until the thread
is complete.
&lt;/p&gt;
&lt;p&gt;
The code below shows how this is accomplished:
&lt;/p&gt;
&lt;pre&gt;// start calculating the local hash (stored in class variable)&lt;br&gt;
this.hashThread = new Thread(new ThreadStart(this.CheckFileHash));&lt;br&gt;
this.hashThread.Start();&lt;br&gt;
&lt;br&gt;
// request the server hash&lt;br&gt;
string ServerFileHash = ws.CheckFileHash(FileName);&lt;br&gt;
&lt;br&gt;
// wait for the local hash to complete&lt;br&gt;
this.hashThread.Join();&lt;br&gt;
&lt;br&gt;
if(this.LocalFileHash == ServerFileHash)&lt;br&gt;
e.Result = "Hashes match exactly";&lt;br&gt;
else 
&lt;br&gt;
e.Result = "Hashes do not match";&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;
There is a good chance that the two operations will finish at approximately the same
time, so very little waiting around will actually happen.
&lt;/p&gt;
&lt;h2&gt;Performance compared with DIME
&lt;/h2&gt;
&lt;p&gt;
I found that MTOM was about 10% faster than DIME in my limited testing. This is probably
to do with the need to package up each chunk into a DIME attachment, which is no longer
necessary with MTOM. I was able to upload files of several gigabytes in size without
problems.
&lt;/p&gt;
&lt;p&gt;
Obviously, there is an overhead with all this business of reading file chunks and
appending them, so the larger the chunk size, the more efficient your application
will be. It should be customised based on the network and the expected size of files.
For very small files, it is no harm to use small chunk sizes (e.g., 32 Kb) because
this will give accurate and regular feedback to the user interface. For very large
files on a fast network, consider using 4000 Kb to make good use of the bandwidth
and reduce the File Input/Output overhead. If you want to send chunks larger than
4 MB, you must increase the .NET 2.0 Max Request Size limit in your &lt;i&gt;web.config&lt;/i&gt;.
&lt;/p&gt;
&lt;h2&gt;Conclusions
&lt;/h2&gt;
&lt;p&gt;
Feel free to use this code and modify it as you please. Please post a comment for
any bugs, suggestions, or improvements. Enjoy!
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=9603c0e9-a99e-4d6e-bfef-d4abb7ae9501" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,9603c0e9-a99e-4d6e-bfef-d4abb7ae9501.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=38544dae-c5b0-487d-a22f-7781459b2416</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,38544dae-c5b0-487d-a22f-7781459b2416.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,38544dae-c5b0-487d-a22f-7781459b2416.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=38544dae-c5b0-487d-a22f-7781459b2416</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I had a transaction comprised of about 5 commands, and in the middle of it, i needed
to do a SELECT on a table to know what values to insert for one of the commands. 
I encountered a timeout just after i called Fill on the DataAdapter.  it took
me a while to figure out that it was because the transaction had already taken out
a lock on the table i was selecting from.  makes sense now, but i spent ages
on it!  just posting it here in case anyone else runs into the same problem. 
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=38544dae-c5b0-487d-a22f-7781459b2416" />
      </body>
      <title>ADO.NET timeouts when filling a DataAdapter in the middle of a transaction</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,38544dae-c5b0-487d-a22f-7781459b2416.aspx</guid>
      <link>http://tim.mackey.ie/ADONETTimeoutsWhenFillingADataAdapterInTheMiddleOfATransaction.aspx</link>
      <pubDate>Fri, 02 Dec 2005 12:26:22 GMT</pubDate>
      <description>&lt;p&gt;
I had a transaction comprised of about 5 commands, and in the middle of it, i needed
to do a SELECT on a table to know what values to insert for one of the commands.&amp;nbsp;
I encountered a timeout just after i called Fill on the DataAdapter.&amp;nbsp; it took
me a while to figure out that it was because the transaction had already taken out
a lock on the table i was selecting from.&amp;nbsp; makes sense now, but i spent ages
on it!&amp;nbsp; just posting it here in case anyone else runs into the same problem. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=38544dae-c5b0-487d-a22f-7781459b2416" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,38544dae-c5b0-487d-a22f-7781459b2416.aspx</comments>
      <category>.Net General</category>
      <category>.Net Windows Forms</category>
      <category>Asp.Net</category>
      <category>Database</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=15a7b3f4-d0b7-4ba1-a33e-65351514f4fa</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,15a7b3f4-d0b7-4ba1-a33e-65351514f4fa.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,15a7b3f4-d0b7-4ba1-a33e-65351514f4fa.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=15a7b3f4-d0b7-4ba1-a33e-65351514f4fa</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
          <img style="WIDTH: 296px; HEIGHT: 236px" alt="" hspace="5" src="http://tim.mackey.ie/content/binary/task_list_control.jpg" align="right" border="0" />
        </p>
        <p>
I decided to write this control when i realised there are some cases where a progress
bar is not enough, even with a label that gets updated for each new stage of a list
of operations. 
</p>
        <p>
Sometimes you want the user to see what's coming next, what has already been done,
and the ProgressTaskList control does just that.  it's nothing new of course,
often used in installers and the like, but there didn't appear to be any .Net control
like this.
</p>
        <p>
I've submitted the control to code-project (URL to follow), which is where any updates
will be posted.  If you have comments or suggestions, it's best to put them on
the code-project site please. 
</p>
        <p>
          <img style="WIDTH: 295px; HEIGHT: 148px" alt="" hspace="10" src="http://tim.mackey.ie/content/binary/task_list_scrolling.jpg" align="left" border="0" />
        </p>
        <p>
I'm quite pleased with the way it turned out.  The code is very simple, and i
couldn't find any bugs having done lots of testing.
</p>
        <p>
As you can see in the screenshot to the left, it handles scrolling quite well, and
automatically jumps to the current task when it is starting a new one.
</p>
        <p>
To use it you just specify TaskItems as a string[] and call Start() to set it off.
Then call NextTask() every time a task is finished to advance it to the next task.  
</p>
        <p>
You can download the source <a href="http://tim.mackey.ie/content/binary/Task_List_Source.zip">here</a> (30Kb)
if you like, but check on code-project for updates.
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=15a7b3f4-d0b7-4ba1-a33e-65351514f4fa" />
      </body>
      <title>A 'Progress-Task-List' control</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,15a7b3f4-d0b7-4ba1-a33e-65351514f4fa.aspx</guid>
      <link>http://tim.mackey.ie/AProgressTaskListControl.aspx</link>
      <pubDate>Sat, 27 Aug 2005 00:28:29 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img style="WIDTH: 296px; HEIGHT: 236px" alt="" hspace=5 src="http://tim.mackey.ie/content/binary/task_list_control.jpg" align=right border=0&gt;
&lt;/p&gt;
&lt;p&gt;
I decided to write this control when i realised there are some cases where a progress
bar is not enough, even with a label that gets updated for each new stage of a list
of operations. 
&lt;/p&gt;
&lt;p&gt;
Sometimes you want the user to see what's coming next, what has already been done,
and the ProgressTaskList control does just that.&amp;nbsp; it's nothing new of course,
often used in installers and the like, but there didn't appear to be any .Net control
like this.
&lt;/p&gt;
&lt;p&gt;
I've submitted the control to code-project (URL to follow), which is where any updates
will be posted.&amp;nbsp; If you have comments or suggestions, it's best to put them on
the code-project site please. 
&lt;/p&gt;
&lt;p&gt;
&lt;img style="WIDTH: 295px; HEIGHT: 148px" alt="" hspace=10 src="http://tim.mackey.ie/content/binary/task_list_scrolling.jpg" align=left border=0&gt;
&lt;/p&gt;
&lt;p&gt;
I'm quite pleased with the way it turned out.&amp;nbsp; The code is very simple, and i
couldn't find any bugs having done lots of testing.
&lt;/p&gt;
&lt;p&gt;
As you can see in the screenshot to the left, it handles scrolling quite well, and
automatically jumps to the current task when it is starting a new one.
&lt;/p&gt;
&lt;p&gt;
To use it you just specify TaskItems as a string[] and call Start() to set it off.
Then call NextTask() every time a task is finished to advance it to the next task.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
You can download the source &lt;a href="http://tim.mackey.ie/content/binary/Task_List_Source.zip"&gt;here&lt;/a&gt; (30Kb)
if you like, but check on code-project for updates.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=15a7b3f4-d0b7-4ba1-a33e-65351514f4fa" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,15a7b3f4-d0b7-4ba1-a33e-65351514f4fa.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=2f6bb56f-6490-4a10-9429-4e4af03b6b33</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,2f6bb56f-6490-4a10-9429-4e4af03b6b33.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,2f6bb56f-6490-4a10-9429-4e4af03b6b33.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=2f6bb56f-6490-4a10-9429-4e4af03b6b33</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
i found a few work arounds to prevent a datagrid from displaying the * new row. one
of them involved using a dataview as the datasource, with AllowNew property set to
false. however, someone called Sameers from theAngrycodeR pointed out that a
datatable has a DefaultView property which also has this AllowNew property. so you
can use the following code (if your datasource is a dataset):
</p>
        <pre>this.dataSet1.Tables[0].DefaultView.AllowNew = false;</pre>
        <p>
and you get to keep the dataset or datatable as the direct datasource. 
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=2f6bb56f-6490-4a10-9429-4e4af03b6b33" />
      </body>
      <title>How to disable new rows in Windows Forms DataGrid</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,2f6bb56f-6490-4a10-9429-4e4af03b6b33.aspx</guid>
      <link>http://tim.mackey.ie/HowToDisableNewRowsInWindowsFormsDataGrid.aspx</link>
      <pubDate>Mon, 22 Nov 2004 17:05:24 GMT</pubDate>
      <description>&lt;p&gt;
i found a few work arounds to prevent a datagrid from displaying the * new row. one
of them involved using a dataview as the datasource, with AllowNew property set to
false. however, someone called&amp;nbsp;Sameers from theAngrycodeR pointed out that a
datatable has a DefaultView property which also has this AllowNew property. so you
can use the following code (if your datasource is a dataset):
&lt;/p&gt;
&lt;pre&gt;this.dataSet1.Tables[0].DefaultView.AllowNew = false;&lt;/pre&gt;
&lt;p&gt;
and you get to keep the dataset or datatable as the direct datasource. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=2f6bb56f-6490-4a10-9429-4e4af03b6b33" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,2f6bb56f-6490-4a10-9429-4e4af03b6b33.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=f9394351-88ed-480b-9ed2-1630d887535a</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,f9394351-88ed-480b-9ed2-1630d887535a.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,f9394351-88ed-480b-9ed2-1630d887535a.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=f9394351-88ed-480b-9ed2-1630d887535a</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
i have a windows form with a textbox inside a panel, and the following code doesn't
work as expected:
</p>
        <pre>private void WizardLoad(object sender, System.EventArgs e)
{
  this.txtUsername.Focus();
}</pre>
        <p>
Thanks to someones <a href="http://www.dotnet247.com/247reference/msgs/29/148558.aspx">post</a>: 
</p>
        <p>
i now know that the best way to do it is as follows:
</p>
        <pre>this.ActiveControl = this.txtUsername;</pre>
        <p>
It works!
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=f9394351-88ed-480b-9ed2-1630d887535a" />
      </body>
      <title>TextBox.Focus() doesn't work within Form_Load</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,f9394351-88ed-480b-9ed2-1630d887535a.aspx</guid>
      <link>http://tim.mackey.ie/TextBoxFocusDoesntWorkWithinFormLoad.aspx</link>
      <pubDate>Tue, 26 Oct 2004 11:06:57 GMT</pubDate>
      <description>
&lt;p&gt;
i have a windows form with a textbox inside a panel, and the following code doesn't
work as expected:
&lt;/p&gt;
&lt;pre&gt;private void WizardLoad(object sender, System.EventArgs e)
{
  this.txtUsername.Focus();
}&lt;/pre&gt;
&lt;p&gt;
Thanks to someones &lt;a href="http://www.dotnet247.com/247reference/msgs/29/148558.aspx"&gt;post&lt;/a&gt;:&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
i now know that the best way to do it is as follows:
&lt;/p&gt;
&lt;pre&gt;this.ActiveControl = this.txtUsername;&lt;/pre&gt;
&lt;p&gt;
It works!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=f9394351-88ed-480b-9ed2-1630d887535a" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,f9394351-88ed-480b-9ed2-1630d887535a.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=a151cc12-edb8-40ca-aa84-6fbab274166c</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,a151cc12-edb8-40ca-aa84-6fbab274166c.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,a151cc12-edb8-40ca-aa84-6fbab274166c.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=a151cc12-edb8-40ca-aa84-6fbab274166c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
My windows application uses a multi-line textbox to allow the user to update text,
which gets sent to and from a web service, and then into and out of a sql database. 
Somewhere along the way, the \r\n characters turn into \n characters.  So when
i re-load the string from the web service into the textbox, it gets displayed as block
characters instead of proper line breaks.  I wrote the following simple function
to work around this issue.  
</p>
        <p>
It firstly removes all the \r characters, which has the effect of changing the \r\n
characters to \n. Then it replaces the \n chars to \r\n.  
</p>
        <p>
Note: The reason you can't just replace the \n chars with \r\n is because you would
end up with \r\r\n chars if there were \r\n's in the string before you did the replace. 
</p>
        <pre>/// 
<summary>
/// this method formats a string for correct display in a multiline text box. ///
It removes \n characters and replaces them with correct \r\n chars /// 
</summary>
public static string FormatForMultiLineTextBox(string s) { return s.Replace("\r","").Replace("\n","\r\n");
}</pre>
        <p>
i will also take this opportunity to share a method i use to prevent errors caused
by sending certain binary characters across a web service (at least in WSE 2). 
The method removes all un-useful binary characters (useful... in terms of my app). 
</p>
        <pre>/// 
<summary>
/// This method removes all binary characters except: /// Vertical Tab 0x09 /// New
Line 0x0A /// Carraiage Return 0x0D /// 
</summary>
public static string StripBinaryChars(string s) { return Regex.Replace(s, @"[\x00-\x08\x0B-\x0C\x0E-\x1F]","");
}</pre>
        <p>
see <a href="http://www.asciitable.com">www.asciitable.com</a> for more information
on the hex codes for these binary characters. 
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=a151cc12-edb8-40ca-aa84-6fbab274166c" />
      </body>
      <title>Complications with textbox and Newline and Carriage Return characters</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,a151cc12-edb8-40ca-aa84-6fbab274166c.aspx</guid>
      <link>http://tim.mackey.ie/ComplicationsWithTextboxAndNewlineAndCarriageReturnCharacters.aspx</link>
      <pubDate>Sun, 03 Oct 2004 17:40:37 GMT</pubDate>
      <description>
&lt;p&gt;
My windows application uses a multi-line textbox to allow the user to update text,
which gets sent to and from a web service, and then into and out of a sql database.&amp;nbsp;
Somewhere along the way, the \r\n characters turn into \n characters.&amp;nbsp; So when
i re-load the string from the web service into the textbox, it gets displayed as block
characters instead of proper line breaks.&amp;nbsp; I wrote the following simple function
to work around this issue.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
It firstly removes all the \r characters, which has the effect of changing the \r\n
characters to \n. Then it replaces the \n chars to \r\n.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Note: The reason you can't just replace the \n chars with \r\n is because you would
end up with \r\r\n chars if there were \r\n's in the string before you did the replace. 
&lt;/p&gt;
&lt;pre&gt;/// 
&lt;summary&gt;
/// this method formats a string for correct display in a multiline text box. ///
It removes \n characters and replaces them with correct \r\n chars /// 
&lt;/summary&gt;
public static string FormatForMultiLineTextBox(string s) { return s.Replace("\r","").Replace("\n","\r\n");
}&lt;/pre&gt;
&lt;p&gt;
i will also take this opportunity to share a method i use to prevent errors caused
by sending certain binary characters across a web service (at least in WSE 2).&amp;nbsp;
The method removes all un-useful binary characters (useful... in terms of my app). 
&lt;/p&gt;
&lt;pre&gt;/// 
&lt;summary&gt;
/// This method removes all binary characters except: /// Vertical Tab 0x09 /// New
Line 0x0A /// Carraiage Return 0x0D /// 
&lt;/summary&gt;
public static string StripBinaryChars(string s) { return Regex.Replace(s, @"[\x00-\x08\x0B-\x0C\x0E-\x1F]","");
}&lt;/pre&gt;
&lt;p&gt;
see &lt;a href="http://www.asciitable.com"&gt;www.asciitable.com&lt;/a&gt; for more information
on the hex codes for these binary characters. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=a151cc12-edb8-40ca-aa84-6fbab274166c" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,a151cc12-edb8-40ca-aa84-6fbab274166c.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=751910b0-a263-43b5-8985-a908349e6175</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,751910b0-a263-43b5-8985-a908349e6175.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,751910b0-a263-43b5-8985-a908349e6175.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=751910b0-a263-43b5-8985-a908349e6175</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I have built a content management system in windows forms, and i set it up with individual
forms to manage each of the aspects to the system. one to manage users, another for
templates etc.  however this made the user interface quite cluttered sometimes
with several windows open.  so i decided to make my app work like outlook 2003
with its nice control on the left with buttons and side panels on the left, and the
main panel on the right for whichever button is selected.  
</p>
        <p>
i chose the pure components navigator control (2.0) and i'm testing it at the moment. 
i don't like the way the developers don't give a public support forum, they say it
shouldn't need support, but i have had several issues with it. 
</p>
        <p>
the main problem i have is that the control seems to crash Visual Studio (2003 enterprise
edition) when i add panels to each group and set properties such as anchoring in the
designer.  i ended up cutting the code to set up the panels from InitialiseComponent
and pasting it into a separate function that i call in the constructor. 
</p>
        <p>
also, the group class is supposed to have a FitPanel() method, but it doesn't fill
the panel to the size of the space in the control between the buttons.  i tried
setting the panel to DockStyle.Fill and it fills the entire control on top of all
the other buttons.  I ended up manually creating the panels (right click a group
and Add Panel) and then resize it to the desired dimensions, and set the anchor to
top|left|bottom|right.  i must say it was quite messy though.  
</p>
        <p>
it seems like a great control and it works quick enough too. i'll need to do
more testing before i pay for the license though. 
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=751910b0-a263-43b5-8985-a908349e6175" />
      </body>
      <title>Some issues with PureComponents Navigator control 2.0</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,751910b0-a263-43b5-8985-a908349e6175.aspx</guid>
      <link>http://tim.mackey.ie/SomeIssuesWithPureComponentsNavigatorControl20.aspx</link>
      <pubDate>Wed, 21 Jul 2004 22:58:51 GMT</pubDate>
      <description>&lt;p&gt;
I have built a content management system in windows forms, and i set it up with individual
forms to manage each of the aspects to the system. one to manage users, another for
templates etc.&amp;nbsp; however this made the user interface quite cluttered sometimes
with several windows open.&amp;nbsp; so i decided to make my app work like outlook 2003
with its nice control on the left with buttons and side panels on the left, and the
main panel on the right for whichever button is selected.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
i chose the pure components navigator control (2.0) and i'm testing it at the moment.&amp;nbsp;
i don't like the way the developers don't give a public support forum, they say it
shouldn't need support, but i have had several issues with it. 
&lt;/p&gt;
&lt;p&gt;
the main problem i have is that the control seems to crash Visual Studio (2003 enterprise
edition) when i add panels to each group and set properties such as anchoring in the
designer.&amp;nbsp; i ended up cutting the code to set up the panels from InitialiseComponent
and pasting it into a separate function that i call in the constructor. 
&lt;/p&gt;
&lt;p&gt;
also, the group class is supposed to have a FitPanel() method, but it doesn't fill
the panel to the size of the space in the control between the buttons.&amp;nbsp; i tried
setting the panel to DockStyle.Fill and it fills the entire control on top of all
the other buttons.&amp;nbsp; I ended up manually creating the panels (right click a group
and Add Panel) and then resize it to the desired dimensions, and set the anchor to
top|left|bottom|right.&amp;nbsp; i must say it was quite messy though.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
it seems like a great control and it works quick enough too.&amp;nbsp;i'll need to do
more testing before i pay for the license though. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=751910b0-a263-43b5-8985-a908349e6175" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,751910b0-a263-43b5-8985-a908349e6175.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=be6ed87d-efe1-4d3d-85f3-05c7ebca563b</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,be6ed87d-efe1-4d3d-85f3-05c7ebca563b.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,be6ed87d-efe1-4d3d-85f3-05c7ebca563b.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=be6ed87d-efe1-4d3d-85f3-05c7ebca563b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
If you add a NotifyIcon (system tray icon) to a Windows forms application, you will
need to modify the dispose event of the form containing the icon, to explicitly
call dispose on the notifyIcon as follows:
</p>
        <pre>protected override void Dispose( bool disposing )
{
 if( disposing )
 {
  this.notifyIcon1.Dispose();
  if (components != null)
  {
   components.Dispose();
  }
 }
 base.Dispose( disposing );
}</pre>
        <p>
if you don't do this, the icon will get left in the system tray after the application
quits, until you move the mouse over the icon and then it will disappear.
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=be6ed87d-efe1-4d3d-85f3-05c7ebca563b" />
      </body>
      <title>System tray icons in Windows forms apps</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,be6ed87d-efe1-4d3d-85f3-05c7ebca563b.aspx</guid>
      <link>http://tim.mackey.ie/SystemTrayIconsInWindowsFormsApps.aspx</link>
      <pubDate>Mon, 12 Jul 2004 09:02:42 GMT</pubDate>
      <description>&lt;p&gt;
If you add a NotifyIcon (system tray icon) to a Windows forms application, you will
need to modify the&amp;nbsp;dispose event of the form containing the icon, to explicitly
call dispose on the notifyIcon as follows:
&lt;/p&gt;
&lt;pre&gt;protected override void Dispose( bool disposing )
{
 if( disposing )
 {
  this.notifyIcon1.Dispose();
  if (components != null)
  {
   components.Dispose();
  }
 }
 base.Dispose( disposing );
}&lt;/pre&gt;
&lt;p&gt;
if you don't do this, the icon will get left in the system tray after the application
quits, until you move the mouse over the icon and then it will disappear.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=be6ed87d-efe1-4d3d-85f3-05c7ebca563b" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,be6ed87d-efe1-4d3d-85f3-05c7ebca563b.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=5f2317f5-3321-445d-8859-651b5738524e</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,5f2317f5-3321-445d-8859-651b5738524e.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,5f2317f5-3321-445d-8859-651b5738524e.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=5f2317f5-3321-445d-8859-651b5738524e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I had originally deployed an app with msi but the advantages of smart clients soon
began to convince me to change my deployment model. 
</p>
        <h4>What you can and can't do in Local Intranet
</h4>
        <p>
As a smart client, the app is executed as <a href="http://myserver/exec/myApp.exe">http://myserver/exec/myApp.exe</a><br />
This works very nicely, until those security exceptions start appearing.  I had
to spend a long time going through my app to find out what was causing the exceptions. 
The obvious reason for the exceptions is that programs coming in from the Intranet
are less trusted than those on My Computer, and hence are subject to more restrictions
by the local security policy.  After much exploration and reading up online,
i found out some interesting facts:
</p>
        <ul>
          <li>
you can't access Environment.Machinename 
</li>
          <li>
you can't access My Documents, or UserAppDataPath, etc. 
</li>
          <li>
you can't call abort() on a Thread, but you can call Sleep() and Start() 
</li>
          <li>
you can read files through openFileDialog 
</li>
          <li>
you can read and write to IsolatedStorage (a virtual file-system specially for your
app), very useful seeing as you can't write to any physical location on the hard disk
by default. 
</li>
          <li>
you can invoke delegates asynchronously</li>
        </ul>
        <p>
You could deduce these by looking in the .Net Framework Security Policy (control panel
&gt; admin tools &gt; .Net Framework configuration &gt; Runtime security policy &gt;
Machine &gt; Permission Sets &gt; Local Intranet), and then double click one of the
items in the main pane to the right, to see what restrictions if any are applied for
the selected zone. 
</p>
        <p>
I found out the above information hard way through trial and error, but it was a very
valuable exercise to learn about the security policy.
</p>
        <h4>Using a class library with your smart client app
</h4>
        <p>
I got a large part of my app working, but i was using a class library of customised
windows forms components, and this was causing a security exception.  It took
a few hours to pin down, but the docs finally revealed that the class library must
have the following attribute (outside a class declaration):
</p>
        <p>
[assembly:AllowPartiallyTrustedCallers] 
</p>
        <p>
The app worked fine after I added that line. 
</p>
        <h4>Requesting permissions from the local Security Policy before your app runs. 
</h4>
        <p>
If you are not sure what zone your app will run in, you can request a minimum level
which your app requires. Add the following line of code outside a class declaration
in one of the files in your project:
</p>
        <p>
[assembly:PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "LocalIntranet")]
</p>
        <p>
This will alert the user that they don't have permissions to run the app
if it is running in a zone less than Local Intranet.  
</p>
        <h4>Conclusion
</h4>
        <p>
I personally have found these bits of information very difficult to pull together. 
There is a ton of stuff about smart clients but its mostly non-technical.  I
even got a CD from msdn about smart clients and i found it useless for helping out
with any of the problems i have encountered along the way. 
</p>
        <p>
I hear there is a tool called PermCalc.exe coming with Whidbey that will probe an
app to see what would cause security problems in a smart client scenario but until
then, we are stuck doing it manually :)
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=5f2317f5-3321-445d-8859-651b5738524e" />
      </body>
      <title>Adventures with .NET smart clients, running with Local Intranet permissions</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,5f2317f5-3321-445d-8859-651b5738524e.aspx</guid>
      <link>http://tim.mackey.ie/AdventuresWithNETSmartClientsRunningWithLocalIntranetPermissions.aspx</link>
      <pubDate>Tue, 22 Jun 2004 18:16:34 GMT</pubDate>
      <description>&lt;p&gt;
I had originally deployed an app with msi but the advantages of smart clients soon
began to convince me to change my deployment model. 
&lt;/p&gt;
&lt;h4&gt;What you can and can't do in Local Intranet
&lt;/h4&gt;
&lt;p&gt;
As a smart client, the app is executed as &lt;a href="http://myserver/exec/myApp.exe"&gt;http://myserver/exec/myApp.exe&lt;/a&gt;
&lt;br&gt;
This works very nicely, until those security exceptions start appearing.&amp;nbsp; I had
to spend a long time going through my app to find out what was causing the exceptions.&amp;nbsp;
The obvious reason for the exceptions is that programs coming in from the Intranet
are less trusted than those on My Computer, and hence are subject to more restrictions
by the local security policy.&amp;nbsp; After much exploration and reading up online,
i found out some interesting facts:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
you can't access Environment.Machinename 
&lt;li&gt;
you can't access My Documents, or UserAppDataPath, etc. 
&lt;li&gt;
you can't call abort() on a Thread, but you can call Sleep() and Start() 
&lt;li&gt;
you can read files through openFileDialog 
&lt;li&gt;
you can read and write to IsolatedStorage (a virtual file-system specially for your
app), very useful seeing as you can't write to any physical location on the hard disk
by default. 
&lt;li&gt;
you can invoke delegates asynchronously&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
You could deduce these by looking in the .Net Framework Security Policy (control panel
&amp;gt; admin tools &amp;gt; .Net Framework configuration &amp;gt; Runtime security policy &amp;gt;
Machine &amp;gt; Permission Sets &amp;gt; Local Intranet), and then double click one of the
items in the main pane to the right, to see what restrictions if any are applied for
the selected zone. 
&lt;/p&gt;
&lt;p&gt;
I found out the above information hard way through trial and error, but it was a very
valuable exercise to learn about the security policy.
&lt;/p&gt;
&lt;h4&gt;Using a class library with your smart client app
&lt;/h4&gt;
&lt;p&gt;
I got a large part of my app working, but i was using a class library of customised
windows forms components, and this was causing a security exception.&amp;nbsp; It took
a few hours to pin down, but the docs finally revealed that the class library must
have the following attribute (outside a class declaration):
&lt;/p&gt;
&lt;p&gt;
[assembly:AllowPartiallyTrustedCallers]&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
The app worked fine after I added that line. 
&lt;/p&gt;
&lt;h4&gt;Requesting permissions from the local Security Policy before your app runs.&amp;nbsp;
&lt;/h4&gt;
&lt;p&gt;
If you are not sure what zone your app will run in, you can request a minimum level
which your app requires. Add the following line of code outside a class declaration
in one of the files in your project:
&lt;/p&gt;
&lt;p&gt;
[assembly:PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "LocalIntranet")]
&lt;/p&gt;
&lt;p&gt;
This will&amp;nbsp;alert the user that they don't have&amp;nbsp;permissions to run the&amp;nbsp;app
if it is running in a zone less than&amp;nbsp;Local Intranet.&amp;nbsp; 
&lt;/p&gt;
&lt;h4&gt;Conclusion
&lt;/h4&gt;
&lt;p&gt;
I personally have found these bits of information very difficult to pull together.&amp;nbsp;
There is a ton of stuff about smart clients but its mostly non-technical.&amp;nbsp; I
even got a CD from msdn about smart clients and i found it useless for helping out
with any of the problems i have encountered along the way. 
&lt;/p&gt;
&lt;p&gt;
I hear there is a tool called PermCalc.exe coming with Whidbey that will probe an
app to see what would cause security problems in a smart client scenario but until
then, we are stuck doing it manually :)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=5f2317f5-3321-445d-8859-651b5738524e" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,5f2317f5-3321-445d-8859-651b5738524e.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=a16f50cf-2e31-431f-bbd6-f0f9f19b378e</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,a16f50cf-2e31-431f-bbd6-f0f9f19b378e.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,a16f50cf-2e31-431f-bbd6-f0f9f19b378e.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=a16f50cf-2e31-431f-bbd6-f0f9f19b378e</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <font color="#000000" size="2">
          <p>
I was using an OpenFileDialog and i wanted it to open at the My Pictures folder for
the current user.  So i looked up the msdn docs for how to locate this folder,
and i come across the Environment.SpecialFolder enumeration, which has an entry for
MyPictures.  Great, my code then was:
</p>
        </font>
        <pre>this.openFileDialog1.InitialDirectory = Environment.SpecialFolder.MyPictures; </pre>
        <p>
but this didn't compile, and it didn't show up in Intellisense.  I read a few
examples online which used the following syntax:
</p>
        <pre>this.openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); 
</pre>
        <p>
and it worked, although it still didn't show up in Intellisense.  you'd think
MS would at least explain this in the docs, weird.
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=a16f50cf-2e31-431f-bbd6-f0f9f19b378e" />
      </body>
      <title>Environment.SpecialFolder enumeration not showing up in Visual Studio Intellisense</title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,a16f50cf-2e31-431f-bbd6-f0f9f19b378e.aspx</guid>
      <link>http://tim.mackey.ie/EnvironmentSpecialFolderEnumerationNotShowingUpInVisualStudioIntellisense.aspx</link>
      <pubDate>Mon, 24 May 2004 11:34:15 GMT</pubDate>
      <description>&lt;font color="#000000" size="2"&gt; 
&lt;p&gt;
I was using an OpenFileDialog and i wanted it to open at the My Pictures folder for
the current user.&amp;nbsp; So i looked up the msdn docs for how to locate this folder,
and i come across the Environment.SpecialFolder enumeration, which has an entry for
MyPictures.&amp;nbsp; Great, my code then was:
&lt;/p&gt;
&lt;/font&gt; &lt;pre&gt;this.openFileDialog1.InitialDirectory = Environment.SpecialFolder.MyPictures; &lt;/pre&gt;
&lt;p&gt;
but this didn't compile, and it didn't show up in Intellisense.&amp;nbsp; I read a few
examples online which used the following syntax:
&lt;/p&gt;
&lt;pre&gt;this.openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); 
&lt;/pre&gt;
&lt;p&gt;
and it worked, although it still didn't show up in Intellisense.&amp;nbsp; you'd think
MS would at least explain this in the docs, weird.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=a16f50cf-2e31-431f-bbd6-f0f9f19b378e" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,a16f50cf-2e31-431f-bbd6-f0f9f19b378e.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://tim.mackey.ie/Trackback.aspx?guid=96f07a79-b450-4cc0-824e-c8a7d7a3242a</trackback:ping>
      <pingback:server>http://tim.mackey.ie/pingback.aspx</pingback:server>
      <pingback:target>http://tim.mackey.ie/PermaLink,guid,96f07a79-b450-4cc0-824e-c8a7d7a3242a.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://tim.mackey.ie/CommentView,guid,96f07a79-b450-4cc0-824e-c8a7d7a3242a.aspx</wfw:comment>
      <wfw:commentRss>http://tim.mackey.ie/SyndicationService.asmx/GetEntryCommentsRss?guid=96f07a79-b450-4cc0-824e-c8a7d7a3242a</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I encountered a frustrating issue using the Windows forms Datagrid today.  This
problem was also posted without reply on an <a href="http://groups.google.com/groups?hl=en&amp;lr=&amp;ie=UTF-8&amp;oe=UTF-8&amp;threadm=1d701e72.0111131333.54804c66%40posting.google.com&amp;rnum=1&amp;prev=/groups%3Fq%3DDataRowView.CancelEdit()%26ie%3DUTF-8%26oe%3DUTF-8%26hl%3Den%26btnG%3DGoogle%2BSearch">ms
newsgroup</a>. I'm posting my work around here for the record.  
</p>
        <p>
          <strong>Problem Description</strong>
          <br />
My windows form had a tabcontrol, with 2 tab pages, each with a datagrid, bound to
a table in a dataset.  The problem occurred when the user switched from the second
tab to the first, with the last row of the datagrid being left as a new row with default
null values. It was in 'edit mode' usually because the user added a new row, or pressed
enter, which automatically places the cursor in another empty new row, with the default
values. The exception I got was generated by the framework and not from my code, as
follows:
</p>
        <p>
Object reference not set to instance of an object, at:
</p>
        <p>
System.Data.DataRowView.CancelEdit() at 
<br />
System.Windows.Forms.CurrencyManager.CancelCurrentEdit() at 
<br />
System.Windows.Forms.DataGrid.OnLeave_Grid() at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
</p>
        <p>
The exception is interesting in that the CurrencyManager kicks in when the focus of
the DataGrid has left, and cancels the cell currently being edited.  
</p>
        <p>
          <strong>Solution</strong>
          <br />
I tried several solutions, and eventually worked around the problem by forcing the
user to click a button to switch from one tab to the other (I hid the tab change buttons
off the screen), and then disabling whichever grid wasn't being used after the button
was pressed.  This seemed to change the way the DataGrid cancelled the edit of
the last row, and the exception doesn't happen now. 
</p>
        <p>
It's not an elegant solution, so I'm open to suggestions. I do think the datagrid
should be able to execute CancelCurrentEdit without throwing exceptions, and I would
be interested to understand why it happens.  I guess it will be fixed in .Net
version 2. 
</p>
        <img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=96f07a79-b450-4cc0-824e-c8a7d7a3242a" />
      </body>
      <title>Windows Forms DataGrid throwing a null reference exception on DataRowView.CancelEdit() </title>
      <guid isPermaLink="false">http://tim.mackey.ie/PermaLink,guid,96f07a79-b450-4cc0-824e-c8a7d7a3242a.aspx</guid>
      <link>http://tim.mackey.ie/WindowsFormsDataGridThrowingANullReferenceExceptionOnDataRowViewCancelEdit.aspx</link>
      <pubDate>Mon, 15 Mar 2004 19:12:33 GMT</pubDate>
      <description>&lt;p&gt;
I encountered a frustrating issue using the Windows forms Datagrid today.&amp;nbsp; This
problem was also posted without reply on an&amp;nbsp;&lt;a href="http://groups.google.com/groups?hl=en&amp;amp;lr=&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;threadm=1d701e72.0111131333.54804c66%40posting.google.com&amp;amp;rnum=1&amp;amp;prev=/groups%3Fq%3DDataRowView.CancelEdit()%26ie%3DUTF-8%26oe%3DUTF-8%26hl%3Den%26btnG%3DGoogle%2BSearch"&gt;ms
newsgroup&lt;/a&gt;. I'm posting my work around here for the record.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Problem Description&lt;/strong&gt;
&lt;br&gt;
My windows form had a tabcontrol, with 2 tab pages, each with a datagrid, bound to
a table in a dataset.&amp;nbsp; The problem occurred when the user switched from the second
tab to the first, with the last row of the datagrid being left as a new row with default
null values. It was in 'edit mode' usually because the user added a new row, or pressed
enter, which automatically places the cursor in another empty new row, with the default
values. The exception I got was generated by the framework and not from my code, as
follows:
&lt;/p&gt;
&lt;p&gt;
Object reference not set to instance of an object, at:
&lt;/p&gt;
&lt;p&gt;
System.Data.DataRowView.CancelEdit() at 
&lt;br&gt;
System.Windows.Forms.CurrencyManager.CancelCurrentEdit() at 
&lt;br&gt;
System.Windows.Forms.DataGrid.OnLeave_Grid() at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
&lt;/p&gt;
&lt;p&gt;
The exception is interesting in that the CurrencyManager kicks in when the focus of
the DataGrid has left, and cancels the cell currently being edited.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Solution&lt;/strong&gt;
&lt;br&gt;
I tried several solutions, and eventually worked around the problem by forcing the
user to click a button to switch from one tab to the other (I hid the tab change buttons
off the screen), and then disabling whichever grid wasn't being used after the button
was pressed.&amp;nbsp; This seemed to change the way the DataGrid cancelled the edit of
the last row, and the exception doesn't happen now. 
&lt;/p&gt;
&lt;p&gt;
It's not an elegant solution, so I'm open to suggestions. I do think the datagrid
should be able to execute CancelCurrentEdit without throwing exceptions, and I would
be interested to understand why it happens.&amp;nbsp; I guess it will be fixed in .Net
version 2. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://tim.mackey.ie/aggbug.ashx?id=96f07a79-b450-4cc0-824e-c8a7d7a3242a" /&gt;</description>
      <comments>http://tim.mackey.ie/CommentView,guid,96f07a79-b450-4cc0-824e-c8a7d7a3242a.aspx</comments>
      <category>.Net Windows Forms</category>
    </item>
  </channel>
</rss>