<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-7563542181873269057</atom:id><lastBuildDate>Mon, 06 Sep 2010 13:26:12 +0000</lastBuildDate><title>.NET Addict</title><description>A glimpse into the daily affairs of an ASP.NET &lt;em&gt;MVC&lt;/em&gt; developer by Nathan Taylor.</description><link>http://blog.nathan-taylor.net/</link><managingEditor>noreply@blogger.com (Nathan Taylor)</managingEditor><generator>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/lakario" /><feedburner:info uri="lakario" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-8894595917231182078</guid><pubDate>Thu, 08 Jul 2010 16:06:00 +0000</pubDate><atom:updated>2010-07-08T10:10:51.653-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">absolute url</category><category domain="http://www.blogger.com/atom/ns#">regular expression</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">relative url</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>ASP.NET – Convert Relative URL to Absolute</title><description>&lt;p&gt;Having built a blogging engine into my proprietary content management system at work, one thing I have to deal with in terms of the blog is making sure that any blog posts with references to website content make use of a fully-qualified, absolute URLs when they are rendered in the RSS feed.&lt;/p&gt;  &lt;p&gt;Here’s two extension methods that will convert relative URLs into absolute URLs which include the full host name and port (if applicable). The first method will take a single app-relative URL (~/path/to/foo) and fully-qualify it, while the second method accepts a block of HTML and uses regular expressions to match HTML attributes which contain root-relative URLs (/path/to/foo) and replaces them using the first method.&lt;/p&gt;  &lt;pre class="brush: csharp; gutter: false;"&gt;/// &amp;lt;summary&amp;gt;
/// Converts the provided app-relative path into an absolute Url containing the full host name
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;relativeUrl&amp;quot;&amp;gt;App-Relative path&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;Provided relativeUrl parameter as fully qualified Url&amp;lt;/returns&amp;gt;
/// &amp;lt;example&amp;gt;~/path/to/foo to http://www.web.com/path/to/foo&amp;lt;/example&amp;gt;
public static string ToAbsoluteUrl(this string relativeUrl) {
    if (string.IsNullOrEmpty(relativeUrl))
        return relativeUrl;

    if (HttpContext.Current == null)
        return relativeUrl;

    if (relativeUrl.StartsWith(&amp;quot;/&amp;quot;))
        relativeUrl = relativeUrl.Insert(0, &amp;quot;~&amp;quot;);
    if (!relativeUrl.StartsWith(&amp;quot;~/&amp;quot;))
        relativeUrl = relativeUrl.Insert(0, &amp;quot;~/&amp;quot;);

    var url = HttpContext.Current.Request.Url;
    var port = url.Port != 80 ? (&amp;quot;:&amp;quot; + url.Port) : String.Empty;

    return String.Format(&amp;quot;{0}://{1}{2}{3}&amp;quot;, url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
}

/// &amp;lt;summary&amp;gt;
/// Converts all root-relatives Urls within the provided HTML string to absolute Urls
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;returns&amp;gt;Provided HTML parameter with fully qualified Urls substituted&amp;lt;/returns&amp;gt;
/// &amp;lt;example&amp;gt;href=&amp;quot;/path/to/foo.jpg&amp;quot; to href=&amp;quot;http://www.web.com/path/to/foo.jpg&amp;quot;&amp;lt;/example&amp;gt;
/// &amp;lt;example&amp;gt;@import url(/path/to/foo) to @import url(http://www.web.com/path/to/foo)&amp;lt;/example&amp;gt;
public static string HtmlAppRelativeUrlsToAbsoluteUrls(this string html) {
    if (String.IsNullOrEmpty(html))
        return html;

    const string htmlPattern = &amp;quot;(?&amp;lt;attrib&amp;gt;\\shref|\\ssrc|\\sbackground)\\s*?=\\s*?&amp;quot;
                              + &amp;quot;(?&amp;lt;delim1&amp;gt;[\&amp;quot;'\\\\]{0,2})(?!#|http|ftp|mailto|javascript)&amp;quot;
                              + &amp;quot;/(?&amp;lt;url&amp;gt;[^\&amp;quot;'&amp;gt;\\\\]+)(?&amp;lt;delim2&amp;gt;[\&amp;quot;'\\\\]{0,2})&amp;quot;;
    
    Regex htmlRegex = new Regex(htmlPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
    html = htmlRegex.Replace(html, m =&amp;gt; htmlRegex.Replace(m.Value, &amp;quot;${attrib}=${delim1}&amp;quot; + (&amp;quot;~/&amp;quot; + m.Groups[&amp;quot;url&amp;quot;].Value).ToAbsoluteUrl() + &amp;quot;${delim2}&amp;quot;));

    const string cssPattern = &amp;quot;@import\\s+?(url)*['\&amp;quot;(]{1,2}&amp;quot;
                              + &amp;quot;(?!http)\\s*/(?&amp;lt;url&amp;gt;[^\&amp;quot;')]+)['\&amp;quot;)]{1,2}&amp;quot;;

    Regex cssRegex = new Regex(cssPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
    html = cssRegex.Replace(html, m =&amp;gt; cssRegex.Replace(m.Value, &amp;quot;@import url(&amp;quot; + (&amp;quot;~/&amp;quot; + m.Groups[&amp;quot;url&amp;quot;].Value).ToAbsoluteUrl() + &amp;quot;)&amp;quot;));

    return html;
}&lt;/pre&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a title="If You Like Regular Expressions So Much, Why Don&amp;#39;t You Marry Them?" href="http://www.codinghorror.com/blog/2005/03/if-you-like-regular-expressions-so-much-why-dont-you-marry-them.html"&gt;Thanks to Jeff Atwood&lt;/a&gt; for the awesome regular expressions that are the magic behind this code. &lt;/li&gt;
&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-8894595917231182078?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sWJWBALvAlJY_YI48sJi1zMs7DY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sWJWBALvAlJY_YI48sJi1zMs7DY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sWJWBALvAlJY_YI48sJi1zMs7DY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sWJWBALvAlJY_YI48sJi1zMs7DY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=cl4_9IHA80U:FRhk3zTcYfY:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=cl4_9IHA80U:FRhk3zTcYfY:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=cl4_9IHA80U:FRhk3zTcYfY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=cl4_9IHA80U:FRhk3zTcYfY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=cl4_9IHA80U:FRhk3zTcYfY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/cl4_9IHA80U" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/cl4_9IHA80U/aspnet-convert-relative-url-to-absolute.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/07/aspnet-convert-relative-url-to-absolute.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-5752753983768330682</guid><pubDate>Tue, 22 Jun 2010 00:02:00 +0000</pubDate><atom:updated>2010-06-23T18:48:10.123-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web.config</category><category domain="http://www.blogger.com/atom/ns#">permanent redirect</category><category domain="http://www.blogger.com/atom/ns#">httpmodule</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">301 redirect</category><category domain="http://www.blogger.com/atom/ns#">redirect</category><category domain="http://www.blogger.com/atom/ns#">http status code</category><category domain="http://www.blogger.com/atom/ns#">moved permanently</category><title>ASP.NET - Redirect Module</title><description>&lt;p&gt;As developers we are all intimately aware of the implications of changing the URL of existing content in our applications which have already been indexed by search engines and users. It is never enough to simply change a URL and update the links because old pages, bookmarks, or search results may still point to the original URL. That being so, it is imperative to add an appropriate &lt;a title="HTTP 301" href="http://en.wikipedia.org/wiki/HTTP_301"&gt;HTTP 301 redirect&lt;/a&gt; for the original URL when modifying the location of existing content. &lt;/p&gt;  &lt;p&gt;In Apache-based web servers adding a 301 Redirect is as simple as adding a &lt;a href="http://httpd.apache.org/docs/2.1/howto/htaccess.html"&gt;.htaccess file&lt;/a&gt; with the appropriate mod_rewrite instructions; unfortunately, this simplicity of configuration is unavailable on an IIS server and when an application requires a redirect be added we are forced to either edit the IIS settings explicitly or add the redirect to the application’s code. Ultimately, the former solution is ideal because it allows IIS to bypass the ASP.NET request engine and immediately serve the redirect, but for many of us, editing the IIS configuration is not an option due to the use of shared hosting environments. In ASP.NET code, issuing a 301 Redirect in your Global.asax looks something like this: &lt;/p&gt;  &lt;pre class="brush: csharp; gutter: false; toolbar: false;"&gt;protected void Application_BeginRequest(object sender, EventArgs e) {
    var oldUrl = new Uri(&amp;quot;http://www.website.com/path/to/content&amp;quot;);
    var newUrl = new Uri(&amp;quot;http://www.website.com/new/path/to/content&amp;quot;);

    if(string.Equals(Request.Url.AbsolutePath, oldUrl.AbsolutePath, StringComparison.OrdinalIgnoreCase)) {
        Response.StatusCode = 301;
        Response.Status = &amp;quot;301 Moved Permanently&amp;quot;;
        Response.RedirectLocation = newUrl;
        Response.End();
    }
}&lt;/pre&gt;

&lt;p&gt;While searching for a more maintainable solution I came across &lt;a href="http://www.hanselman.com/blog/PermanentRedirectsWithHTTP301.aspx"&gt;a blog post by Scott Hanselman&lt;/a&gt; which directed me to &lt;a href="http://www.pluralsight-training.net/community/blogs/fritz/archive/2004/07/21/1651.aspx"&gt;a HttpModule written by Fritz Onion&lt;/a&gt;. The module developed is elegant and effective because it uses a special section in the website's configuration file to define each redirect, thus minimizing maintenance challenges associated with adding and removing individual redirects. That being said, Fritz's solution is dated and uses some obsolete code so I have gone ahead and modernized it a bit. In addition to the original feature set, I have &lt;strong&gt;added support for matching the entire request URL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Issuing redirects with the module is as easy as registering and adding the &amp;lt;redirections /&amp;gt; configuration section and then declaring each redirect rule. &lt;/p&gt;

&lt;pre class="brush: xml; gutter: false;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;section name=&amp;quot;redirections&amp;quot; type=&amp;quot;RedirectModule.RedirectionsSection, RedirectModule&amp;quot;/&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;redirections&amp;gt;
    &amp;lt;add targetUrl=&amp;quot;^http://website.com&amp;quot; destinationUrl=&amp;quot;http://www.website.com&amp;quot; ignoreCase=&amp;quot;true&amp;quot; /&amp;gt;
    &amp;lt;add targetUrl=&amp;quot;^~/FalseTarget.aspx&amp;quot; destinationUrl=&amp;quot;~/RealTarget.aspx&amp;quot; ignoreCase=&amp;quot;true&amp;quot;/&amp;gt;
    &amp;lt;add targetUrl=&amp;quot;^~/2ndFalseTarget.aspx&amp;quot; destinationUrl=&amp;quot;~/RealTarget.aspx&amp;quot; permanent=&amp;quot;true&amp;quot;/&amp;gt;
    &amp;lt;add targetUrl=&amp;quot;^~/(Author|Category|Tool)([A-Za-z0\d]{8}-?[A-Za-z\d]{4}-?[A-Za-z\d]{4}-?[A-Za-z\d]{4}-?[A-Za-z\d]{12}).aspx$&amp;quot; destinationUrl=&amp;quot;~/Pages/$1.aspx?$1=$2&amp;quot;/&amp;gt;
    &amp;lt;add targetUrl=&amp;quot;^~/SomeDir/(.*).aspx\??(.*)&amp;quot; destinationUrl=&amp;quot;~/Pages/$1/Default.aspx?$2&amp;quot;/&amp;gt;
  &amp;lt;/redirections&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;httpModules&amp;gt;
      &amp;lt;add name=&amp;quot;RedirectModule&amp;quot; type=&amp;quot;RedirectModule.RedirectModule&amp;quot;/&amp;gt;
    &amp;lt;/httpModules&amp;gt;
  &amp;lt;/system.web&amp;gt;
  &amp;lt;system.webServer&amp;gt;
    &amp;lt;modules runAllManagedModulesForAllRequests=&amp;quot;true&amp;quot;&amp;gt;
      &amp;lt;add name=&amp;quot;RedirectModule&amp;quot; type=&amp;quot;RedirectModule.RedirectModule, RedirectModule/&amp;gt;
    &amp;lt;/modules&amp;gt;
  &amp;lt;/system.webServer&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;strong&gt;&lt;a href="http://www.nathan-taylor.net/files/RedirectModule.zip"&gt;Download the Full Source Code with Demo Here&lt;/a&gt;&lt;/strong&gt; 

&lt;br /&gt;

&lt;br /&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.hanselman.com/blog/PermanentRedirectsWithHTTP301.aspx" target="_blank"&gt;Permanent Redirects with HTTP 301 - Scott Hanselman&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.pluralsight-training.net/community/blogs/fritz/archive/2004/07/21/1651.aspx" target="_blank"&gt;Redirect Module - Fritz Onion&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-5752753983768330682?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZFh_Obt3u69bHIlmIH9UxBFoeNA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZFh_Obt3u69bHIlmIH9UxBFoeNA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZFh_Obt3u69bHIlmIH9UxBFoeNA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZFh_Obt3u69bHIlmIH9UxBFoeNA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=0Eo8ldWTAUs:pmYlbczsCZQ:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=0Eo8ldWTAUs:pmYlbczsCZQ:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=0Eo8ldWTAUs:pmYlbczsCZQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=0Eo8ldWTAUs:pmYlbczsCZQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=0Eo8ldWTAUs:pmYlbczsCZQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/0Eo8ldWTAUs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/0Eo8ldWTAUs/aspnet-redirect-module.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/06/aspnet-redirect-module.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-8736560222557420798</guid><pubDate>Tue, 08 Jun 2010 23:30:00 +0000</pubDate><atom:updated>2010-06-10T10:52:02.357-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">flagsattribute</category><category domain="http://www.blogger.com/atom/ns#">flags</category><category domain="http://www.blogger.com/atom/ns#">bitwise-or</category><category domain="http://www.blogger.com/atom/ns#">defaultmodelbinder</category><category domain="http://www.blogger.com/atom/ns#">enumeration</category><category domain="http://www.blogger.com/atom/ns#">bitwise enumeration</category><category domain="http://www.blogger.com/atom/ns#">flags enumeration</category><category domain="http://www.blogger.com/atom/ns#">bit</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">bitwise</category><category domain="http://www.blogger.com/atom/ns#">asp.net mvc</category><title>ASP.NET MVC Flags Enumeration Model Binder</title><description>&lt;p&gt;The default model binder that ships with ASP.NET MVC 2 handles the large majority of databinding scenarios; however, one feature it does not support is combining a set of flags enumeration values into a single value. With the default model binder if you try to post a form with multiple enumeration values for a single model item, the returned model will contain only the last enumeration value provided by the form.&lt;/p&gt;  &lt;p&gt;To solve this problem I created a FlagsEnumerationModelBinder to automatically handle the bitwise-or operation required to combine the enumeration values. Given a controller action that receives a model item of an enumeration type with the &lt;a title="System.FlagsAttribute Class" href="http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx"&gt;FlagsAttribute&lt;/a&gt; set, on BindModel() the FlagsEnumerationModelBinder will first check that there is more than one enumeration value in the request and then bitwise-or each individual value into a single byte value which is then returned in a call to &lt;a title="Enum.Parse Method" href="http://msdn.microsoft.com/en-us/library/system.enum.parse.aspx"&gt;Enum.Parse(Type, String)&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="brush: csharp; gutter: false;"&gt;public class FlagEnumerationModelBinder : DefaultModelBinder&lt;br /&gt;{&lt;br /&gt;    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {&lt;br /&gt;        if (bindingContext == null) throw new ArgumentNullException(&amp;quot;bindingContext&amp;quot;);&lt;br /&gt;&lt;br /&gt;        if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) {  &lt;br /&gt;            var values = GetValue&amp;lt;string[]&amp;gt;(bindingContext, bindingContext.ModelName);&lt;br /&gt;&lt;br /&gt;            if (values.Length &amp;gt; 1 &amp;amp;&amp;amp; (bindingContext.ModelType.IsEnum &amp;amp;&amp;amp; bindingContext.ModelType.IsDefined(typeof(FlagsAttribute), false))) {&lt;br /&gt;                long byteValue = 0;&lt;br /&gt;                foreach (var value in values.Where(v =&amp;gt; Enum.IsDefined(bindingContext.ModelType, v))) {&lt;br /&gt;                    byteValue |= (int)Enum.Parse(bindingContext.ModelType, value);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                return Enum.Parse(bindingContext.ModelType, byteValue.ToString());&lt;br /&gt;            }&lt;br /&gt;            else {&lt;br /&gt;                return base.BindModel(controllerContext, bindingContext);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return base.BindModel(controllerContext, bindingContext);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static T GetValue&amp;lt;T&amp;gt;(ModelBindingContext bindingContext, string key) {&lt;br /&gt;        if (bindingContext.ValueProvider.ContainsPrefix(key)) {&lt;br /&gt;            ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(key);&lt;br /&gt;            if (valueResult != null) {&lt;br /&gt;                bindingContext.ModelState.SetModelValue(key, valueResult);&lt;br /&gt;                return (T)valueResult.ConvertTo(typeof(T));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return default(T);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt; &lt;p&gt;The FlagsEnumerationModelBinder assumes that each enumeration value in the request has the same field name. The values can be in string or numeric form.&lt;/p&gt; &lt;p&gt;Careful about using the Html.CheckBox() extension to select your enumeration values in the form because the CheckBox and RadioButton helpers output an additional hidden value for each field that is sent with the request whether or not the field is checked. If you use the helpers you’ll end up with “true” and “false” values in the request which are [probably] not part of your enumeration.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-8736560222557420798?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/IZajCydyZG5Wd6-ms0G_TrnIjmI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IZajCydyZG5Wd6-ms0G_TrnIjmI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/IZajCydyZG5Wd6-ms0G_TrnIjmI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IZajCydyZG5Wd6-ms0G_TrnIjmI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=X-VjG7AJ_MA:EDrtKHF-Qr4:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=X-VjG7AJ_MA:EDrtKHF-Qr4:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=X-VjG7AJ_MA:EDrtKHF-Qr4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=X-VjG7AJ_MA:EDrtKHF-Qr4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=X-VjG7AJ_MA:EDrtKHF-Qr4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/X-VjG7AJ_MA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/X-VjG7AJ_MA/aspnet-mvc-flags-enumeration-model.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>3</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/06/aspnet-mvc-flags-enumeration-model.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-4797416918819678609</guid><pubDate>Tue, 11 May 2010 16:53:00 +0000</pubDate><atom:updated>2010-09-05T15:17:31.920-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">truncate</category><category domain="http://www.blogger.com/atom/ns#">substring</category><category domain="http://www.blogger.com/atom/ns#">string manipulation</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">string</category><title>C# Truncate String</title><description>&lt;p&gt;Something I find myself needing to do quite often is truncate a string to a maximum pre-determined length for display purposes. This is easily accomplished using the &lt;tt&gt;string.Substring(int, int)&lt;/tt&gt; method, however this approach is limited by the fact that without checking the length of the string being truncated, the Substring() method will throw an exception if the second parameter passed to is exceeds the actual length of the string. &lt;/p&gt;Nothing fancy, but here is an extension method to save the trouble of manually evaluating the string before displaying it:  &lt;pre class="brush: csharp; gutter: false;"&gt;public static string Truncate(this string str, int maxLength) {
    if (str == null) return null;
    return str.Substring(0, Math.Min(maxLength, str.Length));
}&lt;/pre&gt;Simply call &lt;tt&gt;string.Truncate(int)&lt;/tt&gt; and the returned string will be chopped accordingly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-4797416918819678609?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dPsWaKDfLdp_mOJoHTuOzpZyMW4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dPsWaKDfLdp_mOJoHTuOzpZyMW4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dPsWaKDfLdp_mOJoHTuOzpZyMW4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dPsWaKDfLdp_mOJoHTuOzpZyMW4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=4TZorrXwi4Y:FJ8nY65afA0:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=4TZorrXwi4Y:FJ8nY65afA0:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=4TZorrXwi4Y:FJ8nY65afA0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=4TZorrXwi4Y:FJ8nY65afA0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=4TZorrXwi4Y:FJ8nY65afA0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/4TZorrXwi4Y" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/4TZorrXwi4Y/c-truncate-string.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/05/c-truncate-string.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-5548198534471295670</guid><pubDate>Thu, 22 Apr 2010 19:29:00 +0000</pubDate><atom:updated>2010-07-01T13:47:34.244-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">htmlhelper</category><category domain="http://www.blogger.com/atom/ns#">tagcloud</category><category domain="http://www.blogger.com/atom/ns#">tag</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">asp.net mvc</category><category domain="http://www.blogger.com/atom/ns#">css</category><title>How to Make a Tag Cloud in ASP.NET MVC</title><description>&lt;p&gt;As many of you are aware, tagging offers users a quick and easy way to filter website content by interesting topics or categories and a tag cloud acts as a visually asethetic way to display links to all of the available tags with their prevelance indicated by font-size. Lately tag clouds have become very popular and they can be found all over the web in many different formats, but the most common format usually looks something like this: &lt;/p&gt;  &lt;p style="width: 375px"&gt;&lt;a href="http://lh4.ggpht.com/_ZIHyZ-EOj1g/S9Cjq2cA4JI/AAAAAAAAADE/pjR6DcYuiOU/s1600-h/tagcloud%5B6%5D.jpg" linkindex="16"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="tagcloud" border="0" alt="tagcloud" src="http://lh3.ggpht.com/_ZIHyZ-EOj1g/S9CjrlC8DeI/AAAAAAAAADI/PwGzElpGpyg/tagcloud_thumb%5B2%5D.jpg?imgmax=800" width="372" height="173" /&gt;&lt;/a&gt; &lt;span style="text-align: right; font-size: smaller" align="right"&gt;Thanks, &lt;a href="http://haacked.com/" linkindex="17"&gt;Phil Haacked&lt;/a&gt;. :)&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;In this tutorial I will show you how to make a simple tag cloud with 5 different size distributions based on the frequency of each tag. The code I have built is contained inside of an HtmlHelper which accepts a Dictionary&amp;lt;string, int&amp;gt; containing the tags and their occurrence counts in each pair and a Func&amp;lt;string, string&amp;gt; which is called on each tag to produce the link which will be displayed. Before we build the tag cloud, we’ll need to get the tags out of our database along with their number of occurrences. This code will obviously vary based on your tagging implementation, but will probably look something like this:&lt;/p&gt;  &lt;pre class="brush: csharp; gutter: false; toolbar: false;"&gt;(from tag in Tags 
 group tag by tag.Name 
 into g 
 select g).ToDictionary(g =&amp;gt; g.Key, g =&amp;gt; g.Count());&lt;/pre&gt;

&lt;p&gt;Once we have the tag list in hand we need to find the mimimum and maximum tag counts and establish a distribution between the difference of the minmum and maximum values.&lt;/p&gt;

&lt;pre class="brush: csharp; gutter: false; toolbar: false;"&gt;var min = tagList.Min(t =&amp;gt; t.Value);
var max = tagList.Max(t =&amp;gt; t.Value);
var dist = (max - min) / 3;&lt;/pre&gt;

&lt;p&gt;The code for this tag cloud supports a total of 5 different sizes, but if you require more you can increase the divisor of the distribution equation and update the CSS class assignment logic accordingly. With the minimum, maximum and distribution values calculated we can now loop through all of the tags and assign CSS classes to each one based on their position in the distribution.&lt;/p&gt;

&lt;pre class="brush: csharp; gutter: false; toolbar: false;"&gt;var links = new StringBuilder();
foreach (var tag in tagsAndCounts) {
    string tagClass;
    
    if (tag.Value == max) {
        tagClass = &amp;quot;largest&amp;quot;;
    }
    else if (tag.Value &amp;gt; (min + (dist * 2))) {
        tagClass = &amp;quot;large&amp;quot;;
    }
    else if (tag.Value &amp;gt; (min + dist)) {
        tagClass = &amp;quot;medium&amp;quot;;
    }
    else if (tag.Value == min) {
        tagClass = &amp;quot;smallest&amp;quot;;
    }
    else {
        tagClass = &amp;quot;small&amp;quot;;
    }

    links.AppendFormat(&amp;quot;&amp;lt;a href=\&amp;quot;{0}\&amp;quot; title=\&amp;quot;{1}\&amp;quot; class=\&amp;quot;{2}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;{3}&amp;quot;, 
                        urlExpression(tag.Key), tag.Key, tagClass, Environment.NewLine);
}&lt;/pre&gt;

&lt;p&gt;After running the above code we now have all of the tag links in a StringBuilder which we can push to the output. Notice in the final line of the foreach loop I am calling &lt;tt&gt;urlExpression(tag.Key)&lt;/tt&gt; this is the Func&amp;lt;string, string&amp;gt; I mentioned above that is used to return the Url for the tag.&lt;/p&gt;

&lt;p&gt;Now that we have all the pieces, here's the full code for the HtmlHelper:&lt;/p&gt;

&lt;pre class="brush: csharp; gutter: false; toolbar: false;"&gt;public static MvcHtmlString TagCloud(this HtmlHelper html, IDictionary&amp;lt;string, int&amp;gt; tagsAndCounts, Func&amp;lt;string, string&amp;gt; urlExpression, object htmlAttributes) {
    if (tagsAndCounts == null || !tagsAndCounts.Any())
        return MvcHtmlString.Empty;
    
    var min = tagsAndCounts.Min(t =&amp;gt; t.Value);
    var max = tagsAndCounts.Max(t =&amp;gt; t.Value);
    var dist = (max - min) / 3;
    
    var links = new StringBuilder();
    foreach (var tag in tagsAndCounts) {
        string tagClass;
        
        if (tag.Value == max) {
            tagClass = &amp;quot;largest&amp;quot;;
        }
        else if (tag.Value &amp;gt; (min + (dist * 2))) {
            tagClass = &amp;quot;large&amp;quot;;
        }
        else if (tag.Value &amp;gt; (min + dist)) {
            tagClass = &amp;quot;medium&amp;quot;;
        }
        else if (tag.Value == min) {
            tagClass = &amp;quot;smallest&amp;quot;;
        }
        else {
            tagClass = &amp;quot;small&amp;quot;;
        }

        links.AppendFormat(&amp;quot;&amp;lt;a href=\&amp;quot;{0}\&amp;quot; title=\&amp;quot;{1}\&amp;quot; class=\&amp;quot;{2}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;{3}&amp;quot;, 
                           urlExpression(tag.Key), tag.Key, tagClass, Environment.NewLine);
    }
    
    var div = new TagBuilder(&amp;quot;div&amp;quot;);
    div.MergeAttribute(&amp;quot;class&amp;quot;, &amp;quot;tag-cloud&amp;quot;);
    div.InnerHtml = links.ToString();
    
    if (htmlAttributes != null) {
        div.MergeAttributes(new RouteValueDictionary(htmlAttributes), false);
    }
    
    return MvcHtmlString.Create(div.ToString());
}&lt;/pre&gt;

&lt;p&gt;And here's the appropriate CSS:&lt;/p&gt;

&lt;pre class="brush: css; gutter: false;"&gt;.tag-cloud { text-align: center; }
.tag-cloud a { white-space: nowrap; padding: 5px; display: inline-block; }
.tag-cloud a:hover { background-color: #E1E1E1;}
.tag-cloud .smallest { font-size: 75%;}
.tag-cloud .small { font-size: 100%; }
.tag-cloud .medium { font-size: 125%;}
.tag-cloud .large { font-size: 150%; }
.tag-cloud .largest { font-size: 200%; }&lt;/pre&gt;

&lt;p&gt;In order to use the above code simply place it in an extension method class, reference the CSS, and call it your view like so:&lt;/p&gt;

&lt;pre class="brush: csharp; gutter: false; toolbar: false;"&gt;&amp;lt;%= Html.TagCloud(Model.Tags, t =&amp;gt; Url.Tag(t), null) %&amp;gt;&lt;/pre&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The basis for this code comes from &lt;a href="http://www.petefreitag.com/item/396.cfm" linkindex="18"&gt;Pete Freitag's Blog&lt;/a&gt; in a similar post that discusses building a tag cloud with ColdFusion. &lt;/li&gt;
&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-5548198534471295670?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PUoZrS6j9R8M_8aUzeLSa_hf3WA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PUoZrS6j9R8M_8aUzeLSa_hf3WA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PUoZrS6j9R8M_8aUzeLSa_hf3WA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PUoZrS6j9R8M_8aUzeLSa_hf3WA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9KjLSLEbDk4:KwnMjwBoeM4:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9KjLSLEbDk4:KwnMjwBoeM4:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9KjLSLEbDk4:KwnMjwBoeM4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=9KjLSLEbDk4:KwnMjwBoeM4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9KjLSLEbDk4:KwnMjwBoeM4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/9KjLSLEbDk4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/9KjLSLEbDk4/how-to-make-tag-cloud-in-aspnet-mvc.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/04/how-to-make-tag-cloud-in-aspnet-mvc.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-5951677406584169382</guid><pubDate>Tue, 20 Apr 2010 21:25:00 +0000</pubDate><atom:updated>2010-07-08T02:50:13.474-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">system.componentmodel.dataannotations</category><category domain="http://www.blogger.com/atom/ns#">displaynameattribute</category><category domain="http://www.blogger.com/atom/ns#">system.componentmodel</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">validationattribute</category><category domain="http://www.blogger.com/atom/ns#">errormessageresourcetype</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">errormessageresourcename</category><category domain="http://www.blogger.com/atom/ns#">displayname</category><title>System.ComponentModel.DataAnnotations Validation Attributes – Using Error Message Resource Files</title><description>&lt;p&gt;Just a quick-tip if you’ve been making use of the wonderful set of model validation attributes available in &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;System.ComponentModel.DataAnnotations&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;If you elect to use the &lt;a href="http://msdn.microsoft.com/en-us/library/cc679227%28v=VS.100%29.aspx"&gt;ValidationAttribute&lt;/a&gt;’s &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.errormessageresourcename.aspx"&gt;ErrorMessageResourceName&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.errormessageresourcetype%28v=VS.100%29.aspx"&gt;ErrorMessageResourceType&lt;/a&gt; properties, make sure the resource file type you point to is marked with a &lt;strong&gt;Public&lt;/strong&gt; access modifier and not the default value of &lt;strong&gt;Internal&lt;/strong&gt; or you will find that all of your validation attributes will be silently ignored (including &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.displaynameattribute.aspx"&gt;System.ComponentModel.DisplayNameAttribute&lt;/a&gt;, interestingly enough).&lt;/p&gt;&lt;pre class="brush:csharp; gutter: false; toolbar: false;"&gt;[DisplayName(&amp;quot;Email&amp;quot;)]
[Required(ErrorMessageResourceName = &amp;quot;EmailMissing&amp;quot;, ErrorMessageResourceType = typeof(GeneralForms))]
public string Email { get; set; }&lt;/pre&gt;&lt;a href="http://lh5.ggpht.com/_ZIHyZ-EOj1g/S84buUrJ9HI/AAAAAAAAAC8/B-NgfAC3Lcc/s1600-h/resourceaccessmodifier%5B12%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="resourceaccessmodifier" border="0" alt="resourceaccessmodifier" src="http://lh6.ggpht.com/_ZIHyZ-EOj1g/S84bvdcaKmI/AAAAAAAAADA/u5NAye9pUCI/resourceaccessmodifier_thumb%5B8%5D.jpg?imgmax=800" width="444" height="57" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-5951677406584169382?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/d1k9Ti6jzg35hRAjc5FeeGRJW0A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d1k9Ti6jzg35hRAjc5FeeGRJW0A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/d1k9Ti6jzg35hRAjc5FeeGRJW0A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d1k9Ti6jzg35hRAjc5FeeGRJW0A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=-4n9zS4F_FA:l1jHI-4JFLQ:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=-4n9zS4F_FA:l1jHI-4JFLQ:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=-4n9zS4F_FA:l1jHI-4JFLQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=-4n9zS4F_FA:l1jHI-4JFLQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=-4n9zS4F_FA:l1jHI-4JFLQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/-4n9zS4F_FA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/-4n9zS4F_FA/systemcomponentmodeldataannotations.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/04/systemcomponentmodeldataannotations.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-3371021343306612728</guid><pubDate>Wed, 17 Feb 2010 20:38:00 +0000</pubDate><atom:updated>2010-02-17T14:13:22.194-07:00</atom:updated><title>ASP.NET MVC2 RC2 - Breaking Area Registration Change</title><description>With the release of ASP.NET MVC RC2 there is a breaking change in the way area registration works. As of RC2, all AreaRegistration types must be marked public, or they will be ignored by calls to AreaRegistration.RegisterAllAreas().

To me this seems rather arbitrary in nature, but I suspect the reasoning for the change stems from the fact that with the initial preview of MVC2 areas had to be implemented as separate projects. Thus, if the access modifier on the AreaRegistration type for a given Area project is not public, it would not be picked up by the call to RegisterAllAreas() in the main web project without violating access modifier constraints (private member reflection).

So to reiterate, if you were originally doing something like this:
&lt;pre class="brush:c#"&gt;
internal class AdminArea : AreaRegistration {}
&lt;/pre&gt;
You must change the access modifier to public in order for the area to be registered and added to the routes table.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-3371021343306612728?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/95o8hg-iqZJ6xcvUV8gKxx5pmBw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/95o8hg-iqZJ6xcvUV8gKxx5pmBw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/95o8hg-iqZJ6xcvUV8gKxx5pmBw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/95o8hg-iqZJ6xcvUV8gKxx5pmBw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=6JWvA7Fo7SU:DHi9NI7_azU:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=6JWvA7Fo7SU:DHi9NI7_azU:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=6JWvA7Fo7SU:DHi9NI7_azU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=6JWvA7Fo7SU:DHi9NI7_azU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=6JWvA7Fo7SU:DHi9NI7_azU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/6JWvA7Fo7SU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/6JWvA7Fo7SU/aspnet-mvc2-rc2-breaking-area.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2010/02/aspnet-mvc2-rc2-breaking-area.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-2669041188817672573</guid><pubDate>Thu, 29 Oct 2009 15:07:00 +0000</pubDate><atom:updated>2010-07-01T21:03:21.236-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web.config</category><category domain="http://www.blogger.com/atom/ns#">format</category><category domain="http://www.blogger.com/atom/ns#">build</category><category domain="http://www.blogger.com/atom/ns#">nant</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">template</category><category domain="http://www.blogger.com/atom/ns#">batch script</category><category domain="http://www.blogger.com/atom/ns#">nant script</category><category domain="http://www.blogger.com/atom/ns#">batch file</category><category domain="http://www.blogger.com/atom/ns#">utility</category><title>Multiple Web.config Management Utility</title><description>&lt;p&gt;Something we all face on a regular basis is managing our Web.config files across multiple deployment environments each with their own specific set of options. The trivial, but repetitive task of managing multiple config files can become quite tedious during development and in order to take some of that stress away I have built some utilities into my own build process that automatically maintain my config files for me, allowing me to worry about more important things. Using a simple batch script which executes some basic NAnt commands I am able to rapidly generate multiple web.config files from a single template with unique values in each. &lt;/p&gt;  &lt;p&gt;To do this, I make use of NAnt’s built-in file merging functionality which takes two files and substitutes values from one into specific locations in the other and produces a combined output. Applying this concept to creating web.config files, I have a single “web.config.format” file which looks like a normal configuration file, but contains ${Property.Name} markers in areas where a value with a given name should be substituted. I then create multiple “{deployment-type}.property” XML files which contain elements indicating each property name and its value. Finally, this is all tied together by a batch script which calls the appropriate merge commands on each file in a directory I specify.&lt;/p&gt; &lt;strong&gt;default.build (NAnt Script)&lt;/strong&gt;   &lt;pre class="brush: xml;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;project default=&amp;quot;configMerge&amp;quot;&amp;gt;
 &amp;lt;property name=&amp;quot;destinationfile&amp;quot;
   value=&amp;quot;web.config&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;propertyfile&amp;quot;
   value=&amp;quot;invalid.file&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;sourcefile&amp;quot;
   value=&amp;quot;web.format.config&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

 &amp;lt;include buildfile=&amp;quot;${propertyfile}&amp;quot; failonerror=&amp;quot;false&amp;quot;
   unless=&amp;quot;${string::contains(propertyfile, 'invalid.file')}&amp;quot; /&amp;gt;

 &amp;lt;target name=&amp;quot;configMerge&amp;quot;&amp;gt;
   &amp;lt;copy file=&amp;quot;${sourcefile}&amp;quot;
       tofile=&amp;quot;${destinationfile}&amp;quot; overwrite=&amp;quot;true&amp;quot;&amp;gt;
     &amp;lt;filterchain&amp;gt;
       &amp;lt;expandproperties /&amp;gt;
     &amp;lt;/filterchain&amp;gt;
   &amp;lt;/copy&amp;gt;
 &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;
&lt;strong&gt;Sample .Property File&lt;/strong&gt; 

&lt;pre class="brush: xml;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;project&amp;gt;
 &amp;lt;property name=&amp;quot;compilationDebug&amp;quot; value=&amp;quot;true&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;customErrorsMode&amp;quot; value=&amp;quot;Off&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;smtpServer&amp;quot; value=&amp;quot;mail.website.com&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;smtpFrom&amp;quot; value=&amp;quot;admin@website.com&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;googleAnalyticsKey&amp;quot; value=&amp;quot;UA-12345678-9&amp;quot; /&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;
&lt;strong&gt;Sample Web.config.format File&lt;/strong&gt; 

&lt;pre class="brush: xml;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
 &amp;lt;configSections&amp;gt;
   &amp;lt;sectionGroup name=&amp;quot;applicationSettings&amp;quot; type=&amp;quot;System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&amp;quot;&amp;gt;
     &amp;lt;section name=&amp;quot;Project.Properties.Settings&amp;quot; type=&amp;quot;System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&amp;quot; requirePermission=&amp;quot;false&amp;quot;/&amp;gt;
   &amp;lt;/sectionGroup&amp;gt;
 &amp;lt;/configSections&amp;gt;
 &amp;lt;appSettings&amp;gt;
   &amp;lt;add key=&amp;quot;GoogleAnalyticsKey&amp;quot; value=&amp;quot;${googleAnalyticsKey}&amp;quot; /&amp;gt;
 &amp;lt;/appSettings&amp;gt;
 &amp;lt;system.web&amp;gt;
   &amp;lt;customErrors mode=&amp;quot;${customErrorsMode}&amp;quot; defaultRedirect=&amp;quot;AppError.aspx&amp;quot;&amp;gt;
     &amp;lt;error statusCode=&amp;quot;404&amp;quot; redirect=&amp;quot;404.aspx&amp;quot;/&amp;gt;
   &amp;lt;/customErrors&amp;gt;
   &amp;lt;compilation debug=&amp;quot;${compilationDebug}&amp;quot; /&amp;gt;
 &amp;lt;/system.web&amp;gt;
 &amp;lt;system.net&amp;gt;
   &amp;lt;mailSettings&amp;gt;
     &amp;lt;smtp from=&amp;quot;${smtpFrom}&amp;quot; deliveryMethod=&amp;quot;Network&amp;quot;&amp;gt;
       &amp;lt;network host=&amp;quot;${smtpServer}&amp;quot; port=&amp;quot;25&amp;quot; defaultCredentials=&amp;quot;true&amp;quot; /&amp;gt;
     &amp;lt;/smtp&amp;gt;
   &amp;lt;/mailSettings&amp;gt;
 &amp;lt;/system.net&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;strong&gt;ConfigMerge.bat (NAnt script invoker)&lt;/strong&gt; 

&lt;pre class="brush: bash;"&gt;@ECHO OFF
SET formatFile=%2
SET outputDir=%1

IF &amp;quot;%2&amp;quot;==&amp;quot;&amp;quot; SET formatFile=%~dp0web.config.format

ECHO USING: %formatFile%
ECHO OUTPUT DIR: %outputDir%
ECHO.
IF NOT EXIST &amp;quot;%formatFile%&amp;quot; (
   ECHO Could not locate format file. Please provide a valid filename.
) ELSE (

   FOR /f %%p in ('dir /b &amp;quot;%~dp0*.property&amp;quot;') DO (
       ECHO GENERATING: web.%%~np.config FROM: %%p
       START /B /WAIT &amp;quot;NAnt&amp;quot; &amp;quot;%~dp0nant\nant.exe&amp;quot; -buildfile:&amp;quot;%~dp0default.build&amp;quot; configMerge -q+ -nologo+ -D:sourcefile=&amp;quot;%formatFile%&amp;quot; -D:propertyfile=&amp;quot;%~dp0%%p&amp;quot; -D:destinationfile=%outputDir%\web.%%~np.config
   )
)&lt;/pre&gt;

&lt;p&gt;To further simplify things, I built an additional batch script that invokes ConfigMerge.bat with it's first argument- output directory. By calling &lt;tt&gt;BuildWebConfigs.bat ..\Web&lt;/tt&gt; I can tell the NAnt script to output the generated config files in my website project's &amp;quot;Web&amp;quot; directory (and additionally replace Web.config with my Web.debug.config).&lt;/p&gt;
&lt;strong&gt;BuildWebConfigs.bat (ConfigMerge.bat invoker)&lt;/strong&gt; 

&lt;pre class="brush: bash;"&gt;@ECHO OFF
call &amp;quot;%~dp0build\ConfigMerge.bat&amp;quot; ..\Web
copy &amp;quot;%~dp0Web\web.debug.config&amp;quot; &amp;quot;%~dp0Web\web.config&amp;quot; /y
echo.
echo ********* BuildWebConfigs Complete *********&lt;/pre&gt;

&lt;p&gt;In the interest of convenience I added a call to the second batch script into my website project's build events and included it as an external tool which I can easily invoke from Visual Studio's UI:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ZIHyZ-EOj1g/SvBu_3etE3I/AAAAAAAAABU/4FDUY1J0tmc/s1600-h/ExternalTools.png"&gt;&lt;img style="width: 320px; height: 301px; cursor: pointer" id="BLOGGER_PHOTO_ID_5399937996720771954" border="0" alt="" src="http://3.bp.blogspot.com/_ZIHyZ-EOj1g/SvBu_3etE3I/AAAAAAAAABU/4FDUY1J0tmc/s320/ExternalTools.png" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Since Visual Studio doesn't let you define per-configuration build events in C# projects (as it does in C++ projects- or so I'm told) I manually edited the CSProj file and added an instruction at the very bottom to call my batch script on all non-Debug builds:&lt;/p&gt;
&lt;strong&gt;Partial .CSProj File&lt;/strong&gt; 

&lt;pre class="brush: xml;"&gt;&amp;lt;Project&amp;gt;
 ......
 .......
 ........
 &amp;lt;PropertyGroup Condition=&amp;quot; '$(ConfigurationName)' != 'Debug' &amp;quot;&amp;gt;
   &amp;lt;PostBuildEvent&amp;gt;
     call $(SolutionDir)BuildWebConfigs.bat
   &amp;lt;/PostBuildEvent&amp;gt;
 &amp;lt;/PropertyGroup&amp;gt;
&amp;lt;/Project&amp;gt;&lt;/pre&gt;

&lt;p&gt;I have configured all of my solutions that use this utility to have BuildWebConfigs.bat and a folder called &amp;quot;build&amp;quot; in the $(SolutionDir). The &amp;quot;build&amp;quot; folder is laid out like so:&lt;/p&gt;
&lt;strong&gt;Folder Structure&lt;/strong&gt; 

&lt;pre style="margin: 0px"&gt;------------------------------
+ nant
  - nant.exe
  - &amp;lt;related nant files&amp;gt;
- ConfigMerge.bat
- default.build
- {somename}.property
- {somename}.property
- {somename}.property
- web.config.format
------------------------------&lt;/pre&gt;

&lt;p&gt;I have also built a NAnt script which performs the same actions as the ConfigMerge batch script, but I find it runs significantly slower (about 4.5 seconds longer) than the batch because the NAnt script has to spawn additional instances of NAnt to perform the required actions. I've included it here in case you'd like to play with it:&lt;/p&gt;
&lt;strong&gt;Alternative NAnt-based NAnt script invoker&lt;/strong&gt; 

&lt;pre class="brush: xml;"&gt;&amp;lt;project name=&amp;quot;generate configs&amp;quot; default=&amp;quot;generate &amp;quot;&amp;gt;
 &amp;lt;property name=&amp;quot;destinationfile&amp;quot;   value=&amp;quot;web.config&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;propertyfile&amp;quot;  value=&amp;quot;invalid.file&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;
 &amp;lt;property name=&amp;quot;sourcefile&amp;quot;   value=&amp;quot;Web.format.config&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

 &amp;lt;include buildfile=&amp;quot;${propertyfile}&amp;quot;   failonerror=&amp;quot;false&amp;quot;   unless=&amp;quot;${string::contains(propertyfile, 'invalid.file')}&amp;quot; /&amp;gt;

 &amp;lt;target name=&amp;quot;configMerge&amp;quot;&amp;gt;
   &amp;lt;echo message=&amp;quot;GENERATING: ${path::get-file-name(destinationfile)} FROM: ${path::get-file-name(propertyfile)}.&amp;quot; /&amp;gt;
   &amp;lt;copy file=&amp;quot;${sourcefile}&amp;quot; tofile=&amp;quot;${destinationfile}&amp;quot; overwrite=&amp;quot;true&amp;quot;&amp;gt;
     &amp;lt;filterchain&amp;gt;
       &amp;lt;expandproperties /&amp;gt;
     &amp;lt;/filterchain&amp;gt;
   &amp;lt;/copy&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&amp;quot;generate &amp;quot;&amp;gt;
   &amp;lt;foreach item=&amp;quot;File&amp;quot; property=&amp;quot;file&amp;quot;&amp;gt;
     &amp;lt;in&amp;gt;
       &amp;lt;items&amp;gt;
         &amp;lt;include name=&amp;quot;*.property&amp;quot; /&amp;gt;
       &amp;lt;/items&amp;gt;
     &amp;lt;/in&amp;gt;
     &amp;lt;do&amp;gt;
       &amp;lt;property name=&amp;quot;propertyfile&amp;quot; value=&amp;quot;${path::get-file-name(file)}&amp;quot; overwrite=&amp;quot;true&amp;quot;/&amp;gt;
       &amp;lt;property name=&amp;quot;destinationfile&amp;quot; value=&amp;quot;web.${path::get-file-name-without-extension(propertyfile)}.config&amp;quot; overwrite=&amp;quot;true&amp;quot;/&amp;gt;
       &amp;lt;property name=&amp;quot;sourcefile&amp;quot; value=&amp;quot;Web.format.config&amp;quot; overwrite=&amp;quot;true&amp;quot;/&amp;gt;
       &amp;lt;echo message=&amp;quot;Generating: ${destinationfile} from ${propertyfile}.&amp;quot;/&amp;gt;

       &amp;lt;exec program=&amp;quot;nant\nant&amp;quot;&amp;gt;
         &amp;lt;arg value=&amp;quot;configMerge&amp;quot;/&amp;gt;
         &amp;lt;arg value=&amp;quot;-nologo+&amp;quot;/&amp;gt;
         &amp;lt;arg value=&amp;quot;-q&amp;quot;/&amp;gt;
         &amp;lt;arg value=&amp;quot;-D:sourcefile=${sourcefile}&amp;quot;/&amp;gt;
         &amp;lt;arg value=&amp;quot;-D:propertyfile=${propertyfile}&amp;quot;/&amp;gt;
         &amp;lt;arg value=&amp;quot;-D:destinationfile=${destinationfile}&amp;quot;/&amp;gt;
       &amp;lt;/exec&amp;gt;
     &amp;lt;/do&amp;gt;
   &amp;lt;/foreach&amp;gt;
 &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;

&lt;h3&gt;Downloads:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.nathantaylor.info/demos/ConfigBuilder/BuildConfigUtility.zip"&gt;Config Builder (Complete Sample)&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.nathantaylor.info/demos/ConfigBuilder/PortableNAnt.zip"&gt;Portable NAnt (Not Required)&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Sources:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.cptloadtest.com/2007/09/22/Managing-Multiple-Environment-Configurations-Through-NAnt.aspx"&gt;Captain Load Test&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://blog.lavablast.com/post/2008/02/Manage-your-ASPNET-Webconfig-Files-using-NAnt.aspx"&gt;JKealey&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-2669041188817672573?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yYSBBKLpmEeMcmD_IckuyCeHYAU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yYSBBKLpmEeMcmD_IckuyCeHYAU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yYSBBKLpmEeMcmD_IckuyCeHYAU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yYSBBKLpmEeMcmD_IckuyCeHYAU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=XCk9yN87yF0:XE6S0POaeTc:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=XCk9yN87yF0:XE6S0POaeTc:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=XCk9yN87yF0:XE6S0POaeTc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=XCk9yN87yF0:XE6S0POaeTc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=XCk9yN87yF0:XE6S0POaeTc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/XCk9yN87yF0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/XCk9yN87yF0/webconfig-build-manager.html</link><author>noreply@blogger.com (Nathan Taylor)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ZIHyZ-EOj1g/SvBu_3etE3I/AAAAAAAAABU/4FDUY1J0tmc/s72-c/ExternalTools.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/10/webconfig-build-manager.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-4617156057532893347</guid><pubDate>Tue, 27 Oct 2009 15:39:00 +0000</pubDate><atom:updated>2009-10-27T10:03:53.870-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tool</category><category domain="http://www.blogger.com/atom/ns#">registry</category><category domain="http://www.blogger.com/atom/ns#">sourcesafe</category><category domain="http://www.blogger.com/atom/ns#">batch file</category><category domain="http://www.blogger.com/atom/ns#">shell</category><category domain="http://www.blogger.com/atom/ns#">utility</category><category domain="http://www.blogger.com/atom/ns#">scripting</category><title>Shell Command - Delete Visual SourceSafe Files</title><description>Visual SourceSafe has a tendency to litter version-controlled directories with 3 types of project tracking files (*.scc, *.vssscc, *.vspscc) that may be undesirable when sharing a project with others. This simple "Delete SourceSafe Files" Shell command will quickly delete all instances of those files in a directory and its sub-directories.

To use, run this registry script:
&lt;pre class="brush:bash"&gt;
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSourceSafe]
@="Delete SourceSafe Files"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSourceSafe\command]
@="cmd.exe /c \"TITLE Removing SourceSafe Files in %1 &amp;amp;&amp;amp; COLOR 9A &amp;amp;&amp;amp; del *.vssscc /s /f &amp;amp;&amp;amp; del *.vspscc /s /f &amp;amp;&amp;amp; del *.scc /s /f\""
&lt;/pre&gt;
I got this idea from &lt;a href="http://weblogs.asp.net/jgalloway/archive/2007/02/24/shell-command-remove-svn-folders.aspx"&gt;Jon Galloway's blog post&lt;/a&gt; on creating a shell entry to remove SubVersion files. (Yes, the code &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; almost identical.)

Note: This will *not* remove source-control bindings from the SLN file. That must be done manually by opening Visual Studio. If this script is run on a source-controlled solution and the solution is run VS will produce an error message regarding missing source-control files. Confirming the default action will permanently remove the binding from the SLN file.

For the lazy: &lt;a href"http://www.nathantaylor.info/files/DeleteSourceSafeFiles.zip"&gt;Download Zipped Registry File&lt;/a&gt;. (My host refused to serve a .reg file, sorry!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-4617156057532893347?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/n9Or2z6eNIMlqOOPWghuY-8azL8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n9Or2z6eNIMlqOOPWghuY-8azL8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/n9Or2z6eNIMlqOOPWghuY-8azL8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n9Or2z6eNIMlqOOPWghuY-8azL8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=DsyIj-GteUU:9hRSdEpV3Yw:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=DsyIj-GteUU:9hRSdEpV3Yw:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=DsyIj-GteUU:9hRSdEpV3Yw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=DsyIj-GteUU:9hRSdEpV3Yw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=DsyIj-GteUU:9hRSdEpV3Yw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/DsyIj-GteUU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/DsyIj-GteUU/shell-command-delete-visual-sourcesafe.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/10/shell-command-delete-visual-sourcesafe.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-5166419902591638645</guid><pubDate>Fri, 04 Sep 2009 01:41:00 +0000</pubDate><atom:updated>2009-09-08T13:01:17.131-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web.config</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">Reflection</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">custom attribute</category><category domain="http://www.blogger.com/atom/ns#">attribute</category><title>ASP.NET Web.config - Simple Website Settings Provider</title><description>While working on a new website today I felt compelled to make myself a simple, type-safe accessor for fields in my Web.config. Using some handy reflection I came up with the solution below. Upon a call to Loader.Initialize(), reflection is used to examine all properties for the AppSettingsKeyAttibute. If the attribute exists for a given property, the property is mapped to the specified key in the provided value collection.  

&lt;pre class="brush: csharp;"&gt;public class WebsiteSettings
{
 [AppSettingsKey("Website.Name"), Required]
 public static string WebsiteName
 {
  get;
  private set;
 }

 [AppSettingsKey("Uploads.TempDirectory")]
 public static string UploadsTemporaryDirectory
 {
  get;
  private set;
 }

 [AppSettingsKey("Products.ImagesDirectory"), Required]
 public static string ProductImagesDirectory
 {
  get;
  private set;
 }

 public static class Loader
 {
  public static void Initialize(NameValueCollection appSettings)
  {
   if (appSettings == null)
    throw new ConfigurationErrorsException("AppSettings collection was null.");

   foreach (var property in typeof(WebsiteSettings).GetProperties())
   {
    if (property.IsDefined(typeof(AppSettingsKeyAttribute), false) &amp;&amp; property.CanWrite)
    {
     var attribute = (AppSettingsKeyAttribute)property.GetCustomAttributes(typeof(AppSettingsKeyAttribute), false)[0];
     var value = appSettings[attribute.AppSettingsKey];

     if (value != null)
     {
      try
      {
       var changeType = Convert.ChangeType(value, property.PropertyType);
       property.SetValue(null, changeType, null);
      }
      catch (Exception ex)
      {
       if (HttpContext.Current != null)
        ErrorSignal.FromContext(HttpContext.Current).Raise(ex);
      }
     }
    }
   }

   if (!Validate())
    throw new ConfigurationErrorsException("One or more required Application Setting is missing or empty.");
  }

  private static bool Validate()
  {
   foreach (var property in typeof(WebsiteSettings).GetProperties())
   {
    if (property.IsDefined(typeof(RequiredAttribute), false) &amp;&amp; property.CanRead)
    {
     var value = property.GetValue(null, null);
     if (value == null)
      return false;
     if (value is string &amp;&amp; string.IsNullOrEmpty(value as string))
      return false;
    }
   }
   return true;
  }
 }

 [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
 private sealed class RequiredAttribute : Attribute { }

 [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
 private sealed class AppSettingsKeyAttribute : Attribute
 {
  public string AppSettingsKey { get; private set; }

  public AppSettingsKeyAttribute(string appSettingsKey)
  {
   this.AppSettingsKey = appSettingsKey;
  }
 }
}&lt;/pre&gt;

Mapping a setting to a property is as simple as decorating the property with the AppSettingsKey attribute which takes a string containing the name of that property in the collection. If the specified key is found, the class will attempt to convert the value of the provided key to the type of the property referencing it. If the type conversion fails, no value is assigned. The rules checked as a result of the Required attribute is that the value is not null and, if it is a string, not empty. If you find yourself using this, you may wish to further customize this evaluation and the conversion failure handlers, depending on your situation of course.

Personally, I am calling the Loader.Initialize() method in the Application_Start() method of Global.asax:

&lt;pre class="brush: csharp;"&gt;
protected void Application_Start(object sender, EventArgs e) 
{
    WebsiteSettings.Loader.Initialize(WebConfigurationManager.AppSettings);
}
&lt;/pre&gt;

If you found this useful, let me know!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-5166419902591638645?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lF0lxstTkgkwtQz_E7wSyIQ_mMs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lF0lxstTkgkwtQz_E7wSyIQ_mMs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lF0lxstTkgkwtQz_E7wSyIQ_mMs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lF0lxstTkgkwtQz_E7wSyIQ_mMs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=NKrHe0HgqDE:KVNjOJJXwzw:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=NKrHe0HgqDE:KVNjOJJXwzw:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=NKrHe0HgqDE:KVNjOJJXwzw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=NKrHe0HgqDE:KVNjOJJXwzw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=NKrHe0HgqDE:KVNjOJJXwzw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/NKrHe0HgqDE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/NKrHe0HgqDE/aspnet-webconfig-simple-website.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/09/aspnet-webconfig-simple-website.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-2841589952758989344</guid><pubDate>Fri, 31 Jul 2009 17:12:00 +0000</pubDate><atom:updated>2010-06-08T09:42:56.077-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">System.Reflection</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">Reflection</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">asp.net mvc</category><category domain="http://www.blogger.com/atom/ns#">Invoke</category><category domain="http://www.blogger.com/atom/ns#">MethodInfo</category><title>.NET Reflection - Generic Method Type Inference of a Boxed Parameter</title><description>&lt;p&gt;Before I begin- this is a fairly lengthy post and if you'd rather not read the whole thing and would just like to know how to pass a boxed object to a generic method and have the run-time properly infer the base type of that object for the method, &lt;a href="#FinalReflectionCode"&gt;jump to the bottom&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Today I was working on an ASP.NET MVC project I've been putting together for the past couple weeks and I realized that I have been duplicating a small piece of code over and over out of a falsely perceived necessity. After considering my options and coming up with a simple solution, I began to put it into place- only to quickly discover that there was no way to do what I wanted without some clever Reflection.&lt;/p&gt;  &lt;p&gt;My project is set up such that all of my View pages inherit from a class I defined, MasterViewModel, which holds a few top level variables my Master Page requires for rendering. While all of my Views do inherit from MasterViewModel, the majority of them take a derived class, ContentViewPage&amp;lt;T&amp;gt;, which contains a simple generic property housing the Data (simple or complex) for that View. With this design, when I construct my View I always have the Master Page Model items included in the Controller result without having to explicitly add them in my Controller method. This is all well and good, but as you may imagine it because rather annoying to have to wrap the Model data I gave the View in a ContentViewModel&amp;lt;T&amp;gt; object at the end of every Controller call.&lt;/p&gt;
&lt;pre class="brush:csharp"&gt;public ViewResult SayHello() {
 return View(new ContentViewModel&lt;string&gt;(&amp;quot;Hello&amp;quot;));
}&lt;/pre&gt;
&lt;p&gt;So after a little digging around on &lt;a href="http://www.stackoverflow.com" target="_blank"&gt;Stack Overflow&lt;/a&gt; I decided to create myself a couple of helpers to assist in the creation of my ContentViewModel&amp;lt;T&amp;gt; object.&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;
public static class ContentViewModel
{
    public static ContentViewModel&amp;lt;T&amp;gt; Create&amp;lt;T&amp;gt;(T data)
    {
        return new ContentViewModel&amp;lt;T&amp;gt;(data);
    }

    public static readonly MasterViewModel Empty = new MasterViewModel();
}
&lt;/pre&gt;
&lt;p&gt;With this in hand I now need only write ContentViewModel.Create(&amp;quot;Hello&amp;quot;) to produce the same object I defined above. This seemed like a pretty decent solution at first, but I still wasn't particularly satisfied. Then it occurred to me that if I overrode the View() method of the Controller class and wrapped my objects in a ContentViewModel&amp;lt;T&amp;gt; before calling base.View() I wouldn't ever need to type ContentView.Create() again.&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;
protected override ViewResult View(IView view, object model)
{
    if (model == null)
        return base.View(view, ContentViewModel.Empty);
    if (model is MasterViewModel)
        return base.View(view, model);
    else
        return base.View(view, ContentViewModel.Create(model));
}

protected override ViewResult View(string viewName, string masterName, object model)
{
    if (model == null)
        return base.View(viewName, masterName, ContentViewModel.Empty);
    else if (model is MasterViewModel)
        return base.View(viewName, masterName, model);
    else
        return base.View(viewName, masterName, ContentViewModel.Create(model));
}
&lt;/pre&gt;
&lt;p&gt;Simple and effective, I thought.&lt;/p&gt;
&lt;h4 style="margin: 2px;"&gt;&lt;font color="#ff0000"&gt;Server Error in '/' Application.&lt;/font&gt;&lt;/h4&gt;
&lt;h5 style="margin: 2px;"&gt;&lt;font color="#804040"&gt;The model item passed into the dictionary is of type 'MvcScratch.Controllers.HomeController+ContentViewModel`1[System.Object]' but this dictionary requires a model item of type 'MvcScratch.Controllers.HomeController+ContentViewModel`1[System.String]'.&lt;/font&gt;&lt;/h5&gt;
&lt;p&gt;Or not. This was all working swell before... what went wrong? Well, the View() method's model property is a non-generic Object, that's what went wrong. Usually that wouldn't matter because our View knows what type to cast the Model to based on the Inherits=&amp;quot;&amp;quot; attribute of &amp;lt;%@ Page %&amp;gt; and therefore although we downcast our Model for the call to View() in the Controller, the View knows what to expect and upcasts it for us. Trouble is, ContentViewModel.Create() doesn't know that at run time and it only has the type of the parameter to go off of, which, no thanks to the View() method is an object. Keep in mind, C# still knows the actual type of the object, but at run time ContentViewModel.Create() is unable to infer that until it is within the scope of the method- which is after T has been given a Type. Thus, instead of a ContentViewModel&amp;lt;string&amp;gt; being returned, we get a ContentViewModel&amp;lt;object&amp;gt;. To confirm this:&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;static void Main(string[] args)
{
    object str = &amp;quot;Hello World&amp;quot;;
    Foo(str);
}

static void Foo&amp;lt;T&amp;gt;(T param)
{
    Console.WriteLine(&amp;quot;typeof(T): {0}&amp;quot;, typeof(T));
    Console.WriteLine(&amp;quot;param.GetType(): {0}&amp;quot;, param.GetType());
}&lt;/pre&gt;
Which outputs: 
&lt;pre&gt;   typeof(T):              System.Object
   param.GetType():        System.String&lt;/pre&gt;
&lt;p&gt;Clearly,we can see that doesn't work quite how we'd like it to, but fear not, we're not out of luck just yet! Using a little bit of reflection we can fix this problem. The solution? Rather than calling ContentViewModel.Create() directly, and allowing the run-time to infer the the generic type T, we're going to invoke it through the class's Type definition and explictly define T's type.&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;typeof(ContentViewModel).GetMethod(&amp;quot;Create&amp;quot;).MakeGenericMethod(new Type[] { data.GetType() }).Invoke(null, new object[] { data });&lt;/pre&gt;
&lt;p&gt;BAM! If you examine this code for a moment or two you should be able to get the general idea. Using Reflection we're grabbing the Type of our method's container and then returning a &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx" target="_blank"&gt;MethodInfo&lt;/a&gt; for that method using its string representation. With that MethodInfo we are calling &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.makegenericmethod%28VS.80%29.aspx" target="_blank"&gt;MethodInfo.MakeGenericMethod()&lt;/a&gt; which takes a array of parameter Types (in the order they're defined in the method signature) that will strongly type the method's generic parameters. So instead of T mapping to an 'object' it maps to whatever 'data.GetType()' returns- the actual parameter type. Finally, we invoke the method with a call to &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.invoke.aspx" target="_blank"&gt;MethodInfo.Invoke()&lt;/a&gt; which receives an instance of the given Type (or null for a static method) and an Object array containing each parameter in order (or null for a parameterless method). Now if we replace the View() code from above with this call instead we can rest easy knowing that ContentViewModel&amp;lt;T&amp;gt;'s generic type is correctly instantiated.&lt;/p&gt;&lt;p&gt;It is worth noting that of course there is some extra overhead being created here because of our calls into System.Reflection and for that reason I am not entirely sure if this working solution is ideal- it's at least a little iffy and I'd be curious to know what the server performance looks like in a high-traffic environment where this reflection call is being run on every Controller request that doesn't explictly wrap its View() model parameter in a ContentViewModel&amp;ltT&amp;gt; first, but maybe one of my readers can shine some light on that?&lt;/p&gt;&lt;p&gt;Here is a complete sample of this method invocation technique outside of my MVC project:&lt;/p&gt;&lt;a id="FinalReflectionCode"&gt;&lt;/a&gt;
&lt;pre class="brush: csharp;"&gt;
namespace TypeInferenceDemo
{
    class Program
    {

        static void Main(string[] args)
        {
            object str = &amp;quot;Hello World&amp;quot;;
            object num = 5;
            object obj = new object();

            Console.WriteLine(&amp;quot;var\tvalue\t\tFoo() Type\tCallFoo() Type&amp;quot;);
            Console.WriteLine(&amp;quot;-------------------------------------------------------&amp;quot;);
            Console.WriteLine(&amp;quot;{0}\t{1}\t{2}\t{3}&amp;quot;, &amp;quot;str&amp;quot;, str, MyClass.Foo(str), MyClass.CallFoo(str));
            Console.WriteLine(&amp;quot;{0}\t{1}\t\t{2}\t{3}&amp;quot;, &amp;quot;num&amp;quot;, num, MyClass.Foo(num), MyClass.CallFoo(num));
            Console.WriteLine(&amp;quot;{0}\t{1}\t{2}\t{3}&amp;quot;, &amp;quot;obj&amp;quot;, obj, MyClass.Foo(obj), MyClass.CallFoo(obj));
        }

    }

    class MyClass
    {
        public static Type Foo&amp;lt;T&amp;gt;(T param)
        {
            return typeof(T);
        }

        public static Type CallFoo(object param)
        {
            return (Type)typeof(MyClass).GetMethod(&amp;quot;Foo&amp;quot;).MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param });
        }

    }
}
&lt;/pre&gt;
&lt;p&gt;Which, outputs:
&lt;/p&gt;
&lt;pre&gt;   var     value           Foo() Type      CallFoo() Type
   -------------------------------------------------------
   str     Hello World     System.Object   System.String
   num     5               System.Object   System.Int32
   obj     System.Object   System.Object   System.Object&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-2841589952758989344?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aRzyOeXrgezv7ZEIbUlE5yMhpMY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aRzyOeXrgezv7ZEIbUlE5yMhpMY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aRzyOeXrgezv7ZEIbUlE5yMhpMY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aRzyOeXrgezv7ZEIbUlE5yMhpMY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=IYOYd6n3JOs:EZN2ZnZlGaw:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=IYOYd6n3JOs:EZN2ZnZlGaw:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=IYOYd6n3JOs:EZN2ZnZlGaw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=IYOYd6n3JOs:EZN2ZnZlGaw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=IYOYd6n3JOs:EZN2ZnZlGaw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/IYOYd6n3JOs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/IYOYd6n3JOs/net-reflection-generic-method-type.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/07/net-reflection-generic-method-type.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-2095667270601944367</guid><pubDate>Tue, 28 Jul 2009 18:55:00 +0000</pubDate><atom:updated>2009-07-28T14:08:43.419-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">recursion</category><category domain="http://www.blogger.com/atom/ns#">contentplaceholder</category><category domain="http://www.blogger.com/atom/ns#">control</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">itextcontrol</category><category domain="http://www.blogger.com/atom/ns#">masterpage</category><title>Check for Content in Control</title><description>While working on a project recently I had a requirement for ContentPlaceHolder in my Master Page that was wrapped in a container that I only wanted to render if the ContentPlaceHolder was actually being populated by a page inheriting the Master. The container was a Firefox-style notice bar that renders at the top of the site with a simple message and a close button. The message area of the notice bar contains the ContentPlaceHolder which will govern whether or not the notice bar gets rendered. To achieve this two things must be done:

&lt;ol&gt;&lt;li&gt;Check if any controls exist in the ContentPlaceHolder's Controls collection&lt;/li&gt;&lt;li&gt;If controls do exist, iterate over each one and check whether or not it: &lt;ul&gt;&lt;li&gt;A) Has a text property which is not whitespace&lt;/li&gt;&lt;li&gt;B) Contains controls in its own control collection meeting the latter condition&lt;/li&gt;&lt;li&gt;&lt;a id="2c"&gt;&lt;/a&gt;C) Is currently visible&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;
These requirements are all relatively straightforward, and as you may have guessed, recursion comes to the rescue in this scenario. Although this code is ultimately going to be called on a ContentPlaceHolder, it makes more sense (and saves code) if the method accepts a non-specific control object, rather than a ContentPlaceHolder as its parameter.

&lt;pre class="brush:csharp"&gt;
public static bool IsNonEmptyControl(Control ctrl)
{
 if (!(ctrl is ITextControl) &amp;&amp; ctrl.Controls.Count &gt; 0)
 {
  for (int i = 0; i &lt; ctrl.Controls.Count; i++)
  {
   if (IsNonEmptyControl(ctrl.Controls[i]))
    return true;
  }
 }
 else if (ctrl is ITextControl &amp;&amp; ctrl.Visible)
 {
  return HasContent(ctrl as ITextControl);
 }
 return false;
}
&lt;/pre&gt;

This method is fairly simple and has one of two paths- immediate result, or recursion leading to a result. We start by checking if we're dealing with a container or a content control. This is a rather arbitrary test, but what this means is it's a control with a non-empty Controls collection or one with a "Text" property. If the control does have children we loop over each child and call IsNonEmptyControl() on it, or if the control has a text property we check the content of that text property with HasContent().

&lt;pre class="brush:csharp"&gt;
private static bool HasContent(ITextControl itc)
{
 if (itc != null &amp;&amp; !string.IsNullOrEmpty(itc.Text) &amp;&amp; !IsWhiteSpace(itc.Text))
  return true;
 //else
 return false;
}

private static bool IsWhiteSpace(string s)
{
 for (int i = 0; i &lt; s.Length; i++)
 {
  if (!char.IsWhiteSpace(s[i]))
   return false;
 }
 return true;
}
&lt;/pre&gt;

Both of these methods are pretty obvious- check thatthe text property is not null, not empty, and does not contain whitespace ("\r, \n, " ", etc).

And that's all there is to it. The method can be called on any control and will correctly indicate whether or not that control has content. In my case I call it in my Master Page's Page_PreRender event and pass it my ContentPlaceHolder.

Now, there is one problem with this method: it doesn't properly address &lt;a href="#2c"&gt;2C&lt;/a&gt; from above- checking whether or not the content is actually visible when we call this from the Master Page on a ContentPlaceHolder. After digging a bit I realized this is actually less intuitive than I would have hoped due to your friend and mine: &lt;a href="http://msdn.microsoft.com/en-us/library/ms178472.aspx"&gt;Page Life Cycle&lt;/a&gt;. When calling this method in the Master Page's PreRender event none of the &lt;span style="font-style: italic;"&gt;content pages&lt;/span&gt; have yet initialized any of their controls from the code/markup so although they are accessible, all control properties are defaulted. In fact, it is not until Page_PreRenderComplete that we are able to see the actual property values of our controls and, unfortunately, the Master Page does not throw this event. I am honestly not sure how to handle this scenario and I would be very interested to know if anyone has some ideas on how to tackle this problem.

&lt;span style="font-weight:bold;"&gt;Tips&lt;/span&gt;
&lt;ul&gt;&lt;li&gt;If you're using C# 3.0 consider changing the signature to IsNonEmptyControl(this Control ctrl) for some Extension Method goodness.&lt;/li&gt;&lt;/ul&gt;
&lt;span style="font-weight:bold;"&gt;Sources&lt;/span&gt;
&lt;ul&gt;&lt;li&gt;Some of these concepts were borrowed from: &lt;a href="http://programcsharp.com/blog/archive/2009/01/22/test-if-masterpage-contentplaceholder-has-content-or-is-empty.aspx"&gt;Chris Hynes's similar post&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-2095667270601944367?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rUORLCfPgP9o9ecyXOrfF46a2NU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rUORLCfPgP9o9ecyXOrfF46a2NU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rUORLCfPgP9o9ecyXOrfF46a2NU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rUORLCfPgP9o9ecyXOrfF46a2NU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=tI57UU79rFI:jvjqz3DyDQ8:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=tI57UU79rFI:jvjqz3DyDQ8:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=tI57UU79rFI:jvjqz3DyDQ8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=tI57UU79rFI:jvjqz3DyDQ8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=tI57UU79rFI:jvjqz3DyDQ8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/tI57UU79rFI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/tI57UU79rFI/check-for-content-in-control.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/07/check-for-content-in-control.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-2965545012874631346</guid><pubDate>Thu, 09 Jul 2009 03:56:00 +0000</pubDate><atom:updated>2009-07-14T10:10:41.273-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">validator</category><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">library</category><category domain="http://www.blogger.com/atom/ns#">demo</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">.net 2.0</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">.net 3.5</category><category domain="http://www.blogger.com/atom/ns#">validation</category><category domain="http://www.blogger.com/atom/ns#">microsoft</category><title>ASP.NET Validation - Client-Side IsControlValid() Function</title><description>&lt;div style="float: left;"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nathantaylor.name/demos/IsControlValid/"&gt;View Demo&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nathantaylor.name/demos/IsControlValid/IsControlValid.zip"&gt;Download Source Code&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;div style="clear: both;"&gt;&lt;/div&gt;
While working on a rather unique form for one of the websites I maintain at work (&lt;a href="http://www.ratedgolf.com/"&gt;Rated Golf&lt;/a&gt;) I found myself needing to do some very case specific form validation on a collection of fields. All of the fields in question had a pair of ASP.NET validation controls attached to them and depending on what the client selected while filling out the form I needed to perform validation on a variable number of fields. Namely, the user could fill out either 9 or 18 of the fields in any order and provided that one of those conditions was met I would allow submission.

I spent a good bit of time digging through the ASP.NET client-side validation API to get a feel for how to go about the task at hand and finally I decided on enumerating over the page's validator collection and making sure the correct number of fields checked out. I went to work on this approach only to soon find out there is no way to check if a given control is valid- only a given validator. Now I knew that each input control had exactly two validators and that would [most likely] never change so after some tooling around I slapped together a solution.

The solution I came up with was not scalable when an input control had more than two validators, so after leaving work I came up with a slightly better, less specialized solution for this problem using some very basic JavaScript.

I started by defining some simple ASP.NET markup to create a TextBox, a RequiredFieldValidator, and a CompareValidator.

&lt;pre class="brush: html; wrap-lines: false"&gt;
&amp;lt;asp:TextBox ID="tbxValue" runat="server" ValidationGroup="vg1" Style="width: 400px;" /&amp;gt;
&amp;lt;asp:RequiredFieldValidator ID="rfvValue" runat="server" ErrorMessage="Value is required."
ControlToValidate="tbxValue" Display="Dynamic" ValidationGroup="vg1" /&amp;gt;
&amp;lt;asp:CompareValidator ID="cvValue" runat="server" ErrorMessage="Value must be a number."
ControlToValidate="tbxValue" Operator="DataTypeCheck" Type="Integer" Display="Dynamic"
ValidationGroup="vg2" /&amp;gt;
&lt;/pre&gt;

Now that our page is setup we can jump into the JavaScript. The first place to start is figuring out how many validators exist for a given control. One of the convenient nuances of the Microsoft JavaScript framework is that input fields having validators are automatically decorated with a "Validators" array at run time, making it very simple to grab a list of validators for that control.

In order to simplify working with the control and its validators after verifying its validity I chose to define an IsControlValidResult object to wrap the Control, its Validators, and an IsValid field. Of course this can easily be swapped out for a simple Boolean result if that better fits your implementation:

&lt;pre class="brush: js; wrap-lines: false"&gt;
function IsControlValidResult() {
    this.IsValid = false;
    this.Control = null;
    this.Validators = new Array();
}
&lt;/pre&gt;

And finally:

&lt;pre class="brush: js; wrap-lines: false"&gt;
function IsControlValid(controlId, validationGroup, displayErrors) {
    var result = new IsControlValidResult();
    var validatorCount = 0;
    var validCount = 0;
    if (controlId != null &amp;&amp; typeof (controlId) == "string") {
        var control = document.getElementById(controlId);
        validatorCount = control.Validators.length;
        if (validatorCount &gt; 0) {
            var i = validatorCount;
            while (i--) {
                if (validationGroup == null || IsValidationGroupMatch(control.Validators[i], validationGroup)) {
                    result.Validators.push(control.Validators[i]);
                    MyValidatatorValidate(control.Validators[i], validationGroup, null, displayErrors);
                    if (control.Validators[i].isvalid) {
                        validCount++
                        if (validCount &gt;= validatorCount)
                            break;
                    }
                }
            }
        }
        result.Control = control;        
    }
    result.IsValid = validCount &gt;= validatorCount;
    return result;
}
&lt;/pre&gt;

IsControlValid() function accepts a controlID string and an optional (read: &lt;span style="font-style:italic;"&gt;nullable&lt;/span&gt;) validationGroup string in order to limit the validation to a given validationGroup for scenarios where more than one ValidationGroup is assigned to a control and its validators. The method is quite simple and works by iterating over the control's Validators array and for each validator it calls MyValidatorValidate(), which performs the actual validation. MyValidatorValidate() is identical to the framework function ValidatorValidate() aside from an additional Boolean variable controlling whether or not the error should be displayed graphically. I chose to do this because I wanted to check the validity of a validator without visually alerting the user that I had done so. Just be warned: even though MyValidatorValidate puts ValidatorUpdateDisplay() in a conditional statement, calling "val.evaluationfunction" &lt;span style="font-style:italic;"&gt;will&lt;/span&gt; still set the state of the control as invalid and if you're using the AJAX Control Toolkit's "ValidatorCalloutExtender" it will render as soon as that function executes. I was not able to identify a workaround for this. Here's the code for MyValidatorValidate():

&lt;pre class="brush: js; wrap-lines: false"&gt;
function MyValidatatorValidate(val, validationGroup, event, displayError) {
    val.isvalid = true;
    if ((typeof (val.enabled) == "undefined" || val.enabled != false) &amp;&amp; IsValidationGroupMatch(val, validationGroup)) {
        if (typeof (val.evaluationfunction) == "function") {
            val.isvalid = val.evaluationfunction(val);
            if (displayError &amp;&amp; (!val.isvalid &amp;&amp; Page_InvalidControlToBeFocused == null &amp;&amp; typeof (val.focusOnError) == "string" &amp;&amp; val.focusOnError == "t")) {
                ValidatorSetFocus(val, event);
            }
        }
    }
    if (displayError)
        ValidatorUpdateDisplay(val);
}
&lt;/pre&gt;

If, after calling MyValidatorValidate, you have any ValidatorCalloutExtenders being rendered on the page that you would like hidden from the user, the following function will turn off all visual validation cues:

&lt;pre class="brush: js; wrap-lines: false"&gt;
function Unvalidate(myValidationGroup) {
    // Remove the validator control(s) from display.
    var myValidators = Page_Validators;
    if ((typeof (myValidators) != "undefined") &amp;&amp; (myValidators != null)) {
        for (i = 0; i &lt; myValidators.length; i++) {
            var myValidator = myValidators[i];
            if (myValidationGroup == null || IsValidationGroupMatch(myValidator, myValidationGroup)) {
                if (myValidator.style.visibility.length &gt; 0 &amp;&amp; myValidator.style.display.length == 0) {
                    myValidator.style.visibility = 'hidden';
                }
                else if (myValidator.style.display.length &gt; 0 &amp;&amp; myValidator.style.visibility.length == 0) {
                    myValidator.style.display = 'none';
                }
                if ((typeof (myValidator.ValidatorCalloutBehavior) != "undefined") &amp;&amp; (myValidator.ValidatorCalloutBehavior != null)) {
                    myValidator.ValidatorCalloutBehavior.hide();
                    if ((typeof (myValidator.ValidatorCalloutBehavior._highlightCssClass) != "undefined") &amp;&amp; (myValidator.ValidatorCalloutBehavior._highlightCssClass != null) &amp;&amp; (typeof (myValidator.ValidatorCalloutBehavior._elementToValidate) != "undefined") &amp;&amp; (myValidator.ValidatorCalloutBehavior._elementToValidate != null))
                        Sys.UI.DomElement.removeCssClass(myValidator.ValidatorCalloutBehavior._elementToValidate, myValidator.ValidatorCalloutBehavior._highlightCssClass);
                }
            }
        }
    }

    // Remove the validator summary(ies) from display.
    if ((typeof (Page_ValidationSummaries) != "undefined") &amp;&amp; (Page_ValidationSummaries != null)) {
        for (i = 0; i &lt; Page_ValidationSummaries.length; i++) {
            var mySummary = Page_ValidationSummaries[i];
            if (myValidationGroup == null || IsValidationGroupMatch(mySummary, myValidationGroup)) {
                mySummary.style.display = 'none';
            }
        }
    }
}
&lt;/pre&gt;

And that's all there is to it. If you found this useful don't hesitate to let me know in the Comments!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-2965545012874631346?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XmB9tYvlUPNDckZqMvbExFaQP5A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XmB9tYvlUPNDckZqMvbExFaQP5A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XmB9tYvlUPNDckZqMvbExFaQP5A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XmB9tYvlUPNDckZqMvbExFaQP5A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=Oymkck0S-eQ:4Bn8Oh01wA8:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=Oymkck0S-eQ:4Bn8Oh01wA8:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=Oymkck0S-eQ:4Bn8Oh01wA8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=Oymkck0S-eQ:4Bn8Oh01wA8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=Oymkck0S-eQ:4Bn8Oh01wA8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/Oymkck0S-eQ" height="1" width="1"/&gt;</description><enclosure type="" url="http://www.nathantaylor.name/demos/IsControlValid/" length="0" /><link>http://feedproxy.google.com/~r/lakario/~3/Oymkck0S-eQ/aspnet-validation-client-side.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/07/aspnet-validation-client-side.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-3420339426744680809</guid><pubDate>Wed, 08 Jul 2009 08:21:00 +0000</pubDate><atom:updated>2009-07-08T03:24:10.987-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">follow-up</category><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">bug</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">scripting</category><category domain="http://www.blogger.com/atom/ns#">visual studio</category><category domain="http://www.blogger.com/atom/ns#">bug report</category><category domain="http://www.blogger.com/atom/ns#">c# 2.0</category><category domain="http://www.blogger.com/atom/ns#">keyword</category><category domain="http://www.blogger.com/atom/ns#">.net 2.0</category><category domain="http://www.blogger.com/atom/ns#">c# 3.0</category><category domain="http://www.blogger.com/atom/ns#">var</category><category domain="http://www.blogger.com/atom/ns#">.net 3.5</category><category domain="http://www.blogger.com/atom/ns#">microsoft</category><category domain="http://www.blogger.com/atom/ns#">2008</category><title>Visual Studio 2008 var Keyword ‘Bug’ – Microsoft Follow-up</title><description>&lt;p&gt;I got a response back from Microsoft support regarding &lt;a href="http://lakario.blogspot.com/2009/07/visual-studio-2008-var-keyword-bug.html" target="_blank"&gt;an issue with the var keyword in Visual Studio 2008&lt;/a&gt; and what they had to say isn’t particularly surprising (or motivating):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Thanks for the feedback! You're seeing that using C# 3.0 specific language features in a .NET 2.0 targeted web project fails since the code is actually being compiled on the server using the C# 2.0 compiler (more specifically, the script blocks of Web App Projects and all of Web Sites). &lt;strong&gt;This is a limitation that we're currently aware of and one that we will be re-evaluating as we begin planning for the next release.&lt;/strong&gt; &lt;strong&gt;In the meantime, when targeting .NET 2.0, you can actually go into &amp;quot;Project | Properties | Build | Advanced Build Settings&amp;quot; and set the language version of the project to be ISO-2, which will force the design time compilers to emit errors for C# 3.0 specific language features. &lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Given that &lt;span style="color: rgb(255,0,0)"&gt;we won't be able to address this issue in the upcoming VS2010 release&lt;/span&gt;, I'm going to go ahead and mark this bug as a &amp;quot;Wont Fix&amp;quot; but please be assured that we are tracking this suggestion internally and will be considering it again for the next product cycle.&lt;/p&gt;    &lt;p&gt;Thanks!      &lt;br /&gt;DJ Park       &lt;br /&gt;C# IDE, Program Manager&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;span style="color: rgb(102,102,102)"&gt;I tested the ISO suggestion the report handler sent me and as far as I could tell ISO-2 does not cause Visual Studio to emit any errors when the &lt;em&gt;var&lt;/em&gt; keyword is used. ISO-1 did produce some non-standard build errors, but nothing to do with the &lt;em&gt;var&lt;/em&gt; keyword. If anyone can demonstrate otherwise I’d love to hear about it in the comments.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(102,102,102)"&gt;It would have been foolish to think Microsoft would actually want to fix this little issue, but at least they know it’s there.&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-3420339426744680809?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3Y6VBK-QC66o9WtMembCATTNTTs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3Y6VBK-QC66o9WtMembCATTNTTs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3Y6VBK-QC66o9WtMembCATTNTTs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3Y6VBK-QC66o9WtMembCATTNTTs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9iy_RHH3khQ:T85uypXKe0o:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9iy_RHH3khQ:T85uypXKe0o:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9iy_RHH3khQ:T85uypXKe0o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=9iy_RHH3khQ:T85uypXKe0o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=9iy_RHH3khQ:T85uypXKe0o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/9iy_RHH3khQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/9iy_RHH3khQ/visual-studio-2008-var-keyword-bug_08.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/07/visual-studio-2008-var-keyword-bug_08.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7563542181873269057.post-6788884553654520931</guid><pubDate>Fri, 03 Jul 2009 02:33:00 +0000</pubDate><atom:updated>2009-07-23T09:11:07.630-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">asp.net</category><category domain="http://www.blogger.com/atom/ns#">bug</category><category domain="http://www.blogger.com/atom/ns#">c#</category><category domain="http://www.blogger.com/atom/ns#">scripting</category><category domain="http://www.blogger.com/atom/ns#">visual studio</category><category domain="http://www.blogger.com/atom/ns#">bug report</category><category domain="http://www.blogger.com/atom/ns#">c# 2.0</category><category domain="http://www.blogger.com/atom/ns#">keyword</category><category domain="http://www.blogger.com/atom/ns#">.net 2.0</category><category domain="http://www.blogger.com/atom/ns#">c# 3.0</category><category domain="http://www.blogger.com/atom/ns#">.net 3.5</category><category domain="http://www.blogger.com/atom/ns#">var</category><category domain="http://www.blogger.com/atom/ns#">microsoft</category><category domain="http://www.blogger.com/atom/ns#">2008</category><title>Visual Studio 2008 var Keyword ‘Bug’</title><description>I stumbled across an interesting bug while editing an ASP.NET web project in Visual Studio 2008 a few days ago and I figure after four years of using the Visual Studio suite without encountering any real bugs, one isn't all that bad. That being said, given the nature of the behavior I encountered, I was compelled to investigate the issue behind it.    &lt;p&gt;With the introduction of C# 3.0's implicit variable keyword &lt;span style="color:blue;"&gt;var &lt;/span&gt;Microsoft added some simple tricks to the compiler in order to produce the traditional C# 2.0 IL code backing this new keyword. That being so, .NET 2.0 projects are fully capable of running projects written with &lt;em&gt;most&lt;/em&gt; C# 3.0 syntax. &lt;/p&gt;    &lt;p&gt;The bug I encountered, if you can call it that, pertains to how Visual Studio treats code written inside ASP script tags within the page markup. As has been the case since classic ASP, C# or VB code can be written directly into the markup using &amp;lt;% %&amp;gt; tags. Consider the following rudimentary example:
&lt;/p&gt;        &lt;pre class="brush:csharp"&gt;&amp;lt;%
  string hello = "Hello";
  Response.Write(hello);
%&amp;gt;
&lt;/pre&gt;  &lt;p&gt;Like code placed in your code behind, this code is run when the page is loaded by the user; unlike the code in your code behind, this code is not &lt;em&gt;compiled&lt;/em&gt; until runtime. A key distinction.&lt;/p&gt;  &lt;p&gt;This brings me to the bug I noticed in the editor that pertains more to syntax highlighting than anything else. Consider this identical example written with C# 3.0 syntax.
&lt;/p&gt;  &lt;pre class="brush:csharp"&gt;&amp;lt;%
  var hello = "Hello";
  Response.Write(hello);
%&amp;gt;
&lt;/pre&gt;&lt;p&gt;Functionally these two blocks of code perform the same task and produce the same IL code when compiled; however, running the latter piece of code in a .NET 3.5 project will not yield the same results as it does in a .NET 2.0 project. Due to the fact that code contained in script tags is not compiled until runtime the target environment ultimately affects the compilation of that code. For that reason, given that the .NET 2.0 runtime doesn’t know what &lt;span style="color:blue;"&gt;var&lt;/span&gt; means it cannot correctly detect the type and compile the code.&lt;/p&gt;  &lt;p&gt;Now this behavior is neither surprising nor a bug in itself, but rather it pertains to small lack of gracefulness on Visual Studio’s part in detecting this specific condition. In Visual Studio 2008 while editing a C# project &lt;span style="color:blue;"&gt;var &lt;/span&gt;is a keyword that is highlighted by the editor regardless of the target platform because in all but this one scenario &lt;span style="color:blue;"&gt;var &lt;/span&gt;can safely be used in a .NET 2.0 project and, unfortunately, the development team overlooked this one scenario.&lt;/p&gt;  &lt;p&gt;One more thing worth noting for all you &lt;a href="http://www.jetbrains.com/resharper/" target="_blank"&gt;ReSharper&lt;/a&gt; users out there is the breaking vulnerability this exposes with the Code Cleanup tool in the plug-in. If you have ever tried configuring the Code Cleanup options you may have noticed it is possible to tell it to replace all explicit variable definitions with the implicit &lt;span style="color:blue;"&gt;var &lt;/span&gt;keyword. If you’re running a .NET 2.0 project with inline script tags in your pages make sure to watch for this setting and ignore the inline code inspection advice.&lt;/p&gt;  &lt;p&gt;Happy Coding!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7563542181873269057-6788884553654520931?l=blog.nathan-taylor.net' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jwPUSCF-sEalP__a_VZEt9veFVU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jwPUSCF-sEalP__a_VZEt9veFVU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jwPUSCF-sEalP__a_VZEt9veFVU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jwPUSCF-sEalP__a_VZEt9veFVU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/lakario?a=vBjhRYnQasY:b-d07F609-w:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=vBjhRYnQasY:b-d07F609-w:aL6AeedTgt8"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=aL6AeedTgt8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=vBjhRYnQasY:b-d07F609-w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?i=vBjhRYnQasY:b-d07F609-w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/lakario?a=vBjhRYnQasY:b-d07F609-w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/lakario?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lakario/~4/vBjhRYnQasY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/lakario/~3/vBjhRYnQasY/visual-studio-2008-var-keyword-bug.html</link><author>noreply@blogger.com (Nathan Taylor)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.nathan-taylor.net/2009/07/visual-studio-2008-var-keyword-bug.html</feedburner:origLink></item></channel></rss>
