posts - 286, comments - 336, trackbacks - 7

My Links

News

View Pietro Libro's profile on LinkedIn

DomusDotNet
   DomusDotNet

Pietro Libro

Tag Cloud

Article Categories

Archives

Post Categories

Blogs amici

Links

venerdì 26 aprile 2013

Enterprise Library 6

Nuova release per Microsoft Enterprise Library. Tutti i dettagli del caso qui.

posted @ venerdì 26 aprile 2013 13.09 | Feedback (0) | Filed Under [ Varie ed eventuali .Net Framework 4.0 .Net Framework 4.5 ]

mercoledì 24 aprile 2013

Le (mie) prime Windows 8 App Store

Alla fine, sono riuscito a pubblicare le mie  prime 4 applicazioni nello Store di Windows 8. L’obiettivo è raddopiare il numero entro la fine di maggio. Se avete voglia di provarle (sono tutte free) e indicarmi qualche suggerimento per le versioni future ed attuali, di seguito  link e nomi :

132780[2] Lazio: Cultura e Turismo

L'applicazione "Lazio: Cultura e Turismo", è un elenco dei Punti d'Interesse (POI) Culturali del Lazio: Musei, Statue, Monasteri, Dipinti, Abbazie, Castelli, Torri ecc....Per ogni POI è presente una descrizione in Italiano (eventualmente in Inglese), foto e geolocalizzazione. Il catalogo dati è mantenuto e fornito da "Lazio futouring", sito internet: http://www.futouring.eu.

128786[1] Farmacie Italiane

Elenco completo delle farmacie italiane aperte al pubblico, comprensivo di dati di localizzazione e geoloclalizzazione. I dati sono mantenuti e forniti tramite piattaforma"cloud" del "Ministero della Salute".

123924[1]Istituti Scolastici Provincia di Roma

"Istituti Scolastici Provincia di Roma" Catalogo con geolocalizzazione degli istituti scolastici (superiori) della provincia di Roma. I dati base sono forniti dalla piattaforma "Open Data".

123362[1]Roma ProvinciaWiFi

Individua facilmente apparati WiFi della provincia di Roma per l'accesso gratuito ad Internet. I dati di geolocalizzazione sono ottenuti tramite il "Portale Opendata della Provincia di Roma".

Buon divertimento :-D.

posted @ mercoledì 24 aprile 2013 8.58 | Feedback (0) | Filed Under [ Varie ed eventuali C# Windows 8 .Net Framework 4.5 ]

venerdì 22 marzo 2013

ASP.NET Web Api a Codemotion Roma 2013

Se domani non avete proprio nulla da fare :-) possiamo vederci a Codemotion 2013 Roma.

 image

Una sessione introduttiva all’utilizzo del Framework ASP.NET Web Api per lo sviluppo di applicazioni RESTful.

posted @ venerdì 22 marzo 2013 18.39 | Feedback (0) | Filed Under [ Varie ed eventuali C# ASP.NET .Net Framework 4.0 .Net Framework 4.5 ]

sabato 9 marzo 2013

ASP.NET and Web Tools 2012.2 : Web Api Help Page

Con il rilascio dell’aggiornamento ASP.NET 2012.2 di qualche settimana fa,  lo sviluppo di una “Help Page” per Web Api, utilizzando l’apposito Package di NuGet, é un’attività che impegna meno di 5 minuti (per completezza di informazione, era già presente una versione alpha del Package prima del rilascio ufficiale).

1) Dalle “references” del progetto Web da “documentare”, apriamo la finestra per la gestione dei “Packages” di NuGet:

image

2) Cerchiamo la voce “Web Api Help Page” e clicchiamo su “Install” (verranno installate le dipendenze necessarie):

image

3) Al progetto verrà aggiunta l’area “HelpPage” sotto la cartella “Areas”, con tutte le classi necessarie (css compreso):

image

4) La classe XmlDocumentationProvider  che implementa l’interfaccia IDocumentationProvider permette di documentare le nostre API nel caso più semplice utilizzando i commenti che decorano le Web API direttamente nel codice (implementando l’interfaccia IDocumentationProvider é possibile personalizzare questo comportamento).

image

5) Aggiungiamo nel Global.asax.cs la riga di codice seguente:

config.Services.Replace(typeof(IDocumentationProvider), new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/file.xml")));

6) A questo punto non ci resta che eseguire la nostra applicazione e digitare “Help” nella barra degli indirizzi:

image

A questo punto é sufficiente passare alle personalizzazioni del caso :-).

posted @ sabato 9 marzo 2013 13.46 | Feedback (0) | Filed Under [ C# ASP.NET .Net Framework 4.0 .Net Framework 4.5 ASP.NET Web Api ]

mercoledì 20 febbraio 2013

ASP.NET and Web Tools 2012.2 Update

Rilasciata la versione finale di “ASP.NET and Web Tools 2012.2 Update”, un download che arrichisce, non di poco, le funzionalità esistenti, in Visual Studio 2012 e ASP.NET (tra le novità, OData EndPoint in ASP.NET Web API, ASP.NET SignalR, Single Page Applications).  Tutti i dettagli del caso sul post originale sul blog di Scott Guthrie.

posted @ mercoledì 20 febbraio 2013 8.32 | Feedback (0) | Filed Under [ ASP.NET .Net Framework 4.5 ]

lunedì 28 gennaio 2013

Modi diversi di recuperare il numero di messaggi in una coda MSMQ

Ultimamente mi trovo a lavorare su di un progetto che utilizza WCF e MSMQ. Una delle classiche operazioni quando si lavora con queste tecnologie è sicuramente recuperare il numero di messaggi presenti in una coda. Tra documentazione e ricerche su internet, alla fine si “scopre” che ci sono diversi metodi per risolvere lo stesso problema:

  1. Cursori di MSMQ
  2. Utilizzo di GetAllMessages
  3. Utilizzo di GetEnumerator2
  4. PowerShell
  5. Performance Counter

Traducendo il tutto in righe di codice, per il punto 1) abbiamo:

public int CountByCursor()
{
    int count = 0;
    Cursor cursor = _messageQueue.CreateCursor();
    Message m = CursorPeekWithoutTimeout(cursor, PeekAction.Current);
    if (m != null)
    {
        count = 1;
        while ((m = CursorPeekWithoutTimeout(cursor, PeekAction.Next)) != null)
        {
            count++;
        }
        if (m != null) m.Dispose();
    }
    cursor.Dispose();
    return count;
}

private Message CursorPeekWithoutTimeout(Cursor cursor, PeekAction action)
{
    Message ret = null;

    try
    {
        ret = _messageQueue.Peek(new TimeSpan(1), cursor, action);
    }
    catch (MessageQueueException mqe)
    {
        if (mqe.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
        {
            throw;
        }
    }
    return ret;
}

Sinceramente questo è il metodo che più non mi piace, sarà per la parola “Cursore”, sarà per la gestione dell’eccezione, sarà perchè la vedo poco pulita.

Passiamo al punto 2):

 public int CountByGetAllMessages()
{
    return _messageQueue.GetAllMessages().Length;
}

Semplice e pulita, ma come vedremo a breve, le prestazioni scendono con l’aumentare dei messaggi in coda.

Punto 3), “GetMessageEnumerator2”:

var x = _messageQueue.GetMessageEnumerator2();
int counter = 0;
while (x.MoveNext())
{
    counter++;
}
return counter;

Sfruttiamo il MessageEnumerator ritornato dal metodo GetEnumerator2 ed iteriamo per spostare il cursore fino alla fine della coda.

Punto 4), “PowerShell” (in questo caso mi sono limitato a copiare del codice trovato in rete):

var path = string.Format(@"\\{0}\root\CIMv2", machine);

ManagementScope scope;

if (string.IsNullOrEmpty(username))
{
    scope = new ManagementScope(path);
}
else
{
    var options = new ConnectionOptions { Username = username, Password = password };
    scope = new ManagementScope(path, options);
}

scope.Connect();

if (queuePath.StartsWith(".\\")) queuePath = queuePath.Replace(".\\", string.Format("{0}\\", machine));

string queryString = String.Format("SELECT * FROM Win32_PerfFormattedData_msmq_MSMQQueue");
var query = new ObjectQuery(queryString);
var searcher = new ManagementObjectSearcher(scope, query);
IEnumerable<int> messageCountEnumerable =
    from ManagementObject queue in searcher.Get()
    select (int)(UInt64)queue.GetPropertyValue("MessagesInQueue");
var x = messageCountEnumerable.First();

return x;

ed infine il punto 5) “Performance Counter”:

System.Diagnostics.PerformanceCounter backupQueueCounter = new System.Diagnostics.PerformanceCounter(
    "MSMQ Queue", "Messages in Queue", "queue_path");

return backupQueueCounter.NextValue();

Bene, ora quale usare ? Proviamo con un piccolo test: ad una coda privata aggiungiamo 10.000 messaggi per volta (all’interno di un ciclo) e proviamo ad utilizzare i metodi su descritti per recuperare il numero di messaggi presenti in coda (si suppone che tra un conteggio e l’altro nella coda non vengano aggiunti altri messaggi). Iteriamo il procedimento per tre volte.

Di seguito i risultati ottenuti (espressi in millisecondi, per le misure del tempo di esecuzione è stata utilizzata la classe System.Diagnostics.Stopwatcher):

Prima Iterazione

#Msgs MSMQ Cursor GetAllMessages GetEnumerator2 PowerShell Performance C.
10.000 449,816 580,703 36,37 78,543 351,86
20.000 928,18 1.297,72 78,16 9,888 0,462
30.000 1.340,44 1.854,52 137,82 10,563 1,121
40.000 1.769,73 2.656,28 194,652 12,061 3,187
50.000 2.188,74 3.427,84 190,672 10,739 0,452
60.000 2.631,29 3.909,71 231,995 10,219 0,364
70.000 3.006,52 4.771,09 264,112 5.802,42 0,462
80.000 3.469,49 6.116,47 309,691 10,075 0,545
90.000 4.000,00 6.134,66 372,885 9,876 0,435
100.000 4.544,33 6.932,08 424,196 9,024 0,41
image

Seconda Iterazione

#Msgs MSMQ Cursor GetAllMessages GetEnumerator2 PowerShell Performance C.
10.000 475,357 609,866 38,022 285,978 351,955
20.000 912,591 1.315,49 76,912 10,453 0,502
30.000 1.417,26 2.066,92 122,745 11,156 0,366
40.000 1.901,66 2.718,64 153,373 9,947 0,349
50.000 2.393,97 3.386,43 203,553 10,962 0,358
60.000 2.659,28 4.546,84 280,257 9,832 0,413
70.000 3.246,77 4.938,01 278,404 11,664 0,517
80.000 3.718,89 5.881,67 330,857 13,688 0,506
90.000 4.230,99 6.677,00 362,374 10,155 0,508
100.000 4.832,89 7.585,19 464,216 16,495 0,681
image

Terza Iterazione

#Msgs MSMQ Cursor GetAllMessages GetEnumerator2 PowerShell Performance C.
10.000 533,294 621,392 41,496 79,286 376,431
20.000 911,513 1.338,41 79,827 9,354 0,38
30.000 1.339,34 2.123,46 120,693 12,969 0,414
40.000 1.799,28 2.658,01 158,606 9,423 0,374
50.000 2.196,96 3.221,87 199,273 10,413 0,426
60.000 2.562,49 4.140,15 257,22 8,81 0,411
70.000 3.358,83 4.715,56 327,474 14,808 0,53
80.000 4.417,58 6.690,44 316,044 17,334 0,825
90.000 4.185,52 6.229,67 340,457 11,773 0,396
100.000 4.407,13 6.658,46 390,498 12,944 0,589
image

Dai risultati ottenuti si ottiene che l’utilizzo del “Performance Counter”, in caso di letture successive, sembrerebbe essere quello più efficiente.

In attesa di altri giudizi ed approfondimenti :-).

posted @ lunedì 28 gennaio 2013 12.13 | Feedback (0) | Filed Under [ Varie ed eventuali C# .Net Framework 4.0 WCF .Net Framework 4.5 ]

mercoledì 12 dicembre 2012

EF6 Alpha 2

Nuova alpha release della versione 6 di Entity Framework, disponibile tramite NuGet. Al solito, tutti i dettagli direttamente sul post del blog di ADO.NET.

posted @ mercoledì 12 dicembre 2012 17.41 | Feedback (0) | Filed Under [ C# Entity Framework 6 ]

martedì 27 novembre 2012

Visual Studio 2012 Update 1

E’ stato rilasciato “l'’Update 1” di Visual Studio 2012. Download qui (multi-language), maggiori dettagli, qui.

Per una versione “offline”, è possibile eseguire i passaggi descritti in questo post.

posted @ martedì 27 novembre 2012 8.46 | Feedback (3) | Filed Under [ .Net Framework 4.5 ]

mercoledì 7 novembre 2012

EF6 Alpha 1

Per chi se lo fosse perso :-) : EF6 Alpha 1. Tra le novità più interessanti il supporto Async per “Query and Save”.

posted @ mercoledì 7 novembre 2012 11.24 | Feedback (0) | Filed Under [ Tools .Net Framework 4.5 Entity Framework 6 ]

venerdì 21 settembre 2012

Elenco di Micro-Framework…

Post promemoria: interessante ed abbondante elenco di Micro-Framework (completo di “motore di ricerca”) microjs.com

posted @ venerdì 21 settembre 2012 9.01 | Feedback (2) | Filed Under [ Varie ed eventuali ASP.NET ]

lunedì 10 settembre 2012

ASP.NET 4.5 e WebSocket: Real Time e Two-Way (parte 2)

Nella prima parte dell’articolo abbiamo introdotto i WebSocket sviluppando una semplice applicazione composta da un client che invia dei messaggi di testo ad un server (WebSocket Server), il quale risponde inviando un testo ed un numero che rappresenta la lunghezza del messaggio ricevuto. Nel post precedente abbiamo descritto con maggior dettaglio il codice lato  client demandando a questa seconda parte maggiori approfondimenti relativamente alla parte  server il cui codice è composto dalla semplice classe WebSochetHandler.ashx, la quale implementa l’interfaccia IHttpHandler, ragion per cui  è necessario scrivere del  codice per il metodo ProcessRequest(HttpContext context), per l’elaborazione delle richieste Web HTTP, e la proprietà  IsReusable  che restituisce un valore che indica se sia possibile riciclare la stessa istanza di classe che implementa IHttpHandler per una successiva richiesta.

Per quanto concerne IsReusable, non dovendo memorizzare nulla tra una richiesta e l’altra,  il codice è semplicemente:

public bool IsReusable
{
    get
    {
        return true;
    }
}
Mentre, per il metodo ProcessRequest(…) abbiamo : 
public void ProcessRequest(HttpContext context)
{
    if (context.IsWebSocketRequest)
    {              
        context.AcceptWebSocketRequest(WebSocketRequestHandler);
    }
    else
    {
        context.Response.StatusCode = 400;
    }
}
Utilizzando la proprietà IsWebSocketRequest verifichiamo che la richiesta entrante sia una richiesta WebSocket valida, in caso positivo demandiamo la gestione della richiesta al metodo WebSocketRequestHandler così definito:
public async Task WebSocketRequestHandler(WebSocketContext webSocketContext)
{
    byte[] buffer = new byte[MAX_MESSAGE_SIZE];
    WebSocket webSocket = webSocketContext.WebSocket;

    while (webSocket.State == WebSocketState.Open)
    {
        WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

        switch (result.MessageType)
        {
            case WebSocketMessageType.Close:
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed.", CancellationToken.None);
                break;
            case WebSocketMessageType.Binary:
                await webSocket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Not supported.", CancellationToken.None);
                break;
            case WebSocketMessageType.Text:
                int count = result.Count;

                while (result.EndOfMessage == false)
                {
                    if (count >= MAX_MESSAGE_SIZE)
                    {
                        string closeMessage = string.Format("Maximum message size: {0} bytes.", MAX_MESSAGE_SIZE);
                        await webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None);
                        return;
                    }

                    result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, count, buffer.Length), CancellationToken.None);
                    count += result.Count;
                }

                string receivedMessage = Encoding.UTF8.GetString(buffer, 0, count);
                string outputMessage = "Text Length: " + receivedMessage.Length;

                await webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(outputMessage)), WebSocketMessageType.Text, true, CancellationToken.None);

                break;
        }
    }
}

In dettaglio, quando invochiamo il metodo WebSocketRequestHandler, ASP.NET passa un’istanza della classe WebSocketContext contenente informazioni quali l’URI utilizzato per stabilire la connessione (compresi i parametri della Query String) e la collezione dei cookies inviati. Per accedere ai metodi per la ricezione e l’invio dei dati è necessario accedere alla proprietà WebSocket . A questo punto, utilizziamo la proprietà State per verificare lo stato della connessione, rimanendo “in ciclo” finché la connessione rimane aperta. Per ricevere i dati utilizziamo il metodo ReceiveAsync che accetta due parametri: un ArraySegment in cui scrivere i dati ricevuti (buffer) ed un Cancellation Token, nel nostro caso CancellationToken.None. Il metodo ritorna un’istanza di WebSocketReceiveResult  che rappresenta il risultato di una singola operazione ReceiveAsync. Tramite la proprietà MessageType della classe risultato verifichiamo il tipo di messaggio:

  1. Close: è stato inviato un close frame (vedi prima parte). A questo punto il server partecipa all’handshake di chiusura utilizzando il metodo CloseAsync. Trattandosi di una normale chiusura, ci limitiamo ad utilizzare la voce Normal dell’enumerativo WebSocketCloseStatus.
  2. Binary: non supportato dalla nostra applicazione, pertanto iniziamo il processo di chiusura della connessione e specifichiamo al client che il tipo dati inviato non è supportato (utilizziamo l’apposito valore dell’enumerativo).
  3. Text: tramite la proprietà EndOfMessage, entriamo in un loop finché non abbiamo letto il contenuto dell’intero del messaggio (o non si raggiunge la dimensione massima del messaggio). Una volta ricevuto il messaggio, utilizzando l’encoding opportuno (UTF8, per formati diversi è necessario  utilizzare il formato binario) “leggiamo” la stringa ed inviamo un testo con l’indicazione della lunghezza della stringa ricevuta tramite il metodo SensAsync.

Il terzo ed ultimo post della serie dedicato alla “costruzione della lavagna” condivisa tra client Web/Windows utilizzando i WebSocket e l’oggetto HTML canvas.

posted @ lunedì 10 settembre 2012 22.14 | Feedback (0) | Filed Under [ C# ASP.NET Windows 8 .Net Framework 4.5 ]

venerdì 7 settembre 2012

ASP.NET 4.5 e WebSocket: Real Time e Two-Way (parte 1)

Chi sviluppa per il Web, si scontra ogni giorno con le “limitazioni” del modello request-response di HTTP, il quale non è pensato “ad hoc” per applicazioni real time, o comunicazione bidirezionale client-server. Per questi scenari, spesso vengono utilizzate tecniche di polling, da parte del client, per verificare l’eventuale presenza di dati “freschi”, eseguendo continuamente delle richieste HTTP, comportando dei “costi”: il server deve utilizzare differenti connessioni TCP per ogni client (una per inviare informazioni ed una per rispondere alla richiesta di aggiornamenti), un continuo scambio di messaggi client-server (comportando quindi un aumento del traffico di rete). Potrebbe sembrare cosa da poco, ma se pensiamo ad applicazioni web con migliaia di client connessi, le risorse di server e banda potrebbero essere velocemente consumate (e dato che la nostra epoca è affamata di risorse potremmo trovarci in situazioni poco piacevoli).

Quindi, quale potrebbe essere la soluzione ? utilizzare una singola connessione TCP per gestire il traffico in entrambe le direzioni, ovvero il protocollo WebSocket, che se gestito mediante le WebSocket API (WSAPI), fornisce un’ottima alternativa alla tecnica di polling di cui parlavamo in precedenza. Possiamo utilizzare i WebSocket in diversi scenari: giochi, applicazioni di editing real time multi-utente, UI web che espongono dati lato server in tempo reale ecc .… tutto questo condividendo le porte standard HTTP 80 e 443, “attraversando” firewalls, proxies e router senza problemi. Possiamo riassumere le due “tecniche” discusse in precedenza con la figura seguente;

image

dalla quale si evince come l’utilizzo del “polling” comporti una maggiore latenza nella trasmissione delle informazioni utili. Nell’immagine, nella comunicazione bidirezionale offerta dai WebSocket, come primo passo (dal client verso il server) c’è la voce “WebSocket upgrade”, cosa sarà mai ?, un passo per volta.

Il protocollo è diviso in due parti: handshakes e transfer data. Durante la  prima parte (di negoziazione),  client e server comunicano scambiandosi dei pacchetti di controllo per stabilire una connessione WebSocket.  Il client invia una richiesta di questo tipo:

 
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Version: 13
ed il server (normalmente) dovrebbe rispondere con:
 
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

In dettaglio, il processo di connessione parte con una standard GET HTTP, e fin qui tutto regolare:

GET /echo HTTP/1.1
Host: example.microsoft.com

poi, l’header “Upgrade” richiede al server di cambiare il protocollo a livello di application-layer da HTTP a WebSocket:

Upgrade: websocket
Connection: Upgrade

Il valore presente in Sec-WebSocket-Key inviato dal client verrà utilizzato dal server per far capire al chiamante che “comprende” la richiesta:

Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

L’header Sec-WebSocket-Version identifica la versione del protocollo da utilizzare:

Sec-WebSocket-Version: 13

A questo punto, se il server “comprende” la nostra richiesta , il server eseguirà un “Upgrade” dell’application-layer e risponderà con lo stato HTTP 101. Il valore contenuto in Sec-WebSocket-Accept verrà utilizzato dal client per validare che il server è un WebSocket server e non un “semplice” HTTP server.

Una volta che client e server hanno entrambi inviati i loro handshakes, (e l’handshaking ha avuto successo) può iniziare il trasferimento dati su un unico canale di comunicazione bidirezionale, tra client e server, sfruttando la connessione TCP precedentemente stabilita.

I dati trasferiti tra le due parti sono racchiusi in unità logiche chiamate “messaggi”, ogni messaggio è fisicamente  composto da uno o più frames.

Dopo la teoria la pratica…

Il protocollo WebSocket, definisce due nuove tipologie di URI:

  1. ws://host [: port] path [? query] (di default usa la porta 80 e connessione non cifrata)
  2. wss://host [:port] path [? query] (di default utilizza la porta 443, ed una connessione cifrata HTTP over TLS)

Le ultime specifiche del protocollo  sono definite nel documento RFC 6455. Per “sporcarci le mani” con i  WebSocket, possiamo sviluppare un semplice pagina web con estensione .html, come la seguente:

image

I bottoni Open e Close, sono rispettivamente utilizzati per aprire e chiudere la connessione del WebSocket, mentre il campo text per inviare un messaggio al server, il quale risponderà inviando al client la lunghezza della stringa inviata (ovviamente il livello pratico dell’esempio è praticamente nullo Sorriso).

Per stabilire una connessione con il server, utilizziamo le seguenti righe di codice client-script:

var uri = 'ws://localhost:9915/WebSocketHandler.ashx';
websocket = new WebSocket(uri);

Per conoscere quando la connessione con il server è stata creata è necessario sottoscriversi all’evento onopen:

 websocket.onopen = function () {
    appendData("Connected.");
    appendData(uri);

    $('#wsform').submit(function (event) {
        websocket.send($('#inputbox').val());
        $('#inputbox').val('');
        event.preventDefault();
    });

    $("#closeButton").removeAttr("disabled");
};
Con lo script precedente, all’apertura della connessione visualizziamo il messaggio “Connected.” e l’URI utilizzato per la connessione. Dopodiché ci registriamo all’evento submit per inviare al server, utilizzando l’API Send, messaggi al WebSocket server sotto forma di testo UTF-8 o Blobs.

Per ricevere messaggi, dobbiamo registrarsi all’evento onmessagge dell’oggetto websocket il quale riceve messageEvent che espone la proprietà data, contenente le informazioni inviate al client:

websocket.onmessage = function (messageEvent) {
    var receivedData = messageEvent.data.toString();
    appendData(receivedData);
};

Il codice precedente è veramente banale, in quanto si limita a recuperare il testo inviato dal server in risposta al client e visualizzarlo sul browser tramite un div.

Come per l’apertura, c’è una sorta di handshaking per la chiusura della connessione, che può essere iniziata indipendentemente dal client o dal server. Chi inizia il processo di chiusura, invia uno speciale frame, detto close frame, che può contenere, opzionalmente, un codice di stato (il protocollo fornisce un insieme di codici di stato appropriati per la chiusura) e la ragione  (una descrizione testuale) della chiusura. Quando una delle due parti riceve un close frame, invia lo stesso frame all’altra parte (eventualmente, prima di rinviarlo, invia i messaggi pending) e la comunicazione viene chiusa.

Per iniziare il processo di close handshake, bisogna invocare l’API close:

function closeWebSocket() {
   websocket.close(1000, "Normal.");
}

Il valore 1000 indica lo stato “Normal Closure”. Come “ragione” della chiusura specifichiamo il testo “Normal”. Per sapere quando la chiusura è stata completata, ci sottoscriviamo all’evento onclose:

websocket.onclose = function () {
    appendData("Closed.");

    $("#closeButton").attr("disabled", "disabled");
};

Con la funzione precedente, visualizziamo il messaggio “Closed.”, e disabilitiamo il button per la chiusura del WebSocket.

La parte server è composta da una classe IHttpHandler che fa uso della classe WebSocketContext (.NET 4.5) utilizzata per accedere alle informazioni di WebSocket handshake. Attraverso altri semplici post, l’obiettivo è realizzare una semplice “lavagna” interattiva real time, utilizzando sia un browser web, che un client WPF, come mostrato seguente:

image

A tal fine, utilizzeremo lato Windows, la classe ClientWebSocket, presente nel namespace System.Net.WebSockets, la quale fornisce un client per connettersi a servizi esposti tramite WebSocket.

Source Code Source Code

posted @ venerdì 7 settembre 2012 6.58 | Feedback (0) | Filed Under [ C# ASP.NET WPF .Net Framework 4.5 ]

mercoledì 22 agosto 2012

Web API: Circular Object References

Quando utilizziamo le Web API, per leggere e scrivere oggetti nel corpo di un messaggio Http utilizziamo delle classi particolari, le media-type formatters. "Gratis" Web API fornisce media-type formatters per JSON e XML, utilizzate secondo della richiesta da parte dei client (“Accept”). Se JSON e XML non sono i "formati" di cui abbiamo bisogno possiamo sempre creare la nostra classe derivata da MediaTypeFormatter o BufferedMediaTypeFormatter, rispettivamente per scenari asincroni o sincroni, ma non sono l’argomento di questo post promemoria.

Quando abbiamo a che fare con grafi di oggetti complessi, possono crearsi situazioni in cui abbiamo riferimenti circolari tra oggetti. Ad esempio in uno scenario di questo tipo:

image

Dove abbiamo due classi, Book ed Author , referenziate tramite collection (praticamente un’associazione molti-a-molti) l’una con l’altra.

Se abbiamo una Web API di questo tipo :

private BookshelfDb _db = new BookshelfDb();
public IEnumerable<Book> GetBooks()
{
    return _db.Books.Include(b => b.Authors).AsEnumerable();
}
...

ed una configurazione standard delle Web API, ad eccezione dell’indentatura:

JsonMediaTypeFormatter json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.Indent = true;

In presenza di dati, invocando GetBooks() (ad esempio tramite browser), otterremo un’eccezione di questo tipo:

{ 
  "Message": "An error has occurred.", 
  "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.", 
  "ExceptionType": "System.InvalidOperationException", 
  "StackTrace": null, 
  "InnerException": { 
    "Message": "An error has occurred.", 
    "ExceptionMessage": "Self referencing loop detected with type 'BookshelfWebApi.Models.Book'. Path '[0].Authors[0].Books'.", 
    "ExceptionType": "Newtonsoft.Json.JsonSerializationException", 
    "StackTrace": "   …
}

La soluzione al problema è abbastanza semplice  in quanto è sufficiente aggiungere la riga:

json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;

Il caso Xml, non è immediato come nel caso JSON, in quanto è necessario decorare le classi con l’attributo DataContract impostando la proprietà IsReference a true. In questo caso però è necessario decorare anche le proprietà con l’attributo DataMember:

[DataContract(IsReference = true)]
public class Book
{
    public Book()
    {
        this.Authors = new List<Author>();
    }
    [DataMember()]
    public int Id { get; set; }
    [DataMember()]
    public int Paperback { get; set; }
    [DataMember()]
    public string Title { get; set; }
    [DataMember()]
    public string ISBN_10 { get; set; }
    [DataMember()]
    public string ISBN_13 { get; set; }
    [DataMember()]
    public string Language { get; set; }
    [DataMember()]
    public string Publisher { get; set; }
    [DataMember()]
    public ICollection<Author> Authors { get; set; }
}

Se non si vuole “sporcare” le classi “farcendole” di attributi possiamo optare per un DataContractSerializer. Le Web API possono essere configurate modificando il codice presente nella classe WebApiConfig.cs:

image

Quanto detto è sicuramente famigliare per chi espone entità collegate tramite Http, ad esempio utilizzando WCF.

posted @ mercoledì 22 agosto 2012 10.17 | Feedback (0) | Filed Under [ C# ASP.NET Entity Framework 5 .Net Framework 4.5 ]

martedì 21 agosto 2012

DomusDotNet: ALM@Work

Pubblicata l'agenda dell'evento ALM@Work organizzato da DomusDotNet per il 28 settembre 2012 presso la sede Microsoft di Roma, insieme a Matteo Emili e Gian Maria Ricci, MVP italiani di Visual Studio ALM.

Tutti i dettagli dell'agenda ed il link per l'iscrizione qui .

posted @ martedì 21 agosto 2012 19.57 | Feedback (0) | Filed Under [ Varie ed eventuali ]

giovedì 16 agosto 2012

EF5 Released

Con l’arrivo in RTM di Windows 8 e Visual Studio 2012 è stata rilasciata la nuova versione di Entity Framework (scaricabile ovviamente tramite NuGet). Le novità presenti sono diverse, quella più “gettonata” è sicuramente il supporto agli “Enum”. Diverse novità coinvolgono anche il Designer di EF per Visual Studio 2012, come il supporto a diagrammi multipli per lo stesso modello (una delle funzionalità che più apprezzo).

Per tutti i dettagli del caso, per la compatibilità delle funzioni utilizzabili secondo del targeting del .NET Framework, lista dei bug corretti ed altro, è possibile iniziare da qui.

posted @ giovedì 16 agosto 2012 7.54 | Feedback (0) | Filed Under [ Entity Framework 5 .Net Framework 4.5 ]

Powered by: