ASP.NET MVC & Microsoft Chart Controls

7 novembre 2011

Ultimamente mi sono concentrato molto sull’utilizzo di ASP.NET MVC per lo sviluppo di un progetto abbastanza grosso, tra le varie cose è sorta l’esigenza di poter utilizzare uno strumento per la generazione di grafici di vario tipo.

All’inizio la mia scelta è ricaduta su “Libero API for Fusion Charts”, un prodotto fatto davvero molto bene e che offre la possibilità di implementare diverse tipologie di grafico (tante!). Nonostante le sue caratteristiche ho dovuto mettere da parte questa libreria in quanto legata all’utilizzo del componente Flash (sempre questioni di legacy).

Alla fine ho optato per la soluzione che poi si è rivelata anche la migliore (e ancora mi chiedo perché non ci ho pensato prima?). La scelta è ricaduta su “Microsoft Chart Controls”.

Partiamo dal presupposto che questo prodotto non si presta bene, se non dopo qualche piccolo accorgimento, per essere utilizzato con ASP.NET MVC. Infatti nasce per funzionare principalmente all’interno di applicazioni Web Forms, la cui struttura è nettamente diversa da quella di un progetto MVC. Essendo il chart un controllo Server, necessita di una pagina web di tipo System.Web.UI.Page in cui poter essere posizionato, sappiamo bene che in una pagina MVC non è possibile inserire controlli di questo tipo.

Oggi vorrei spiegarvi come configurare il vostro progetto MVC perché i Microsoft Charts possano funzionare correttamente e senza alcun tipo di problema.

Prima di tutto è necessario estendere le funzionalità dell’oggetto Page perché possa occuparsi anche del disegno dei grafici ms. Lo facciamo realizzando un helper come nell’esempio che segue:

namespace MvcApplication.Helpers
{
	public static class HelperCharts
	{
		public static void RenderChart(this Page page, System.Web.UI.DataVisualization.Charting.Chart chart)
		{
			var writer = new HtmlTextWriter(page.Response.Output);
			chart.RenderControl(writer);
		}
	}
}

Chiaramente le istruzioni che abbiamo scritto sono poche e semplici, ritengo in ogni caso che lavorare in questo modo garantisce una migliore leggibilità e pulizia del codice  e, soprattutto per quanto riguarda MVC, rispetto delle regole imposte dal pattern.

Completato il metodo dobbiamo assicurarci che tale funzionalità sia poi disponibile in tutte le Views e che la gestione dei Charts possa essere correttamente eseguita dal .Net Framework, per tale motivo è necessario il file web.config:

<configuration>
	<appSettings>
		<add key="ChartImageHandler" value="storage=file;timeout=20" />
	</appSettings>
	<system.web>
		<httpHandlers>
		<add path="ChartImg.axd" verb="GET,HEAD,POST"
			type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler,
				System.Web.DataVisualization, Version=4.0.0.0,
				Culture=neutral, PublicKeyToken=31bf3856ad364e35"
	        	validate="false" />
		</httpHandlers>
		<pages>
			<namespaces>
				<add namespace="MvcApplication.Helpers" />
			</namespaces>
		</pages>
	</system.web>
</configuration>

Come da documentazione è necessario aggiungere la chiave ChartImageHandler per definire le modalità di generazione del grafico (considerando che questo alla fine non è altro che un’immagine). Nell’elenco degli HttpHandlers è necessario configurare la risorsa utilizzata per la generazione dei grafici e, per concludere, volendo rendere visibile la funzione precedentemente scritta (RenderChart) in tutte le viste senza dover effettuare una import in ogni pagina del namespace, aggiungiamo all’elenco dei default namespaces anche quello in cui risiede il metodo da noi implementato.

In seguito possiamo realizzare un DTO fatto in questo modo:

namespace MvcApplication.Models.DTO
{
	public sealed class SampleDTO
	{
		public Chart Chart { get; private set; }

		public SampleDTO(Chart chart)
		{
			Chart = chart;
		}
	}
}

Possiamo ora creare un controller di esempio che dispone di un’Action che restituisce il DTO precedentemente realizzato:

namespace MvcApplication.Controllers
{
	using MvcApplication.Models.DTO;
	public class SampleController : Controller
	{
		[HttpGet] public ActionResult GetSampleChart()
		{
			Chart chart = new Chart();
			// Configure Chart...
			SampleDTO sampleDTO = new SampleDTO(chart);
			return View(sampleDTO);
		}
	}
}

E per concludere si passa alla View che si presenta come nell’esempio:

<%@ Page
	Title="Sample"
	Language="C#"
	MasterPageFile="~/Views/Shared/Shell.Master"
	Inherits="System.Web.Mvc.ViewPage<MvcApplication.Models.DTO.SampleDTO>" %>
<h2>Chart Sample</h2>
<div>
<% 	Page.RenderChart(Model.Chart); >
</div>

Con poche righe, abbiamo realizzato quanto necessario per poter sfruttare in modo corretto e pulito i Microsoft Charts nel nostro progetto MVC.

Enjoy!

IIS – “Could not load file or assembly ‘Oracle.DataAccess’ or one of its dependencies. An attempt was made to load a program with an incorrect format.”

27 giugno 2011

In quest’ultimo periodo mi sono occupato dello sviluppo di un progetto basato su ASP.NET MVC ed Oracle. Per l’accesso ai dati abbiamo utilizzato Oracle.DataAccess, una libreria presente all’interno di un pacchetto di strumenti raggruppati sotto il nome di “Oracle Client”.

Nel dover rilasciare l’applicativo si è verificato un particolare problema all’interno del Web Server IIS ospitante. Provando a chiamare l’applicazione da Browser veniva visualizzato il seguente messaggio di errore:

Could not load file or assembly 'Oracle.DataAccess' or one of its dependencies. An attempt was made to load a program with an incorrect format.

Provando a cercare online una possibile soluzione al problema mi sono imbattuto in una serie di Post infiniti in cui vengono proposti particolari workground da applicare direttamente sul file web.config per risolvere un problema di riferimenti che si creano durante l’utilizzo della libreria. C’è da notare che questo problema non si verifica se si lavora con il server web Cassini integrato in Visual Studio.

Poi però ho trovato una soluzione meno invasiva a livello applicativo ma configurabile direttamente sul web server. In pratica per risolvere il problema è necessario apportare una piccola modifica al Pool Applicativo utilizzato per l’esecuzione dell’applicazione quando questa gira su un server a 64bit. Aprendo Internet Information Services Manager è possibile, all’interno della voce “Application Pools” configurare in maniera più dettagliata uno di questi pool selezionando la voce “Advanced Settings…” subito dopo averne selezionato uno.

Per l’applicazione MVC realizzata è stato scelto come pool predefinito “ASP.NET v4.0”, nelle opzioni avanzate ho spuntato la voce “Enable 32-Bit Applications” in modo tale da permettere l’esecuzione di codice a 32 ed a 64 bit insieme.

Rigenerando il pool e riavviando l’applicazione, il problema non si presenta più!

Windows Phone 7 – Installare NoDo

29 marzo 2011

Prima di continuare nella lettura di questa breve guida sono necessarie due considerazioni:

  1. è necessario avere molta pazienza perchè questo processo funzioni;
  2. il processo è stato testato da me personalmente dopo non pochi tentativi totalmente falliti;

In ogni caso se avete problemi o non vi è chiaro qualche passaggio potete lasciare un commento e provvederò a rispondere non appena possibile. Ora partiamo con la guida!

  • Scarichiamo USAIP.pbk dal seguente link e successivamente facciamo doppio-click sul file appena scaricato.
  • Nella finestra che ci viene proposta selezioniamo la connessione “EUROIP PPTP Hungary” ed inseriamo le seguenti credenziali di accesso:
    Username: demo
    Password: demo
    Attenzione: questa connessione viene automaticamente chiusa dopo 7 minuti quindi cerchiamo di fare in fretta e con attenzione le operazioni successive (in ogni caso è sempre possibile effettuare una riconnessione).
    Altra nota: se la connessione di rete non viene aperta, è necessario modificare il registro di sistema scaricando una patch (un file reg) dal seguente link, successivamente è necessario riavviare il computer perchè tutto funzioni correttamente (quindi ripetiamo il primo passaggio).
  • Ora sul nostro terminale Windows Phone disattiviamo la Connessione WIFI e ci assicuriamo che “Modalità Aereo” sia disattivata e “Rete Dati” sia attiva
  • Avviamo Zune e nello stesso tempo lasciamo la configurazione “rete dati” (sul dispositivo) aperta in modo tale da poterci operare velocemente (fare un fast siwtch On|Off).
  • Manualmente cerchiamo aggiornamenti da Zune (Settings ->Phone->Update)
  • Dopo qualche secondo (il tempo è molto variabile, leggendo i vari commenti su XDA Developers alcune persone hanno aspettato 10-15 secondi, altre dai 33 ai 35 ed altre ancora addirittura oltre i 55 secondi), io con il mio HTC HD7 ho aspettato 15 secondi(dopo aver effettuato ben 3 diversi tentativi con 3 tempi diversi e 3 ripetizioni per ogni range temporale) prima di disattivare la rete dati (rispettivamente le voci “Rete dati” e “Connessione 3G“).
  • Aspettiamo un’altro pò ed un popup sul nostro cellulare dovrebbe notificarci che un nuovo aggiornamento è disponibile!
  • Questi primi passaggi avranno sicuramente impegnato molto tempo (più o meno 7 minuti, io in totale sono andato oltre i 30 minuti prima di completare l’operazione, tempo in cui è stata effettuata più volte la riconnessione tramite pbk) quindi riattiviamo la connessione alla rete “EUROIP L2TP Hungary” ed ora, con molta calma, Zune procederà al download del primo aggiornamento ufficiale per Windows Phone 7!
  • Se non dovesse funzionare ripetiamo questo passaggio facendo attenzione al numero totale di secondi che aspettiamo ogni volta prima di disattivare la rete dati.

Lascio ad un altro giorno la mia recensione sull’HTC HD7 o più in generale su Windows Phone ma voglio concludere questo brevissimo post esponendo la mia opinione: quando ho comprato Windows Phone una delle caratteristiche che più mi attraeva (o che forse ho idealizzato io nella mia mente) era la poca frammentazione che questo sistema avrebbe creato (rispetto ad Android per esempio) o più in generale la facilità con cui un utente avrebbe potuto ricevere aggiornamenti sul proprio terminale senza dover aspettare o fare chissà cosa. Il fatto che io abbia scritto questo post è per me una delusione. Il primo update ufficiale è stato rilasciato quasi una settimana fà ed ancora oggi la maggior parte dei possessori di un Windows Phone riscontrano problemi nel reperire facilmente gli aggiornamenti (quindi non sto parlando solo di Italia).

In ogni caso spero che questa guida sia utile a voi tanto quanto lo è stata per me! Enjoy and stay tuned!

Fonte ufficiale: http://forum.xda-developers.com/showthread.php?t=1012189

Differenze tra Web Site e Web Application Project in Visual Studio

9 marzo 2011

Secondo me è fondamentale capire quali siano le reali differenze tra questi due tipi di progetti, io personalmente sono abituato ad utilizzare sempre e solo Web Application Project ma mi è capitato di lavorare su progetti in cui è stato utilizzato un “Web Site” (guarda caso proprio un progetto in Team). Conoscerne le differenze è un buon punto di partenza per poter capire quale delle due soluzione è più giusto scegliere in base al contesto.

Web Site

Un progetto “Web Site” non è altro che un insieme di file raggruppati all’interno di cartelle e sotto cartelle il cui tipo varia dalla semplice immagine, al file di testo per finire con i file di codice dell’applicazione. Non esiste un progetto reale associato ma una cartella root in cui tutto è contenuto. Un progetto di questo tipo è compilato dinamicamente mentre l’applicazione è in esecuzione e non contiene al suo interno una cartella bin.

Vantaggi:

  • non è necessario avere un file di progetto o una cartella virtuale per la sua esecuzione
  • il sito può essere facilmente distribuito facendo un copia incolla dei file da cui è composto

Svantaggi:

  • non essendoci il file di progetto non è possibile avere un file di questo tipo con cui, facendo doppio click, è possibile aprire il progetto ottenendo l’elenco completo di tutto il materiale da cui è composto.
  • per DEFAULT tutti i file che sono presenti all’interno della cartella del progetto sono da considerare parte stessa di questo, per tale motivo, se alcuni di questi vogliamo escluderli, dobbiamo inserire un suffisso per i file in questione: .exclude
Web Application Project

Questo tipo di progetto è molto più con un semplice “Web Site”. Pensato più in la nel tempo rispetto al suo predecessore, è considerato come un Add On di Visual Studio, aggiunto per la prima volta a partire da VS 2005, viene predisposto anche nei nuovi ambienti (Visual Studio 2008 e 2010).

Vantaggi:

  • Tutto il codice viene compilato in un singolo Assembly il cui contenuto viene piazzato all’interno della cartella bin.
  • Escludere file che non servono direttamente nel progetto è più semplice, essendoci una soluzione ed un file di progetto che ne identifica la struttura.

Svantaggi:

  • Condividere il lavoro con altri colleghi risulta più complesso nel caso si utilizzi Microsoft Visual Source Safe e roba simile.

Chiariti questi macro concetti diventa più facile decidere, in ogni caso la documentazione MSDN mette a disposizione molta più roba in merito, il mio articolo vuole essere un riassunto molto “short” di ambedue le possibilità. A voi la scelta developer!

.Net – Windows Form Applications & Context Sensitive Help

2 marzo 2011

Esistono diverse strategie con cui è possibile realizzare un Help che realmente possa essere utile. Il .Net Framework, per le applicazioni “Windows Form” mette a disposizione una serie di strumenti che è possibile utilizzare a proprio piacimento per la realizzazione di una documentazione in linea, tema la cui importanza non va assolutamente sottovalutata perché un buon software è sempre corredato da una buona documentazione.

Oggi voglio mostrarvi come ho realizzato una guida in linea sensibile al contesto (Context Sensitive Help) all’interno di una Client Application realizzata con il .Net Framework.

* Tralasciando la spiegazione di come si realizza una guida in linea (Microsoft Compiled HTML Help), argomento su cui ci sarebbe molto da discutere, questo post vuole spiegare come integrare un file di questo tipo all’interno di un’applicazione Windows Form.

Partiamo dai presupposti, un oggetto di tipo System.Windows.Forms.Form espone una serie di proprietà, tra queste troviamo anche un evento chiamato HelpRequested che lo sviluppatore può eventualmente implementare, a riguardo la documentazione parla chiaro:

L’evento HelpRequested viene solitamente generato quando l’utente preme il tasto F1 o fa clic su un pulsante della Guida sensibile al contesto.

L’implementazione risulta molto semplice, nei form in cui vogliamo fornire aiuto possiamo decidere di invocare un metodo che possa, in base al contesto, darci informazioni utili reperite direttamente dal file di guida.

Inoltre è necessario sapere che un file di guida “Microsoft Compiled HTML Help” contiene al suo interno una serie di file html compressi, questi file vengono associati ad un identificatore univoco definito in un file Header (scritto in C) e che riporta il riferimento ad ogni link, questo file viene utilizzato in fase di compilazione della guida e serve propri per indicizzare i contenuti della nostra documentazione per poterla successivamente interrogare utilizzando un TopicId.

Ora, all’interno dei Windows Form sono si presenti delle proprietà per la gestione dell’Help ma non sono quelle di cui noi abbiamo bisogno (in pratica il .Net Framework mette a disposizione una serie di Tooltip che vengono visualizzati per dare aiuto). Supponiamo di aver definito nel nostro file di guida un argomento chiamato “Come effettuare il login”, a questo è stato assegnato l’indice 1000, come fare per ottenere un focus su questo argomento nella guida in linea direttamente dall’applicazione? La soluzione che ho applicato è molto semplice, ogni controllo, all’interno di un applicazione Windows espone una proprietà chiamata Tag che è di tipo Object, lo scopo di questa è proprio memorizzare informazioni aggiuntive nel nostro form come per esempio oggetti, stringhe o quanto ci possa tornare più utile, io ho deciso di inserire in questo campo il TopicId che dovrebbe essere richiamato se l’utente chiede aiuto durante l’esecuzione dell’applicazione, successivamente ho realizzato un oggetto che ho chiamato HelpProvider il cui compito è attivare l’help in linea su un determinato form:

internal sealed class HelpProvider
{
	//Nome del file guida
	private const string ChmFileName = "Docs.chm";
	private Form _form;

	internal Form Form
	{
		get
		{
			return (this._form);
		}
	}

	private HelpProvider()
	{
		this._form = null;
	}

	internal HelpProvider(Form form)
	{

		HelpNamespace = Path.Combine(
			Environment.CurrentDirectory,
			ChmFileName);

		_form = form;
		_form.HelpRequested += new HelpEventHandler(OnHelpRequestedAction);
	}

	internal void TryAsk()
	{
		Control ctrl = null;
		if ((this._form.ActiveControl != null)
			&&
		    (!IsNull(this._form.ActiveControl)))
			ctrl = this._form.ActiveControl;
		else
			ctrl = _form;

		if (ctrl.Tag == null)
		{
			Program.ShowWarning("Unable to retrive help information for this argument.");
			return;
		}

		Help.ShowHelp(ctrl, HelpNamespace, HelpNavigator.TopicId, ctrl.Tag as string);
	}

	/// <summary>
	/// Event Handled when an help request is execute by pressing F1
	/// </summary>
	/// <param name="sender" />
	/// <param name="hlpevent" />
	private void OnHelpRequestedAction(object sender, HelpEventArgs hlpevent)
	{
		this.TryAsk();

		hlpevent.Handled = true;
	}
}

Il funzionamento è molto semplice, questo oggetto riceve in ingresso un Form su cui imposta l’evento  HelpRequested per poter successivamente intercettare le richieste da parte dell’utente, resta in attesa, quando una richiesta viene inoltrata, viene scatenato l’evento OnHelpRequestedAction in cui viene invocato il metodo TryAsk.

Questo metodo effettua diverse operazioni, prima di tutto legge il valore del Tag del controllo che gli viene passato, se questo valore è diverso da NULL,  invoco un metodo, ShowHelp, che fornisce la classe Help del .Net Framework in cui passo:

  • ctrl: Controllo che chiede Aiuto (un form o un qualsiasi controllo presente nella maschera corrente)
  • HelpNamespace: nome del file di guida da invocare per la documentazione
  • HelpNavigator.TopicId: modalità di lettura della documentazione,cioè, quando apro la guida, cosa devo fare esattamente, se cercare per argomento, per indice etc.
  • ctrl.Tag: identificativo dell’argomento di cui vogliamo le informazioni.

L’HelpProvider, può essere facilmente utilizzato in questo modo: nel form in cui vogliamo rendere attiva la funzionalità di help, dichiariamo una variabile privata di tipo HelpProvider che andiamo ad inizializzare nel costruttore del nostro Form come nell’esempio che segue:

public class MyWindowsApp : System.Windows.Forms.Form {
	private HelpProvider _helpProvider;

	public MyWindowsApp() {
		_helpProvider = new HelpProvider(this);
	}
}

Con queste poche righe di codice abbiamo attivato un help in linea completo e funzionante!

Ricordate che per funzionare è necessario che i controlli e / o direttamente i form per cui devono essere disponibili informazioni, devono avere la variabile Tag valorizzata con un certo indice equivalente ad un TopicId del nostro file “Windows Compiled HTML Help”, in caso contrario l’help non viene mostrato.