3

Mar

ASP.NET Chart Storages & Custom Storage cone IChartStorageHandler per scenari webfarm/webgarden e Windows Azure

l’ASP.NET Chart control è un controllo per generare grafici in applicazioni web molto potente

Questo il suo funzionamento:

1) la sorgente dati viene processata per generare il grafico

2) il grafico viene renderizzato in immagine png/jpg/bmp/emf (si può scegliere cambiando la proprietà ImageType sugli oggetti asp:Chart

3) l’immagine viene messa in un luogo temporaneo: in sessione utente, in un path di temp locale, in memoria

4) un nome random viene dato ad ogni immagine

5) il browser cercherà di leggerle ed un custom HttpHandler andrà a rileggere l’immagine dallo storage TEMP per ritornare il grafico corretto

 

il controllo Chart si imposta negli appsettings. es:

 

la proprietà storage è la più importante. questa la sua spiegazione su MSDN:

  • file: Store the rendered chart images as temporary files. You must also specify the storage location in the url or dir parameter. In a server cluster or a multiple-process site, you must specify the dir parameter.

  • memory: Store the rendered chart images in the memory space of the running process. Do not use this option in a server cluster or a multiple-process site.

  • session: Store the rendered chart images in a session variable.

 

l’uso della memoria è da preferire in casi di single-server

in casi di webfarm o di windows azure le cose si complicano: se abbiamo la sessione impostata su di un DB SQL allora possiamo usare la sessione, altrimenti rimane solo un path di temp su una SAN o NAS visibile da tutti i server di front-end

 

nel caso specifico di Windows Azure però, abbiamo anche alcune possibilità aggiuntive non supportate automaticamente dal Chart: un blob storage, ed una cache di AppFabric usabile come provider del SessionState, o direttamente connessa alla configurazione del Chart

in questi casi, implementare IChartStorageHandler ci da la flessibilità richiesta. vediamone 2 esempi:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.DataVisualization.Charting;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Web.SessionState;
using System.Threading;
using System.Diagnostics;
using Microsoft.IdentityModel.Claims;
using Microsoft.ApplicationServer.Caching;

 

public class ChartBlobStorageImageHandler : IChartStorageHandler
{
    CloudStorageAccount account;
    CloudBlobClient client;
    CloudBlobContainer container;

    public ChartBlobStorageImageHandler()
    {
        //wire up azure
        account = new CloudStorageAccount(new StorageCredentialsAccountAndKey("[BLOBNAME]", "[BLOBKEY]"), false);
        client = account.CreateCloudBlobClient();
        container = new CloudBlobContainer("chartcontainer", client);
        container.CreateIfNotExist();
    }

    private string GetUri(string key)
    {
        var p = HttpContext.Current.User as ClaimsPrincipal;
        var i = p.Identity as ClaimsIdentity;
        var id = i.Claims.FirstOrDefault(x => x.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
        return string.Format("{0}/{2}_{1}", container.Uri, key, id.Value);
    }

    public void Delete(string key)
    {
        CloudBlob image = container.GetBlobReference(GetUri(key));
        image.Delete();
    }

    public bool Exists(string key)
    {
        CloudBlob blob = container.GetBlobReference(GetUri(key));
        try
        {
            var s = blob.OpenRead();
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public byte[] Load(string key)
    {
        CloudBlob blob = container.GetBlobReference(GetUri(key));
        return blob.DownloadByteArray();
    }

    public void Save(string key, byte[] data)
    {
        CloudBlob image = container.GetBlobReference(GetUri(key));
        image.UploadByteArray(data);
    }
}

 

vediamo l’esempio con l’AppFabricCache, la configurazione da incollare nel proprio .config viene scaricata direttamente dal portale di Windows Azure

 

public class ChartAppFabricCacheImageHandler : IChartStorageHandler
{
    private DataCache Cache = new DataCacheFactory(new DataCacheFactoryConfiguration("SslEndpoint")).GetCache("default");

    private string Key(string key)
    {
        var p = HttpContext.Current.User as ClaimsPrincipal;
        var i = p.Identity as ClaimsIdentity;
        var id = i.Claims.FirstOrDefault(x => x.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
        return string.Join("|", id.Value, key);
    }

    public void Delete(string key)
    {
        Cache.Remove(Key(key));
    }

    public bool Exists(string key)
    {
        return Cache.Get(Key(key)) != null;
    }

    public byte[] Load(string key)
    {
        return Cache.Get(Key(key)) as byte[];
    }

    public void Save(string key, byte[] data)
    {
        Cache.Add(Key(key), data, TimeSpan.FromMinutes(1));
    }
}

 

questi due esempi, rendono particolarmente flessibile l’uso del controllo Chart su scenari WebFarm e Windows Azure

per usare poi il proprio comportamento custom, basta modificare l’appsetting:

 

 

a presto

by Antonio Esposito on 3/3/2012