…meie igapäevast IT’d anna meile igapäev…

2013-09-26

T4 templates for Web.config/App.config AppSettings

Filed under: Programmeerimine — Sander @ 11:37:47
Tags: , , ,

I’ve written before about generic methods to access configuration values. As nice as such generics are, there is still one major issue – you’ll still have to use strings as configuration value keys. Which means there is a possibility to get an invalid key name by accident – or even worse, wrong value from the configuration. Such problems will often come out only after the project has been shipped.

One – and preferred – solution is to use Settings instead of AppSettings. These are strongly typed and can be accessed via keys (Properties.Settings.Default.SomeNiceSetting) – while the values are still in the configuration file (section <applicationSettings>).

Unfortunately, we cannot always use Settings, for several reasons.

So, I got fed up by having to memorize or copy the keys, do casting and so forth – and decided to figure out some better way to get the AppSettings values. After some other ideas, I ended up with two T4 templates.

First approach: string fields

 

  1. <#@ template debug="false" hostspecific="true" language="C#" #>
  2. <#@ assembly name="System.Configuration" #>
  3. <#@ assembly name="System.Core" #>
  4. <#@ import namespace="System.Configuration" #>
  5. <#@ import namespace="System.Linq" #>
  6. using System.Configuration;
  7.  
  8. namespace <your-namespace-here>
  9. {
  10.     public static class AppSettings {
  11.       <#
  12.     var configurationFileMap = new ExeConfigurationFileMap();
  13.     configurationFileMap.ExeConfigFilename = this.Host.ResolvePath("Web.config");
  14.     var configuration = ConfigurationManager.OpenMappedExeConfiguration(configurationFileMap, ConfigurationUserLevel.None);
  15.     foreach(string key in configuration.AppSettings.Settings.AllKeys.Where(x => !x.Contains(":")))
  16.     { #>
  17.         public static readonly string <#= key #> = ConfigurationManager.AppSettings["<#= key #>"];
  18.     <#} #>
  19.     }
  20. }

This is my first approach – generate a static AppSettings class, which has readonly static string fields for all the AppSetting keys (note the !x.Contains(“!”) bit – that is to avoid the ASP.NET MVC keys).

This has both benefits and disadvantages over the second template – namely, you’ll get string values and will have to convert them to the required data type yourself. When someone messes up configuration (i.e. instead of “40” types in “4O” then obviously the cast to integer will fail), you have the option to fail gracefully – fall back to default value or such.

You can also combine this approach with generic methods linked above – i.e. use the t4 template to create constant strings for keys and send the now-hardcoded keys to generic method for appropriate handling.

Second approach: strongly typed properties

  1. <#@ template debug="false" hostspecific="true" language="C#" #>
  2. <#@ assembly name="System.Configuration" #>
  3. <#@ assembly name="System.Core" #>
  4. <#@ import namespace="System.Configuration" #>
  5. <#@ import namespace="System.Linq" #>
  6. <#@ import namespace="System.Globalization" #>
  7. using System.Configuration;
  8.  
  9. namespace <your-namespace-here>
  10. {
  11.     public static class AppSettings {
  12. <#
  13.     var configurationFileMap = new ExeConfigurationFileMap();
  14.     configurationFileMap.ExeConfigFilename = this.Host.ResolvePath("Web.config");
  15.     var configuration = ConfigurationManager.OpenMappedExeConfiguration(configurationFileMap, ConfigurationUserLevel.None);
  16.     foreach(KeyValueConfigurationElement setting in configuration.AppSettings.Settings)
  17.     {
  18.         if (setting.Key.Contains(":")) //these are ASP.NET MVC keys
  19.             continue;
  20.  
  21.         string settingType;
  22.         int i; bool b; decimal d;
  23.         if (int.TryParse(setting.Value, out i))
  24.             settingType = "int";
  25.         else if (bool.TryParse(setting.Value, out b))
  26.             settingType = "bool";
  27.         else if (decimal.TryParse(setting.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out d))
  28.             settingType = "decimal";
  29.         else { #>
  30.         public static string <#= setting.Key #> { get { return ConfigurationManager.AppSettings["<#= setting.Key #>"]; }}
  31. <# continue; } #>
  32.         public static <#= settingType #> <#= setting.Key #> { get { return <#= settingType #>.Parse(ConfigurationManager.AppSettings["<#= setting.Key #>"]); }}
  33. <# } #>
  34.     }
  35. }

Second approach tries to guess the appsetting type by trying to cast the value into several common types (int, boolean and decimal in the code above) and create the AppSettings class property in an already correct type.

This could be improved in several ways – for example, use TryParse() in non-string properties, use IConvertible and so forth. You probably need add your own types, too.

As an example, here is my test <appSettings>:

  1. <appSettings>
  2.     <add key="TestDecimal" value="6.02214129" />
  3.     <add key="TestBoolean" value="True" />
  4.     <add key="TestInt" value="420" />
  5.     <add key="TestString" value="Alea jacta est" />        
  6. </appSettings>

and output from the template:

public static class AppSettings {
    public static decimal TestDecimal { get { return decimal.Parse(ConfigurationManager.AppSettings["TestDecimal"]); }}
    public static bool TestBoolean { get { return bool.Parse(ConfigurationManager.AppSettings["TestBoolean"]); }}
    public static int TestInt { get { return int.Parse(ConfigurationManager.AppSettings["TestInt"]); }}
    public static string TestString { get { return ConfigurationManager.AppSettings["TestString"]; }}
}

You’ll have to add the AppSettings.tt template to the root folder of your application – or modify the this.Host.ResolvePath("Web.config") accordingly.

One thing that you have to note is that the configuration XML keys can have symbols that are not allowed in C# field/property names, such as the aforementioned colons in ASP.NET MVC keys. Best approach is probably to remove such symbols from field names, but not from the key names in return statements, as latter can handle just fine code such as ConfigurationManager.AppSettings["I:Really:Suck:At:Naming!"].

Another problem is that I was unable to get the template generation to auto-run when the Web.config changes. I tried to follow an old answer from Stack Overflow, but no dice. If you have any ideas/suggestions about this or other possible improvements, please post them to the comments – meanwhile you’ll just need to right-click on AppSettings.tt in Visual Studio and choose “Run custom tool” (if that option is missing, set in AppSettings.tt file properties “Custom Tool” to “TextTemplatingFileGenerator”).

2013-03-04

jQuery.viewSource

Filed under: HTML,Isiklikud,JavaScript — Sander @ 16:13:10
Tags: , ,

I finally released jQuery.viewSource – a jQuery plugin to show the HTML source of current web page, or just a HTML snippet from a page. This is useful for web pages which include HTML/JS/CSS examples and such.

image

As you can see from the image, the plugin can also highlight the HTML, using google-code-prettify script. You have to include the prettify script and CSS to the page yourself.

There are just two methods:

  1. Add $(someselector).viewSource(code-to-show-selector); to document.ready() method. This will bind the click event to the element(s) specified by your jQuery selector – i.e. clicking on those elements will show the source.
  2. Call $().showSource(code-to-show-selector); yourself to immediately show the source.

Note: "code-to-show-selector" is optional selector for the element which code to show. If left empty or passed an empty string, it will default to "html", ie. the whole page.

Download includes both minified and normal version of the script, along with a barebones example. jQuery.viewSource is licenced under Mozilla Public Licence 1.1.

2012-12-14

Microsoft Exam 70-483: Programming in C#

Filed under: Programmeerimine — Sander @ 10:44:40
Tags: , , ,

51qpENQXLkL._SS500_

Yesterday I passed MS exam 70-483: Programming in C#. It was not an exam I really needed for MS Visual Studio 2012 certifications, as I already have MCPD (VS 2010 certifications) for both Windows and Web – so I could have done just the two exams required for an upgrade. However, I wanted to ensure I am properly up to date with .NET 4.5.

As of now, there really aren’t any “official” study materials. Microsoft’s Exam Ref 70-483: Programming in C# will come out in April 2013, Wrox’s MCSD Certification Toolkit (Exam 70-483): Programming in C# won’t be out until May 2013. Andreas Hammar has collected study links for the exam in his blog.

I read Pro C# 5.0 and the .NET 4.5 Framework, skipping quite a few sections as it is a very basic introduction (and the attempted humor in the book is just bad). Jeffrey Richter’s excellent CLR via C#, 4th Edition was both more interesting and in-depth – I read only Part II: Designing Types and  Part III: Essential Types for the exam, rest will be my Christmas reading (hey, to each his own!).

The exam itself was easy – probably easiest out of all eight Microsoft exams I’ve done so far. That wasn’t really surprising, as I am working daily with those areas covered in the exam. Maybe I should have paid more attention to performance counters, but despite Microsoft pushing those heavily, next to no one uses performance counters, opting for various other profilers instead.

However, what was surprising was how bad the exam questions were. Yes, that is a new, fresh exam – but that is not an excuse for sloppiness. Obviously I cannot go into details of the questions, but several of the questions were ambiguous – i.e. they did not cover all the requirements. Formatting of the code sometimes skipped spaces, i.e. instead of int i there was inti and so forth.

At least one question promoted just horrible way of coding. Yes, the problems are artificially constructed, but whoever prepared the exam should realize a lot of newbie programmers will see the code and think this is the way that particular casting operation should be done – and they will use it in their production code, causing bad performance and hard-to-find bugs.

And even worse, one question about nullable types and LINQ did not have a simplest and most logical answer. Again, this is something I have been working with daily for years, often implementing complex business logic.

I left quite a few comments to the exam review, but unfortunately, I really doubt anyone will actually read those and fix the issues. Which is a shame, as exams (same as study books) should always promote best practices and clean code.

« Eelmine lehekülgJärgmine lehekülg »

The Rubric Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 71 other followers