<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.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>I may have joined the wrong side : ASP.NET</title><link>http://msmvps.com/blogs/calinoiu/archive/tags/ASP.NET/default.aspx</link><description>Tags: ASP.NET</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>What's wrong with ASP.NET?  Cultures</title><link>http://msmvps.com/blogs/calinoiu/archive/2006/06/30/103426.aspx</link><pubDate>Fri, 30 Jun 2006 19:30:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:103426</guid><dc:creator>calinoiu</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/rsscomments.aspx?PostID=103426</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/commentapi.aspx?PostID=103426</wfw:comment><comments>http://msmvps.com/blogs/calinoiu/archive/2006/06/30/103426.aspx#comments</comments><description>&lt;H3&gt;The problem&lt;/H3&gt;
&lt;P&gt;The ability offered by .NET to set a thread-level culture then automatically format and select localizable resources using that culture's settings is wonderful stuff. Unfortunately, it's an approach that plays out quite a bit better in a client-side application than in a server-based application. The reason for this lies in the nature of the work one performs in a server-based application: some formatting and/or rendering is intended for consumption by client applications, but some (&lt;I&gt;e.g.&lt;/I&gt;: log entries) is intended for consumption on the server. &lt;/P&gt;
&lt;P&gt;Things tend to muddle along just fine as long as both the client and the server use the same or similar cultures. This is helped along by the fact that most servers are unlikely to have additional .NET language packs installed, so any exceptions logged on the server are likely to contain English error messages. However, there are plenty of cases in which it might be necessary to install additional language packs on the server (&lt;I&gt;e.g.&lt;/I&gt;: server and/or application administrators don't speak English), so it might be a wee bit naïve for a software vendor to assume that the only .NET language supported on a server is one that will be understood by folks who read text generated for comsumption on the server. &lt;/P&gt;
&lt;P&gt;In case this all sounds a bit odd, let's take a look at some concrete examples. Our base scenario is a localizable ASP.NET application that, as is typical, sets the current thread's &lt;A href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.currentculture.aspx"&gt;CurrentCulture&lt;/A&gt; and &lt;A href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.currentuiculture.aspx"&gt;CurrentUICulture&lt;/A&gt; properties to match the preferred culture of the client user. Amongst other things, this application happens to create a log entry every time an invoice is created via its UI. &lt;I&gt;e.g.&lt;/I&gt;: &lt;/P&gt;&lt;PRE class=shaded&gt;	
private void LogOrder(int invoiceId, double price)
{
	string logText = string.Format("Invoice {0:N0} for {1:C} created at {2:G}.",
		invoiceId, price, DateTime.Now);

	// Text written to log here...
}
	&lt;/PRE&gt;
&lt;P&gt;If the application has set the current thread's CurrentCulture property to the client's preferred culture, here is what will be written to the server-side log for various values of the client culture: &lt;/P&gt;
&lt;TABLE class=standardPostTable cellSpacing=0 cellPadding=4&gt;

&lt;TR&gt;
&lt;TH class=standardPostTable&gt;Client culture&lt;/TH&gt;
&lt;TH class=standardPostTable&gt;Logged text&lt;/TH&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;en-US&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21,456 for $5,000.00 created at 5/6/2006 9:30:00 AM.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;en-CA&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21,456 for $5,000.00 created at 06/05/2006 9:30:00 AM.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;en-GB&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21,456 for £5,000.00 created at 06/05/2006 09:30:00.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;fr-FR&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21 456 for 5 000,00 € created at 06/05/2006 09:30:00.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;fr-CA&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21 456 for 5 000,00 $ created at 2006-05-06 09:30:00.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;es-ES&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21.456 for 5.000,00 € created at 06/05/2006 9:30:00.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;es-MX&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21,456 for $5,000.00 created at 06/05/2006 09:30:00 a.m..&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;ja-JP&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Invoice 21,456 for ¥5,000 created at 2006/05/06 9:30:00.&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;
&lt;P&gt;The above table shows some of the sorts of trouble that one can get into applying client-side culture options to formatting of server-side texts, and things will only get worse &lt;A href="http://blogs.msdn.com/michkap/archive/2004/12/01/272864.aspx"&gt;when/if&lt;/A&gt; &lt;A href="http://msdn2.microsoft.com/en-us/library/system.globalization.numberformatinfo.digitsubstitution.aspx"&gt;digit substitution&lt;/A&gt; is fully implemented. The problem is compounded by the fact that the client-specified culture used to apply formatting is no longer known at the time one reads the server-side text. Of course, formatting as in the above example is a mistake, and there are ways to avoid the problem, but more on that after we look at something a little more difficult to work around. &lt;/P&gt;
&lt;P&gt;Like many applications built upon it, the .NET framework emits a variety of texts based on localized resources. The examples with which many developers will likely be most familiar are exception messages. In fact, in most applications, a very large majority of exception messages will have been generated within the .NET Framework base class libraries. Let's say that your application happens to be running on a server with the Hungarian language pack, and an exception is logged while a Hungarian client is using the application. Would you have any idea what the exception message "Nem megfelelő a bemeneti karakterlánc formátuma" means? (It happens to be the Hungarian version of "Input string was not in a correct format", but &lt;A href="http://babelfish.altavista.com/" target=_blank&gt;BabelFish&lt;/A&gt; won't exactly be helping you figure that one out...) &lt;/P&gt;
&lt;P&gt;To add to the fun, some Framework-generated texts (including exception messages) are automatically formatted from resource strings containing placeholders. Since you cannot control the formatting applied in these instances, you may run into interpretation issues even if you don't have any additional language packs installed. For example, if you see an exception message containing the number "2,345", how can you tell if this was a 2345 written under an American culture option or a 2.345 written under a French Canadian setting? Sometimes context may help, but other times you'll just plain have to guess. &lt;/P&gt;&lt;BR&gt;
&lt;H3&gt;The workaround&lt;/H3&gt;
&lt;P&gt;So what can we do to avoid the problem? The easy answer is to not use the thread culture as a store for the client's preferred culture. This, of course, means that we would then need to perform explicit formatting of any non-string values before passing them to UI elements for rendering. While somewhat burdensome, particularly for folks who like living the RAD life, this isn't exactly the end of the world. There's also a bit of good news: &lt;A href="http://www.gotdotnet.com/team/fxcop/"&gt;FxCop&lt;/A&gt; can help you identify at least those cases of explicit formatting that are defaulting to using the thread culture. &lt;/P&gt;
&lt;P&gt;The first bit of rather bad news with this approach is that you can't use ASP.NET's auto-magical client culture detection since it pops the detected culture into the current thread properties. Things might be a bit different if the ASP.NET team had chosen to make the HttpApplication.SetCulture method virtual, but it's not, so we're stuck implementing our own mechanism from scratch if we want to use an alternate store for the client culture. &lt;/P&gt;
&lt;P&gt;The second bit of bad news is that there are several ASP.NET controls that are rather aggressive about using the thread culture internally. For example, when using the CompareValidator with ValidationDataType.Double, it's possible to use culture-specific parsing&lt;SUP&gt;1&lt;/SUP&gt;. However, there's no way to specify which culture one wants to use for parsing. Unless you choose to use culture-invariant parsing, the thread culture will be used. That means that a French Canadian user's 5,123 would theoretically be interpreted as 5123 rather than 5.123 if the thread culture is set to en-US because that's the appropriate setting for server-side use. However, things are even worse in practice than in theory, and our 5,123 will fail validation since the CompareValidator does not permit use of thousands group separators and will reject the comma if the thread culture is en-US. &lt;/P&gt;
&lt;P&gt;For a fully functional workaround, you'll need to implement at least four sets of changes: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Use an alternate store for the client culture, 
&lt;LI&gt;Create a mechanism for populating this new store with the client-preferred culture (rather than setting Culture and UICulture attributes to "auto"), 
&lt;LI&gt;Where possible, pre-format non-string values that will be rendered by controls, and 
&lt;LI&gt;Implement custom versions of control that take the rendering culture as a property rather than using the thread culture exclusively.&lt;/LI&gt;&lt;/OL&gt;&lt;BR&gt;
&lt;H3&gt;The solution&lt;/H3&gt;
&lt;P&gt;The workarounds are a pack of trouble, and far more work than most folks would be willing to put in unless they've already been bitten by client vs. server culture bugs. The real solution here is for the ASP.NET platform to properly accomodate separate tracking of client and server cultures. Obviously, items 1 and 2 from the workarounds list above would be a start. In addition, it would probably be a great idea if controls defaulted to using the client culture but allowed easy overriding to use either the server culture or a custom assigned culture. &lt;/P&gt;&lt;BR&gt;
&lt;HR&gt;

&lt;P&gt;&lt;SUP&gt;1&lt;/SUP&gt;For some bizarre reason, CompareValidator is strictly culture-invariant for some data types (&lt;I&gt;e.g.&lt;/I&gt;: ValidationDataType.Integer), which presents its own set of potential problems. However, this isn't directly relevant to the client vs. server culture issue, so I'll drop it for now. However, if you want to complain, &lt;A href="http://connect.microsoft.com/feedback/default.aspx?SiteID=210"&gt;connect.microsoft.com&lt;/A&gt; is the place.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=103426" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/calinoiu/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>What's wrong with ASP.NET?  HTML encoding</title><link>http://msmvps.com/blogs/calinoiu/archive/2006/06/13/what-s-wrong-with-asp-net-html-encoding.aspx</link><pubDate>Tue, 13 Jun 2006 19:58:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:102957</guid><dc:creator>calinoiu</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/rsscomments.aspx?PostID=102957</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/commentapi.aspx?PostID=102957</wfw:comment><comments>http://msmvps.com/blogs/calinoiu/archive/2006/06/13/what-s-wrong-with-asp-net-html-encoding.aspx#comments</comments><description>&lt;h3&gt;The problem&lt;/h3&gt;
&lt;p&gt;Back when ASP.NET was first introduced, I had pretty high hopes that the new controls would offer support for automatic HTML encoding. Unfortunately, there was very little of this, and most of it was more than a bit lukewarm (more on this later). In some ways, things have improved a bit in v. 2.0, but they&amp;#39;re considerably worse in others.&lt;/p&gt;
&lt;p&gt;Before you read any further, you might want to ask yourself which ASP.NET controls perform HTML encoding for you and under what circumstances this is done. If the answer doesn&amp;#39;t leap to mind, you&amp;#39;ve perhaps got a first inkling that there might be a little problem with API consistency and/or the documentation. Then again, maybe you&amp;#39;ve never worried about HTML encoding in your web applications, in which case I&amp;#39;d strongly recommend that you read up on HTML injection and cross-site scripting. A good starting point might be &lt;a href="http://www.cert.org/advisories/CA-2000-02.html"&gt;CERT Advisory CA-2000-02&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll look at which controls perform HTML encoding soon. First, we&amp;#39;re going to need to nail down some conceptual stuff because not all encoding is created equal. You may already be aware that HTML, URLs, and client-side script use different encodings. For the sake of simplicity, the remainder of this post will refer mainly to HTML encoding, although the other two forms of encoding do merit consideration as well.&lt;/p&gt;
&lt;p&gt;There is more than one flavour of HTML encoding, even within ASP.NET. The first is exposed via the System.Web.HttpUtility.HtmlEncode methods. These encode the characters &amp;gt;, &amp;lt;, &amp;amp;, &amp;quot;, as well as any characters with codes between 160 and 255, inclusive. The other main encoding flavour used by ASP.NET is &amp;quot;attribute&amp;quot; encoding, which is exposed via the System.Web.HttpUtility.HtmlAttributeEncode methods. In ASP.NET 1.1., these encode the &amp;amp; and &amp;quot; characters only. In ASP.NET 2.0, these encode the characters &amp;lt;, &amp;amp;, and &amp;quot;. &lt;/p&gt;
&lt;p&gt;Attribute encoding ought to be a superset of full HTML encoding that also encodes the single quote character in case that&amp;#39;s what happens to be wrapping the attribute. However, as you may have noticed from the above, the ASP.NET version of attribute encoding is even wimpier than its full encoding brother. To make matters worse, the full HTML encoding implemented by ASP.NET is no great shakes in the first place. Security isn&amp;#39;t the only reason for HTML encoding, and failure to encode everything outside the low ASCII range can impact on page readability when client browsers don&amp;#39;t apply the correct code page (which happens more often than you might think, whether it&amp;#39;s the client&amp;#39;s or the server&amp;#39;s fault). &lt;/p&gt;
&lt;p&gt;Now that we know what kinds of HTML encoding are available in ASP.NET, let&amp;#39;s take a look at the encoding support offered by the built-in ASP.NET controls.&amp;nbsp; The following table covers some of the more commonly used controls and properties.&amp;nbsp; (There are, of course, many other controls and properties that one might wish to see encoded, but I&amp;#39;ve tried to keep the list down to things that most folks are likely to use reasonably frequently.)&lt;/p&gt;&lt;br /&gt;
&lt;table class="standardPostTable" cellspacing="0" cellpadding="4" class="standardPostTable"&gt;

&lt;tr&gt;
&lt;th class="standardPostTable" align="left" class="standardPostTable"&gt;Control&lt;/th&gt;
&lt;th class="standardPostTable" class="standardPostTable"&gt;ASP.NET 1.1&lt;/th&gt;
&lt;th class="standardPostTable" class="standardPostTable"&gt;ASP.NET 2.0&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Literal&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;None&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;None by default.&lt;br /&gt;HTML encoded if Mode property is set to LiteralMode.Encode.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="" style="HEIGHT:29px;"&gt;Label&lt;/td&gt;
&lt;td class="" style="HEIGHT:29px;" colspan="2"&gt;None&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Button&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;Text is attribute encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;LinkButton&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;None&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;ImageButton&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Image URL is attribute encoded.&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Image URL is URL path encoded then attribute encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;HyperLink&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Text is not encoded.&lt;br /&gt;NavigateUrl is attribute encoded.&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Text is not encoded.&lt;br /&gt;NavigateUrl is URL path encoded (unless it uses the BLOCKED SCRIPT protocol) then attribute encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;TextBox&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;Single-line text box (input type=&amp;quot;text&amp;quot;) is attribute encoded.&lt;br /&gt;Multi-line text box (textarea)&amp;nbsp;is HTML encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;DropDownList and ListBox&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;Option values are attribute encoded.&lt;br /&gt;Option display texts are HTML encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;CheckBox and CheckBoxList&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;Value is not used.&lt;br /&gt;Display text is not encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;RadioButton and RadioButtonList&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;Value is attribute encoded.&lt;br /&gt;Display text is not encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Table&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;None&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;DataGrid&lt;/td&gt;
&lt;td class="standardPostTable" colspan="2" class="standardPostTable"&gt;None for text columns.&lt;br /&gt;Hyperlink columns follow the pattern for HyperLink controls.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Validators (BaseValidator subclasses) and ValidationSummary&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Validator display text is not encoded.&lt;br /&gt;For client script, the validator error message and validation summary header text are attribute encoded.&lt;br /&gt;When rendering &amp;quot;populated&amp;quot; validators and the validation summary controls from the server, no encoding is applied.&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Validator display text is not encoded.&lt;br /&gt;For client script, the validator error message and validation summary header text are javascript encoded (blacklisting approach).&lt;br /&gt;When rendering &amp;quot;populated&amp;quot; validators and the validation summary controls from the server, no encoding is applied.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;HiddenField&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;N/A&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Value is attribute encoded.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;GridView and DetailsView&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;N/A&lt;/td&gt;
&lt;td class="standardPostTable" class="standardPostTable"&gt;Text fields HTML encode if their HtmlEncode property is set to true. (This is the default, which is also used for auto-generated columns.) However, the null display text for text fields is not encoded even if the field&amp;#39;s HtmlEncode is set to true.&lt;br /&gt;Hyperlink fields follow the pattern for HyperLink controls.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;Assuming you&amp;#39;ve actually taken the time to read the above, you might have noticed that there are five basic patterns of encoding usage:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;No encoding ever applied. 
&lt;li&gt;HTML and/or attribute encoding, as appropriate (with a bit of additional URL and/or javascript encoding applied when appropriate), applied all the time. 
&lt;li&gt;Attribute encoding applied for attributes, but no encoding applied for other text. 
&lt;li&gt;Optional encoding set via a boolean property, defaulting to applying the encoding. 
&lt;li&gt;Optional encoding set via an enumerated property, defaulting to not applying the encoding.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;If this strikes you as perhaps a wee bit inconsistent, you wouldn&amp;#39;t be alone. Wouldn&amp;#39;t it be great to see a consistent approach that telegraphs well and acts as a &lt;a href="http://blogs.msdn.com/brada/archive/2005/10/07/478375.aspx"&gt;pit of success&lt;/a&gt;? If all the controls performed HTML encoding by default but allowed overriding when necessary (preferably via a single approach), the vast majority of developers writing for ASP.NET would end up generating a more secure, more reliable applications with considerably less effort. &lt;/p&gt;
&lt;h3&gt;Workarounds&lt;/h3&gt;
&lt;p&gt;While we&amp;#39;re all waiting around for the ASP.NET team to eventually provide reasonable built-in support for HTML encoding, what can we do to ensure that our apps are both protected from HTML injection and character mis-rendering? A good starting point would be to fully encode all data (&lt;i&gt;i.e.&lt;/i&gt;: anything not 100% known at compile time, and even some stuff that is) that will be pushed to the client browser. Unfortunately, as was already mentioned above, the built-in encoding scheme leaves a little something to be desired. Luckily, the &lt;a href="http://blogs.msdn.com/ace_team/"&gt;ACE team&lt;/a&gt; folks at Microsoft have been working on &lt;a href="http://blogs.msdn.com/ace_team/archive/2006/03/19/554714.aspx"&gt;a couple of tools&lt;/a&gt; that take a more robust approach to HTML (and URL and script) encoding. Rather than blacklisting a fixed set of potentially problematic characters for encoding, they whitelist a set of known safe characters (low ASCII a-z, A-Z, 0-9, space, period, comma, dash, and underscore for HTML encoding) and encode everything else. This quite nicely takes care of both security and appearance issues, and you may wish to seriously consider using this approach rather than calling System.Web.HttpUtility.HtmlEncode to perform your HTML encoding. &lt;/p&gt;
&lt;p&gt;Regardless of which HTML encoding approach you select, you&amp;#39;re quickly going to run into a bit of trouble with double encoding if you simply start assigning pre-encoded text to control properties (&lt;i&gt;e.g.&lt;/i&gt;: someTextBox.Text = HttpUtility.HtmlEncode(someString)). When dealing with malicious input, this is pretty much a non-issue. However, not all data that ought to be encoded is malicious, and you usually wouldn&amp;#39;t want users seeing stuff like &lt;b&gt;a&amp;nbsp;&amp;amp;gt;&amp;nbsp;b&lt;/b&gt; rather than &lt;b&gt;a&amp;nbsp;&amp;gt;&amp;nbsp;b&lt;/b&gt;. Unfortunately, if we want to avoid double encoding in the set of controls that perform non-overrideable encoding (including attribute encoding), we need to use custom controls. To make matters worse, it can require rather a lot of work to subclass most of the controls in order to override the encoding behaviour. In quite a few cases, simply starting from scratch would probably make more sense than trying to subclass the built-in controls. Also, even for those controls where double encoding wouldn&amp;#39;t be an issue (&lt;i&gt;e.g.&lt;/i&gt;: Label, CheckBox), it&amp;#39;s probably worth considering using custom controls anyway since the pain of authoring the custom control isn&amp;#39;t likely to outweigh the cumulative effort of all the manual encoding calls you might make across all your projects. &lt;/p&gt;
&lt;p&gt;Don&amp;#39;t like these workarounds? Maybe it&amp;#39;s time to start &lt;a href="https://connect.microsoft.com/default.aspx"&gt;complaining&lt;/a&gt;...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=102957" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/calinoiu/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>What’s wrong with ASP.NET?  Validation</title><link>http://msmvps.com/blogs/calinoiu/archive/2006/06/09/102956.aspx</link><pubDate>Fri, 09 Jun 2006 16:20:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:102956</guid><dc:creator>calinoiu</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/rsscomments.aspx?PostID=102956</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/commentapi.aspx?PostID=102956</wfw:comment><comments>http://msmvps.com/blogs/calinoiu/archive/2006/06/09/102956.aspx#comments</comments><description>&lt;P&gt;ASP.NET introduced a fancy new user input validation framework that, at least at first glance, appears to be a great advance over the complete lack of built-in validation support in ASP.OLD. Declarative validation is certainly wonderful stuff, and getting client-side validation with no additional effort (at least if your clients are using supported browsers) isn’t too shabby either. Overall, using the built-in validation controls certainly seems like a good idea, particularly for those folks who wouldn’t be performing any validation otherwise because of the amount of work involved.&lt;/P&gt;
&lt;P&gt;But what about those of us who had been performing validation all along? Do the ASP.NET validation controls really offer equivalent protection to our former "manual" validation? Unfortunately, for many of us, the answer is probably "no". The main problem lies with the validation paradigm chosen for ASP.NET, which has the following properties:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Each validation control operates independently of the others. 
&lt;LI&gt;The validation process does not output a validated value.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;So what’s wrong with that, you ask? Well, each of the validation controls needs to re-read the target control value, as does the code that will ultimately process that value. To make the problem a bit more concrete, let’s look at the example of validating a birth date provided via a text box:&lt;/P&gt;&lt;BR&gt;
&lt;TABLE class=standardPostTable cellSpacing=0 cellPadding=4&gt;

&lt;TR&gt;
&lt;TH&gt;&lt;/TH&gt;
&lt;TH align=left class=standardPostTable&gt;Validation rule&lt;/TH&gt;
&lt;TH align=left class=standardPostTable&gt;Validation control&lt;/TH&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;1&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Value is required.&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;RequiredFieldValidator&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;2&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Value must be parseable to a valid date value without any time portion.&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;CompareValidator&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;3&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Date may not be in the future or more than 130 years in the past.&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;CompareValidator &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=standardPostTable&gt;4&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;If the value indicates an age of less than 10 years or greater than 90 years, the user must provide confirmation that the value is correct (as opposed to a data entry error).&lt;/TD&gt;
&lt;TD class=standardPostTable&gt;Custom control for soft validation&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;BR&gt;
&lt;P&gt;In the above example, each validation control reads the text box value independently, which means that they cannot build upon parsing and restriction steps performed by the other validators. In addition, when our code needs to process the birth date, it must go back to the text box and read the string value again. That mean that there are at least 5 reads and 4 separate parsing operations from the original text box value, each of which represents an opportunity to parse inconsistently with respect to culture and/or format. In addition, there’s no guarantee that each of those 5 reads is even accessing the same value since it’s possible for the text box’s Text property to be altered between the reads (even if this is somewhat unlikely in an ASP.NET app).&lt;/P&gt;
&lt;P&gt;How can we address this problem? There are plenty of workarounds, including using only custom validation controls, but that means quite a bit more work for developers. A much more reliable approach would involve reading the "raw" value from the text box only once. It would then be passed from one validator to another in a pre-defined order and would only require a single parsing. In the birth date example, the validator at step 2 would output a strongly typed DateTime value (assuming, of course, that step 2 validation passed), and that’s the value that would be passed to the validator at step 3. The output from step 5 would be the value that our code would read, rather than going back to the text box to read its Text property.&lt;/P&gt;
&lt;P&gt;It’s entirely feasible to develop such a framework, but it’s also quite a bit of a lot of work, particularly when one considers addition of appropriate design-time support. It’s obviously not the sort of thing on which most shops would want their developers spending time. Unfortunately, it’s also not the sort of thing that many shops would be willing to pay for as a third-party product, particularly given that most developers probably perceive themselves as getting by just fine with the existing ASP.NET validation controls.&lt;/P&gt;
&lt;P&gt;On the other hand, it would probably be a reasonably small project on the Microsoft scale of things, and I suspect that I’m not the only one who would sleep better if the built-in tools would help the Morts of this world develop more reliable and secure applications out of the box, particularly given that most of us use applications built on those tools sooner on a more or less regular basis.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=102956" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/calinoiu/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>What’s wrong with ASP.NET?</title><link>http://msmvps.com/blogs/calinoiu/archive/2006/06/09/102954.aspx</link><pubDate>Fri, 09 Jun 2006 16:18:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:102954</guid><dc:creator>calinoiu</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/rsscomments.aspx?PostID=102954</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/calinoiu/commentapi.aspx?PostID=102954</wfw:comment><comments>http://msmvps.com/blogs/calinoiu/archive/2006/06/09/102954.aspx#comments</comments><description>&lt;P&gt;For quite some time now, I’ve been harbouring an increasing bit of frustration with ASP.NET. Overall, I like the platform, and I think that it’s a great advance over ASP.OLD. Unfortunately, there are a few areas in which I can’t help but feel that the design team missed the boat by just a wee bit too much, and compensating for these lacunae can mean a ridiculous amount of work for the individual developer.&lt;/P&gt;
&lt;P&gt;There are three main areas that have been grating on my nerves of late: 
&lt;OL&gt;
&lt;LI&gt;User input validation 
&lt;LI&gt;HTML encoding 
&lt;LI&gt;Culture usage&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;I’d love to see the ASP.NET team address fundamentals like these in upcoming versions, but new features generally garner considerably more interest amongst users&amp;nbsp;than fixing things that very few people ever realized were broken. In an attempt to perhaps rouse a bit of interest in the latter, I’m starting a short series of posts on the above topics, starting with &lt;A href="http://spaces.msn.com/calinoiu/blog/cns!31EA56DADA219211!175.entry"&gt;What’s wrong with ASP.NET? Validation&lt;/A&gt;.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=102954" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/calinoiu/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item></channel></rss>