20160324032017Vi hanno mai detto che "violenza genera violenza"? Pensateci voi che esprimete violenza su Facebook, che condividete e fate vostro, il pensiero violento di un tiranno come Putin. Pensateci voi che magari siete stati cresciuti nell'insegnamento cristiano del "porgi l'altra guancia", senza comprenderne il significato.

Io negli atti di Bruxelles, nelle violenze terroriste, leggo l'invidia. L'invidia per un sistema tutto sommato civile che tutela - entro i limiti dell'umana fallibilità - l'essere umano ed i suoi diritti, contrapposto alla povertà, all'ingiustizia e alla sofferenza che vivono certi popoli.

Questo dovremmo avere sempre a mente e questo dovrebbe rivelarci chiara la strada per porre fine al terrorismo, alle violenza, alla guerra. "Non c'è pace senza giustizia, non c'è giustizia senza il perdono" ha detto Karol Wojtyla, il Papa di cui molti hanno richiesto la santificazione ma di cui tutti scordano gli insegnamenti... 

E oggi è il momento di essere forti nel perdonare, forti nel ristabilire la giustizia e soprattutto forti nel riconoscere i propri peccati... i peccati di una società, la nostra, che assorbe la ricchezza del mondo anzichè distribuirla, una società che è, essa stessa, alla base dell'ingiustizia che assieme all'ignoranza è terreno fertile per atti di violenza.

Non sono bombe quelle che voglio vedere sganciate sui cittadini inermi, sugli sfortunati che sono esclusi dal benessere della civiltà occidentale... Per una volta, invece che riversare esplosivi, sganciamo ricchezza, istruzione, benessere e cultura. Accogliamo queste popolazioni, facciamo loro vedere la nostra cultura, le arti, le scienze e ascoltiamo le loro... diamogli le opportunità che abbiamo noi, rischiando così anche di perdere una parte delle nostre prerogative. Ne uscirà una eguaglianza sociale, una amalgama di usi e costumi che ci renderà finalmente un solo popolo sulla terra. Noi occidentali, noi europei, noi fortunati, non siamo per forza dalla parte giusta!

Facciamo giustizia... la pace verrà...


Pere al cioccolato è la prima cosa che m'è venuta in mente... Quegli squisiti frutti che divoravo cogliendoli direttamente dalla pianta nelle campagne del Cilento dove eri nato.

Ma non solo... Le passeggiate a piazzale Giovanacci... il te nero con i biscotti alle quattro... le domeniche in officina Jarach & Cecconi... quando mi hai insegnato a smontare e rimontare il carburatore... il tuo orgoglio di Carabiniere e come mi misuravi perché mi avresti voluto Corazziere... l'accompagnarti alla caccia e infilarmi in un pantano da cui mi hai dovuto estrarre... Le corse con il carro armato nel piazzale del battaglione... la tua FIAT 127 con cui mi hai insegnato a guidare... Il paese dove eri nato 96 anni fa, il ciucci...

E i tuoi interminabili racconti delle tue avvertire di guerra... Tutto questo ed altro mi hai regalato nella tua vita. Ma soprattutto il ricordo di un lavoratore indefesso e di una persona integerrima come ce ne sono poche. Se esiste il paradiso tu hai l'ingresso garantito di diritto, ma di certo esiste la vita eterna, perché ora che non ci sei più vivrai per sempre nei miei più bei ricordi.

Grazie nonno Carmine...


Mi sono reso conto oggi che è passato poco più di un anno da quando ho postato l’ultima volta in queste pagine. Da allora tante, tantissime cose, sono cambiate e questo giustifica un po’ il silenzio in cui mi sono rifugiato. Non è ancora il caso che scriva pubblicamente gli eventi che mi hanno riguardato in questi 365 giorni. Forse verrà il giorno in cui potrò e vorrò parlarne ampiamente e liberamente, ma quel momento, se mai verrà, è ancora molto remoto nel futuro.

Per chi mi legge, se è ancora rimasto qualcuno che lo fa, ripensandoci oggi quello che è accaduto non è niente più di quello che in fondo sono gli imprevisti della vita che spesso ti capitano quando meno te lo aspetti, cambiandola radicalmente e cambiandoti radicalmente... oppure semplicemente facendo emergere quello che sei veramente.

Quello che conta è che ci sono ancora, un po’ (molti dicono tanto) diverso, un po’ “imprevisto” io stesso. In questo periodo di grande difficoltà mista a grande rivoluzione sono riemersi un po’ di vecchi interessi e ne sono maturati molti di nuovi ed è di questo che cercherò di parlare prossimamente.

Primo fra tutti quello che oggi mi spinge a tornare a redigere questo post che spero sarà seguito da molti altri. Mi riferisco alla mia passione per lo scrivere, passione che in realtà non ho mai riconosciuto come tale se non in questo ultimo periodo della mia vita, quando essa è diventata qualcosa che mi ha gratificato molto e molto mi ha aiutato a focalizzare quelli che sono i miei pensieri e le mie idee. Mi sono trovato spesso a scrivere per varie ragioni, tra le quali anche, banalmente, il fissare concetti che diversamente sarebbero svaniti nel flusso di miei pensieri o travolti dalle emozioni. Ho scritto molto, moltissimo, per comunicare e per comunicarmi, per organizzare e riorganizzare, per verificare se, alla prova dei fatti, quello che pensavo in un dato momento si rivelava ancora vero dopo tempo.

Ci sono tante altre cose che mi hanno accompagnato, mia figlia, il ballo e la musica, la fotografia, la lettura, il cinema e il teatro, l'arte in generale, il mio lavoro. La montagna e talvolta il mare, la città e la campagna. In definitiva, come qualcuno mi ha insegnato, la "esperienza", questo valore fondamentale che vale oltre ad ogni denaro e ad ogni oggetto che possiamo comprare con esso...

Riparto da qui, dalla voglia di comunicare qualcosa... ma non chiedetemi cosa...

Bentornato Andrea.


Le modal dialog sono uno strumento molto usato nelle applicazioni per interagire con l’utente. Purtroppo, mentre in una applicazione Windows esse sono tutto sommato semplici da gestire dato che il framework ci mette a disposizione più o meno tutto ciò di cui abbiamo bisogno, così non è nelle applicazione web in cui abbiamo solo alert e confirm che sono quanto di meno user friendly si possa immaginare. Inoltre, inserire delle proprie dialog è più o meno complicato in quando richiede non solo l’inserimento del codice Javascript che le gestisce, ma anche sel markup HTML. Un doppio lavoro quindi che complica non poco la questione. Personalmente ho trovato molto proficuo usare un servizio di AngularJS, scritto in Typescript, per cercare di risolvere questo problema alla radice. Per farlo mi sono appoggiato alle Modal popop di bootstrap che sono semplici ed efficaci e gestiscono molto efficacemente la responsività. Vediamo il servizio come è realizzato:

   1: module sys.services
   2: {
   3:     export class Constants
   4:     {
   5:         static containerId: string = '#modalContainer';
   6:         static defaultModalTitle: string = 'Message';
   7:         static modalDialogId: string = '#modalDialog';
   8:     
   9:         static Negative: string = '0';
  10:         static Positive: string = '1';
  11:         static Cancel: string = '2';
  12:     
  13:         static modalYesNo: sys.services.IDialogCommand[] = [
  14:             { id: Constants.Negative, text: 'No' },
  15:             { id: Constants.Positive, text: 'Yes', style: 'btn-primary' }];
  16:         static modalYesNoCancel: sys.services.IDialogCommand[] = [
  17:             { id: Constants.Cancel, text: 'Cancel' },
  18:             { id: Constants.Negative, text: 'No' },
  19:             { id: Constants.Positive, text: 'Yes', style: 'btn-primary' }];
  20:         static modalOkCancel: sys.services.IDialogCommand[] = [
  21:             { id: Constants.Cancel, text: 'Cancel' },
  22:             { id: Constants.Positive, text: 'Ok', style: 'btn-primary' }];
  23:     
  24:         static containerMarkup: string =
  25:         '<span></span>';
  26:         static modalMarkup: string =
  27:         '<div id="modalDialog" class="modal fade"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h4 class="modal-title">Modal title</h4></div><div class="modal-body"><p>One fine body&hellip;</p></div><div class="modal-footer"></div></div></div></div>';
  28:         static modalButtonMarkup: string =
  29:         '<button type="button" class="btn" data-dismiss="modal">Close</button>';
  30:     }
  31:     
  32:     export interface IDialogCommand
  33:     {
  34:         id: string;
  35:         text: string;
  36:         style?: string;
  37:     }
  38:  
  39:     export class ModalManager
  40:     {
  41:         private container: JQuery;
  42:         private modalDialog: JQuery;
  43:  
  44:         constructor()
  45:         {
  46:             this.appendModals();
  47:         }
  48:  
  49:         private exists(name: string): boolean
  50:         {
  51:             if (this.container == undefined)
  52:                 this.container = $(Constants.containerId);
  53:  
  54:             return this.container.find(name).length != 0;
  55:         }
  56:  
  57:         private appendModals(): void
  58:         {
  59:             if (!this.exists(Constants.containerId))
  60:             {
  61:                 this.container = $(Constants.containerMarkup);
  62:                 this.container.appendTo($(document.body));
  63:             }
  64:  
  65:             if (!this.exists(Constants.modalDialogId))
  66:             {
  67:                 this.modalDialog = $(Constants.modalMarkup);
  68:                 this.modalDialog.appendTo(this.container);
  69:             }
  70:         }
  71:  
  72:         public showDialog(message: string, title: string = Constants.defaultModalTitle, commands?: IDialogCommand[], callback?: (id: string) => void)
  73:         {
  74:             this.modalDialog.find('.modal-body').text(message);
  75:             this.modalDialog.find('.modal-title').text(title);
  76:  
  77:             var footer = this.modalDialog.find('.modal-footer');
  78:             footer.empty();
  79:  
  80:             for (var i in commands)
  81:             {
  82:                 var cmd = commands[i];
  83:  
  84:                 var button = $(Constants.modalButtonMarkup);
  85:  
  86:                 button.text(cmd.text);
  87:                 button.addClass(cmd.style == undefined ? 'btn-default' : cmd.style);
  88:                 button.data('command-id', cmd.id);
  89:  
  90:                 button.click((ev) =>
  91:                 {
  92:                     var id = $(event.srcElement).data('command-id');
  93:  
  94:                     this.modalDialog.modal('hide');
  95:  
  96:                     if (callback != undefined)
  97:                         callback.apply(this, [id]);
  98:                 });
  99:  
 100:                 button.appendTo(footer);
 101:             }
 102:  
 103:             this.modalDialog.modal('show');
 104:         }
 105:     }
 106: }

Il servizio così impostato è completo di tutto ciò che serve al funzionamento. Da solo per scontato che siano reparibili le librerie suddette (AngularJS e Bootstrap). Il metodo appendModals() in particolare si occupa di creare il markup necessario utilizzando alcune stringhe costanti. Esso verifica che il markup non sia già presente ed eventualmente lo inserisce aggiungendolo al body. Questo favorisce l’utilizzo della libreria che non richiede alcuna gestione del markup HTML. L’utilizzo è molto semplice. E’ sufficiente infatti registrare il servizio assieme al controller con la seguente riga:

   1: .service('$modalManager',
   2:     () => new sys.services.ModalManager());

Avremo così a disposizione il servizio $modalManager che possiamo iniettare in un controller. A questo punto, potremo richiamare la gdialog molto semplicemente usando uno dei metodi del servizio:

   1: this.$modalManager.showDialog(
   2:     'Are you sure you want to delete the resource',
   3:     'Confirm operation',
   4:     sys.Constants.modalYesNo,
   5:     (id: string) =>
   6:     {
   7:         if (id == sys.Constants.Positive)
   8:         {
   9:             this.clocks.push(timezone);
  10:         }
  11:  
  12:         this.selectedTimezone = undefined;
  13:         this.scope().$apply();
  14:     });

La dialog è sufficientemente intelligente da gestire numerose combinazioni di pulsanti. Le costanti presenti nella dichiarazione sono di aiuto in questo ma se ne possono creare di proprie dato che si tratta a tutti gli effetti di un array di IDialogCommand.

   1: static modalOkCancel: sys.services.IDialogCommand[] = [
   2:     { id: Constants.Cancel, text: 'Cancel' },
   3:     { id: Constants.Positive, text: 'Ok', style: 'btn-primary' }];

Senza dimenticare l’uso appropriato degli stili di bootstrap.


E' di questi giorni l'annuncio che Angular 2.0 è ora completamente scritto in Typescript. Questo è forse uno dei più sorprendenti risultati della politica di Satya Nadella che sta aprendo giorno dopo giorno alle librerie open source di terze parti. E ancora più sorprendente se pensiamo che Angular è un prodotto dei team di Google che recentemente, supportato da Microsoft ha deciso di adottare questo linguaggio. La cosa che più mi entusiasma, come riportato in questo post, è che la collaborazione sarà fonte di nuovi miglioramenti per Typescript che già dalla versione 1.5 vedrà l'introduzione delle annotations, espressamente progettate per Angular. Le annotation apriranno la strada a una sorta di Reflection che tipicamente è fonte di numerose soluzioni che risparmiano lavoro. Attendiamo con ansia...


L'asincronia sta ormai diventando una questione di tutti i giorni nelle applicazioni moderne così i linguaggi come C# si sono adeguati con costrutti come async/await. Javascript, pur essendo un linguaggio ormai antico secondo i tempi cui l'informatica ci ha abituato, gestisce da sempre molte attività in modo asincrono, utilizzando il meccanismo dei callback. Un esempio è il setInterval in cui uno degli argomenti passati è la funzione da chiamare ad intervalli regolari.

Librerie come jQuery e Angular stesso espongono numerosi casi di utilizzo di metodi asincroni. L'http service di Angular ad esempio è uno di questi casi. Esso però non utilizza normali callback ma un sistema molto simile al Task<T> di C#. Le promise. In effetti da ciascuna chiamata asincrona è ritornato un oggetto Promise che dispone dei metodi then, catch e finally. Questi servono per associare un callback a ciascuno delle condizioni che i nomi dei metodi evocano.

Ma la domanda cui vogli rispondere in questo post è la seguente: come faccio ad esporre una promise da un mio metodo asicrono se esso stesso no usa un servizio che la utilizzi? E' il caso ad esempio di un metodo che visualizzi una dialog modale. Essono mo potrà mai essere sincrono perchè oltre a risultare bloccante per il browser, non sarà comunque possibile gestire una eventuale "attesa" e ritornare dal metodo alla chiusure della dialog. Quello che ci viene in soccorso è il Q service. Esso è usato dallo stesso http service è ha come unico scopo la gestione asincrona. Vediamo un esempio:

   1: public showDialog(message: string, title: string = Constants.defaultModalTitle, commands?: IDialogCommand[]): ng.IPromise<string>
   2: {
   3:     var defer: ng.IDeferred<any> = this.$q.defer<string>();
   4:  
   5:     try
   6:     {
   7:         this.modalDialog.find('.modal-body').text(message);
   8:         this.modalDialog.find('.modal-title').text(title);
   9:  
  10:         var footer = this.modalDialog.find('.modal-footer');
  11:         footer.empty();
  12:  
  13:         for (var i in commands)
  14:         {
  15:             var cmd = commands[i];
  16:  
  17:             var button = $(Constants.modalButtonMarkup);
  18:  
  19:             button.text(cmd.text);
  20:             button.addClass(cmd.style == undefined ? 'btn-default' : cmd.style);
  21:             button.data('command-id', cmd.id);
  22:  
  23:  
  24:             button.click((ev) =>
  25:             {
  26:                 var id = $(event.srcElement).data('command-id');
  27:                 this.modalDialog.modal('hide');
  28:                 defer.resolve(id);
  29:             });
  30:  
  31:             button.appendTo(footer);
  32:         }
  33:  
  34:         this.modalDialog.modal('show');
  35:     }
  36:     catch (error)
  37:     {
  38:         defer.reject(error);
  39:     }
  40:  
  41:     return defer.promise;
  42: }

Diamo per assodato che questo metodo faccia capo ad una classe che ha ricevuto una istanza del Q service come argomento del costruttore. Come segue:

   1: constructor(private $q: ng.IQService)
   2: {
   3: }

Il metodo showDialog al proprio inizio crea una istanza di una classe di tipo IDeferred<any>, dove any è il tipo del valore ritornato dal metodo in questione. L'oggetto deferred è quello che ci serve per gestire l'asincronia. Al termine del metodo infatti viene ritornata la promise che esso contiene con "defer.promise".

A questo punto è necessario invocare i callback di successo (then) e quello di fallimento (catch). Per farlo sono utilizzati i metodi "resolve" e "reject" dell'oggetto deferred.

Così facendo è possibile usare il metodo come segue:

   1: this.showDialog(
   2:     'Are you sure you want to delete the item',
   3:     'Confirm operation',
   4:     sys.Constants.modalYesNo).then(
   5:         (id: string) =>
   6:         {
   7:             if (id == sys.Constants.Positive)
   8:             {
   9:                 // delete the item here
  10:             }
  11:         });

Il sistema è l'unico consigliato. Infatti l'utilizzo dei callback normali crea problemi al sistema di databinding di AngularJS. Invece il q service è perfettamente in grado di supportarlo.


Spesso può risultare molto comodo caricare una porzione di html dal server, magari generata da una partial view di ASP.NET MVC (o magari proprio da una View, perchè no?). con angular questo è del tutto possibile grazie alla direttiva ng-include che consente di specificare l'url da cui  caricare una risorsa all'interno della pagina. Vediamo un esempio con typescript:

Per prima cosa si crea una partialview  che dimostri un po' di dinamismo. Ecco un semplice esempio:

   1: <h2>@DateTime.Now.ToLongDateString()</h2>
   2: <h3>@DateTime.Now.ToLongTimeString()</h3>

In seguito aggiungiamo al controller il codice per poterla chiamare dal browser:

   1: public ActionResult _PartialContent()
   2: {
   3:     return PartialView();
   4: }

A questo punto diciamo che l'url per raggiungere la partial view sia il seguente:

/Include/_PartialContent

Creaiamo quindi un controller come segue:

   1: class IncludeController
   2: {
   3:     count: number = 0;
   4:     includeUri: string = undefined;
   5:  
   6:     click(): void
   7:     {
   8:         this.includeUri = '../Include/_PartialContent?ts=' + (++this.count).toString();
   9:     }
  10: }
  11:  
  12: angular.module('include', ['ngRoute'])
  13:     .controller('includeIndex', IncludeController);

Nel controller usiamo una variabile "count" per tenere conto delle volte in cui l'utente clicca il pulsante di test. Questo valore viene accodato all'uri della partial-view per forzarne il caricamento a ciascun click. L'uri così calcolato viene riposto nella proprietà includeUri. Vediamo ora la view:

   1: @{
   2:     ViewBag.Title = "Test Include";
   3: }
   4: <div>
   5:     &nbsp;
   6: </div>
   7: <div ng-app="include" ng-controller="includeIndex as ct" class="row">
   8:     <form>
   9:         <button type="button" class="btn btn-primary" ng-click="ct.click();">Click Me!</button>
  10:         <p ng-show="ct.count>0">clicked {{ct.count}} times</p>
  11:         <div ng-include="ct.includeUri"></div>
  12:     </form>
  13: </div>
  14: @section Scripts {
  15:     <script src="~/Scripts/Views/Include/index.js"></script>
  16: }

Niente più di un normale binding, con un pulsante per invocare la funzione click(), la visualizzazione del count e l'assegnazione della direttiva ng-include sulla variabile includeUri. Il risultato è che la partial view viene inclusa all'interno delle pagina ogni volta che clicchiamo il pulsante.

Interessante notare che mediante questa tecnica possiamo agevolmente caricare nella pagina qualunque tipo di file il server sia in grado di servire. Se ad esempio all'url della partial sostituiamo quello del file TS vedremo apparire il codice.


Sempre più spesso, nelle moderne applicazioni web, il codice Javascript di una pagina ha la necessità di accedere ad una webapi. Questo è certamente il più semplice metodo per attivare la pagina caricando informazioni dal server senza necessariamente effettuare il refresh dell'intera pagina. La chiamata può essere necessaria per riempire una semplice dropdowlist il cui contenuto dipende da qualche altro valore impostato in una form, piuttosto che una lista di risultati di una ricerca. Qualunque sia il contenuto, l'operazione è sempre quella di richiemare un metodo di una webapi e in seguito alla risposta deserializzare il json per popolare l'interfaccia utente.

In casi come questi ho trovato molto utile usare una classe proxy, mimando quello che avviene in C# quando si interroga un servizio WCF. La cosa interessante è che le WebApi mettono a disposizione di un ApiExplorer che è in grado di fare l'inspect della api stessa e restituire tutti i dettagli quali i metodi, i loro parametri, tipi di ritorno etc.. Grazie ad esso è possibile scrivere il seguente metodo:

   1: public abstract class ApScriptableController : ApiController
   2: {
   3:     /// <summary>
   4:     /// Il metodo restituisce lo script Javascript che consente di interrogare il controller
   5:     /// </summary>
   6:     /// <returns>Ritorna il </returns>
   7:     [HttpGet]
   8:     public HttpResponseMessage GetScript()
   9:     {
  10:         ApiExplorer explorer = new ApiExplorer(this.Configuration);
  11:  
  12:         StringBuilder builder = new StringBuilder();
  13:  
  14:         builder.Append("var __extends = this.__extends || function (d, b) {");
  15:         builder.Append("    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
  16:         builder.Append("    function __() { this.constructor = d; }");
  17:         builder.Append("    __.prototype = b.prototype;");
  18:         builder.Append("    d.prototype = new __();");
  19:         builder.Append("};");
  20:  
  21:         var actions = (from api in explorer.ApiDescriptions
  22:                        where  api.ActionDescriptor.ControllerDescriptor.ControllerType.IsAssignableFrom(this.GetType())
  23:                        orderby api.ActionDescriptor.ActionName ascending
  24:                        select api).ToArray();
  25:  
  26:         if (actions.Count() > 0)
  27:         {
  28:             string controllerName = actions.First().ActionDescriptor.ControllerDescriptor.ControllerName;
  29:             controllerName = controllerName.Substring(0, 1).ToUpper() + controllerName.Remove(0, 1);
  30:  
  31:             builder.AppendFormat("var {0}Proxy = (function (_super) {{", controllerName);
  32:             builder.AppendFormat("    __extends({0}Proxy, _super);", controllerName);
  33:             builder.AppendFormat("    function {0}Proxy(baseUri, accessToken, context) {{", controllerName);
  34:             builder.Append("        _super.call(this, baseUri, accessToken);");
  35:             builder.Append("        this.context = context;");
  36:             builder.Append("    }");
  37:  
  38:             foreach (var item in actions)
  39:             {
  40:                 builder.AppendFormat("    {1}Proxy.prototype.{0} = function (value) {{", item.ActionDescriptor.ActionName, controllerName);
  41:                 builder.AppendFormat("        return _super.prototype.callApi.call(this, '{0}', value, this.context);", item.RelativePath);
  42:                 builder.Append("    };");
  43:             }
  44:  
  45:             builder.AppendFormat("    return {0}Proxy;", controllerName);
  46:             builder.Append("})(sys.net.Proxy);");
  47:         }
  48:  
  49:         var response = new HttpResponseMessage(HttpStatusCode.OK);
  50:         response.Content = new StringContent(builder.ToString(), Encoding.UTF8, "text/javascript");
  51:         return response;
  52:     }
  53: }

Il codice rappresenta una classe base da utilizzare per i controller delle WebApi. Essa implementa un metodo GetScript che non fa altro che ispezionare i metodi della api stessa e genera di conseguenza un codice Javascript che rappresenterà il proxy della WebApi. In coda al metodo, le ultime righe cambiano il content-type della risposta impostandolo e text/javascript. In questo modo sarà possibile fornire l'url della api ad un tag script e di conseguenza far leggere il codice e caricarlo nel browser.

   1: <script src="~/api/Home/getscript"></script>

L'ultimo tassello di questo piccolo puzzle è una classe Typescript che rappresenta la base per il proxy Javascript. Il codice generato infatti fa uso delle funzioni e dei tipi presenti in questo breve snippet.

   1: module sys.net
   2: {
   3:     // represents a base for api responses
   4:     export interface IApiResponseBase 
   5:     {
   6:         HasErrors: boolean
   7:         Message: string;
   8:     }
   9:  
  10:     // represents a successful response from an api
  11:     export interface IApiResponse<T> extends IApiResponseBase
  12:     {
  13:         Result: T;
  14:     }
  15:  
  16:     export class Proxy 
  17:     {
  18:         // creates and initializes the proxy with the given base uri
  19:         constructor(private baseUri: string, private accessToken: string)
  20:         { }
  21:  
  22:         // calls a generic API with the specified route and argument
  23:         public callApi<T>(route: string, argument: any, context?: string): JQueryPromise<T>
  24:         {
  25:             var uri = this.baseUri + route;
  26:  
  27:             return $.Deferred(
  28:                 (deferred: JQueryDeferred<T>) =>
  29:                 {
  30:                     $.ajax({
  31:                         url: uri,
  32:                         type: 'POST',
  33:                         data: JSON.stringify(argument),
  34:                         contentType: 'application/json; charset=utf-8',
  35:                         beforeSend: (xhr) =>
  36:                         {
  37:                             xhr.setRequestHeader('Authorization', 'Bearer ' + this.accessToken);
  38:  
  39:                             if (context != undefined)
  40:                                 xhr.setRequestHeader('X-Tsf-Context', context);
  41:                         }
  42:                     })
  43:                         .done(
  44:                         (retVal: IApiResponse<T>) =>
  45:                         {
  46:                             if (retVal.HasErrors)
  47:                                 deferred.reject(retVal);
  48:                             else
  49:                                 deferred.resolve(retVal.Result);
  50:                         })
  51:                         .fail((err: any) => deferred.reject(this.mapToError(uri, err)));
  52:                 }).promise();
  53:         }
  54:  
  55:         // maps any error information to a common object
  56:         private mapToError(uri: string, err: any): IApiResponseBase
  57:         {
  58:             return <IApiResponseBase>
  59:                 {
  60:                     Message: 'Api "' + uri + '" reported an error: ' + err.statusText,
  61:                     HasErrors: true
  62:                 };
  63:         }
  64:     }
  65: }

Una volta che il codice sia caricato nell'ordine corretto, avremo a disposizione una classe che riporta il nome del controller seguito dalla parola Proxy. Perciò se il controller ha il nome "Home" il proxy sarà "HomeProxy".

   1: var proxy = new HomeProxy(sys.Application.ServiceUri, sys.Application.AccessToken, sys.Application.Context);
   2: proxy.GetValuesForList()
   3:     .done((result) =>
   4:      {
   5:         // TODO: process here
   6:      });

Il proxy fa uso delle promise di jQuery perciò il suo utilizzo è molto semplice e gestisce perfettamente la asincronicità.


Capita talvolta (spesso in effetti), che quando entrate in una pagina in cui sia utilizzato AngularJS per una frazione di secondo appaiano le notazioni del binding che spariscono poco dopo quando il databinding viene applicato. Questo accade perchè in quella frazione di secondo in cui il browser scarica il codice e avvia angular, tutte quelle parentesi graffe sono niente più che semplice testo e in gran parte esse sono visualizzate dal browser perchè occupano posizioni "visibili".

Per evitare questo comportamento viene in aiuto la direttiva ng-Cloak. Essa, come testimonia la documentazione ha proprio lo scopo di applicare un "display:none" agli elementi, e questo funzione nella maggioranza dei casi. Tuttavia anche se applichiamo la direttiva ng-Cloak (ad esempio al body per generalizzare, ma anche ad un singolo elemento come invece è consigliabile) talvolta le graffe appaiono comunque. Questo è imputqabile al medesimo ritardo. Per evitarlo è opportuno aggiungere al proprio css il seguente:

   1: [ng\:cloak], [ng-cloak], .ng-cloak {
   2:   display: none !important;
   3: }

In questo modo il CSS cercherà tutti gli elementi con l'attributo ng-Cloak e li nasconderà automaticamente.

Il trick è spiegato più estensivamente qui: http://stackoverflow.com/questions/11249768/angularjs-ng-cloak-ng-show-elements-blink


Ho sempre avuto l’insana convinzione che fosse meglio vivere, sempre e invariabilmente, scommettendo il possibile contro il probabile. Questo perchè in definitiva il probabile esiste e basta… è probabile, e quindi serve il minimo sforzo perchè di verifichi, ma da esso non ti puoi aspettare sorprese, niente di positivo, niente che faccia evolvere la tua situazione in meglio, niente che sia in più rispetto a quello che tutti si aspettano. Il probabile è il minimo sindacale, è l’oppressore che vince sull’oppresso, è lo stesso quotidiano tutti i giorni, è il latte consegnato all’uscio, quello che non ti fa “mandare dalla mamma”.

Il possibile invece è creativo. Lui non esiste e te lo devi costruire, pezzo per pezzo, con fantasia e immaginazione. Il possibile in realtà sono i tuoi sogni, quelli che fai mentre guidi sulla via del ritorno dall’ufficio, e che tutti il più delle volte archiviano dicendo… “ah, impossibile!”.

Alla fine il probabile è una vacanza in una comune località di mare dove il massimo che ti puoi aspettare è che un ombrellone sia un po’ fuori posto. Arriva il bagnino, lo sistema e tutto torna nell’ambito della semplice probabilità. Il possibile invece è una settimana in barca, alla scoperta di angoli del mondo che nemmeno ti aspettavi potessero esistere, pieno del colore, del profumo e delle sensazioni che mai avresti immaginato.

Il problema è che mentre il probabile non ti delude mai, dato che non ti da nulla, il possibile è armato di scimitarra ed è pronto, in ogni istante, a menarti un fendente che ti lascia tramortito. Succede, spesso, che inseguendo il possibile si rimanga trafitti, bastonati, delusi e tramortiti, ma alla fine ne vale sempre la pena. Vale la pena il sapere di aver fatto qualcosa che ti ha cambiato o che ha cambiato, sentire la soddifazione di essere riusciti a lasciare un segno, a migliorare le cose, a… a… a… … anche se il prezzo il da pagare il più delle volte è lo stare male perchè il probabile ha vinto ancora una volta.

Già, impossibile… tutti invariabilmente lo hanno detto almeno una volta, i più se lo dicono sempre con insistenza. Il risultato è l’aver dovuto archiviare con una sola parola un sogno, e aver chiuso un libro di speranze senza nemmeno provare a renderlo concreto. Anche io spesso, ma mai volentieri, cedo al probabilismo, alla tentazione della uniformità e prevedibilità. Ma spesso, soprattutto se mi fermo a pensarci, allora il possibile mi illumina e braccio a braccio al mio ottimismo mi guida alla scoperta di aspetti e possibilità che nemmeno osavo esprimere.

Lasciamo la noia a quei dannati probabilisti. La vita sta nel possibile.


mvplogoPrimo luglio, la calura, l'estate che arriva e anche quest'anno come da otto a questa parte è arrivata l'attesissima mail, regalandomi un'emozione cui non sono ancora riuscito ad abituarmi. MVP Windows Platform Development.

MVP ancora una volta, parte di questa straordinaria community di persone che condivisono la passione per la tecnologia, la condivisione della conoscenza e il lavoro, quello pratico, "sul pezzo", a risolvere problemi e a escogitare soluzioni.

Ma un ricordo particolare va a Silverlight. Ho avuto l'onore di essere il primo italiano ad entrare nella categoria MVP su questa tecnologia e sono anche l'ultimo che la lascia. Abbiamo ormai tutti digerito i motivi che hanno portato alla trasformazione di questo splendido strumento in quello che oggi vediamo in Windows 8 e in Windows Phone... è tutta farina che viene da quella splendida esperienza. E ora Windows Platform Development ne è la logica conclusione.

Grazie. Grazie a tutti, in particolare a Cristina Gonzalez Herrero e Marjorie di Clemente che si occupano del programma per l'Italia. Grazie a Microsoft Italia, Grazie al nostro "sommo" lead Alessandro Teglia :) e in definitiva grazie a Microsoft.

E naturalmente Grazie e tutti quelli che ci seguono, nei nostri eventi, e che ci scrivono e leggono ogni giorno.

tags: - categories: News