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!

Web Application Development – Web Communication

28 aprile 2012

Dopo moltissimo tempo torno a scrivere! Questa volta ho un preciso obiettivo. Molti dei post che pubblicherò d’ora in poi potranno sembrare scontati e semplici per qualcuno mentre per me rappresentano dei veri e propri appunti, a breve dovrò sostenere molti esami che mi permetteranno di ricevere diverse certificazioni in ambiente Microsoft, per questo motivo ho deciso di riportare qui un riassunto di ripassi/nuove conoscenze/curiosità/dubbi!

Oggi si parte con una panoramica delle attività svolte tra Client e Server per quanto concerne il funzionamento di una web application. Capire cosa accade durante la navigazione all’interno di un sito web è importante per poter meglio comprendere le mimiche che si nascondono dietro l’interazione con un server IIS. Un Web Browser (Client) ed un Web Server (Server) comunicano tra di loro utilizzando l’HTTP (Hypertext Transfer Protocol) che è un protocollo di rete assegnato alla porta 80, se il server è provvisto di un certificato, la comunicazione può avvenire su porta 443, in questo caso parliamo di HTTPS.

Tipicamente la comunicazione Client/Server prevede diverse operazioni:

  1. L’utente si collega al sito www.sample.com
  2. Il Browser attiva una connessione HTTP con www.sample.com ed inoltra un comando GET, questo comando tenta di accedere al path / (root del sito web) per cui, generalmente, è specificata una pagina di default da caricare. Tecnicamente il comando inoltrato assomiglia a questo:
    GET /
    host http://www.sample.com
  3. Il web server restituisce una risposta preceduta da un HTTP STATUS CODE che ne indica il tipo di contenuto (200 se è stata trovata una pagina web da visualizzare, 404 se la pagina non esiste, 302 se è stato effettuato un inoltro presso un’altra pagina etc. per ulteriori info sugli status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).

Volendo entrare nel merito delle attività, possiamo suddividere il lavoro svolto tra Client e Server, il client esegue una serie di operazioni volte alla preparazione ed inoltro/ricezione della richiesta al web server:

  1. Inoltra la richiesta al web server: se, come nell’esempio precedente, dobbiamo accedere a www.sample.com, il browser risolve l’indirizzo ed inoltra la chiamata per la richiesta della pagina.
  2. Autenticazione: se è attiva una connessione HTTPS, la richiesta deve contenere le informazioni necessarie per poter poi essere autenticata dal server.
  3. Elaborazione della risposta: quando il web server restituisce l’output della richiesta il web browser si occupa dell’elaborazione della risposta (es. se il web server ha restituito la pagina, il browser provvede a tradurla in elementi grafici, se invece sono restituiti particolari HTTP STATUS CODE, il web server si comporta nel modo più appropriato per poterli gestire).
  4. Esecuzione di codice Client Side (Scripts): se all’interno della pagina è presente del codice javascript, il browser si fa carico della sua esecuzione.

Questo processo è ripetuto ogni qual volta l’utente clicca su un bottone o seleziona un link. Il Server Web, come è facile immaginare, fa molto più del client. Una serie di processi sono innescati quando una richiesta HTTP arriva, tali processi, in parte operazioni di validazione, in parte comportamenti di contesto, concorrono alla preparazione dell’output finale da inoltrare al client. Quando una richiesta arriva sono eseguite diverse attività:

  1. Validazione: il server verifica che la richiesta sia correttamente strutturata, tale operazione si rende necessaria per evitare l’introduzione di richieste malformate che possono compromettere il corretto funzionamento del web server.
  2. Autenticazione: se la richiesta è in HTTPS (es. https://www.sample.com), è necessario autenticare la chiamata (il tutto avviene utilizzando il Secure Sockets Layer SSL).
  3. Autenticazione dell’utente: se è previsto un particolare meccanismo di autenticazione per l’utente, è necessario applicarlo, nel caso non siano presenti le credenziali necessarie per poter accedere, è visualizzata una maschera di login.
  4. Impostazione delle autorizzazioni dell’utente: successivamente è necessario impostare le autorizzazioni dell’utente, una serie di informazioni che indicano quali sono i permessi disponibili per il profilo connesso.
  5. Determinare come gestire la richiesta: a questo punto il server web deve capire in che modo interpretare ed eseguire la richiesta, se per esempio l’utente ha richiesto una pagina statica provvederà a restituirne il contenuto, se ha chiesto una pagina ASPX provvederà a servirla nel modo corretto.
  6. Gestione degli errori: se si verificano eventuali errori nel determinare il corretto percorso della richiesta, il server web cerca di fornire un dettaglio chiaro dell’errore che si è verificato (es. un Internal Server Error solitamente restituisce uno status code 500).
  7. Cache Output: il web server, provvede ad applicare anche meccanismi di cache con cui è possibile migliorare i tempi di risposta.
  8. Logging: per finire, tutte le operazioni eseguite per la chiamata, generalmente vengono loggate per questioni di sicurezza/monitoring.

La comunicazione descritta tra client e server è gestita mediante l’utilizzo di una richiesta. In ASP.NET è disponibile un oggetto, appunto Request, in cui sono raccolte tutte le informazioni che girano intorno a questa informazione. L’oggetto richiesta contiene informazioni sui Cookies, la cache, la scadenza delle pagine e molto altro. Tecnicamente parlando, il web server restituisce una risposta del genere:

HTTP/1.1 200 OK
Server: Microsoft-IIS/7.0
Content-Type: text/html
Content-Length: 154
<html><head><title>Hello World Sample</title></head><body><p>Hello World Sample Page!</p></body></html>
  • la prima linea indica il protocollo di comunicazione e le informazioni di stato (HTTP STATUS CODE).
  • la seconda linea contiene le informazioni sul tipo di web server che ha generato la risposta (Microsoft-IIS/7.0).
  • la terza linea (Content-Type) indica il tipo di contenuto erogato dal web server. Questo indicatore è anche conosciuto come MIME TYPE (Multipurpose Internet Mail Extensions). In questo esempio il MIME indica che il tipo di file è HTML.
  • la linea successiva contiene informazioni sulla grandezza effettiva del dato restituito.
  • ciò che è presente dopo è il dato vero e proprio che verrà trattato dal web browser in base alle specifiche del Content-Type.

Per ora può bastare, nel prossimo articolo: FORMS, POSTBACK e gestione degli HTTP METHODS.

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!

ASP.NET – Trasformazione del Web.Config (Debug | Release)

24 settembre 2010

Chi sviluppa applicazioni web ASP.NET avrà famigliarità con la gestione del web.config, questo file generalmente contiene tutte le impostazioni della nostra applicazione web, dalle stringhe di connessione ai messaggi di errore passando per chiavi personalizzate (appSettings), configurazione di account email, Authentication Provider e tantissimi altri servizi che è possibile configurare direttamente qui.

Ovviamente la configurazione delle nostre applicazioni cambia notevolmente quando passiamo, per esempio, da un ambiente di test a quello di esercizio, sicuramente avremo a che fare con modiche di diverso tipo, personalmente nella maggior parte dei casi mi trovo a dover apportare qualche piccolo cambiamento alle stringhe di connessione (dal server di test a quello di esercizio cambiano e non sarebbe normale il contrario!),poi utilizzando servizi esterni mi è utile modificare le API Key per l’autenticazione con gli stessi, per esempio, per quanto riguarda Google Maps è necessario essere in possesso di una API Key registrata su ogni host in cui lavoriamo (io ho registrato localhost e anche ambiente-di-deploy, ne consegue che in fase di debug utilizzerò la prima, pubblicando la Release dovrò cambiare ed utilizzare la seconda).

Con .Net Framework 4 è stata introdotta la possibilità di poter gestire il web.config in maniera molto diversa rispetto al passato, mentre prima era necessario modificare manualmente i valori di questo file di configurazione, ora è possibile manipolare direttamente da progetto le informazioni contenute, con delle regole di controllo che, in base alla modalità di compilazione (Release o Debug) , generano un diverso file di configurazione. Aprendo il progetto, per il file web.config, troviamo una struttura del genere:

  • Web.config
    • Web.Debug.config
    • Web.Release.config

È facile intuire che partendo dall’elemento principale, le due sotto voci non sono altro che le diverse configurazioni disponibili per il Deploy. Non è, come si potrebbe credere, un copia incolla della stessa configurazione root su cui apportare delle modifiche, si tratta invece, di un manipolatore di stringhe, ognuno dei due file (Debug e Release) viene predisposto in modo tale da permettere all’utente di manipolare sempre l’elemento root ma secondo precise regole.

Per l’intercettazione degli elementi da manipolare, all’interno dello stesso file, è possibile utilizzare diversi attributi, uno di questi si chiama xdt:Locator con cui è possibile specificare un pattern di ricerca per gli elementi che corrispondono alle caratteristiche indicate, la sintassi da utilizzare per le ricerca viene ereditata direttamente da XPath.

Per capire quanto detto fino ad ora, ho pensato di realizzare un esempio pratico. Supponiamo di avere il nostro web.config che contiene le seguenti informazioni:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <connectionStrings>
  <add 
	name="Connessione" 
	connectionString="Initial Catalog=TestDB;Integrated Security=SSPI" 
  />
 </connectionStrings>
</configuration>

Ho inserito una una stringa di connessione, questa attualmente punta al database di Test, manipolando il file Web.Release.Config posso specificare la stringa di connessione che deve essere utilizzata quando l’applicazione viene compilata in modalità Release:

<?xml version="1.0" encoding="utf-8">
<configuration>
 <connectionStrings>
  <add 
	name="Connessione" 
	connectionString="Initial Catalog=TestDB;Integrated Security=SSPI" 
        xdt:Transform="Replace"
  />
 </connectionStrings>
</configuration>

Cosa accade? Avendo impostato in modalità Release una nuova stringa di connessione, quando andrò a pubblicare la mia web-application direttamente in ambiente di deploy, facendo attenzione ad impostare la modalità di compilazione su Release, viene pubblicata una versione del web.config che contiene le informazioni della ConnectionString specificata in Web.Release.Config!

ASP.NET Application State

3 agosto 2010

Quando usarla? Quando è più giusto scegliere questo contenitore mettendo da parte la cache? Prima di rispondere a questa domanda è necessaria una breve introduzione sull’argomento. L’Application State è un contenitore di dati accessibile da tutte le classi presenti all’interno di un’applicazione web. Diversamente dalle sessioni, la cui accessibilità e ristretta all’utente che ne è proprietario, l’Application State è accessibile a tutti gli utenti (proprio come la cache). Per tale motivo questo contenitore si presta bene per la memorizzazione di piccole quantità di dati spesso richieste all’interno dell’intero ciclo di vita dell’applicazione.

L’Application State viene fornito tramite un istanza di HttpApplicationState che espone un dizionario di key(string)/value(object). Questo oggetto viene istanziato la prima volta quando un qualsiasi utente si collega all’applicazione web ed è successivamente disponibile per tutto il ciclo di vita dell’applicazione stessa.

Generalmente l’accesso gestito tramite l’HttpContext (HttpContext.Current.Application) da cui possiamo inserire, modificare e cancellare valori. Le modalità con cui effettuare questa operazione viene effettuata necessitano particolare attenzione, a differenza della cache, in cui basta semplicemente richiamare il metodo Add o Insert per memorizzare valori, nell’Application State è necessario isolare il contenitore di dati per averne l’accesso esclusivo essendo questa una risorsa globale. Nell’esempio viene chiarito il concetto:

DataTable data = database.GetData();
HttpContext.Current.Application.Lock();
HttpContext.Current.Application.Add("Data", data);
HttpContext.Current.Application.UnLock();

[ad#ad-lungo]

Come potete notare, ho reso più visibile la porzione di codice prima e dopo l’inserimento, fondamentale se vogliamo assicurare che questo contenitore funzioni bene. Prima di utilizzare questo strumento è necessario conoscere alcune informazioni preliminari:

  • Essendo questa una risorsa incorporata permette di ottenere prestazioni ottimali (molto più veloci del salvataggio dei dati su database o file system). Se però la quantità dei dati memorizzati è molto grande, viene esaurita anche la memoria a disposizione del server web producendo più problemi che benefici, quindi se la quantità di dati da salvare è molto grande sarebbe opportuno pensare ad una soluzione alternativa come la cache.
  • I dati memorizzati in questo contenitore sono Volatili, ciò significa che se l’applicazione web viene riavviata o terminata per diverse motivazioni (modifiche al web.config, crash etc.) i dati vengono persi. Si deduce che non è una buona pratica affidarsi alla completa memorizzazione di informazioni nel contenitore Application ma è opportuno affidarsi anche alla gestione di questi dati in una memoria non volatile da cui poterli successivamente ripristinare.
  • Non è una soluzione adatta alla scalabilità: l’Application State non viene condiviso se stiamo lavorando in una web-farm o scenari simili (server multiprocessori, macchine virtuali etc.), quindi in questi casi è opportuno pensare ad un’alternativa più efficiente (come una vera e propria base dati e quindi l’utilizzo di un server di database) che possa assicurare il recupero dei dati in ogni momento.

Fatte queste premesse, penso sia possibile valutare quando e come introdurre l’Application State nelle proprie applicazioni!