Wednesday, November 3, 2010

Log4Net: esempio di configurazione

Un piccolo suggerimento per chi di voi utilizza Log4Net (http://logging.apache.org/log4net/index.html) ma utile: Invece di utilizzare log4net.Appender.FileAppender sarebbe consigliato l’utilizzo di log4net.Appender.RollingFileAppender, che vi da decisivamente più funzionalità per esempio potete impostare la grandezza massima del file di log o anche potete specificare che il file venga rinominato con un “date pattern”.

Ecco un esempio di configurazione:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    </configSections>
    <log4net debug="false">
        <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender, log4net">
            <file value="C:\xxx\xxx_Log4Net" />
            <appendToFile value="true" />
            <rollingStyle value="Composite" />
            <datePattern value=".yyyyMM'.log'" />
            <maxSizeRollBackups value="-1" />
            <maximumFileSize value="50MB" />
            <layout type="log4net.Layout.PatternLayout, log4net">
                <conversionPattern value="%d [%t] %-5p %c - %m%n" />
            </layout>
        </appender>
        <root>
            <priority value="ALL" />
            <appender-ref ref="RollingLogFileAppender" />
        </root>
    </log4net>
</configuration>

Qualche note:

Impostando la proprietà RollingStyle uguale a Composite istruisco a Log4Net che il file corrente si chiami xxx_Log4Net e i file successivi vengano denominati con il seguente pattern .yyyyMM'.log' (yy sta per anno e MM sta per mese). Per essere più esatti passato un mese il file corrente xxx_Log4Net verrà rinominato a xxx_Log4Net.yyyy.MM.log. Inoltre se il file supera la grandezza di 50Mb verrà creato un nuovo file con il nome xxx_Log4Net.1.

Tuesday, October 26, 2010

How to post your source code on blogspot

I am using SyntaxHighlighter (http://alexgorbatchev.com/SyntaxHighlighter/) for formatting and highlighting source code on blogspot and I will explain in this post step by step how to set it up. Btw: For writing my blogs I am using Windows Live Writer with the plug-in Precode (http://precode.codeplex.com/) which gives support for SyntaxHighlighter and snippet indentation.

1) From the navigation menu of blogspot select DesignEdit HTML. Add following lines:




2) For posting a piece of c# source code it is enough to wrap it between:

source code

HAPPY POSTING!!

Tuesday, September 21, 2010

Just Another String Enum

Enum sono molto utili. Uno dei problemi degli Enum in .NET è la mancanza di supporto per stringhe. Infatti questi possono essere solamente di tipo numerico.
Vediamo come aggiungere il supporto delle stringhe agli Enum. L’idea è di utilizzare un “Extension Methods” per aggiungere alla classe Enum il metodo GetStrOfEnumMemberAtt e per enumerare i valori con le stringhe utilizziamo la classe EnumMember.

La seguente classe contiene “Extension Methods” che poi utilizzeremmo per accedere alla stringa. Vorrei fare notare, che questa classe utilizza un oggetto Dictionary come cache per essere più performante.

public static class EnumExtensions
{
    //cache
    private static Dictionary<Enum, string> _stringValues = new Dictionary<Enum, string>();

    public static string GetStrOfEnumMemberAtt(this Enum value)
    {
        if (!_stringValues.ContainsKey(value))
        {
            //Add to cache
            Type type = value.GetType();
            FieldInfo fi = type.GetField(value.ToString());
            EnumMemberAttribute[] attrs = fi.GetCustomAttributes(typeof(EnumMemberAttribute), false) as EnumMemberAttribute[];
            if (attrs.Length > 0 && !string.IsNullOrEmpty(attrs[0].Value))
            {
                _stringValues.Add(value, attrs[0].Value);
            }
            else
            {
                _stringValues.Add(value, value.ToString());
            }
        }
        return _stringValues[value];
    }
}

Questo è un esempio di come decorare gli Enum con le stringhe:

public enum MachineTypes{
    [EnumMember(Value = "Motorcycle")]
    MOTO,
    [EnumMember()]
    BICYCLE,
    CAR
}

Poi è semplice, per accedere al stringa basta chiamare il metodo GetStrOfEnumMemberAtt come in questo esempio:

//s1=Motorcycle
string s1 = MachineTypes.MOTO.GetStrOfEnumMemberAtt(); 
//s2=BICYCLE
string s2 = MachineTypes.BICYCLE.GetStrOfEnumMemberAtt();
//s3=CAR
string s3 = MachineTypes.CAR.GetStrOfEnumMemberAtt();

Monday, September 20, 2010

Performanceprobleme??? Hier die Lösung

Jeder seriöse Webentwickler sollte den Artikel “Best Practices for Speeding Up Your Website” (http://developer.yahoo.com/performance/rules.html) von Yahoo Developer Network kennen.
Hier nochmals eine kleine Zusammenfassung der wichtigsten Regeln:

  • Minimieren Sie HTTP-Requests
    • Alle Script Dateien sollten zu einer großen Script Datei zusammengeführt werden, das gleich gilt für CSS Dateien.
  • Verwenden Sie einen Content Delivery Network
  • Verwenden Sie eine Expires oder Cache Header
  • Verwenden Sie Gzip Components
  • Referenzieren Sie Stylesheets im Header
  • Referenzieren Sie Scripts auf der Unterseite
  • Vermeiden Sie CSS Ausdrücke
  • Script und CSS sollten in externen Dateien vorliegen
  • Reduzieren Sie DNS-Lookups
  • Verkleinern Sie Script und CSS Dateien
    • Entfernen Sie unnötige Zeichen (Leerzeichen, Zeilenumbruch und Tabulator)
    • Entfernen Sie Kommentare und unnötigen Code

Nachdem wir ein bisschen die Theorie aufgefrischt haben nun die Praxis:
Die NET-Bibliothek COMBRES (http://combres.codeplex.com/) ermöglicht das Verkleinern, die Kompression und die Kombination von Script und CSS Dateien. Zudem erlaubt diese das Zwischenspeichern (= Caching) von Script und CSS Ressourcen für ASP.NET und ASP.NET MVC Web-Anwendungen.

Saturday, September 18, 2010

Un estensione utile per l’oggetto NameValueCollection

Queste poche righe di codice permettono di trasformare una NameValueCollecition in un oggetto Dictionary<string, string>.

public static class NameValueCollectionExentsions
{
    public static IDictionary<string, string> ToDictionary(this NameValueCollection source)
    {
        return source.AllKeys.ToDictionary<string, string, string>(x => x, x => source[x]);
    }
}

Cosi facendo sarà possibile utilizzare LINQ per fare delle queries.

IDictionary<string, string> queryStr = context.Request.QueryString.ToDictionary();
queryStr.SingleOrDefault(x => x.Key.Equals("Value", StringComparison.InvariantCultureIgnoreCase));

Wednesday, September 15, 2010

A riguardo della sicurezza...

Technorati Tags: ,

Secondo questo articolo (http://visualstudiomagazine.com/articles/2010/09/14/aspnet-security-hack.aspx) ci sarebbe un bug nell’ implementazione del algoritmo AES di .NET.
Per sviluppatori e amministratori di sistemi ASP.NET io consiglio di  aggiungere o modificare la sezione  machineKey del file web.config come segue:

Thursday, August 5, 2010

Localize ASP.NET MVC 2 DataAnnotations validation messages with a custom resource provider

The problem

If in ASP.NET applications you are using a Customized Resource Provider and System.ComponentModel.DataAnnotations for validating your model, then you will have problems to localize messages. To be more precise, I am using a Database Resource Provider, which I wrote some years ago, for pulling localization information from a Database and to localize, in this way, ASP.NET and ASP.NET MVC Web Applications. Data Annotations are using two properties for localizing messages, ErrorMessageResourceType and ErrorMessageResourceName, which accept a Type (i.e. a compiled resource file) and a String respectively. Having a Customized Resource Provider (= Database Resource Provider) does not allow me to specify a Type for the ErrorMessageResourceType, since resources are not compiled.

Approaches to solve the problem:

  1. Writing a Custom Build Provider, which compiles resources from the Database.
  2. Creating a Dynamic Object, which transforms the property name to a key for the Resource Manager.
  3. Extending Attributes of Data Annotations.
  4. Using a T4 Template for generating a class containing the resources.

First approach

The Idea was to have a Custom Build Provider (namely DataBaseResourceBuildProvider) for compiling resources that are in a Database. So I started with a simple implementation. During this task I want to underline, that the tool CodeDom Assistant (http://www.codeproject.com/KB/cs/codedom_assistant.aspx) was helping me a lot, since I could convert some pieces of source code into a CodeDom object. Finally I registered the Build Provider in my web.config file and I found out that it is not working. It took me some time to find out that adding a Customized Build Provider class to the web.config file works in an ASP.NET Web Site but does not work in an ASP.NET Web Application project. In a Web Application project, the code that is generated by the Build Provider class cannot be included in the application. This information I found in Microsoft MSDN (http://msdn.microsoft.com/en-us/library/system.web.compilation.buildprovider.aspx). I was very surprised and angry about this, therefore abandoned this approach and moved on to the second one.

Second approach

My second approach was to create a Dynamic Object and to encapsulate the call to the Resource Manager in a general implementation. Basically, the idea was that you can call any property that you want on this object, even if this property was not explicitly defined. In the background the property name would be used as a key for retrieving the resources. First, I extended the class System.Dynamic.DynamicObject and I overrode the function TryGetMember. This is a sketch of the implementation:

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    result = HttpContext.GetLocalResourceObject("", "Resource_KEY822.Title") as string
    return (result != null);
}

It turned out that the Data Annotations needs static property for retrieving resources, and therefore I discarded this approach.

Third approach

I tried to avoid this approach, because I would have had to extend several classes, which requires time. It consists to extend all Attributes of Data Annotations and to write some logic for displaying localized messages. To show that it works, I extended on Attribute, namely the DisplayNameAttribute. This is a sketch of the implementation:

public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
    public LocalizedDisplayNameAttribute(string displayNameKey)
        : base(displayNameKey)
    {
    }
    
    public override string DisplayName
    {
        get
        {
            string s = HttpContext.GetLocalResourceObject("", base.DisplayName) as string;
            if (string.IsNullOrWhiteSpace(s))
                return base.DisplayName;
            else
                return s;
        }
    }
}

Fourth approach and Solution

I use T4 Template for generating a wrapper class, which encapsulates all resources of the Database as properties. To be more precise, I generate a property with the name of the key of the resource in the Database. In this way, I generate a class where every property corresponds to a call to the Resource Manager that, given the key, returns the localized resource message. Moreover, I generate a constant of type String, whose name is composed of a prefix Prop and the key. The value of the constant is the name of the property. Having constants and properties allows me to use Data Annotations for validating my model: for the property ErrorMessageResourceType I will pass the type of my generated class; for the property ErrorMessageResourceName I will set it to the constant that encapsulates the name of the property. I would like to emphasize that properties have to be declared as static for working with Data Annotations. Using constants for specifying the ErrorMessageResourceName has the following two fundamental advantages:

  1. Using of IntelliSense
  2. Error detection at compile time

The following example shows a sketch of the T4 Template:

public class Resources
{
<#
string connectionString = CurrentConnectionStrings["xxx"].ConnectionString;
string providerName = CurrentConnectionStrings["xxx"].ProviderName;
string applicationName = CurrentApplicationName["xxx"].Value;
DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
DbConnection connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
DataBaseResourceProvider provider = new DataBaseResourceProvider(applicationName, connection);
foreach (DictionaryEntry entry in provider.ResourceReader)
    {
        string propName = createUnderscore(Convert.ToString(entry.Key));
        WriteLine(string.Format("    public const string Prop_{0}=\"{1}\";", propName, propName));
        WriteLine(string.Format("    public static string {0}", propName));
        WriteLine("    {");
        WriteLine("        get { return HttpContext.GetLocalResourceObject(\"a\", \""+Convert.ToString(entry.Key)+"\") as string; }");
        WriteLine("    }");
        WriteLine("");
    }
#>    
}

Friday, July 30, 2010

T4 Template: Tool fondamentale

Mio padre una volta mi ha detto: “Per fare un buon lavoro servono gli attrezzi giusti altrimenti ti trovi a tribolare per niente.” Siccome Visual Studio 2010 non da nessun supporto (IntelliSense, Syntax Highlighting, …) per la sviluppazione di Templates T4 dobbiamo installare un tool che ci dia un supporto minimo. Io ho scelto la versione free di Tangible T4 Editor (http://visualstudiogallery.msdn.microsoft.com/en-us/60297607-5fd4-4da4-97e1-3715e90c1a23).

Thursday, July 29, 2010

ASP.NET MVC Suggerimento: Compilare le "View"!

Una cosa fondamentale subito dopo avere creato un progetto ASP.NET MVC è di modificare il file *.csproj aprendolo con un semplice editore di testo e aggiungere all’ elemento <PropertyGroup> la seguente riga: <MvcBuildViews>true</MvcBuildViews>

Il vantaggio fondamentale nel compilare le “views” è di individuare gli errori di sintassi.  In questo modo evitiamo di individuare questi tipi di errore a “runtime”. Naturalmente questa impostazione comporta, che la compilazione del progetto richieda un po’ più di tempo. Se questo per voi non è accettabile potete impostare la compilazione delle “views” solamente per la versione “release” . Io personalmente ho impostato questo settaggio sia per versione “release” che anche per la versione “debug” .