<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>David Kline : Networking &amp;&amp; Web Services</title><link>http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx</link><description>Tags: Networking &amp;&amp; Web Services</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Exploring The NetCF WebCrawler Sample III - Visual Studio 2005 Beta 2</title><link>http://blogs.msdn.com/davidklinems/archive/2005/04/26/412378.aspx</link><pubDate>Wed, 27 Apr 2005 07:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:412378</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/412378.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=412378</wfw:commentRss><description>&lt;P&gt;In the first &lt;A href="https://blogs.msdn.com/davidklinems/archive/2005/03/08/389698.aspx"&gt;part&lt;/A&gt; of this series, I discussed how the WebCrawler uses an HTTP HEAD request to determine if the URL can be crawled (points to an HTML page).&amp;nbsp; The Visual Studio.NET 2003 version of the WebCrawler used a very simple check of the Content-Type header (equal to "text/html").&amp;nbsp; &lt;/P&gt;
&lt;P&gt;When I was reviewing the sample for the Visual Studio 2005 Beta 2 release, I ran the WebCrawler under the debugger and noticed that some URLs were failing unexpectedly.&amp;nbsp; While stepping through the Crawler.PageIsHtml method, I noticed that one of the failing sites were specifying the text encoding (ex: "text/html; charset=utf-8") as part of the content type.&amp;nbsp; Because of the WebCrawler's very simple approach to checking the URL's content type, this site was not being crawled.&lt;/P&gt;
&lt;P&gt;To fix this, I changed the content type comparison to use String.StartsWith instead of String.Equals.&amp;nbsp; After making this change, the previously failing URL was correctly identified and the WebCrawler successfully crawled the page.&lt;/P&gt;
&lt;P&gt;The code fragment, below, is an excerpt from the Crawler.PageIsHtml method and shows the updated content type check.&amp;nbsp;&amp;nbsp;For a complete source listing, please consult the files that were installed with Visual Studio .NET 2005 / .NET Framework SDK Beta 2.&lt;/P&gt;&lt;CODE&gt;
&lt;P&gt;// check the content type&lt;BR&gt;string contentType = headers["Content-type"];&lt;BR&gt;if (contentType != null)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = contentType.ToLower(CultureInfo.InvariantCulture);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (contentType.StartsWith(TypeHTML))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isHtml = true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/CODE&gt;
&lt;P&gt;For reference, the original code looked like this:&lt;/P&gt;&lt;CODE&gt;
&lt;P&gt;// check the content type&lt;BR&gt;string contentType = headers["Content-type"];&lt;BR&gt;if(contentType != null)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = contentType.ToLower();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(contentType.Equals(TypeHTML))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isHtml = true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/CODE&gt;
&lt;P&gt;Until next time,&lt;BR&gt;-- DK&lt;/P&gt;
&lt;P&gt;&lt;FONT size=1&gt;Disclaimer(s):&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;BR&gt;Some of the information contained within this post may be in relation to beta software.&amp;nbsp; Any and all details are subject to change.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=412378" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category></item><item><title>Exploring the NetCF Web Crawler sample (Visual Studio .NET 2003) - Part II: Updating the UI</title><link>http://blogs.msdn.com/davidklinems/archive/2005/03/21/400102.aspx</link><pubDate>Mon, 21 Mar 2005 23:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:400102</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/400102.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=400102</wfw:commentRss><description>&lt;p&gt;A couple of weeks ago, I discussed &lt;A href="http://blogs.msdn.com/davidklinems/archive/2005/03/08/389698.aspx"&gt;link tracking in the NetCF Web Crawler sample&lt;/a&gt; from Visual Studio .NET 2003.&amp;nbsp; Today, I would like to use the Web Crawler sample to discuss updating an application's user interface from a worker thread.&lt;/p&gt; &lt;p&gt;When updating user interface elements, it is very important to perform the tasks while running in the context of the thread that created the controls.&amp;nbsp; One side effect of attempting to modify controls from a different thread are application hangs.&amp;nbsp; This is most often seen when attempting to update a control (ex: modify it's Text property) in a asynchronous method callback.&amp;nbsp; While callback methods typically live in the class that owns the controls, they are most often called by a thread that was created by another piece of code (the NetCF HTTP client class library, for example).&amp;nbsp; When UI updates are attempted from this callback, application hangs may occur.&lt;/p&gt; &lt;p&gt;The way to avoid these side effects is to marshal the callback calls to your user interface's thread context.&amp;nbsp; This can be achived using the Invoke method of the System.Windows.Forms.Control class.&amp;nbsp; The Web Crawler example uses this technique to provide runtime status to the user.&lt;/p&gt; &lt;p&gt;NOTE: The code in this post has been edited for clarity and to reduce size.&amp;nbsp; For full sample code, please consult the files that were installed with Visual Studio .NET 2003 (\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Samples\VC#\Pocket PC\WebCrawler).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Events and event handlers&lt;br /&gt;&lt;/strong&gt;The Web Crawler's Crawler class supports a number of events for which that clients can register handlers.&amp;nbsp; To keep my example as clear as possible, I am going to focus on a very simple case -- the PageFoundEvent.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The WebCrawler.Crawler object exposes a public EventHandler field for the PageHandledEvent as shown below:&lt;/p&gt;&lt;code&gt; &lt;p&gt;public EventHandler PageFoundEvent;&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The client (WebCrawler.MainForm) registers it's event hander:&lt;/p&gt;&lt;code&gt; &lt;p&gt;// from startButton_Click&lt;br /&gt;this.crawler = new Crawler(startingPage,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; noProxy);&lt;br /&gt;this.crawler.PageFoundEvent += new EventHandler(this.HandlePageFoundEvent);&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The event handler implementation also lives in the client (WebCrawler.MainForm):&lt;/p&gt;&lt;code&gt; &lt;p&gt;private void HandlePageFoundEvent(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(CustomInvokeRequired())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.linkCount.Invoke(new EventHandler(this.HandlePageFoundEvent));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.linkCount.Text = string.Format("{0}", Int32.Parse(this.linkCount.Text)+1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(FormatException)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { }&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The HandlePageFoundEvent method first checks to see if the call was made in the context of the user interface thread by calling CustomInvokeRequired() (more on this soon).&amp;nbsp; If not (returns true), it calls the linkCount object's Invoke method to marshal the call to the user interface thread.&amp;nbsp; The HandlePageFoundEvent method is then re-called on the user interface thread.&amp;nbsp; CustomInvokeRequired() is called (returns false) and the method updates the linkCount control's Text property.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Determining if thread marshaling is required&lt;br /&gt;&lt;/strong&gt;I mentioned earlier that I would go into more detail on the web crawler's CustomInvokeRequired method (WebCrawler.MainForm).&amp;nbsp; At startup, the web crawler's MainForm object stores it's thread in a private member variable:&lt;/p&gt;&lt;code&gt; &lt;p&gt;private readonly System.Threading.Thread FormThread = System.Threading.Thread.CurrentThread;&lt;/p&gt;&lt;/code&gt; &lt;p&gt;This member is marked as readonly so that it cannot be modified.&lt;/p&gt; &lt;p&gt;When called, the CustomInvokeRequired method checks to see if the current thread is the same as the FormThread (the thread that owns the user interface):&lt;/p&gt;&lt;code&gt; &lt;p&gt;if(this.FormThread.Equals(System.Threading.Thread.CurrentThread))&lt;/p&gt;&lt;/code&gt; &lt;p&gt;If the current thread is the user interface thread (&lt;code&gt;this.FormThread.Equals(Thread.CurrentThread)&lt;/code&gt;), there is no marshaling required and CustomInvokeRequired returns false.&amp;nbsp; Otherwise, true is returned indicating that thread marshaling is needed.&lt;/p&gt; &lt;p&gt;Using this technique, the web crawler's worker thread can keep the user informed, and not cause any undesirable side effects.&lt;/p&gt; &lt;p&gt;Until next time,&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=400102" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/GUI/default.aspx">GUI</category></item><item><title>Exploring the NetCF WebCrawler sample (Visual Studio .NET 2003)</title><link>http://blogs.msdn.com/davidklinems/archive/2005/03/08/389698.aspx</link><pubDate>Tue, 08 Mar 2005 18:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:389698</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/389698.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=389698</wfw:commentRss><description>&lt;p&gt;Every so often, I talk to people about the NetCF WebCrawler sample that shipped as part of Visual Studio .NET 2003 (\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Samples\VC#\Pocket PC\WebCrawler).&amp;nbsp; One of the things I get asked about is how the sample keeps track of the pages it has visited and when it knows to stop.&amp;nbsp; The way the WebCrawler sample handles this is in how it uses the StatusCode member of the LinkInfo class.&lt;/p&gt; &lt;p&gt;The LinkInfo.StatusCode member is declared as being of type HttpStatusCode.&amp;nbsp; HttpStatusCode is an enum defined in the System.Net namespace.&amp;nbsp; Whenever a link is discovered, the WebCrawler creates an instance of LinkInfo and stores the Url in the LinkPath member.&amp;nbsp; It also sets the value of StatusCode to 0.&amp;nbsp; As shown in the code fragment, below, 0 is being used to indicate that a connection to this Url has not been attempted.&amp;nbsp; There are also two other special values noted: -1 and -2, which denote application specific special case values.&lt;/p&gt; &lt;p&gt;NOTE: The code in this post has been edited for clarity and to reduce size.&amp;nbsp; For full sample code, please consult the files that were installed with Visual Studio .NET 2003.&lt;/p&gt;&lt;code&gt; &lt;p&gt;public class LinkInfo&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// The link's address (ex: &lt;a href="http://www.microsoft.com/"&gt;http://www.microsoft.com&lt;/a&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public readonly string LinkPath;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// HttpStatusCode received when we attempted to&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// connect to the link&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// NOTE: Other possible values&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ///&amp;nbsp; 0 == no connection attempted&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// -1 == generic failure&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// -2 == link does not point to html data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public HttpStatusCode StatusCode;&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Each LinkInfo object that is created by the WebCrawler (in WebCrawler.Crawler.GetPageLinks) is stored for future reference -- the WebCrawler sample uses a Hashtable for storage.&amp;nbsp; Each Url found by the WebCrawler is stored only once.&amp;nbsp; If the same Url is identified later in the crawl, the new instance is discarded.&amp;nbsp; This helps to avoid circular crawls (a page that links to another, which links back to the first).&lt;/p&gt;&lt;code&gt; &lt;p&gt;// add the link&lt;br /&gt;links.Add(linkString, new LinkInfo(linkString, (HttpStatusCode)0));&lt;/p&gt;&lt;/code&gt; &lt;p&gt;In the above, you can see the use of 0 (not visited) for the LinkInfo.StatusCode value.&amp;nbsp; As mentioned before, System.Net.HttpStatusCode is an enum and since enums are defined as being of an integer type (ex: short, int, etc), integer values can be cast to the enum type (in this case HttpStatusCode).&lt;/p&gt; &lt;p&gt;Later in the crawl, the discovered links are read from the Hashtable and if their StatusCode is equal to 0, an &lt;A href="http://blogs.msdn.com/davidklinems/archive/2004/12/07/277876.aspx"&gt;HTTP header request&lt;/a&gt; is issued (in WebCrawler.Crawler.PageIsHtml):&lt;/p&gt;&lt;code&gt; &lt;p&gt;// create the web request&lt;br /&gt;HttpWebRequest req = (HttpWebRequest)WebRequest.Create(pageAddress);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;//&amp;nbsp; get headers only&lt;br /&gt;req.Method = "HEAD";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// make the connection&lt;br /&gt;HttpWebResponse resp = (HttpWebResponse)req.GetResponse();&lt;/p&gt; &lt;p&gt;// read the headers&lt;br /&gt;WebHeaderCollection headers = resp.Headers;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// check the content type&lt;br /&gt;string contentType = headers["Content-type"];&lt;br /&gt;if(contentType != null)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = contentType.ToLower();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(contentType.Equals(TypeHTML))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isHtml = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;// get the status code (should be 200)&lt;br /&gt;status = resp.StatusCode;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// close the connection&lt;br /&gt;resp.Close();&lt;/p&gt;&lt;/code&gt; &lt;p&gt;In the above example TypeHTML is defined as being "text/html".&lt;/p&gt; &lt;p&gt;The result of the header request (HttpWebRequest.StatusCode) is stored in the link's LinkInfo.StatusCode field.&amp;nbsp; If the request fails, the exception handler (not shown) stores the value of WebException.Response.StatusCode or -1 (generic error) if the exception is anything other than a WebException.&amp;nbsp; If the Content-Type header reports anything other than "text/html", the caller sets LinkInfo.Status code to -2 (defined in LinkInfo as denoting a link to non-HTML data).&lt;/p&gt; &lt;p&gt;Once it has been determined that the Url points to HTML, the crawler requests the full page, stores the StatusCode and if successful searches for additional links (in WebCrawler.Crawler.Crawl).&amp;nbsp; As you can se below, the WebCrawler sample supports links that are found in the a, frame, area and link HTML tags.&lt;/p&gt;&lt;code&gt; &lt;p&gt;string pageData = "";&lt;br /&gt;li.StatusCode = GetPageData(ref pageUri,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out pageData);&lt;br /&gt;// if we successfully retrieved the page data&lt;br /&gt;if(HttpStatusCode.OK == li.StatusCode)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &amp;lt;a href=&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetPageLinks(pageUri,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pageData,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "a",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "href",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; found);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &amp;lt;frame src=&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetPageLinks(pageUri,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pageData,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "frame",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "src",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; found);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &amp;lt;area href=&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetPageLinks(pageUri,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pageData,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "area",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "href",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; found);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &amp;lt;link href=&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetPageLinks(pageUri,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pageData,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "link",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "href",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; found);&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Once the crawler finds that there are no more unvisited links (LinkInfo.StatusCode == 0) in it's Hashtable, it stops.&lt;/p&gt; &lt;p&gt;It is important to note that the WebCrawler sample keeps a master Hashtable (not shown in the above exampled) that holds all of the Urls that it discovers (regardless of whether or not it was able to successfully visit them) as well as a temporary Hashtable used while collecting links from a Url.&amp;nbsp; This technique is used to avoid modifying the list of discovered links while iterating through them.&amp;nbsp; Once all links have been discovered, the temporary Hashtable is merged with the master Hashtable and is discarded, to be cleaned up by the Garbage Collector.&lt;/p&gt; &lt;p&gt;As we have seen, the WebCrawler uses it's master Hashtable to keep track of the Urls it has found and uses the data stored in the Urls associated LinkInfo object to determine if it has previously visited the link.&amp;nbsp; Like I mentioned earlier, this post touches on a very small part of the WebCrawler sample code -- for the complete sample, please consult your Visual Studio .NET 2003 installation (\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Samples\VC#\Pocket PC\WebCrawler).&lt;/p&gt; &lt;p&gt;Until next time,&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=389698" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category></item><item><title>Accessing a WebService's WebRequest and WebResponse in NetCF</title><link>http://blogs.msdn.com/davidklinems/archive/2005/01/31/364279.aspx</link><pubDate>Tue, 01 Feb 2005 04:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:364279</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/364279.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=364279</wfw:commentRss><description>&lt;p&gt;One common question regarding the .NET Compact Framework involves the availability of the WebRequest and WebResponse objects used by the SOAP client when making a web service call.&amp;nbsp; If you are using version 1 of the .NET Compact Framework (1.0.2268.0), these objects are not available to your code.&amp;nbsp; Since the release of Service Pack 1 (1.0.3111.0), it is become possible to gain access to these objects.&lt;/p&gt; &lt;p&gt;Why access the underlying request and response?&lt;br /&gt;&lt;br /&gt;There are a number of reasons why access to the WebRequest and/or WebResponse is useful.&amp;nbsp; Custom headers can be used for simple client identification, cookies can be implemented, etc.&amp;nbsp; I'm sure many other interesting scenarios will come to mind.&lt;/p&gt; &lt;p&gt;A&amp;nbsp;few notes...&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Most web service client proxy classes are autogenerated (either by WSDL.exe or Add Web Reference in Visual Studio .NET).&amp;nbsp; Changes to the generated code files will be lost the next time they are regenerated (ex: "Update web reference" in Visual Studio). &lt;li&gt;GetWebRequest and GetWebResponse are protected methods on WebClientProtocol (a parent class to SoapHttpClientProtocol) and are called by the SOAP client class library, not by application code.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Keeping the above in mind, I recommend implementing your customizations in a derived class.&amp;nbsp; Reference your derived class in your application, instead of the generated one.&amp;nbsp; This way, you can update your web service client proxy as often as you need, without risk of losing your custom code.&lt;/p&gt; &lt;p&gt;Below is a simple example that sets a custom HTTP header on the underlying WebRequest.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Web service client proxy&lt;br /&gt;&lt;code&gt;public class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // autogenerated code will be in here&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Derived proxy class&lt;br /&gt;&lt;code&gt;public class MyCustomWebService : MyWebService&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String m_HeaderName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String m_HeaderValue;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //----------------&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // GetWebRequest&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Called by the SOAP client class library&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //----------------&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override WebRequest GetWebRequest(Uri uri)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // call the base class to get the underlying WebRequest object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(uri);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(null != this.m_HeaderName)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the header&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; req.Headers.Add(this.m_HeaderName, this.m_HeaderValue);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return the WebRequest to the caller&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (WebRequest)req;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //----------------&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // SetRequestHeader&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Sets the header name and value that GetWebRequest will add to the&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // underlying request used by the SOAP client when making the &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // we method call&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //----------------&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void SetRequestHeader(String headerName, String headerValue)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.m_HeaderName = headerName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.m_HeaderValue = headerValue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; &lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Simple client application&lt;br /&gt;&lt;code&gt;class MyApplication&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create the web service client object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyCustomWebService service = new MyCustomWebService();&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the custom header&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; service.SetRequestHeader("ACustomHeader", "Go Huskies!");&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // call the desired web service method&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Object result = service.ExampleMethod( ... );&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;GetWebResponse can be overriden similarly.&amp;nbsp; As you can see, it is easy to gain access to the underlying WebRequest and WebResponse objects.&amp;nbsp; Please remember that GetWebRequest and GetWebResponse are not called by application code -- they are methods you implement for the SOAP client to call.&lt;/p&gt; &lt;p&gt;Have fun!&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;[Edit: fix version number]&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=364279" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Determining the IP address of your device</title><link>http://blogs.msdn.com/davidklinems/archive/2005/01/18/355471.aspx</link><pubDate>Tue, 18 Jan 2005 21:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:355471</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/355471.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=355471</wfw:commentRss><description>&lt;p&gt;Device's do not typically register a name with the network.&amp;nbsp; This means you cannot just use a name to connect to or ping the device.&amp;nbsp; Back in July 2004, I &lt;A href="http://blogs.msdn.com/davidklinems/archive/2004/07/06/174475.aspx"&gt;posted&lt;/a&gt; a snippet that shows all of the IP addresses (IPv4 and IPv6) that equate to "localhost".&amp;nbsp; Today, I am posting a slightly modified version that displays the IP addresses that you can use to connect to your device.&lt;/p&gt; &lt;p&gt;Please note: I intentionally did not make a user interface to keep the snippet as small as possible.&amp;nbsp; Also, since many devices do not come with a command prompt, I did not use Console.WriteLine.&lt;/p&gt;&lt;code&gt; &lt;p&gt;using System;&lt;br /&gt;using System.Net;&lt;br /&gt;using System.Windows.Forms;&lt;/p&gt; &lt;p&gt;class WhoAmI&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPHostEntry he = Dns.Resolve(Dns.GetHostName());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(IPAddress addr in he.AddressList)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show(addr.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(Exception e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show(String.Format("Caught: {0}\r\n{1}", e.GetType().ToString(), e.Message));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;That's all there is to it!&amp;nbsp; I use code based on the above when running the &lt;A href="http://blogs.msdn.com/windowsmobile"&gt;Windows Mobile&lt;/a&gt;&amp;nbsp;emulator as a &lt;A href="http://blogs.msdn.com/windowsmobile/archive/2004/12/10/279834.aspx"&gt;standalone&lt;/a&gt; application (with ethernet enabled).&lt;/p&gt; &lt;p&gt;Enjoy!&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=355471" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Determining the type of data pointed to by a Url - VB.NET version</title><link>http://blogs.msdn.com/davidklinems/archive/2004/12/07/277979.aspx</link><pubDate>Wed, 08 Dec 2004 01:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:277979</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/277979.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=277979</wfw:commentRss><description>&lt;p&gt;Earlier today, I posted &lt;A href="http://blogs.msdn.com/davidklinems/archive/2004/12/07/277876.aspx"&gt;an example of some Visual C# code that checks the type of the data pointed to by a Url&lt;/a&gt;.&amp;nbsp; I was thinking that it might be nice to post a Visual Basic .NET equivalent...&lt;/p&gt; &lt;p&gt;This version is a direct port of the Visual C# code and comes with the same caveat:&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;"&lt;strong&gt;&lt;em&gt;Please note&lt;/em&gt;&lt;/strong&gt;: To keep this example as small as possible, only minimal error checking is performed - any real-world implementation would need to do much more than what I show here."&lt;/p&gt;&lt;/blockquote&gt;&lt;code&gt; &lt;p&gt;Imports System&lt;br /&gt;Imports System.Net&lt;/p&gt; &lt;p&gt;module Module1&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sub Main(args as String())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(args.Length &amp;lt;&amp;gt; 1) then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Please specify a url path.")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end if&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' display the content type for the url&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim url as String = args(0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(String.Format("Url : {0}", url))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(String.Format("Type: {0}", GetContentType(url)))&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end sub&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function GetContentType(url as String) as String&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim response as HttpWebResponse = nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim contentType as String = ""&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' create the request&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim request as HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' instruct the server to return headers only&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; request.Method = "HEAD"&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' make the connection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = CType(request.GetResponse(), HttpWebResponse)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' read the headers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim headers as WebHeaderCollection = response.Headers&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' get the content type&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = headers("Content-type")&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch e as WebException&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' we encountered a problem making the request&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '&amp;nbsp; (server unavailable (404), unauthorized (401), etc)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = CType(e.Response, HttpWebResponse)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' return the message from the exception&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = e.Message&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch e as NotSupportedException&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' this will be caught if WebRequest.Create encounters a uri&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '&amp;nbsp; that it does not support (ex: mailto)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' return a friendly error message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = "Unsupported Uri"&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch e as UriFormatException&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' the url is not a valid uri&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' return a friendly error message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = "Malformed Uri"&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not (response is nothing) then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.Close()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end if&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return contentType&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end function&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;end module&lt;/p&gt;&lt;/code&gt; &lt;p&gt;As with the &lt;A href="http://blogs.msdn.com/davidklinems/archive/2004/12/07/277876.aspx"&gt;Visual C# version&lt;/a&gt;, the above code can be compiled and run on either the .NET Framework or the .NET Compact Framework.&lt;/p&gt; &lt;p&gt;Take care,&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=277979" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Determining the type of data pointed to by a Url</title><link>http://blogs.msdn.com/davidklinems/archive/2004/12/07/277876.aspx</link><pubDate>Tue, 07 Dec 2004 21:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:277876</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/277876.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=277876</wfw:commentRss><description>&lt;p&gt;Have you ever wanted to know what type of file was being pointed to by a given url before clicking the link?&amp;nbsp; Maybe you are writing an application that needs to filter out certain types of links.&amp;nbsp; A web crawler is a good example of an application which needs to do such link filtering (skip links to graphics, audio, zip files, etc).&lt;/p&gt; &lt;p&gt;In order to check the type of data pointed to by a url, you are going to need to issue a request to the server.&amp;nbsp; Normally, this involves receiving the entire page or file at that location.&amp;nbsp; This can be a time consuming proposition, especially over slow network connections, and defeats the purpose of allowing your application to filter out undesired links.&lt;/p&gt; &lt;p&gt;The solution is to issue a request to the server, asking only for the HTTP headers.&amp;nbsp; This "HEAD" request is small, fast (does not transfer file contents) and provides you with exactly the data your application needs.&amp;nbsp; While there are plenty of interesting headers, the header we are interested in today is "Content-type".&lt;/p&gt; &lt;p&gt;Below is a simple console application that takes a url path and displays the value of the content-type header.&amp;nbsp; &lt;strong&gt;&lt;em&gt;Please note&lt;/em&gt;&lt;/strong&gt;: To keep this example as small as possible, only minimal error checking is performed -&amp;nbsp;any real-world implementation would need to do much more than what I show here.&lt;/p&gt;&lt;code&gt; &lt;p&gt;using System;&lt;br /&gt;using System.Net;&lt;/p&gt; &lt;p&gt;class ContentType&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main(String[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(args.Length != 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Please specify a url path.");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // display the content type for the url&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String url = args[0];&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(String.Format("Url : {0}", url));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(String.Format("Type: {0}", GetContentType(url)));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static String GetContentType(String url)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebResponse response = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String contentType = "";&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create the request&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // instruct the server to return headers only&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; request.Method = "HEAD";&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // make the connection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = request.GetResponse() as HttpWebResponse;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // read the headers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WebHeaderCollection headers = response.Headers;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the content type&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = headers["Content-type"];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(WebException e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // we encountered a problem making the request&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; (server unavailable (404), unauthorized (401), etc)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = e.Response as HttpWebResponse;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return the message from the exception&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = e.Message;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(NotSupportedException)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this will be caught if WebRequest.Create encounters a uri&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; that it does not support (ex: mailto)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return a friendly error message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = "Unsupported Uri";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(UriFormatException)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the url is not a valid uri&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return a friendly error message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentType = "Malformed Uri";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // make sure the response gets closed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; this avoids leaking connections&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(response != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return contentType;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The above code can be compiled and run on either the .NET Framework or the .NET Compact Framework.&lt;/p&gt; &lt;p dir="ltr" style="MARGIN-RIGHT: 0px"&gt;Here's a sampling of the content types I received when running the above application against a handful of urls:&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p dir="ltr" style="MARGIN-RIGHT: 0px"&gt;text/html&lt;br /&gt;text/html; charset=utf-8&lt;br /&gt;image/gif&lt;br /&gt;application/octet-stream&lt;br /&gt;text/plain&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Enjoy!&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;br /&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=277876" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Simpifying socket exception handling</title><link>http://blogs.msdn.com/davidklinems/archive/2004/11/04/252689.aspx</link><pubDate>Fri, 05 Nov 2004 05:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:252689</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/252689.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=252689</wfw:commentRss><description>&lt;p&gt;Remembering numeric error codes is hard.&amp;nbsp; Unless the error handling code is well documented, code reviews take longer and maintenance is more difficult as you may need to consult reference manuals, native code header files or online help frequently.&lt;/p&gt; &lt;p&gt;Socket errors are particularly hard for me to remember.&amp;nbsp; To help myself out, I have collected Windows Sockets error codes into a couple of enums.&lt;/p&gt; &lt;p&gt;The first enum, SocketErrorCodes uses friendly descriptions based on the following &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;819124"&gt;Microsoft Support article &lt;/a&gt;.&amp;nbsp; For detailed descriptions of the error codes, please refer to this article or a Windows Sockets reference.&lt;/p&gt;&lt;code&gt; &lt;p&gt;public enum SocketErrorCodes&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; InterruptedFunctionCall&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10004,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PermissionDenied&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10013,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BadAddress&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10014,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; InvalidArgument&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10022,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TooManyOpenFiles&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10024,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResourceTemporarilyUnavailable&amp;nbsp; = 10035,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationNowInProgress&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10036,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationAlreadyInProgress&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10037,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SocketOperationOnNonSocket&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10038,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DestinationAddressRequired&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10039,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessgeTooLong&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10040,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WrongProtocolType&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10041,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BadProtocolOption&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10042,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProtocolNotSupported&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10043,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SocketTypeNotSupported&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10044,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationNotSupported&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10045,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProtocolFamilyNotSupported&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10046,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AddressFamilyNotSupported&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10047,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AddressInUse&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10048,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AddressNotAvailable&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10049,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NetworkIsDown&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10050,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NetworkIsUnreachable&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10051,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NetworkReset&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10052,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionAborted&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10053,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionResetByPeer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10054,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NoBufferSpaceAvailable&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10055,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AlreadyConnected&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10056,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NotConnected&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10057,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CannotSendAfterShutdown&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10058,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionTimedOut&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10060,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ConnectionRefused&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10061,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HostIsDown&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10064,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HostUnreachable&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10065,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TooManyProcesses&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10067,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NetworkSubsystemIsUnavailable&amp;nbsp;&amp;nbsp; = 10091,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UnsupportedVersion&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10092,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NotInitialized&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10093,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ShutdownInProgress&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10101,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClassTypeNotFound&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10109,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HostNotFound&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11001,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HostNotFoundTryAgain&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11002,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NonRecoverableError&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11003,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NoDataOfRequestedType&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11004&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The second, WinSockErrorCodes, uses the symbolic names you see in native WinSock application code.&lt;/p&gt;&lt;code&gt; &lt;p&gt;public enum WinSockErrorCodes&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEINTR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10004,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEACCES&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10013,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEFAULT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10014,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEINVAL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10022,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEMFILE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10024,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEWOULDBLOCK&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10035,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEINPROGRESS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10036,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEALREADY&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10037,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENOTSOCK&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10038,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEDESTADDRREQ&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10039,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEMSGSIZE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10040,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEPROTOTYPE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10041,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENOPROTOOPT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10042,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEPROTONOSUPPORT = 10043,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAESOCKTNOSUPPORT = 10044,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEOPNOTSUPP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10045,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEPFNOSUPPORT&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10046,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEAFNOSUPPORT&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10047,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEADDRINUSE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10048,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEADDRNOTAVAIL&amp;nbsp;&amp;nbsp; = 10049,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENETDOWN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10050,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENETUNREACH&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10051,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENETRESET&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10052,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAECONNABORTED&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10053,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAECONNRESET&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10054,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENOBUFS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10055,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEISCONN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10056,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAENOTCONN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10057,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAESHUTDOWN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10058,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAETIMEDOUT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10060,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAECONNREFUSED&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10061,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEHOSTDOWN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10064,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEHOSTUNREACH&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10065,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEPROCLIM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10067,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSASYSNOTREADY&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10091,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAVERNOTSUPPORTED = 10092,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSANOTINITIALIZED&amp;nbsp; = 10093,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAEDISCON&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 10101,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSATYPE_NOT_FOUND&amp;nbsp; = 10109,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSAHOST_NOT_FOUND&amp;nbsp; = 11001,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSATRY_AGAIN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11002,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSANO_RECOVERY&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11003,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WSANO_DATA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 11004&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;I find the descriptive enum (SocketErrorCodes) most useful when I am writing new code.&amp;nbsp; The WinSockErrorCodes enum is handy when porting native code to .NET.&amp;nbsp; With either enum, I can simply cast the Int32 found in SocketException.ErrorCode to the appropriate enum to make my code easier to read and maintain.&amp;nbsp; For example:&lt;/p&gt;&lt;code&gt; &lt;p&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // code that causes a SocketException&lt;br /&gt;}&lt;br /&gt;catch(SocketException se)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SocketErrorCodes errorCode = (SocketErrorCodes)se.ErrorCode;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch(errorCode)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case SocketErrorCodes.PermissionDenied:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // error handling&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case SocketErrorCodes.AddressInUse:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // error handling&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; // etc..&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;As mentioned earlier, the data used to create the above enums can be found &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;819124"&gt;here&lt;/a&gt; .&amp;nbsp; Of course, any mistakes you may find here are entirely mine.&amp;nbsp; When in doubt, please consult the support article or a Windows Sockets reference.&lt;/p&gt; &lt;p&gt;Until next time,&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;[Edit: fix typeo]&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimer(s):&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=252689" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>Simple object remoting using the XmlSerializer</title><link>http://blogs.msdn.com/davidklinems/archive/2004/10/27/248885.aspx</link><pubDate>Thu, 28 Oct 2004 04:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:248885</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/248885.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=248885</wfw:commentRss><description>&lt;p&gt;Today, I'm going to talk about how you can use the XmlSerializer, TcpClient and TcpListener classes to create a simple remoting layer to send your custom objects from one device to another.&amp;nbsp; This post requires the .NET Compact Framework version 2 (beta 1) or the .NET Framework for desktop PCs.&lt;/p&gt; &lt;p&gt;Since NetCF doesn't support the TCP Remoting classes, you will need to setup the network connection yourself.&amp;nbsp; The serializer handles all of the data transfer.&amp;nbsp; You can use this technique to send data between any combination of systems which support the XmlSerializer and network connectivity.&lt;/p&gt; &lt;p&gt;As you can see from the code below, there isn't too much to making a simple connection, though a real application will need to be more robust and will typically need to handle bi-directional data flow.&lt;/p&gt; &lt;p&gt;Let's take a look at simple client and server code that remotes a custom object between devices.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Object&lt;br /&gt;&lt;/strong&gt;The only requirements on the object is that it is serializable.&amp;nbsp; This means that it contains a nullary constructor and all of the public fields are either read/write or are a collection (supporting the Add method).&amp;nbsp; The example we will be using is a very simple object containing a name, a team name and a player's jersey number.&lt;br /&gt;&lt;code&gt;public class Player&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String Name;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pulbic String Team;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Int32 Number;&lt;br /&gt;}&lt;/p&gt;&lt;/code&gt; &lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;&lt;br /&gt;The client application instantiates the Player object and populates it's data fields.&lt;br /&gt;&lt;code&gt;Player p = new Player();&lt;br /&gt;p.Name = "David";&lt;br /&gt;p.Team = "NetCF";&lt;br /&gt;p.Number = 43;&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Next, it creates an XmlSerializer object, informing the serializer of the type of data which will be sent.&lt;br /&gt;&lt;code&gt;XmlSerializer xs = new XmlSerializer(typeof(Player));&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Once we have our serializer, we create a TcpClient object, get connected to the remote server and acquire the stream to be used to communicate with the server.&lt;br /&gt;&lt;code&gt;TcpClient client = new TcpClient();&lt;br /&gt;client.Connect(serverAddress, serverPort);&lt;br /&gt;Stream stream = client.GetStream();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/code&gt; &lt;br /&gt;Now, we can serialize our Player object.&amp;nbsp; Since the stream we provide the serializer is a network stream, the data is sent to the server when the serializer writes the XML.&lt;br /&gt;&lt;code&gt;xs.Serialize(stream, p);&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The rest of our client is housekeeping.&amp;nbsp; We need to be sure to close our stream and client objects.&lt;br /&gt;&lt;code&gt;stream.Close();&lt;br /&gt;client.Close();&lt;/p&gt;&lt;/code&gt; &lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;&lt;br /&gt;Now let's&amp;nbsp;take a look at the server code.&lt;br /&gt;&lt;code&gt;Player p;&lt;/p&gt;&lt;/code&gt; &lt;p&gt;As with the client, we need to create an XmlSerializer object, informing the serializer of the type of data which will be received.&lt;br /&gt;&lt;code&gt;XmlSerializer xs = new XmlSerializer(typeof(Player));&lt;/p&gt;&lt;/code&gt; &lt;p&gt;Next, a listener needs to be created and started.&lt;br /&gt;&lt;code&gt;TcpListener listener = new TcpListener(port);&lt;br /&gt;listener.Start();&lt;/p&gt;&lt;/code&gt; &lt;p&gt;The listener accepts the incoming connection.&lt;br /&gt;&lt;code&gt;TcpClient client = listener.AcceptTcpClient();&lt;/p&gt;&lt;/code&gt; &lt;p&gt;And we can get the data stream from the client which was created by the call to AcceptTcpClient.&lt;br /&gt;&lt;code&gt;Stream stream = client.GetStream();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now we can deserialize the Player object sent by the remote client.&amp;nbsp; Like the client, the stream used for deserialization is a network stream.&amp;nbsp; This causes the data to be received when the serializer reads the XML.&lt;br /&gt;&lt;code&gt;p = (Player)xs.Deserialize(stream);&lt;/code&gt; &lt;/p&gt; &lt;p&gt;Again, we need to perform some housekeeping.&amp;nbsp; We need to be sure to close our stream, client and listener objects.&lt;br /&gt;&lt;code&gt;stream.Close();&lt;br /&gt;client.Close();&lt;br /&gt;listener.Close();&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And we can display the received object.&lt;br /&gt;&lt;code&gt;MessageBox.Show(String.Format("Name: {0}\r\nTeam: {1}\r\nNumber: {2}",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p.Name, p.Team, p.Number));&lt;/p&gt;&lt;/code&gt; &lt;p&gt;As mentioned earlier, the above is a very simple example of how to remote a data object using the XmlSerializer.&amp;nbsp;&amp;nbsp;The networking code for real world applications will likely be significantly more involved and handle being sent and received by both devices.&lt;/p&gt; &lt;p&gt;Enjoy!&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;[Edited to fix formatting]&lt;br /&gt;[Edited to fix typo]&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;Disclaimers:&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;br /&gt;Some of the information contained within this post may be in relation to beta software.&amp;nbsp; Any and all details are subject to change.&lt;br /&gt;&lt;/p&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=248885" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/XML/default.aspx">XML</category></item><item><title>WebExceptions, ServicePoints and Connection Limits</title><link>http://blogs.msdn.com/davidklinems/archive/2004/09/10/228169.aspx</link><pubDate>Sat, 11 Sep 2004 03:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:228169</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/228169.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=228169</wfw:commentRss><description>&lt;p&gt;Today's topic involves WebExceptions and their proper handling.&amp;nbsp; Along the way, we'll talk a little about HttpWebResponse, ServicePoint and connection limits.&lt;br /&gt;&lt;br /&gt;Whenever you write an application that communicates on the web, you inevitably run into connection issues (site moved, incorrect access credentials, insufficient privileges to view the site, etc).&amp;nbsp; .NET applications inform you of these issues by throwing a WebException when you attempt to establish your connection (by calling &lt;code&gt;HttpWebRequest.GetResponse()&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;The handling of a WebException requires a bit of care.&amp;nbsp; This brings us to the topic of resonses and connection limits.&lt;br /&gt;&lt;br /&gt;The .NET Compact Framework has a default connection limit, per ServicePoint (more on these later), of two (2).&amp;nbsp; What this means is that you can only have two open connections on a given ServicePoint at the same time.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;You may be asking what constitutes a ServicePoint.&amp;nbsp; ServicePoints are made up of the scheme (ex: http), the host (ex: &lt;a href="http://www.microsoft.com/"&gt;www.microsoft.com&lt;/a&gt;) and the port (ex:80).&amp;nbsp; Paths, query strings, etc are not taken into consideration as part of the ServicePoint.&amp;nbsp; This means that if you connect to both "folderA/page1.htm" and "folderB/page2.htm" on the same server, using the same port, you will have consumed the maximum number of connections on your service point (&lt;a href="http://www.microsoft.com/"&gt;http://www.microsoft.com:80&lt;/a&gt;, in our example).&lt;br /&gt;&lt;br /&gt;While you can increase the connection limit using the following,&lt;/p&gt; &lt;p&gt;&lt;code&gt;// set connection limit to 5&lt;br /&gt;ServicePointManger.DefaultConnectionLimit = 5;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;I only recommend doing this if the users of your application must have more than two connections to any given server open at the same time.&lt;br /&gt;&lt;br /&gt;Which brings us back to handling WebExceptions...&lt;br /&gt;&lt;br /&gt;When your application catches a WebException, the first thing you should do is extract the response:&lt;/p&gt; &lt;p&gt;&lt;code&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // http connection code&lt;br /&gt;}&lt;br /&gt;catch(WebException we)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // check the response&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebResponse response = we.Response as HttpWebResponse;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the rest will be filled in below&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;If the response is not null (Nothing in VisualBasic.NET), you can extract more information regarding the reason for the exception (from the HttpWebResponse.StatusCode property).&amp;nbsp; Once you have the data, be sure to close the response object.&amp;nbsp; This will release the connection and allow you to make another connection to the same server,&lt;/p&gt; &lt;p&gt;&lt;code&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // http connection code&lt;br /&gt;}&lt;br /&gt;catch(WebException we)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // check the response&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebResponse response = we.Response as HttpWebResponse;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(null != response)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // get the reason for the exception&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpStatusCode status = response.StatusCode;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; String description = response.StatusDescription;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // close the response&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; response.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // do any further exception processing here&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;Handling web exceptions in this way allows your application to take recovery steps (ex: re-prompt for credentials and retry the connection) and/or to display connection failure information to your customers.&lt;br /&gt;&lt;br /&gt;Earlier, I mentioned that you can change the connection limit.&amp;nbsp; If you are going to change the default value, please note that any active service points will not abide by the new limit.&amp;nbsp; To ensure that all service points use the desired limit, you should modify the connection prior to making any connections (ex: at application startup).&lt;/p&gt; &lt;p&gt;Take care,&lt;br /&gt;-- DK&lt;/p&gt; &lt;p&gt;&lt;font size="1"&gt;[Edit: Fixed formatting &amp;amp;&amp;amp; add missing null check]&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font size="1"&gt;Disclaimers:&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;br /&gt;Some of the information contained within this post may be in relation to beta software.&amp;nbsp; Any and all details are subject to change.&lt;br /&gt;&lt;/p&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=228169" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category></item><item><title>NetCF application hanging when remote server disconnects from the network?</title><link>http://blogs.msdn.com/davidklinems/archive/2004/07/29/201164.aspx</link><pubDate>Thu, 29 Jul 2004 22:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:201164</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/201164.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=201164</wfw:commentRss><description>&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;I've been seeing a few reports of NetCF web service applications hanging when the target server disconnects from the &lt;/FONT&gt;&lt;FONT face=Arial&gt;network.&amp;nbsp; If you are experiencing this, I may have a solution for you.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;What we have found is that if the server disconnects before sending the initial HTTP response to the client (maybe &lt;/FONT&gt;&lt;FONT face=Arial&gt;it never actually received the HTTP request, or failed just prior to sending the response), NetCF (v1 and v2 beta1) &lt;/FONT&gt;&lt;FONT face=Arial&gt;will wait indefinitely for the response to be received.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Many of you may note that there is a Timeout property on the SoapHttpClientProtocol class (the parent class of each &lt;/FONT&gt;&lt;FONT face=Arial&gt;of your web service client proxy classes).&amp;nbsp; This timeout does not come into play here (it applies to individual &lt;/FONT&gt;&lt;FONT face=Arial&gt;reads and writes between the client and server &lt;EM&gt;after&lt;/EM&gt; the client receives the initial server &lt;/FONT&gt;&lt;FONT face=Arial&gt;response -- it does not specify the maximum amount of time for the call to complete).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Please note that since mobile devices typically operate on slow connections, timing out the entire request would &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;likely cause most, if not all web service calls to fail and that sometimes your application may &lt;EM&gt;look&lt;/EM&gt; &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;hung and then eventually, start responding again (if the server was just really slow in responding).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If you are encountering this issue, the following workaround may be helpful.&amp;nbsp; Please note that while this code &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;utilizes web services, the workaround applies equally to the HTTP client (HttpWebRequest).&amp;nbsp; Also note that this code &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;implements a timeout on the complete method call and the timer will need to wait long enough to receive &lt;EM&gt;all&lt;/EM&gt; &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;of the expected data from the server (I recommend a few minutes in most cases).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;orignal code&lt;BR&gt;&lt;/STRONG&gt;&lt;FONT face="Courier New" color=#800080&gt;&lt;STRONG&gt;MyService service = new MyService();&lt;BR&gt;service.Method( /* args */ );&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;workaround code&lt;BR&gt;&lt;/STRONG&gt;&lt;FONT face="Courier New" color=#800080&gt;&lt;STRONG&gt;System.Threading.Timer timer;&lt;BR&gt;Int32 timeout = 60000;&lt;BR&gt;MyService service = new MyService();&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;private void CallService()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the timeout to longer than you reasonably expect a user to wait for the call to complete&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.timeout = 600000;&amp;nbsp;&amp;nbsp; // NOTE: this is a really long timeout&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create the timer&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.timer = new System.Threading.Timer(new TimerCallback(TimeoutHandler), &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.timeout);&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // call the web service method&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.service.Method( /* args */ );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(Exception e)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // dispose of the timer&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.timer.Dispose();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // handle failure&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO: perform any required cleanup and/or user notification, etc&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;private void TimeoutHandler(Object obj)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; // we have waited long enough for the server to respond&lt;BR&gt;&amp;nbsp;&amp;nbsp; //&amp;nbsp; abort the call&lt;BR&gt;&amp;nbsp;&amp;nbsp; this.service.Abort();&lt;BR&gt;}&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Hope this helps!&lt;BR&gt;-- DK&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=1&gt;Disclaimers:&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;BR&gt;Some of the information contained within this post may be in relation to beta software.&amp;nbsp; Any and all details are subject to change.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=201164" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category></item><item><title>NTLM authentication support in NetCF</title><link>http://blogs.msdn.com/davidklinems/archive/2004/07/18/187038.aspx</link><pubDate>Mon, 19 Jul 2004 06:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:187038</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/187038.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=187038</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Many folks have asked the .NET Compact Framework team when our HTTP client was going to support NTLM authentication.&amp;nbsp; For version 1 (and all service packs) our answer was: 'Sorry, we do not support NTLM.&amp;nbsp; You may wish to locate a third party solution or write the auth code yourself...'.&amp;nbsp; Not too cool.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;With the beta 1 release of NetCF version 2, NTLM support is here!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If you have previously protected your web site / service using Digest authentication, all you need to do is enable NTLM on your server, install NetCF v2 on your clients and you'll authenticate using NTLM.&amp;nbsp; As long as your client application collects credentials from the user and places them into a NetworkCredential object, you're set.&amp;nbsp; The HTTP client will authenticate using whichever is the most secure method (Negotiate, NTLM, Digest, Basic) supported by the server.&amp;nbsp; The code fragment, below, shows the construction and use of a NetworkCredential object.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;using System.Net;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;public void SetCredentials(HttpWebRequest request, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String userName,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String password,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String domain)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // construct the credentials object&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NetworkCredential credentials = new NetworkCredential(userName,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; password,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; domain);&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#800080&gt;&lt;STRONG&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the credentials on the request&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; request.Credentials = credentials;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;}&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Nothing to it!&amp;nbsp; Your client will now authenticate to your server using the most secure method available.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Please note, if your device has NetCF v1 &lt;STRONG&gt;and&lt;/STRONG&gt; v2 installed, you must target your application to version 2 for NTLM authentication to occur.&amp;nbsp; This can be done by:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Building your application against the v2 beta&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Uninstall v1 from your device (not possible on PPC 2003 devices, as v1 is installed in ROM)&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Construct an application configuration file for your executable, instructing it to run against the v2 beta&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Option 1 is the simplest and ensures that your application always has NTLM support available.&lt;BR&gt;Options 2 and 3 provide NTLM support for existing applications by retargeting them to the NetCF v2 runtime.&amp;nbsp; (I will talk more about application configuration file support in NetCF v2 in a future post.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;-- DK&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=1&gt;Disclaimers:&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;BR&gt;Some of the information contained within this post may be in relation to beta software.&amp;nbsp; Any and all details are subject to change.&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;BR&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=187038" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category></item><item><title>IPv6 and the NetCF v2 beta</title><link>http://blogs.msdn.com/davidklinems/archive/2004/07/06/174475.aspx</link><pubDate>Tue, 06 Jul 2004 23:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:174475</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/174475.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=174475</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;One of the new features of the .NET Compact Framework v2 beta is support for IPv6.&amp;nbsp; Unlike the full .NET Framework, &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;you do not need to explicitly enable IPv6 in NetCF -- if your device has support for IPv6 installed, it will be &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;available to NetCF applications.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;On devices supporting both IPv6 and IPv4 addressing, when resolving a host (localhost, in this example) the IPv6 &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;addresses are always listed first in the resulting IPHostEntry.AddressList field.&amp;nbsp; &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;The code below resolves the local machine (via "localhost") and displays the addresses as they appear in the &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;IPHostEntry.AddressList field:&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New" color=#800080&gt;&lt;STRONG&gt;using System;&lt;BR&gt;using System.Net;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&lt;STRONG&gt;public class TestClass&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPHostEntry hostent = Dns.Resolve("localhost");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(IPAddress addr in hostent.AddressList)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(String.Format("{0} [{1}]", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addr.ToString(), &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addr.AddressFamily.ToString()));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(Exception e)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(String.Format("Caught: {0}", e.GetType().ToString()));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(e.Message);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Output from above sample code:&lt;BR&gt;&lt;FONT face="Courier New" color=#800080&gt;::1 [InterNetworkV6]&lt;BR&gt;127.0.0.1 [InterNetwork]&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Of course, resolving localhost is not very interesting -- replacing "localhost" with my machine name yields a better example &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;(actual addresses have been removed):&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800080 size=2&gt;&amp;lt;&amp;lt;IPv6 over IPv4&amp;gt;&amp;gt; [InterNetworkV6]&lt;BR&gt;&amp;lt;&amp;lt;IPv6 #1&amp;gt;&amp;gt; [InterNetworkV6]&lt;BR&gt;&amp;lt;&amp;lt;IPv6 #2&amp;gt;&amp;gt; [InterNetworkV6]&lt;BR&gt;&amp;lt;&amp;lt;IPv4 #1&amp;gt;&amp;gt; [InterNetwork]&lt;BR&gt;&amp;lt;&amp;lt;IPv4 #2&amp;gt; [InterNetwork]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Note: The above system has two network adapters.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This behavior effects how the HTTP client attempts to communicate with a remote server -- if the remote machine supports IPv6, the v6 address will be tried first.&amp;nbsp; If you wish to force the HTTP client to use an IPv4 address, you will need to resolve the host yourself and then replace the host name with it's corresponding v4 address.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Until next time.&lt;BR&gt;-- DK&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=1&gt;Disclaimers:&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;BR&gt;The information contained within this post is in relation to beta software.&amp;nbsp; Any and all details are subject to change.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=174475" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category></item><item><title>Why do I get SocketExceptions on NetCF when setting some socket options?</title><link>http://blogs.msdn.com/davidklinems/archive/2004/06/25/166208.aspx</link><pubDate>Fri, 25 Jun 2004 19:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:166208</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/166208.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=166208</wfw:commentRss><description>&lt;p&gt;&lt;font face="Arial" size="2"&gt;I am frequently asked why NetCF applications encounter a SocketException when attempting to use some socket options, when applications written to the full .NET Framework do not.&amp;nbsp; The companion question is invariably "Is this a bug in NetCF?".&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Arial" size="2"&gt;If the result is &lt;strong&gt;WSAENOPROTOOPT&lt;/strong&gt; (&lt;strong&gt;10042&lt;/strong&gt;), what we are seeing is limitations of the operating system -- in this case, Windows CE -- so the answer is “no, this is not a bug, it is a limiation of the underlying operating system.“&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Arial" size="2"&gt;Since the beginning, the .NET Compact Framework was designed to be portable -- run on more than one operating system.&amp;nbsp; Because of this, we did not limit the available options in the SocketOptionNames enum.&amp;nbsp; When calling Socket.GetSocketOption() or Socket.SetSocketOption(), the request is forwarded on to the operating system to do the work.&amp;nbsp; If the result is a failure, the return code is wrapped into a &lt;strong&gt;SocketException&lt;/strong&gt; and thrown.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Arial" size="2"&gt;The list of socket options which you can expect to throw, as described above, can be seen below (taken from the Windows CE API reference).&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;font face="Arial"&gt;&lt;strong&gt;GetSocketOption&lt;/strong&gt;&lt;br /&gt;BSD options not supported for &lt;b&gt;getsockopt&lt;/b&gt; are as follows.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;div class="tablediv"&gt; &lt;table class="dtTABLE" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr valign="top"&gt; &lt;th width="33%"&gt;&lt;font face="Arial" size="2"&gt;Value &lt;/font&gt;&lt;/th&gt; &lt;th width="26%"&gt;&lt;font face="Arial" size="2"&gt;Type &lt;/font&gt;&lt;/th&gt; &lt;th width="41%"&gt;&lt;font face="Arial" size="2"&gt;Description &lt;/font&gt;&lt;/th&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_RCVLOWAT &lt;/font&gt;&lt;/td&gt; &lt;td width="26%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="41%"&gt;&lt;font face="Arial" size="2"&gt;Retrieves &lt;b&gt;recv&lt;/b&gt; low watermark. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_RCVTIMEO &lt;/font&gt;&lt;/td&gt; &lt;td width="26%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="41%"&gt;&lt;font face="Arial" size="2"&gt;Retrieves &lt;b&gt;recv&lt;/b&gt; time-out value.&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_SNDLOWAT &lt;/font&gt;&lt;/td&gt; &lt;td width="26%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="41%"&gt;&lt;font face="Arial" size="2"&gt;Retrieves send low watermark. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_SNDTIMEO &lt;/font&gt;&lt;/td&gt; &lt;td width="26%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="41%"&gt;&lt;font face="Arial" size="2"&gt;Retrieves time-out value for send.&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;TCP_MAXSEG &lt;/font&gt;&lt;/td&gt; &lt;td width="26%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="41%"&gt;&lt;font face="Arial" size="2"&gt;RetrievesTCP maximum-segment size. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;font face="Arial" size="2"&gt;Note: The above table taken from the MSDN documentation for &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcewinsk/html/_wcesdk_getsockopt.asp"&gt;getsockopt&lt;/a&gt;&lt;/strong&gt;.&lt;/font&gt;&lt;/div&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;font face="Arial"&gt;&lt;strong&gt;SetSocketOption&lt;/strong&gt;&lt;br /&gt;The following table shows BSD options not supported for &lt;b&gt;setsockopt&lt;/b&gt; .&lt;/font&gt;&lt;/p&gt; &lt;div class="tablediv"&gt; &lt;table class="dtTABLE" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr valign="top"&gt; &lt;th width="33%"&gt;&lt;font face="Arial" size="2"&gt;Value &lt;/font&gt;&lt;/th&gt; &lt;th width="24%"&gt;&lt;font face="Arial" size="2"&gt;Type &lt;/font&gt;&lt;/th&gt; &lt;th width="43%"&gt;&lt;font face="Arial" size="2"&gt;Description &lt;/font&gt;&lt;/th&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_ACCEPTCONN &lt;/font&gt;&lt;/td&gt; &lt;td width="24%"&gt;&lt;font face="Arial" size="2"&gt;BOOL &lt;/font&gt;&lt;/td&gt; &lt;td width="43%"&gt;&lt;font face="Arial" size="2"&gt;Sets socket listening.&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_RCVLOWAT &lt;/font&gt;&lt;/td&gt; &lt;td width="24%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="43%"&gt;&lt;font face="Arial" size="2"&gt;Sets recv low watermark. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_RCVTIMEO &lt;/font&gt;&lt;/td&gt; &lt;td width="24%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="43%"&gt;&lt;font face="Arial" size="2"&gt;Sets time-out for recv. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_SNDLOWAT &lt;/font&gt;&lt;/td&gt; &lt;td width="24%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="43%"&gt;&lt;font face="Arial" size="2"&gt;Sets send low watermark. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_SNDTIMEO &lt;/font&gt;&lt;/td&gt; &lt;td width="24%"&gt;&lt;font face="Arial" size="2"&gt;int &lt;/font&gt;&lt;/td&gt; &lt;td width="43%"&gt;&lt;font face="Arial" size="2"&gt;Sets time-out value for send. &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt; &lt;td width="33%"&gt;&lt;font face="Arial" size="2"&gt;SO_TYPE &lt;/font&gt;&lt;/td&gt; &lt;td width="24%"&gt;&lt;font face="Arial" size="2"&gt;Int &lt;/font&gt;&lt;/td&gt; &lt;td width="43%"&gt;&lt;font face="Arial"&gt;&lt;font size="2"&gt;Sets socket type.&lt;/font&gt; &lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;font face="Arial"&gt;Note: The above table taken from the MSDN documentation for &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcewinsk/html/_wcesdk_setsockopt.asp"&gt;setsockopt&lt;/a&gt;&lt;/strong&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/div&gt; &lt;p&gt;&lt;font face="Arial" size="2"&gt;If you are writing portable code (runs on both the .NET Framework and the .NET Compact Framework), you will need to handle this exception and change your application behavior as needed.&amp;nbsp; For example, you may wish to disable controls related to expert socket features (ex: Receive Timeout).&amp;nbsp; The code fragment below shows&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#800080" size="2"&gt;&lt;strong&gt;using System.Net;&lt;br /&gt;using System.Net.Sockets;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#800080" size="2"&gt;&lt;strong&gt;class SocketHelpers&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; bool ReceiveTimeoutSupported(Socket socket)&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // try to get ReceiveTimeout option (this will get the default value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Int32 timeout = (Int32)socket.GetSocketOption(SocketOptionLevel.Socket,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SocketOptionName.ReceiveTimeout);&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#800080" size="2"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // try to set what we received (we don't want to change the default value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; socket.SetSocketOption(SocketOptionLevel.Socket,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SocketOptionName.ReceiveTimeout,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeout);&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#800080" size="2"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if we get here, ReceiveTimeout is supported&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(SocketException e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // check to see if the selected option is supported&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(10042 != e.ErrorCode)&amp;nbsp;&amp;nbsp; // WSAENOPROTOOPT&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ReceiveTimeout not supported by operating system&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // no, let the caller handle the exception&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Arial" size="2"&gt;I hope this helps clear up some of the confusion around socket options and the .Net Compact Framework.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Arial" size="2"&gt;-- DK&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Arial" size="1"&gt;Disclaimer:&lt;br /&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=166208" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category></item><item><title>Increasing web service client performance</title><link>http://blogs.msdn.com/davidklinems/archive/2004/06/18/159473.aspx</link><pubDate>Fri, 18 Jun 2004 21:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:159473</guid><dc:creator>DavidKlineMS</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/davidklinems/comments/159473.aspx</comments><wfw:commentRss>http://blogs.msdn.com/davidklinems/commentrss.aspx?PostID=159473</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;As the demand for web enabled smart devices grows, more and more mobile applications will be using web services.&amp;nbsp; Many of the folks who are already using web services with the .NET Compact Framework (NetCF) have come to me with performance issues.&amp;nbsp; More often than not, the problem boils down to what happens when NetCF sees the first web method call on an instance of the service object.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;When the first web method on a service object is called, NetCF uses Reflection to examine the service's proxy (to identify methods, headers, properties, etc).&amp;nbsp; Unlike the full .NET Framework, NetCF (for working set size reasons) does not cache the results of this examination.&amp;nbsp; Because of this, NetCF applications incur a performance penalty if they use multiple instances of the same service.&amp;nbsp; The code below illustrates an application demonstrating this performance hit.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;class SlowerWebServicePerformance&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // application setup&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(String name in Friends)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String phoneNumber = CallWebService(name);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // process / display the received data&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // application cleanup&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string CallWebService(String name)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create new instance of the web service proxy object&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PhoneBookService service = new PhoneBookService();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // call the desired web method&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; proxy reflection occurs here&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return service.LookupPhoneNumber(name);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;In the above example, each call to &lt;STRONG&gt;CallWebService&lt;/STRONG&gt; creates a new instance of the fictitios &lt;STRONG&gt;PhoneBookService&lt;/STRONG&gt; object with each call to the &lt;STRONG&gt;LookupPhoneNumber&lt;/STRONG&gt; method causing NetCF to reflect over the service proxy code.&amp;nbsp; In this example, users with a fewer friends are better off than those with more -- at least as far as application performance goes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;To minimize the effects of this issue, applications can create a class global instance of their web service object and make a simple call to it (check version, etc) during the startup code.&amp;nbsp; The code below is a re-write of the previous example, this time using a class global service object.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;class FasterWebServicePerformance&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static PhoneBookService service = new PhoneBookService();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // call a simple web service method to "prime the pump"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; proxy reflection occurs here&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; service.GetVersion();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // application setup&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(String name in Friends)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String phoneNumber = CallWebService(name);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // process / display the received data&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // application cleanup&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string CallWebService(String name)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // call the desired web method&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; proxy reflection does not occur&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return service.LookupPhoneNumber(name);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;As you can see from the second implementation, the &lt;STRONG&gt;Main&lt;/STRONG&gt; method makes a call to the service's &lt;STRONG&gt;GetVersion&lt;/STRONG&gt; method so that the reflection occurs exactly once during the course of the application.&amp;nbsp; The data received from this call is not relevant here, since we merely wish to “prime the pump“.&amp;nbsp; With this change, the penalty for having more friends is gone.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;Please keep in mind, when writing your applications in this manner, any headers required by the web service are applied to all method calls, so do not modify them while a web method call is in progress (or your calls may fail based on bad header data).&amp;nbsp; While this applies to asynchronous and multi-threaded applications, it's still a good idea to keep it in mind whenever working with web services.&amp;nbsp; Since NetCF's web service client classes are thread safe, so you can feel free to pass your class global service instance to child threads -- provided that you remember the previous statement.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;-- DK&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=1&gt;[Edit: categorization]&lt;BR&gt;&lt;BR&gt;Disclaimer:&lt;BR&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=159473" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Networking+_26002600_+Web+Services/default.aspx">Networking &amp;&amp; Web Services</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.msdn.com/davidklinems/archive/tags/Performance/default.aspx">Performance</category></item></channel></rss>