lunedì 20 luglio 2015

[.NET - MVC] Bundling e Minification come implementarlo.

Di cosa si parla
In ASP.NET MVC sfruttando i meccanismi di Bundling e il Minification possiamo ridurre drasticamente, se usati insieme, il tempo di caricamento della nostra applicazione web aumentandone le performance.

Una breve panoramica
Il Bundling utilizza i meccanismi del .net per permetterci di comprimere il puntamento ai file Css o ai file Js in un'unica chiamata mentre il Minification ci permette di ridurre semplicemente la grandezza dei file puntati eliminando i righe vuote, commenti e altro.
Ogni volta che creiamo un progetto web MVC partendo dalla versione 4+ partendo dal template base,
Screenshot di creazione progetto web base

utilizziamo il meccanismo del Bundling e Minification.
La classe che si occupa di gestirli si trova sotto la cartella app_start del progetto e si chiama BundleConfig.cs, aprendo questa classe troviamo al suo interno già configurati di default i puntamenti alle librerie javascript di Jquery e ai loro css.
Struttura del nostro progetto
Come possiamo vedere,  la semantica del Bundling è molto semplice, si tratta di dare un nome fittizio ad un'insieme di link di librerie javascript che vogliamo raggruppare.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));
Nell'esempio sopra, come potete vedere, la libreria jQuery presente nella cartella Scripts viene associata al link fittizio ~/bundles/jquery.
Da notare poi che nell'istruzione che troviamo sopra è presente il segna posto {version}, tale segnaposto è molto utile è viene interpretato in maniera differente in base a vari fattori, in particolare viene interpretata:
  • In ambiente di Relase come il .min della versione di jquery che è presente nella cartella di Scripts mentre in Debug come la versione non .min della libreria
  • Quando eseguiamo un'aggiornamento delle librerie con Nuget riconosce automaticamente il cambio della versione, dandoci a noi la tranquillità di non dover modificare il file ogni volta. 
Come si implementa?
Implementare questi due meccanismi è molto semplice.
Creando un progetto base siamo già avvantaggiati, poiché l'IDE Visual Studio implementerà il meccanismo di Bundling automaticamente.
Ma se volessimo implementarlo da noi?
Per cominciare creiamo una classe sotto la cartella App_start di nome BundlingConfig.cs che avrà tra gli using la System.Web.Optimization, contenente tutti i tipi e i metodi di cui abbiamo bisogno (Se si comincia con un progetto vuoto si dovrà recuperare da nuget il pacchetto Optimization ed inserire all'interno del web.config "<add namespace="System.Web.Optimization" /> "), e il metodo public static void RegisterBundles(BundleCollection bundles).
All'interno del metodo andremmo a implementare l'istruzione per  eseguire il Bundling delle libbrerie jQuery-ui nella nostra applicazione:

bundles.Add(new ScriptBundle("~/bundles/jqueryUI").Include(
                        "~/Scripts/jquery-ui-{version}.js"));
o nel caso dei suoi stili:
bundles.Add(new StyleBundle("~/Content/css").Include(
            "~/Content/themes/base/jquery.ui.core.css",
            "~/Content/themes/base/jquery.ui.resizable.css",
            "~/Content/themes/base/jquery.ui.selectable.css",
            "~/Content/themes/base/jquery.ui.accordion.css",
            "~/Content/themes/base/jquery.ui.autocomplete.css",
            "~/Content/themes/base/jquery.ui.button.css",
            "~/Content/themes/base/jquery.ui.dialog.css",
            "~/Content/themes/base/jquery.ui.slider.css",
            "~/Content/themes/base/jquery.ui.tabs.css",
            "~/Content/themes/base/jquery.ui.datepicker.css",
            "~/Content/themes/base/jquery.ui.progressbar.css",
            "~/Content/themes/base/jquery.ui.theme.css"));
Successivamente nel Global.asax nel metodo Application_Start() implementiamo il metodo che eseguirà la nostra classe BundlingConfig.cs così facendo:

BundlingConfig.RegisterBundles(BundleTable.Bundles);

in tal modo diciamo che ad ogni avvio della nostra applicazione dovremmo eseguire il nostro metodo creando così i nostri "Bundle".
A questo punto all'interno della nostra pagina andremo a inserire il link al nostro "Bundle":

@Scripts.Render("~/bundles/jqueryUI")

Best practice
Di norma per usare in modo corretto queste pratiche è quello di implementare i Bundle dei Css nel head della pagina mentre il Bundle js appena sotto il @RenderBody.
Il motivo più semplice è quello di non incorrere in eccezioni di oggetti richiamati nei javascript e non ancora istanziati nella pagina oppure di problemi di fouc.

Conclusioni
Potete trovare informazioni più precise sull'argomento qui e qua spero che questo breve articolo sia stato abbastanza esaustivo per iniziare o per darvi delle delucidazioni.
Ringrazio tutti quelli che mi seguono e che mi hanno mandato mail per chiedermi che fine avevo fatto in questo annetto circa e anche quelli che mi hanno aiutato.
Ricordo a tutti che per ogni informazione aggiuntiva, se ci sono degli errori nelle istruzioni presentate qui o semplicemente per aggiungere qualcosa è possibile farlo scrivendo al mio indirizzo mail o semplicemente commentando qui sotto.

venerdì 24 ottobre 2014

[C#] Configurare e utilizzare LOG4NET per scrittura su file

A volte capita di dover integrare un meccanismo di logging all'interno della nostra applicazione. A tal proposito trovo molto comoda la libreria LOG4NET di Apache scaricabile qui per creare i log in applicazioni .net, per chi di voi conoscesse già LOG4J non ci sono molte differenze nella configurazione di questa libbreria. 

Oggi vedremmo come configurarla e sfruttarla nelle nostre applicazioni .net, per iniziare dobbiamo scaricare la libreria e successivamente aggiungere il riferimento alla nostra applicazione, ricordiamoci di far copiare localmente a Visual Studio la libreria, in caso contrario se esporteremo il progetto avremmo dei problemi a causa della libreria mancante. 

Successivamente dovremmo configurare il file AssemblyInfo.cs aggiungendo la seguente riga:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Web.config", Watch = true)]   

tale riga ci permette di dire a LOG4NET dove si trova la configurazione da utilizzare per costruire i log, se si tratta di una web application tale file comunemente è il WEB.CONFIG nel caso di applicazioni si tratta del file APP.CONFIG. 

Dopo di che andremmo a inserire nel file Web.config la configurazione dei log nella sezione <configuration>:

Nota bene: il seguente codice deve essere inserito immediatamente sotto al tag di apertura di configuration in caso negativo si avrà un'errore. 

<configSections>
    <!-- Add log4net config section-->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
<log4net debug="true">
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="Log\log.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
      </layout>
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="RollingLogFileAppender" />
    </root>
  </log4net>

come potete vedere la configurazione ci permette di indicare la posizione del file di log tramite il tag <file value="Log\log.txt" /> e la sua dimensione massima tramite il tag <maximumFileSize value="10MB" />. La parte più importante è il tag <level value="DEBUG" />, questo tag indica il livello nel quale LOG4NET inizia a scrivere i log nel file di log, in ordine di importanza i livelli disponibili sono: DEBUG, INFO, WARNING, ERROR. Nel nostro caso LOG4NET è configurato per scrivere tutti i tipi di log. 

Infine all'interno del nostro codice c# dovremmo aggiungere la dichiarazione globale nella classe da sottoporre a logging:

private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
ricordandoci di aggiungere using Log4Net, mentre nel nostro codice andremmo a inserire il seguente codice:

log.Error(ex.Message);

nell'esempio che segue ho inserito sia un log informativo sia un log di errore.

public DataTable StrSqlToDataTable( String sqlStr)
        {
            DataTable dt = new DataTable();
            SqlConnection cnn = new SqlConnection(connStr);
            try
            {
               
                cnn.ConnectionString = connStr;
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = cnn;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = sqlStr;
                if (cnn.State != ConnectionState.Open)
                {
                    cnn.Open();
                }
                dt.Load(cmd.ExecuteReader());
               
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);            }
            finally {
                cnn.Close();
                cnn.Dispose();
                log.Info("Eseguita query: " + sqlStr);            }
           
            return dt;
        }

Come potrete vedere LOG4NET ci offre molte possibilità per creare dei log completi.

Come al solito spero di essere stato di aiuto. 


lunedì 14 luglio 2014

[SQL] COLLATE eseguire ricerche Case Sensitive in SQLServer.

A volte capita di dover eseguire una ricerca di una particolare stringa, con maiuscole e minuscole, all'interno di una campo di una tabella a cui non è stata impostata nessuna regola di confronto. L'istruzione COLLATE fa al caso nostro in quanto può essere usata per impostare momentaneamente in fase di ricerca una regola di confronto.
Nel mio caso avevo bisogno di ricercare all'interno di una tabella tutti i record che in un dato campo iniziassero con una Particolare stringa di caratteri ("Users") per poi modificare tale stringa nel suo corrispettivo lowercase ("users"). Per effettuare tale ricerca ho sfruttato il COLLATE Latin1_General_CS_AS che mi ha permesso di fare una ricerca case sensitive all'interno della tabella.
Di seguito la mia query di update:

update folders
set folderpath = lower(folderpath)
where FolderPath COLLATE Latin1_General_CS_AS like 'Users%'

La cosa utile del COLLATE è l'utilizzo di esso anche all'interno della creazione di DB e TABLE per impostare la regola di confronto. Per ulteriori informazioni vi rimando qui alla pagina Msdn dove vi spiega per bene come sfruttare l'istruzione COLLATE.

Edit:

Da notare che il collate viene utilizzato anche per eseguire query tra più DB che abbiano regole di cofronto differenti tra loro.