<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7826592425749291002</id><updated>2011-04-22T06:20:40.744+01:00</updated><category term='C#'/><category term='users'/><category term='Firefox'/><category term='XPath'/><category term='SkakkiNostri'/><category term='Email'/><category term='bug'/><category term='Nokia'/><category term='RequiredFieldValidator'/><category term='W3C'/><category term='internet'/><category term='asp.net 2'/><category term='ResolveUrl'/><category term='.net'/><category term='html validator'/><category term='advertising'/><category term='Rant'/><category term='VS2005'/><category term='postback'/><category term='JavaScript'/><category term='error'/><category term='Symbian'/><category term='Web'/><category term='ASP.NET'/><title type='text'>Lego programming</title><subtitle type='html'>What's more well-designed, elegant and technically perfect than a Lego brick?</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-2737903780374413800</id><published>2008-01-17T12:50:00.000+01:00</published><updated>2008-01-17T13:00:50.627+01:00</updated><title type='text'>Generating ASP.NET web pages, without web servers</title><content type='html'>Today I had to find a way to embed some dynamic web pages in a Windows Forms application - better: I have the usual couple of .aspx and .cs files, and want to get the html output.&lt;br /&gt;Some alternatives come up to mind: Cassini and Mono's XSP can easily be embedded in a standalone exe and provide a fully featured web server. However my requirements were much simpler, I don't need the ability to process requests and give responses - just spit out some HTML to display to the user, like a report. Moreover these approaches require listening to ports, running real web requests... I know that .NET contains all the required magic to process ASP.NET pages, so why can't I call some magic function and get the job done?&lt;br /&gt;&lt;br /&gt;Well, it turns out that it's not as simple as calling a function, but with a few lines of code it can be done.&lt;br /&gt;&lt;br /&gt;Create a solution with two projects. One is a Class Library project (called HostMarshaller), the other is our main app - for simplicity, let's choose a Console Application. In both projects add a reference to &lt;code&gt;System.Web&lt;/code&gt;, and in the Console App add a reference to &lt;code&gt;HostMarshaller&lt;/code&gt;.&lt;br /&gt;Open the properties window of the Console App and switch to the Build Events tab. You'll need to add the following post-build command:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;copy "$(TargetDir)HostMarshaller.dll" "$(TargetDir)bin\HostMarshaller.dll"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now let's get to the code.&lt;br /&gt;In HostMarshaller's generated Class1.cs, paste these lines:&lt;br /&gt;﻿&lt;pre&gt;using System;&lt;br /&gt;using System.IO;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Hosting;&lt;br /&gt;&lt;br /&gt;public class HostMarshaller: MarshalByRefObject&lt;br /&gt;{&lt;br /&gt;  public string Run(string page, string query)&lt;br /&gt;  {&lt;br /&gt;    StringWriter outputWriter = new StringWriter();&lt;br /&gt;    SimpleWorkerRequest request = new SimpleWorkerRequest(page, query, outputWriter);&lt;br /&gt;    HttpRuntime.ProcessRequest(request);&lt;br /&gt;&lt;br /&gt;    return outputWriter.GetStringBuilder().ToString();&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Now open the Program.cs in the Console App. In the main() body, paste these lines:&lt;br /&gt;&lt;pre&gt;// For this to work, the HostMarshaller assembly must be located &lt;br /&gt;// in a \bin\ subfolder of the directory containing this EXE.&lt;br /&gt;// A post-build command takes care of this.&lt;br /&gt;&lt;br /&gt;System.Reflection.Assembly a = System.Reflection.Assembly.GetEntryAssembly();&lt;br /&gt;string baseFolder = System.IO.Path.GetDirectoryName(a.Location);&lt;br /&gt;&lt;br /&gt;HostMarshaller result = (HostMarshaller)ApplicationHost.CreateApplicationHost(typeof(HostMarshaller), "/", baseFolder);&lt;br /&gt;string output = result.Run("report.aspx", String.Empty);&lt;br /&gt;&lt;br /&gt;Console.WriteLine(output);&lt;/pre&gt;&lt;br /&gt;And add the using statement for System.Web.Hosting.&lt;br /&gt;This code is enough to achieve our purpose. Now we just need to create the report.aspx.&lt;br /&gt;Compile the project and ignore any errors, these are normal.&lt;br /&gt;&lt;br /&gt;Open a file manager and go to the bin\Debug\ folder of the Console App project. Here you'll have to create another &lt;code&gt;bin&lt;/code&gt; subfolder.&lt;br /&gt;Recompile - this time it will build just fine.&lt;br /&gt;&lt;br /&gt;In the debug folder, create a file called "report.aspx" with this content:&lt;br /&gt;&lt;pre&gt;&amp;lt;%@ Page Language="C#" %&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;        &amp;lt;asp:Label runat="server" Font-Bold="true"&amp;gt;3 + 2 is &amp;lt;%=3 + 2 %&amp;gt;&amp;lt;/asp:Label&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/pre&gt;&lt;br /&gt;Run the project and enjoy the generated web page :)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;What's happening there&lt;/h4&gt;&lt;br /&gt;As you may have noticed, the bulk of the work is done by the HttpRuntime.ProcessRequest call. However this call requires a specially-setup AppDomain, that our Console App does not have, so we have to create another AppDomain by the use of ApplicationHost.CreateApplicationHost. &lt;br /&gt;An instance of the HostMarshaller class gets created in this new AppDomain, and in its Run method we launch the request processing.&lt;br /&gt;To pass parameters to the web page, you can use the second parameter of the Run method, it is a standard query string in the form key=value&amp;key=value...&lt;br /&gt;&lt;br /&gt;That's it, have fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-2737903780374413800?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/2737903780374413800/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=2737903780374413800' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/2737903780374413800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/2737903780374413800'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2008/01/generating-aspnet-web-pages-without-web.html' title='Generating ASP.NET web pages, without web servers'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-383199239708345309</id><published>2007-12-20T19:01:00.000+01:00</published><updated>2007-12-20T19:12:56.025+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ResolveUrl'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='SkakkiNostri'/><title type='text'>ResolveUrl not resolving</title><content type='html'>Since the .net conversion of SkakkiNostri, we were facing a rare and strange problem.&lt;br /&gt;When the user clicks the quick Search button, it is internally redirected to a more specialized page using the line:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Response.Redirect(ResolveUrl("~/search_users.aspx?quickValue=" + txtUser.Text), true);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This line was causing 404 errors, with the ResolveUrl call apparently not doing what it has to do: the user was redirected to &lt;code&gt;http://www.skakkinostri.it/~/search_users.aspx?quickValue=something&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Can you spot the problem?&lt;br /&gt;&lt;br /&gt;Hint: today, while skimming through the error list I noticed something strange. All of these error reports were for users that contained unicode characters. Lots of them, like in the word "•]•·´º´·» .:. rO£@Lb@ ιи ℓσνє.:. [♡] «·´º´·•[•".&lt;br /&gt;&lt;br /&gt;Then came the enlightenment: maybe the ResolveUrl call fails if the URL is not perfectly url-formatted!&lt;br /&gt;And it turns out it's just that way. As simple as it seems, the offending call was promptly replaced with:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Response.Redirect(ResolveUrl("~/search_users.aspx?quickValue=" + Server.UrlEncode(txtUser.Text)), true);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and suddenly exceptions stopped.&lt;br /&gt;Now let's go for a check of all the Response.Redirect calls in the web site :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-383199239708345309?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/383199239708345309/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=383199239708345309' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/383199239708345309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/383199239708345309'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/12/resolveurl-not-resolving.html' title='ResolveUrl not resolving'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-8627026727963791031</id><published>2007-11-30T10:34:00.000+01:00</published><updated>2007-11-30T10:40:01.092+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Nokia'/><category scheme='http://www.blogger.com/atom/ns#' term='RequiredFieldValidator'/><category scheme='http://www.blogger.com/atom/ns#' term='Symbian'/><title type='text'>Custom validators and Nokia Browser</title><content type='html'>On SkakkiNostri, we have a custom RequiredFieldValidator for a custom control that basically boils down to a textarea. We had a bug report stating that people using the Nokia S60 built-in browser always failed the required field validation. Well, it turns out that the standard .net ValidatorTrim function simply does not work there, probably has something to do with the order of loading of scripts, or maybe our code isn't perfect (I did not try to write a test case, and standard RequiredFieldValidators work just fine). Since I do not have much time at all, I just wrote a simple TrimString function and now we can post messages in SkakkiNostri's forum using the Nokia Browser :)&lt;br /&gt;&lt;br /&gt;Code:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;// On Nokia Browser, the .net ValidatorTrim always returns null.&lt;br /&gt;function TrimString(s) { return s.replace(/^\s+/g, "").replace(/\s+$/g, ""); }&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-8627026727963791031?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/8627026727963791031/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=8627026727963791031' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/8627026727963791031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/8627026727963791031'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/11/custom-validators-and-nokia-browser.html' title='Custom validators and Nokia Browser'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-898369943401928916</id><published>2007-07-02T09:35:00.000+02:00</published><updated>2007-07-02T09:46:14.508+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='html validator'/><category scheme='http://www.blogger.com/atom/ns#' term='W3C'/><title type='text'>The downlevel W3C html validator</title><content type='html'>ASP.net is smart enough to know which html content render to which browser, which is good. However there's a small flaw in the browser detection: the W3C html validator is detected as pre-DOM (and since it's not a real browser it logically is one of those), but that defeats the purpose of validating the output of a website.&lt;br /&gt;Luckily it's quite easy to fix this issue. Just create a folder called &lt;span style="font-family:courier new;color:#990000;"&gt;App_Browsers&lt;/span&gt; in your website root and place a file called &lt;span style="font-family:courier new;color:#990000;"&gt;w3cvalidator.browser&lt;/span&gt;, containing the following code:&lt;br /&gt;&lt;br /&gt;&amp;lt;browsers&amp;gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;  Browser capability file for the W3C validator&lt;br /&gt;  Sample User-Agent: "W3C_Validator/1.432.2.22"&lt;br /&gt;--&amp;gt;&lt;br /&gt;&amp;lt;browser id="w3cValidator" parentid="Default"&amp;gt;&lt;br /&gt;&amp;lt;identification&amp;gt;&lt;br /&gt;&amp;lt;useragent match="^W3C_Validator"&amp;gt;&lt;br /&gt;&amp;lt;/identification&amp;gt;&lt;br /&gt;&amp;lt;capture&amp;gt;&lt;br /&gt;&amp;lt;useragent match="^W3C_Validator/(?'version'(?'major'\d+)(?'minor'\.\d+)\w*).*"&amp;gt;&lt;br /&gt;&amp;lt;/capture&amp;gt;&lt;br /&gt;&amp;lt;capabilities&amp;gt;&lt;br /&gt;&amp;lt;capability value="w3cValidator" name="browser"&amp;gt;&lt;br /&gt;&amp;lt;capability value="${major}" name="majorversion"&amp;gt;&lt;br /&gt;&amp;lt;capability value="${minor}" name="minorversion"&amp;gt;&lt;br /&gt;&amp;lt;capability value="${version}" name="version"&amp;gt;&lt;br /&gt;&amp;lt;capability value="1.0" name="w3cdomversion"&amp;gt;&lt;br /&gt;&amp;lt;capability value="true" name="xml"&amp;gt;&lt;br /&gt;&amp;lt;capability value="System.Web.UI.HtmlTextWriter" name="tagWriter"&amp;gt;&lt;br /&gt;&amp;lt;/capabilities&amp;gt;&lt;br /&gt;&amp;lt;/browser&amp;gt;&lt;br /&gt;&amp;lt;/browsers&amp;gt;&lt;br /&gt;&lt;br /&gt;One small side note. Initially I was placing this file along with another &lt;span style="font-family:courier new;color:#990000;"&gt;.browser&lt;/span&gt; file that I use to render PNG images with transparences (will talk about this little gem in the future). That one was called &lt;span style="font-family:courier new;color:#990000;"&gt;All.browser&lt;/span&gt; and rendered the right code for all browsers, but somehow it prevented the use of the &lt;span style="font-family:courier new;color:#990000;"&gt;w3cvalidator.browser&lt;/span&gt; file. Merging those two files into one did the trick.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-898369943401928916?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/898369943401928916/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=898369943401928916' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/898369943401928916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/898369943401928916'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/07/downlevel-w3c-html-validator.html' title='The downlevel W3C html validator'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-466853777764113033</id><published>2007-06-13T22:34:00.000+02:00</published><updated>2007-06-13T22:41:03.242+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net 2'/><category scheme='http://www.blogger.com/atom/ns#' term='postback'/><title type='text'>Preventing double postback</title><content type='html'>&lt;p&gt;Today I had to make sure a certain button could not be pressed twice, to avoid processing errors. Initially I just set the disabled property to true, but that would not work since postback from disabled controls is inhibited. I invoked manually the postback, and it worked, but broke when validators prevented the postback. After a little bit of wondering, I crafted this small routine, to be placed in a Page-derived class for simplicity.&lt;/p&gt;&lt;p&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Makes a certain button one-shot only,&lt;br /&gt;/// preserving validator functionality&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="btn"&amp;gt;The button that can't be clicked twice&amp;lt;/param&amp;gt;&lt;br /&gt;protected void RegisterSinglePostButton(Button btn)&lt;br /&gt;{&lt;br /&gt;System.Text.StringBuilder sb = new System.Text.StringBuilder();&lt;br /&gt;sb.Append("if (typeof(Page_ClientValidate) == 'function') { ");&lt;br /&gt;sb.Append("if (Page_ClientValidate() == false) { return false; }} ");&lt;br /&gt;sb.Append("this.disabled = true;");&lt;br /&gt;sb.Append(ClientScript.GetPostBackEventReference(btn, ""));&lt;br /&gt;sb.Append(";");&lt;br /&gt;btn.Attributes.Add("onclick", sb.ToString());&lt;br /&gt;}&lt;/p&gt;It can be easily transformed in a control if needed, for further clarity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-466853777764113033?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/466853777764113033/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=466853777764113033' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/466853777764113033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/466853777764113033'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/06/preventing-double-postback.html' title='Preventing double postback'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-2915442648595205154</id><published>2007-06-09T00:45:00.000+02:00</published><updated>2007-06-09T00:52:21.230+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='users'/><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='SkakkiNostri'/><title type='text'>A small step for a man</title><content type='html'>Just a small accomplishment, yet I'm very happy. In the last days I was having a lot of 404 reports for a no-longer existing page on SkakkiNostri. The referrer page was null, so I had to find the source myself. I grep'd the source code, queried nearly every table in the database, but there was no link to that page there. So chances were a) some search engine b) some user.&lt;br /&gt;Looking at the UserAgent/IP address, I quickly found it wasn't a search engine. So probably it had a user that dumbily had bookmarked that page, and now used my 404 error page to come back to the site. I have been thinking about what I could do to avoid this error, then I had a sudden realization: I could just track down the user using the cookies collection and send him a private message. Guess what? It worked. The user wasn't understanding what a 404 error was, but could access the site, so he was happy. Nonetheless explaining the situation to him we have been to fix the wrong link in the Favorites, and I'm no longer receiving emails. Well, not for that error :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-2915442648595205154?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/2915442648595205154/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=2915442648595205154' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/2915442648595205154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/2915442648595205154'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/06/small-step-for-man.html' title='A small step for a man'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-1584436689170018391</id><published>2007-05-30T17:56:00.000+02:00</published><updated>2007-05-30T18:39:35.149+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS2005'/><title type='text'>Score another one for me!</title><content type='html'>So, after a clean format of my machine, I had this weird error in Microsoft Visual Studio 2005: it wouldn't compile one of my web projects. Compilation failed with the following error:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;(O): Build (web): Unable to find the required module. (Exception from HRESULT: 0x8007007E)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As you can see, it says nothing about WHICH module is missing. I tried for a few days to fiddle with dependant assemblies, web.config settings, etc. but only today I have been able to investigate and fix it. I downloaded ProcessMonitor from the Microsoft site and after defining the appropriate filters I tracked down the missing assembly: it was MSVCR71.DLL. Just found a copy on some other location on the HD, placed it into C:\Windows\System32 and it worked flawlessly.&lt;br /&gt;&lt;br /&gt;I feel like I deserve a reward. Going to buy an icecream! :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-1584436689170018391?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/1584436689170018391/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=1584436689170018391' title='1 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/1584436689170018391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/1584436689170018391'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/score-another-one-for-me.html' title='Score another one for me!'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-6674787815220856988</id><published>2007-05-13T10:19:00.000+02:00</published><updated>2007-05-13T10:27:05.189+02:00</updated><title type='text'>WTF?</title><content type='html'>&lt;p&gt;While checking the error logs for &lt;a href="http://www.skakkinostri.it"&gt;SkakkiNostri&lt;/a&gt;, this morning, I noticed something strange. Yesterday night something like a spider crawled my site, querying the robots.txt as usual, but then it started messing with the file paths.&lt;/p&gt;&lt;p&gt;It tried to visit the pages listed in the web site root (e.g. /forum.aspx), but under the /admin/ folder (/admin/forum.aspx). These do not exist, so I received a notification of the 404 error.&lt;/p&gt;&lt;p&gt;The user agent for those request is Java/1.5.0_11, and the originating host is a dynamic IP of the Telecom Italia range. So maybe one of my user tried a lame scanning tool, but that IP was not in the http logs. How strange...&lt;/p&gt;&lt;p&gt;However I am starting to be annoyed by these notifications. Please, fix that scanning tool! :-) &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-6674787815220856988?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/6674787815220856988/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=6674787815220856988' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/6674787815220856988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/6674787815220856988'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/wtf.html' title='WTF?'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-5360715717668757640</id><published>2007-05-12T10:14:00.000+02:00</published><updated>2007-05-12T10:19:48.941+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS2005'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Now I have no excuses</title><content type='html'>...for not documenting my code, that is. I just installed the excellent and free &lt;a href="http://www.roland-weigelt.de/ghostdoc/"&gt;GhostDoc&lt;/a&gt; plugin for Visual Studio 2005. Simple and neat, with a right clic on a function prototype this is what is does:&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Processes the HTML message.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="message"&amp;gt;The message.&amp;lt;/param&amp;gt;&lt;br /&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;public static string ProcessHtmlMessage(string message)&lt;br /&gt;{&lt;br /&gt;[ ... ]&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-5360715717668757640?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/5360715717668757640/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=5360715717668757640' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/5360715717668757640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/5360715717668757640'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/now-i-have-no-excuses.html' title='Now I have no excuses'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-1889970100445241515</id><published>2007-05-11T13:08:00.000+02:00</published><updated>2007-05-11T13:10:50.997+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>A little gem</title><content type='html'>I always liked the way Opera remembers the tabs that were open when it gets closed. Today I looked for a similar Firefox extension, and after a little search I found it is already present in the browser! Just enable it in Tools &gt; Options &gt; Main &gt; Startup. Cool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-1889970100445241515?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/1889970100445241515/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=1889970100445241515' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/1889970100445241515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/1889970100445241515'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/little-gem.html' title='A little gem'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-1047605116031674116</id><published>2007-05-11T12:15:00.000+02:00</published><updated>2007-05-11T12:22:38.289+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='advertising'/><category scheme='http://www.blogger.com/atom/ns#' term='Rant'/><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><title type='text'>A rant</title><content type='html'>While surfing the net, I usually visit just a handful of sites, and usually three-four times a day.&lt;br /&gt;&lt;br /&gt;Now, three of them have video ads. I just can't stand them. Just move the mouse above them, say to click on a link, and they start playing. One of them even starts without intervention. ARGH! It's a long time since I subconsciously installed a brain filter for moving images in web pages, but now they have audio! Imagine my beloved classical music overtaken by a loud voice saying "Take control of the compliance!".&lt;br /&gt;&lt;br /&gt;Stop now, please. PLEASE! Video adverts make baby Jesus cry!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-1047605116031674116?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/1047605116031674116/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=1047605116031674116' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/1047605116031674116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/1047605116031674116'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/rant.html' title='A rant'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-7733187510217218093</id><published>2007-05-09T17:04:00.000+02:00</published><updated>2007-05-09T17:10:01.998+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Email'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>SmtpExceptions</title><content type='html'>While migrating &lt;a href="http://www.skakkinostri.it"&gt;SkakkiNostri&lt;/a&gt; from classic ASP to ASP.NET, I noticed quite a lot of unhandled SmtpExceptions. I was fairly shocked, since, before the migration, I did not have any feedback about the relaying of the E-Mails sent by the site, and thought errors were a lot more infrequent.&lt;br /&gt;Right now, my inbox is full of SmtpException notifications. I need to do something to track them in an appropriate place, possibly filtering and grouping notifications. Any ideas are welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-7733187510217218093?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/7733187510217218093/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=7733187510217218093' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/7733187510217218093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/7733187510217218093'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/smtpexceptions.html' title='SmtpExceptions'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-5536269571904969099</id><published>2007-05-09T16:58:00.000+02:00</published><updated>2007-05-09T17:02:29.206+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Reminder to myself</title><content type='html'>&lt;strong&gt;Request.UserAgent can be null&lt;/strong&gt; (when the client does not specify it). I was trying to detect the Googlebot and be nice with it, and later found it failed with a few other requests because of a missing null check. DOH!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-5536269571904969099?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/5536269571904969099/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=5536269571904969099' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/5536269571904969099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/5536269571904969099'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/reminder-to-myself.html' title='Reminder to myself'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7826592425749291002.post-8014845610946993006</id><published>2007-05-09T16:41:00.000+02:00</published><updated>2007-05-09T16:51:32.826+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XPath'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to escape apostrophes in XPath / .net</title><content type='html'>&lt;p&gt;Yesterday I found something interesting: there isn't a correct way to escape string literals in XPath queries.&lt;/p&gt;&lt;p&gt;Example:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;galleryDocument.SelectSingleNode("//photo[filename='" + photoFileName + "']");&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This line raises an exception if photoFileName contains an apostrophe. Neither &amp;apos; nor \' nor '' work as an escape sequence - the XPath specifications do not handle that. So, how do we deal with it?&lt;/p&gt;&lt;p&gt;The answer is a small routine that relies on the &lt;span style="font-family:courier new;color:#990000;"&gt;concat&lt;/span&gt; XPath function:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;public static string EscapeApostropheForXPathParameter(string parameter)&lt;br /&gt;{&lt;br /&gt;    if (!parameter.Contains("'")) return "'" + parameter + "'";&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;    string[] parts = parameter.Split('\'');&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;    string result = String.Empty;&lt;br /&gt;    foreach (string part in parts)&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;       result += ", \"'\", '" + part + "'";&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;    return "concat(" + result.Substring(7) + ")";&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;color:#990000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This routine basically maps the string &lt;span style="font-family:courier new;color:#990000;"&gt;"foo'bar"&lt;/span&gt; into &lt;span style="font-family:courier new;color:#990000;"&gt;concat('foo', "'", 'bar')&lt;/span&gt;. Please note the different kind of quotes around the apostrophe. Nice to know, huh? :-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7826592425749291002-8014845610946993006?l=legoprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://legoprogramming.blogspot.com/feeds/8014845610946993006/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7826592425749291002&amp;postID=8014845610946993006' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/8014845610946993006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7826592425749291002/posts/default/8014845610946993006'/><link rel='alternate' type='text/html' href='http://legoprogramming.blogspot.com/2007/05/how-to-escape-apostrophes-in-xpath-net.html' title='How to escape apostrophes in XPath / .net'/><author><name>Luca Leonardo Scorcia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
