Formattare un numero decimale

A volte capita di voler visualizzare solo n posti decimali per un valore numerico. E' possibile utilizzare a questo scopo il metodo ToString("Nx") dove con x indichiamo il numero di decimali da visualizzare in output. Vediamo un esempio:

static void Main(string[] args)
{
   Decimal d = new Decimal(120.4893621489);
   Console.WriteLine(d.ToString("N2"));
   Console.ReadLine();
}
//print: 120,49

Come indicato nell'esempio il valore viene approssimato.


Utilizzare SyntaxHighlighter nei post di BlogEngine.NET

Se vogliamo inserire dei code snippet all'interno dei nostri post tecnici e vogliamo che questi siano facilmente leggibili non possiamo fare a meno di un formattatore di codice ed in questi casi due sono gli approcci possibili: css o css+javascript.
Inizialmente per i post di questo blog facevo affidamento sul code formatter on-line di Manoli che effettua l'highlight delle parole chiave esclusivamente tramite i css. L'utilizzo dei soli css però, soprattutto se vogliamo visualizzare anche i numeri di riga, introduce una quantità spropositata di tag ed impedisce il copia/incolla del codice "pulito".
Cercando sulla rete una valida alternativa a tale approccio mi sono imbattuto nella libreria SyntaxHighlighter.

SyntaxHighlighter è una libreria javascript "non intrusiva" che formatta il codice attraverso l'aggiunta di attributi class alle parole chiave in fase di caricamento del dom utilizzando le espressioni regolari.

Decido quindi di utilizzarla e seguo passo-passo le seguenti istruzioni:

  • Scarico da Google Code la versione 1.5.1 di SyntaxHighlighter
  • Salvo nella root del blog le cartelle Scripts e Styles
  • Modifico il site.master del mio tema inserendo nell'head i riferimenti seguenti:


A questo punto decido di provare la libreria in un vecchio post nel quale avevo utilizzato del codice c#. Pulisco il pezzo di codice formattato con lo strumento precedente togliendo tutti i tag html e lo racchiudo in un tag <pre name="code" class="c-sharp"> come specificato dalle linee guida di SyntaxHighlighter.
Salvo e vado a vedere... il risultato: niente di niente, ovvero nessuna formattazione.

Osservando attentamente il codice html della pagina mi accorgo che il tag pre non ha più nè class nè name. Arrivo quindi alla conclusione che l'editor di BlogEngine.NET, il TinyMCE, pulisce il tag pre di tutti i suoi attributi prima di salvarlo.

Deciso a non mollare cerco di capire come aggirare il problema e trovo questo articolo che spiega brillantemente come utilizzare Syntax Highlighter con TinyMCE, ovvero modificando la funzione init dell'editor specificando quali sono i tag e i relativi attributi da considerare validi (e quindi da non rimuovere nel salvataggio).

In pratica vado nel controllo TinyMCE.ascx del BlogEngine.NET e modifco la proprietà extended_valid_elements della funzione init aggiungendo in fondo: pre[name|class].

And That's all folks!


DotNetKicks button in BlogEngine.NET

Se vogliamo "farci prendere a calci" dai lettori del nostro blog ed inserire il pulsante di DotNetKicks in fondo ai nostri post tecnici dobbiamo modificare il controllo PostView.ascx del nostro tema. Il come è abbastanza semplice, è sufficiente inserire il seguente script:


 
bgcolor=FFFFFF border="0" alt="kick it on DotNetKicks.com"/>

Nota: In questo esempio ho inserito in modo statico il nome di dominio, ovviamente è possibile inserire il valore corretto prendendolo direttamente dalla Request, a voi la scelta.


Track Active Item in Solution Explorer

Lavorando con MonoRail di Castle Project capita spesso di avere viste con lo stesso nome, specialmente quando sviluppiamo applicazioni data-centric. In Visual Studio questo può portare, soprattutto quando si hanno molte viste aperte, a non riconoscere subito il controller al quale fa riferimento la vista che stiamo modificando.

In questo caso ci viene in aiuto il Solution Explorer che evidenzia di volta in volta nell'albero il file aperto nella scheda corrente. Se questa funzionalità non dovesse essere attiva è sufficiente andare sotto Tools > Options > Projects And Solutions > General e mettere una spunta su Track Active Item in Solution Explorer come evidenziato nella figura qui sotto.

SolutionExplorerTrackItem


Could not find dialect in configuration

In questi giorni ho avuto l'occasione di utilizzare l'ultima build di Castle Project. Utilizzando ActiveRecord mi sono però scontrato con il seguente errore di configurazione: "Could not find the dialect in configuration". Il problema è dovuto ad un cambiamento nei nomi delle proprietà di configurazione di NHibernate, infatti se vogliamo utilizzare Castle ActiveRecord nell'ultima build compatibile con NHibernate 2.0 dobbiamo togliere dal nome delle proprietà di configurazione il prefisso hibernate, come mostrato qui sotto:


  
    
    
    
    
  


Dynamic Data: attributo DisplayColumn e override di ToString()

Nei Dynamic Data quando abbiamo una relazione uno a molti possiamo utilizzare l'attributo DisplayColumn per determinare quale tra le proprietà della classe sulla parte uno della relazione viene utilizzata nel testo del link.

[MetadataType(typeof(CustomerMetadata))]
[DisplayColumn("CompanyName", "CompanyName", false)]
public partial class Customer
{
   ...
}

Analizzando nel dettaglio il controllo ForeignKey.ascx che visualizza il campo chiave esterna notiamo che il testo del link viene popolato utilizzando il metodo GetDisplayString della classe MetaTable. Utilizzando Reflector vediamo come si comporta questo metodo:

public string GetDisplayString(object row)
{
  if (row != null)
  {
    row = this.PreprocessRowObject(row);
    if (this.HasToStringOverride)
    {
      return row.ToString();
    }
    object propertyValue = 
      DataBinder.GetPropertyValue(row, this.DisplayColumn.Name);
    if (propertyValue != null)
    {
      return propertyValue.ToString();
    }
  }
  return string.Empty;
}

Dall'analisi del codice notiamo come l'attributo DisplayColumn non abbia effetto se abbiamo eseguito l'override del metodo ToString() nella classe della chiave esterna.

In questo modo se nella classe Customer dell'esempio andiamo ad eseguire l'override del metodo ToString() nel seguente modo...

public override string ToString()
{
  return String.Format("{0} - ({1})", this.CompanyName, this.Country);
}

... l'effetto che otteniamo è il seguente:

DisplayColumn

Ovviamente possiamo ovviare a questo comportamento modificando opportunamente il controllo ForeignKey affinché utilizzi direttamente l'attributo DisplayColumn.


Passaggio di parametri ad un dynamic data control tramite l'attributo UIHint

Nei Dynamic Data possiamo, attraverso l'attributo UIHint, impostare il FieldTemplate da utilizzare per un determinato campo dati, e non solo, tramite la proprietà ControlParameters possiamo passare delle informazioni ai controlli, per esempio per impostarne delle proprietà. Vediamo come:

public IDictionary ControlParameters { get; private set; }

La proprietà ControlParameters è un insieme di coppie chiave/valore che possiamo popolare direttamente nella decorazione del campo nella classe dei metadati intervallando chiavi e valori separati da una virgola:

// ControlParameters populating: key1, value1, key2, value2 ...
[UIHint("Text", null, "Columns", 75 )
public string ContactName { ge; set; }

Nell'esempio sopra utilizziamo per il campo ContactName il template Text al quale passiamo una coppia chiave/valore con la quale vogliamo impostare la lunghezza della TextBox a 75 colonne.

Nel FieldTemplate andiamo ad intercettare l'evento PreRender e ciclando sulla collezione dei parametri utilizziamo la chiave per ottenere la proprietà corrispondente per il controllo TextBox esposto dalla proprietà DataControl. A questo punto assegnamo alla proprietà il valore utilizzando l'opportuno convertitore ottenuto dal tipo attraverso la classe TypeDescriptor.

public partial class Text_EditField 
     : System.Web.DynamicData.FieldTemplateUserControl
{
  ...
  protected void OnPreRender(EventArgs e)
  {
    UIHintAttribute hint = null;
    hint=(UIHintAttribute)this.Column.Attributes[typeof(UIHintAttribute)];
    if (hint != null)
    {
      foreach (KeyValuePair kvp in hint.ControlParameters)
      {
        PropertyInfo prop = DataControl.GetType().GetProperty(kvp.Key);
        String value = kvp.Value.ToString();
        var converter = TypeDescriptor.GetConverter(prop.PropertyType);
        if (prop != null)
        {
          prop.SetValue(DataControl, 
             converter.ConvertFromInvariantString(value), null);
        }
      }
    }
  }
  protected override void ExtractValues(IOrderedDictionary dictionary)
  {
    dictionary[Column.Name] = ConvertEditedValue(TextBox1.Text);
  }
  public override Control DataControl
  {
    get
    {
      return TextBox1;
    }
  }
}

In questo esempio ho utilizzato il FieldTemplate Text_Edit.ascx, ma se vogliamo estendere tale funzionalità a tutti i controlli possiamo pensare di creare una nostra classe che erediti direttamente da FieldTemplateUserControl ed inserire questo codice nell'override del metodo OnPreRender. Ovviamente questo implica (per questa soluzione) che le proprietà impostate nella ControlParameters vengano propagate per tutti i controlli utilizzati per renderizzare i dati del campo così decorato (ad esempio Text.ascx, Text_Edit.ascx e se esiste Text_Insert.ascx).


Upload di file via HTTP POST in ASP.NET

In una applicazione web ASP.NET un file viene normalmente caricato via HTTP POST attraverso un HtmlInputFile con runat="server" oppure tramite la sua controparte server FileUpload (introdotto con la versione 2.0 del .NET Framework). Lato code-behind si accede poi al file tramite la proprietà PostedFile identica per entrambi i controlli.
Se non abbiamo a disposizione una pagina web con i controlli sopra citati, ma la richiesta ci arriva da un applicazione esterna che utilizza ad esempio l'API Windows Internet (WinINet), dobbiamo leggere i dati direttamente dalla Request e precisamente dalla proprietà Files. Ecco come fare:

// Request with enctype="multipart/form-data"
// Destination path from Web.config
string path = Server.MapPath(ConfigurationManager.AppSettings["path"]);
foreach (string key in Request.Files.AllKeys)
{
  HttpPostedFile file = Request.Files[key];
  string fileName = System.IO.Path.GetFileName(file.FileName);
  file.SaveAs(path + fileName);
}

Sviluppo Model-Driven

Un argomento molto dibattuto in questi mesi è lo sviluppo di software a partire dalla definizione di modelli astratti. Un tentativo di portare il processo di sviluppo software verso un livello più alto eliminando quasi completamente la scrittura di codice e forse la figura del programmatore così come la conosciamo oggi. Questa corrente di pensiero ha portato alla definizione di diverse metodologie tra cui MDSD e MDA.
Parlando di Model Driven Software Development (MDSD) cito Martin Fowler:

Model Driven Software Development (MDSD) is a style of software development that considers itself as an alternative to the traditional style of programming. The approach centers itself on building models of a software system. These models are typically made manifest through diagrammatic design notations - the UML is one option. The idea is that you use these diagrams, to specify your system to a modeling tool and then you generate code in a conventional programming language.

L'idea di fondo è quella di definire un modello software attraverso diagrammi astratti dai quali poter ottenere completamente o parzialmente il codice sorgente tramite tool o sistemi di generazione automatica.
Tale filosofia è condivisa da MDA (Model Driven Architecture) che differisce sostanzialmente da MDSD per il fatto che considera il modello del tutto astratto ed indipendente sia dalla piattaforma di sviluppo che dal linguaggio che si vuole utilizzare.
Per avere un'idea più precisa dello stato dell'arte vi consiglio di dare una occhiata ad iQgen uno dei tool più diffusi attualmente scritto 100% in Java.
Purtroppo questi tool hanno ed impongono ancora parecchi limiti tra i quali:

  • Il tempo dedicato al mantenimento e allo sviluppo dell'architettura e di gran lunga maggiore rispetto al tempo risparmiato con la generazione del codice.
  • I diagrammi che definiscono il modello software, essendo astratti rispetto al codice prodotto, complicano il debugging ed il versioning dell'applicazione.
  • Le modifiche al codice sono possibili, ma devono essere poi riportate nel diagramma con la difficoltà di riconoscere dove intervenire.
  • La necessità di definire dei template di generazione del codice complica notevolmente (se non impedisce) l'utilizzo di codice sorgente esistente come ad esempio framework open source quali Hibernate, Spring, etc.
  • Lo sviluppo rischia di diventare dipendente dal tool di disegno utilizzato per i diagrammi di modello.

In conclusione possiamo tirare un sospiro di sollievo e rimandare per ora il momento in cui i programmi manderanno in pensione il programmatore. ;-)


Database: tabelle temporanee in PL/SQL

Può essere di grande aiuto in alcune operazioni SQL avere a disposizione tabelle intermedie su cui salvare dei risultati per una successiva elaborazione. Quando lavoriamo con database Oracle abbiamo a diposizione due soluzioni.
Possiamo creare delle tabelle temporanee globali direttamente con un CREATE TABLE, oppure ricorrere a variabili di tipo tabella. La prima soluzione è utile nel caso di manipolazione di grandi quantità di dati e ci permette di decidere se lasciare o meno i dati in tabella conclusa la sessione. Vediamo la sintassi PL/SQL:

CREATE GLOBAL TEMPORARY TABLE tempPhoneBookTable
(
   name VARCHAR2(40),
   surname VARCHAR2(60),
   phoneNumber VARCHAR2(15)
) ON COMMIT PRESERVE ROWS; --preserve data after commit

Per approfondire l'argomento sulle tabelle temporanee globali vi consiglio l'ottimo articolo di Don Burleson su come utilizzare le tabelle temporanee per aumentare le performance di una query.

La seconda soluzione consente di definire variabili di tipo tabella direttamente all'interno dello statement o della procedura e di utilizzare metodi specifici per manipolare i dati della collezione. In Oracle le variabili di tipo tabella possono essere paragonate a tabelle di database ad una sola colonna. Nella dichiarazione della variabile devo quindi indicare il tipo di dato da memorizzare. In alcuni casi, come nell'esempio seguente, avrò bisogno di più colonne, devo ricorrere quindi all'utilizzo dei record:

SET serveroutput ON
DECLARE
--define a record
TYPE contact IS RECORD (
    name VARCHAR2(40),
    surname VARCHAR2(60),
    phoneNumber VARCHAR2(15)
    );
--define a table composed of records
TYPE phoneBook IS TABLE OF contact
   INDEX BY BINARY_INTEGER;

--declare a TABLE variable of this type
myPhoneBook phoneBook;
counter INTEGER :=1;

BEGIN
    myPhoneBook(1).name := 'Manuel';
    myPhoneBook(1).surname := 'Scapolan';
    myPhoneBook(1).phoneNumber := '555-5555';

    myPhoneBook(2).name := 'Mario';
    myPhoneBook(2).surname := 'Rossi';
    myPhoneBook(2).phoneNumber := '666-66666';

    WHILE myPhoneBook.EXISTS(counter) LOOP
    dbms_output.put_line(myPhoneBook(counter).surname || ' ' 
        || myPhoneBook(counter).name || ' tel. ' 
        || myPhoneBook(counter).phoneNumber);
    counter := counter+1;
    END LOOP;
END;
/