ASP.NET MVC – Caricare un file JAVASCRIPT EMBEDDED.

25 luglio 2012

Appunto qui per ricordarmene in futuro (visto che dimentico tutto ultimamente). Ho realizzato una libreria di classi in cui, oltre ad oggetti C#, sono presenti diversi file JAVASCRIPT il cui contenuto è necessario perché le classi possano funzionare correttamente all’interno di un’APP MVC.

Come è possibile caricare questi file all’interno di un progetto di questo tipo? Con pochi è semplici passaggi il lavoro è fatto.

  1. Selezionare il file JAVASCRIPT che è necessario importare all’interno del progetto libreria.
  2. Dal menu contestuale (click destro del mouse), selezionare la voce Proprietà.
  3. Nella finestra delle Proprietà modificare Build Action: Embedded Resource.
  4. Nel file AssemblyInfo.cs della del progetto libreria aggiungere una nuova riga di codice:
    [assembly: System.Web.UI.WebResource("YourNamespace.Resource.js, "application/x-javascript")]

Questi passaggi bastano per poter incorporare la libreria all’interno di un’applicazione ASP.NET Web Forms utilizzando ClientScript.GetWebResourceUrl(Type, resourceName), con MVC è necessario eseguire ulteriori passaggi per poter rendere tutto funzionante. Realizziamo per questo scopo un oggetto con cui deve essere possibile ottenere l’URL dei file embedded molto semplicemente.

public static class ResLocator
{
	private const string UrlLocatorMethodName = "GetWebResourceUrlInternal";

	public static string Resolve(Type assemblyObjectType, string resourceName) 
	{
		MethodInfo resourceLocatorMethod = assemblyObjectType.GetMethod(UrlLocatorMethodName, 
			BindingFlags.NonPublic | BindingFlags.Static);
		string url = string.Format("/{0}", resourceLocatorMethod.Invoke(
			null,
			new object[] { Assembly.GetAssembly(assemblyObjectType), resourcePath, false })
		);

		return url;
	}
}

Il metodo Resolve accetta in input un Type che deve necessariamente riferirsi ad un tipo di oggetto contenuto nel progetto libreria e resourceName, cioè il nome della risorsa da includere. Successivamente, referenziando il namespace in cui è contenuto l’helper all’interno della nostra MasterPage, è possibile includere lo script di riferimento in questo modo:

<script 
	type="text/javascript" 
	src="@ResLocator.Resolve(typeof(SampleAssemblyObject), "YourNamespace.Resource.js)" />

Completati questi passaggi ed avviata la nostra applicazione MVC, il risultato dell’inclusione è simile a questo:

/WebResource.axd?d=HWyLh7g77XDqhYfNG0fioE3hSIzYB4uYmoUs3cJSuFRbnk9cZT1AWVuijZ81&t=634788092174760080

Spero possa essere utile anche ad altri per eventuali EMBEDDED RESOURCES!

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!