<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://dotnetmarche.org/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Articoli</title><link>http://dotnetmarche.org/blogs/article/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>Creare un programma estensibile tramite plugins - Parte 2</title><link>http://dotnetmarche.org/blogs/article/archive/2007/01/29/Creare-un-programma-estensibile-tramite-plugins-_2D00_-Parte-2.aspx</link><pubDate>Mon, 29 Jan 2007 00:37:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:1459</guid><dc:creator>Alkampfer</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://dotnetmarche.org/blogs/article/rsscomments.aspx?PostID=1459</wfw:commentRss><comments>http://dotnetmarche.org/blogs/article/archive/2007/01/29/Creare-un-programma-estensibile-tramite-plugins-_2D00_-Parte-2.aspx#comments</comments><description>&lt;div class="mainAuthor"&gt;&lt;p&gt;Di: Ricci Gian Maria&lt;/p&gt;&lt;/div&gt;&lt;div class="wlWriterSmartContent" id="57DB9511-4ED8-456d-8E06-AF9EC0A0BF46:a48e9dab-8210-4faf-9f04-91bfd45c7c5d" style="display:inline;margin:0px;padding:0px;"&gt;&lt;div class="subTitle"&gt;&lt;p&gt;La tecnologia .NET consente di iniettare codice in maniera dinamica in un processo, rendendolo di fatto estendibile mediante unit&amp;agrave; di codice chiamate &lt;em&gt;plugin&lt;/em&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="Normal"&gt;&lt;div class="subHeading"&gt;Attributi alla riscossa&lt;/div&gt;&lt;p&gt;Nel precedente articolo sono state esaminate le basi per gestire l&amp;rsquo;Inversion of Control tramite plugin, in questo articolo si cercher&amp;agrave; di dare pi&amp;ugrave; dignit&amp;agrave; alla classe PluginManager in modo da renderla un po&amp;rsquo; pi&amp;ugrave; robusta. Il problema principale del codice del precedente esempio &amp;egrave; che i plugin vengono individuati in base all&amp;rsquo;interfaccia implementata, generando di fatto due problemi: il primo &amp;egrave; che l&amp;rsquo;esposizione di un plugin all&amp;rsquo;esterno della dll viene fatta in maniera implicita ed il secondo &amp;egrave; che non si hanno informazioni dettagliate da mostrare all&amp;rsquo;utente. Per risolvere entrambi i problemi &amp;egrave; necessario agire su due punti: dare la possibilit&amp;agrave; di decidere in maniera programmatica quali classi verranno esportate e fornire nel contempo un set di informazioni standard da mostrare all&amp;rsquo;utente o da utilizzare per gestire il plugin in maniera meno implicita.&lt;/p&gt;&lt;p&gt;Da questa mini analisi si evince subito che un attributo custom &amp;egrave; probabilmente la soluzione ottimale dato che consente di aggiungere informazioni ad una classe sotto forma di metadati compilati nell&amp;rsquo;assembly e pu&amp;ograve; essere utilizzato anche per marcare esplicitamente tutte le classi che dovranno essere gestite come plugin.&lt;/p&gt;&lt;div class="subHeading"&gt;Creare un attributo custom per i plugin &lt;/div&gt;&lt;p&gt;Il primo passo &amp;egrave; creare l&amp;rsquo;attributo per identificare i plugin come mostrato dalla classe PluginAttribute presente nell&amp;rsquo;esempio accluso. La creazione di un attributo custom esula da questo articolo, ma si pu&amp;ograve; comunque notare che &amp;egrave; sufficiente ereditare dalla classe &lt;em&gt;Attribute&lt;/em&gt; e decorare la classe con l&amp;rsquo;attributo &lt;em&gt;AttributeUsage&lt;/em&gt; che consente di specificare come deve essere gestito l&amp;rsquo;attributo stesso.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;[AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false), Serializable()] 
public class PluginAttribute : Attribute {
&lt;/textarea&gt; &lt;p&gt;In questo caso si &amp;egrave; specificato che il nostro attributo pu&amp;ograve; essere utilizzato solamente con le classi e che non pu&amp;ograve; essere ereditato. La classe attributo deve poi contenere le propriet&amp;agrave; che identificano il plugin ed esporre un costruttore di convenienza per rendere pi&amp;ugrave; semplice l&amp;rsquo;utilizzo dell&amp;rsquo;attributo stesso. Nel caso in esame sono state scelte quattro propriet&amp;agrave; distintive per il plugin: il nome, una sigla che indica il creatore, la versione ed infine una descrizione testuale che permette di specificare dettagliatamente cosa fa il plugin in questione.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;public PluginAttribute(
	System.String name,
	System.String manufacturer,
	System.String version,
	System.String description) {
	
	this.Name	= name;
	this.Manufacturer	= manufacturer;
	this.Version	= version;
	this.Description	= description;
}
&lt;/textarea&gt; &lt;p&gt;Per completare la classe viene anche fatto l&amp;rsquo;override del metodo virtuale &lt;em&gt;ToString()&lt;/em&gt; per dare una descrizione pi&amp;ugrave; user friendly dell&amp;rsquo;attributo.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;public override System.String ToString() {
	return this.Name + &amp;quot;(&amp;quot; + this.Version + &amp;quot;)&amp;quot;; 
}
&lt;/textarea&gt; &lt;p&gt;Un istanza di un PluginAttribute &amp;egrave; quindi a tutti gli effetti una descrizione completa di un plugin che pu&amp;ograve; essere sia mostrata all&amp;rsquo;utilizzatore a titolo informativo, sia utilizzata internamente dal gestore per la catalogazione di tutti i plugin caricati.&lt;/p&gt;&lt;div class="subHeading"&gt;Le altre classi di supporto&lt;/div&gt;&lt;p&gt;Prima di esaminare il codice del nuovo gestore &amp;egrave; necessario creare altre classi ausiliarie necessarie per una gestione efficente. Prima di tutto si deve creare un altro attributo custom chiamato &lt;em&gt;PluginInterfaceAttribute &lt;/em&gt;il cui scopo &amp;egrave; specificare in maniera esplicita le interfacce implementate da una classe plugin.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;[AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false), Serializable()] 
public class PluginInterfaceAttribute : Attribute {
	public PluginInterfaceAttribute(
		String interfaceName) {
		mInterfaceName = interfaceName;
	}
	public String InterfaceName {
		get {return mInterfaceName;}
	}
	String mInterfaceName;
}
&lt;/textarea&gt; &lt;p&gt;In questo caso la propriet&amp;agrave; AllowMultiple &amp;egrave; pari a true dato che una singola classe pu&amp;ograve; implementare se vuole pi&amp;ugrave; interfacce di plugin e quindi presentare un&amp;rsquo;istanza di questo attributo per ognuna di esse. Con questa tecnica abbiamo del tutto eliminato il caricamento implicito dato che ogni classe che vuole essere caricata dinamicamente deve essere decorata in maniera esplicita con una serie di attributi che ne identificano l&amp;rsquo;utilizzo.&lt;/p&gt;&lt;p&gt;L&amp;rsquo;ultima classe da esaminare si chiama &lt;em&gt;PluginInfo&lt;/em&gt; ed il suo scopo &amp;egrave; contenere tutte le informazioni su di un plugin caricato in modo da permetterne la gestione. Il costruttore accetta come parametro il tipo di dato da gestire ed internamente inserisce in una collection tutte le interfacce implementate recuperando tramite reflection.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;public PluginInfo(
	Type	pluginType) {
	
	mPluginType = pluginType;
	ExtractPluginInformation(pluginType);
}
private void ExtractPluginInformation(
	Type pluginType) {
	//Iterate in all interfaces implemented by the plugin
	foreach(PluginInterfaceAttribute pia in 
	pluginType.GetCustomAttributes(typeof(PluginInterfaceAttribute), false)) {
	
	mInterfaceList.Add(pia.InterfaceName); 
	}
}
&lt;/textarea&gt; &lt;p&gt;Come si pu&amp;ograve; notare le interfacce implementate vengono individuate semplicemente esaminando la la lista di attributi &lt;em&gt;PluginInterface&lt;/em&gt; definiti sul tipo. La classe PluginInfo al suo interno tiene inoltre un riferimento al tipo di oggetto e fornisce un metodo &lt;em&gt;ImplementInterface()&lt;/em&gt; che restituisce un boolean che indica se il tipo implementa una particolare interfaccia.&lt;/p&gt;&lt;div class="subHeading"&gt;Il nuovo gestore di plugin&lt;/div&gt;&lt;p&gt;Il nuovo gestore internamente mantiene la lista di tutti i plugin caricati in un dictionary la cui chiave &amp;egrave; un&amp;rsquo;istanza della classe PluginAttribute e il valore &amp;egrave; un PluginInfo; due clausole using rendono pi&amp;ugrave; leggibile il codice dichiarando due alias di convenienza&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;using LoadedPluginList = System.Collections.Generic.Dictionary&amp;lt;
	DotNetMarche.Plugin.PluginAttribute, 
	DotNetMarche.Plugin.PluginInfo&amp;gt;;
using LoadedPlugin = System.Collections.Generic.KeyValuePair&amp;lt;
	DotNetMarche.Plugin.PluginAttribute, 
	DotNetMarche.Plugin.PluginInfo&amp;gt;;
using PluginList = System.Collections.Generic.List&amp;lt;DotNetMarche.Plugin.PluginAttribute&amp;gt;;
&lt;/textarea&gt; &lt;p&gt;Come per la versione precedente la classe PluginManager accetta nel costruttore il nome della cartella che internamente contiene i plugin da caricare e chiama la funzione &lt;em&gt;AnalyzeAssemblyFile()&lt;/em&gt; su tutti i file .dll che trova nella cartella specificata.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;private void AnalyzeAssemblyFile(String fileName) {
	try {
		System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFrom(fileName);
 		foreach (Type Ty in asm.GetTypes()) {
			if (Ty.IsDefined(typeof(Plugin.PluginAttribute), false)) {
				mLoadedPlugins.Add((PluginAttribute) Attribute.GetCustomAttribute(Ty, typeof(PluginAttribute)), new PluginInfo(Ty));
			}                   
		}
	} catch (Exception Ex) {
		System.Diagnostics.Debug.WriteLine(Ex.Message);
	}
}  
&lt;/textarea&gt; &lt;p&gt;Questa nuova versione &amp;egrave; se possibile anche pi&amp;ugrave; semplice rispetto alla precedente, in particolare la scansione degli assembly &amp;egrave; ora desicamente pi&amp;ugrave; lineare. Come nella versione precedente si esaminano tutti i tipi definiti nell&amp;rsquo;assembly e per sapere se il tipo esaminato deve essere caricato &amp;egrave; sufficiente utilizzare il metodo &lt;em&gt;IsDefined() &lt;/em&gt;della classe Type che permette di controllare se il tipo &amp;egrave; stato decorato con un particolare attributo. Per identificare i plugin basta quindi cercare un attributo di tipo PluginAttribute e in caso positivo inserirlo nell&amp;rsquo;apposito dictionary creando il corrispondente PluginInfo().&lt;/p&gt;&lt;p&gt;Il gestore fornisce due soli metodi per interagire con l&amp;rsquo;esterno, &lt;em&gt;GetPluginListForInterface() &lt;/em&gt;restituisce una lista di PluginAttribute contenente tutti i plugin che implementano una determinata interfaccia, mentre &lt;em&gt;CreateInstance&amp;lt;T&amp;gt;() &lt;/em&gt;permette di creare un&amp;rsquo;istanza di plugin passando il corrispondente PluginAttribute.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;public PluginList GetPluginListForInterface(
	String intefaceName) {
	PluginList result = new PluginList();
	foreach (LoadedPlugin plugin in mLoadedPlugins) {
		if (plugin.Value.ImplementInterface(intefaceName))
			result.Add(plugin.Key); 
		}
	return result;
}
public T CreateInstance&amp;lt;T&amp;gt;( 
	PluginAttribute info) {
	return (T) Activator.CreateInstance(mLoadedPlugins[info].PluginType); 
}
&lt;/textarea&gt; &lt;p&gt;Come si pu&amp;ograve; vedere la creazione di nuove istanze viene fatta utilizzando l&amp;rsquo;oggetto Activator che chiama il costruttore di default dell&amp;rsquo;oggetto, come si pu&amp;ograve; vedere l&amp;rsquo;implementazione &amp;egrave; decisamente semplice e facile da gestire.&lt;/p&gt;&lt;div class="subHeading"&gt;Cosa cambia lato client&lt;/div&gt;&lt;p&gt;Questi cambiamenti non complicano assolutamente il codice lato client. Il programma di esempio &amp;egrave; costituito infatti dalla solita combobox con cui si seleziona il plugin da utilizzare e in aggiunta viene inserito un controllo PropertyGrid che permette di visualizzare tutti i dati dei plugin caricati. &lt;/p&gt;&lt;p&gt;Nell&amp;rsquo;evento FormLoad viene creata l&amp;rsquo;istanza del gestore passando la cartella contenente i plugin. Un client pi&amp;ugrave; efficace dovrebbe tenere una singola istanza del gestore con un pattern di tipo singleton, ma questo esercizio &amp;egrave; lasciato al lettore. La creazione di un PluginManager &amp;egrave; infatti piuttosto onerosa dato che internamente si utilizzano numerosi metodi di reflection.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;private PluginManager mPluginManager = null;
private void Form1_Load(object sender, EventArgs e) {
			
	mPluginManager = new PluginManager(pluginDir);
	comboBox1.DataSource = mPluginManager.GetPluginListForInterface(interfaceName);			
}
&lt;/textarea&gt; &lt;p&gt;Per visualizzare la lista dei plugin &amp;egrave; sufficiente impostare il DataSource della ComboBox che automaticamente chiama il metodo ToString() per ogni oggetto della lista, mostrando di fatto la descrizione dell&amp;rsquo;attributo. Tramite la gestione dell&amp;rsquo;evento SelectedIndexChanged viene invece aggiornata la visualizzazione sulla PropertyGrid.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
	pgPluginDetail.SelectedObject = comboBox1.SelectedValue;
}
&lt;/textarea&gt; &lt;p&gt;Infine la pressione del bottone crea un&amp;rsquo;istanza del plugin ed invoca il suo unico metodo Greet(). Anche in questo caso l&amp;rsquo;interfaccia generica consente di scrivere codice senza cast ed inoltre, dato che il metodo CreateInstance accetta un PluginAttribute, &amp;egrave; sufficiente passare il parametro comboBox1.SelectedValue.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;private void button1_Click(object sender, EventArgs e) {
	ProgramInterfaces.IGreeter greeter;
	greeter = mPluginManager.CreateInstance&amp;lt;ProgramInterfaces.IGreeter&amp;gt;((PluginAttribute) comboBox1.SelectedValue);
	MessageBox.Show(greeter.Greet());
}
&lt;/textarea&gt; &lt;p&gt;Come si pu&amp;ograve; notare utilizzare il gestore &amp;egrave; veramente immediato ed efficace e richiede poche linee di codice.&lt;/p&gt;&lt;div class="subHeading"&gt;Implementare un plugin&lt;/div&gt;&lt;p&gt;L&amp;rsquo;ultimo cambiamento rispetto all&amp;rsquo;esempio precedente riguarda i plugin, che per poter essere caricati debbono ora essere compilati con gli appositi attributi, ecco ad esempio l&amp;rsquo;implementazione dell&amp;rsquo;EducatedGreeter.&lt;/p&gt;&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;[Plugin(&amp;quot;Educated Greeter&amp;quot;, &amp;quot;DotNetMarche&amp;quot;, &amp;quot;2.0&amp;quot;, &amp;quot;Plugin that greets in formal way.&amp;quot;)]
[PluginInterface(&amp;quot;ProgramInterfaces.IGreeter&amp;quot;)]
public class EducatedGreeter : ProgramInterfaces.IGreeter  {
	public String Greet() {
		return &amp;quot;Hello Mister!&amp;quot;;
	}
}
&lt;/textarea&gt; &lt;p&gt;Come si pu&amp;ograve; vedere sono presenti due attributi, il primo imposta le informazioni base sul plugin ed il secondo indica l&amp;rsquo;interfaccia implementata. &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div class="mainAuthor"&gt;&lt;p&gt;Biografia: &lt;a href="http://dotnetmarche.org/user/Profile.aspx?UserID=2105"&gt;http://dotnetmarche.org/user/Profile.aspx?UserID=2105&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=1459" width="1" height="1"&gt;</description><enclosure url="http://dotnetmarche.org/blogs/article/attachment/1459.ashx" length="32013" type="application/x-zip-compressed" /><category domain="http://dotnetmarche.org/blogs/article/archive/tags/Framework/default.aspx">Framework</category></item><item><title>Personalizzare i log di ELMAH</title><link>http://dotnetmarche.org/blogs/article/archive/2007/01/16/Personalizzare-i-log-di-ELMAH.aspx</link><pubDate>Tue, 16 Jan 2007 08:42:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:1398</guid><dc:creator>Alkampfer</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://dotnetmarche.org/blogs/article/rsscomments.aspx?PostID=1398</wfw:commentRss><comments>http://dotnetmarche.org/blogs/article/archive/2007/01/16/Personalizzare-i-log-di-ELMAH.aspx#comments</comments><description>
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
 &lt;div class="wlWriterSmartContent" id="57DB9511-4ED8-456d-8E06-AF9EC0A0BF46:90821795-93b3-4a81-ad2e-0ee07a163ec1" style="margin:0px;padding:0px;display:inline;"&gt;
  
    

    
      &lt;div class="mainAuthor"&gt;
      
&lt;p&gt;Di:  
						Ricci Gian Maria&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="subTitle"&gt;
      
&lt;p&gt;ELMAH &amp;egrave; un prodotto open source e completamente freeware per gestire il log automatico degli errori nelle proprie applicazioni ASP.Net. Grazie a questo tool &amp;egrave; possibile individuare e correggere tempestivamente gli errori delle proprie applicazioni web una volta in produzione.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="Normal"&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="subHeading"&gt;ELMAH&lt;/div&gt;
&lt;p&gt;Il modulo di gestione delle eccezioni &lt;em&gt;ELMAH&lt;/em&gt; ha il grande vantaggio di essere sia un buon prodotto, sia di essere open source e quindi liberamente utilizzabile ed estendibile per le proprie necessit&amp;agrave;. Essenzialmente &amp;egrave; un modulo di log degli errori composto da un &lt;em&gt;HttpModule&lt;/em&gt; che intercetta ogni errore non gestito e crea un log pieno di informazioni il quale viene poi passato ad uno o pi&amp;ugrave; oggetti dispatcher che spostano le informazioni nelle destinazioni scelte. Attualmente ci sono due implementazioni: una salva su un normale database SqlServer, l&amp;rsquo;altra invia l&amp;rsquo;errore per posta per avere la massima rapidit&amp;agrave; di risposta.&lt;/p&gt;

&lt;p&gt;Questo tool &amp;egrave; particolarmente utile perch&amp;eacute; nel caso di web application quando si genera un errore non &amp;egrave; possibile contattare il navigatore che lo ha generato per chiedergli informazioni ed &amp;egrave; necessario quindi sia tracciare l&amp;rsquo;errore, sia effettuare il log di quante pi&amp;ugrave; informazioni possiamo per poter diagnosticare il problema.&lt;/p&gt;

&lt;p&gt;Il setup di questo tool &amp;egrave; minimale, basta refenziare la dll ed aggiungere alcune opzioni nel &lt;em&gt;web.config&lt;/em&gt;, nel progetto di esempio &amp;egrave; tra l&amp;rsquo;altro accluso un web.config dimostrativo che mostra le voci da inserire. La cosa che attira di pi&amp;ugrave; &amp;egrave; che &amp;egrave; comunque possibile aggiungere informazioni a quelle standard, opzione utilissima se si necessita di memorizzare informazioni critiche pertinenti solo al proprio applicativo web.&lt;/p&gt;

&lt;p&gt;Per aiutare nelle operazioni di personalizzazione qui di seguito verr&amp;agrave; fatta una breve panoramica su come aggiungere alle informazioni standard anche un dump completo delle variabili di sessione. L&amp;rsquo;esempio non contiene codice perch&amp;eacute; preferisco che scarichiate il prodotto sul sito originale per correttezza verso l&amp;rsquo;autore. Le modifiche verranno presentate indicando in che punti della libreria agire e sono di cos&amp;igrave; facile comprensione che la mancanza del codice di esempio non influisce sulla comprensione. &lt;/p&gt;
&lt;div class="subHeading"&gt;Aggiungere informazioni sulla sessione&lt;/div&gt;
&lt;p&gt;Uno dei maggiori pregi di elmah &amp;egrave; che &amp;egrave; molto facile aggiungere informazioni a quelle di base che vengono memorizzate per ogni eccezione intercettata. Nel database infatti esiste un campo xml dove il modulo va a inserire tutti i dati dell&amp;rsquo;errore, in questo modo la struttura del database non deve essere modificata se vogliamo aggiungere informazioni addizionali che vanno invece inserite nel campo XML dell&amp;rsquo;errore stesso. In questo piccolo articolo si mostrer&amp;agrave; dove agire per aggiungere alle informazioni anche un dump completo delle variabili di sessione, opzione che non &amp;egrave; stata inserita tra le funzionalit&amp;agrave; base di Elmah e che io ritengo invece molto importante.&lt;/p&gt;

&lt;p&gt;Ogni informazione aggiuntiva per un log deve essere mantenuta dentro un oggetto di tipo NameValueCollection e tutte le modifiche al codice da fare riguardano solamente il file &lt;em&gt;Error.cs&lt;/em&gt;, rendendo la customizzazione un operazione veramente banale. La prima cosa da fare &amp;egrave; aggiungere una variabile di tipo NameValueCollection per ogni gruppo di informazioni aggiuntive che si desidera memorizzare. Il posto pi&amp;ugrave; corretto dove impostare questi dati &amp;egrave; in calce alla dichiarazione dei gruppi gi&amp;agrave; presenti.&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;private NameValueCollection _serverVariables;
private NameValueCollection _queryString;
private NameValueCollection _form;
private NameValueCollection _cookies;
//Modifica
private NameValueCollection _sessionVariables;
&lt;/textarea&gt;
&lt;p&gt;Una volta che il contenitore &amp;egrave; stato creato basta inserire i dati richiesti nel costruttore della classe Error, per correttezza sempre nello stesso punto dove la libreria imposta le informazioni base.&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;_serverVariables	= CopyCollection(request.ServerVariables);
_queryString		= CopyCollection(request.QueryString);
_form					= CopyCollection(request.Form);
_cookies				= CopyCollection(request.Cookies);
_sessionVariables = CopyCollection(context.Session);
&lt;/textarea&gt;
&lt;p&gt;Naturalmente la funzione CopyCollection non accetta una sessione come argomento, per questa ragione &amp;egrave; necessario scrivere una propria implementazione che inserisca tutte le informazioni necessarie, nel nostro caso il timeout della sessione, il suo Id e di seguito tutte le variabili.&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;private NameValueCollection CopyCollection(System.Web.SessionState.HttpSessionState session) {
  if (session == null || session.Count == 0) 
  {
    return null;
  }
  NameValueCollection copy = new HttpValuesCollection();
  copy.Add(&amp;quot;Session Timeout&amp;quot;, session.Timeout.ToString());
  copy.Add(&amp;quot;Session LCID&amp;quot;, session.LCID.ToString());
  for (int i = 0; i &amp;lt; session.Count; i++) 
  {
    copy.Add(session.Keys&lt;img src="http://dotnetmarche.org/emoticons/emotion-55.gif" alt="Idea" /&gt;, session&lt;img src="http://dotnetmarche.org/emoticons/emotion-55.gif" alt="Idea" /&gt;.ToString());
  }
	return copy;
}
&lt;/textarea&gt;
&lt;p&gt;A questo punto &amp;egrave; necessario intervenire anche su altre funzioni affinch&amp;eacute; elmah sia in grado di serializzare da e nell&amp;rsquo;xml il contenuto delle informazioni aggiuntive, il primo passo &amp;egrave; aggiungere alla &lt;em&gt;WriteInnerXml()&lt;/em&gt; la serializzazione delle informazioni appena aggiunte&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;...
WriteCollection(writer, &amp;quot;cookies&amp;quot;, _cookies);
WriteCollection(writer, &amp;quot;Session&amp;quot;, _sessionVariables);
&lt;/textarea&gt;
&lt;p&gt;Per quanto riguarda la deserializzazione &amp;egrave; necessario invece modificare la routine &lt;em&gt;ReadInnerXml() &lt;/em&gt;al cui interno si trova un&amp;rsquo;istruzione &lt;em&gt;switch &lt;/em&gt;che in base al nome del nodo ripristina l&amp;rsquo;oggetto NameValueCollection corretto.&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;switch (reader.LocalName) 
{
  ...
  case &amp;quot;cookies&amp;quot;: collection = this.Cookies; break;
  case &amp;quot;Session&amp;quot;: collection = this.Session; break;
  default: return;
&lt;/textarea&gt;
&lt;p&gt;Tutto il contenuto della collection session &amp;egrave; ora presente nel log e viene salvato correttamente nel database.&lt;/p&gt;

&lt;p&gt;A questo punto &amp;egrave; naturalmente necessario modificare anche il codice che genera la pagina di visualizzazione in modo che mostri anche le nuove informazioni memorizzate. In questo caso il file da modificare &amp;egrave; &lt;em&gt;ErrorDetailPage.cs &lt;/em&gt;e precisamente deve essere editato alla fine della funzione &lt;em&gt;RenderError() &lt;/em&gt;che nella versione base di ELMAH mostra solamente le informazioni aggiuntive delle variabili di applicazione. Se si vuole mostrare ogni info aggiuntiva basta aggiungere il seguente codice&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;RenderCollection(writer, error.Session, &amp;quot;Session&amp;quot;, &amp;quot;Session Data&amp;quot;);
RenderCollection(writer, error.QueryString, &amp;quot;QueryString&amp;quot;, &amp;quot;QueryString Data&amp;quot;);
RenderCollection(writer, error.QueryString, &amp;quot;Form&amp;quot;, &amp;quot;Form Data&amp;quot;);
RenderCollection(writer, error.Cookies, &amp;quot;Cookies&amp;quot;, &amp;quot;Cookies Data&amp;quot;);
RenderCollection(writer, error.ServerVariables, &amp;quot;ServerVariables&amp;quot;, &amp;quot;Server Variables&amp;quot;);
&lt;/textarea&gt;
&lt;p&gt;Come si pu&amp;ograve; vedere la funzione &lt;em&gt;RenderCollection() &lt;/em&gt;si occupa della generazione dell&amp;rsquo;html e quindi &amp;egrave; particolarmente facile visualizzare le informazioni aggiuntive. &lt;/p&gt;

&lt;p&gt;Con poche righe di codice &amp;egrave; possibile quindi estendere la struttura base di ELMAH in modo da tracciare informazioni personalizzate che possono aiutare ad individuare pi&amp;ugrave; rapidamente la causa dell&amp;rsquo;errore.  &lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
    &lt;div class="mainAuthor"&gt;
      
&lt;p&gt;
						Biografia:
						&lt;a href="http://dotnetmarche.org/user/Profile.aspx?UserID=2105"&gt;http://dotnetmarche.org/user/Profile.aspx?UserID=2105&lt;/a&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=1398" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Alcune considerazioni sul cache di pagina</title><link>http://dotnetmarche.org/blogs/article/archive/2006/11/14/Acune-considerazioni-sul-cache-di-pagina.aspx</link><pubDate>Mon, 13 Nov 2006 23:24:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:1045</guid><dc:creator>Alkampfer</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://dotnetmarche.org/blogs/article/rsscomments.aspx?PostID=1045</wfw:commentRss><comments>http://dotnetmarche.org/blogs/article/archive/2006/11/14/Acune-considerazioni-sul-cache-di-pagina.aspx#comments</comments><description>&lt;div class="wlWriterSmartContent" id="57DB9511-4ED8-456d-8E06-AF9EC0A0BF46:b67fa6a7-c2ad-448f-9703-e53b9ea33d96" style="margin:0px;padding:0px;display:inline;"&gt;

    &lt;div class="mainAuthor"&gt;
&lt;p&gt;Di: 	Ricci Gian Maria&lt;/p&gt;
    &lt;/div&gt;
&lt;div class="subTitle"&gt;
&lt;p&gt;Un adeguato caching permette di aumentare le prestazioni di un sito Asp.NET in maniera considerevole, in particolare la cache di pagina &amp;egrave; la tecnica che d&amp;agrave; i maggiori risultati, ma se non la si conosce a fondo si potrebbe rimanere sorpresi da alcuni comportamenti.&lt;/p&gt;
&lt;/div&gt;&lt;div class="Normal"&gt;&lt;div class="subHeading"&gt;Cache di pagina&lt;/div&gt;
&lt;p&gt;La cache di pagina viene impostata con la direttiva di pagina &lt;em&gt;OutputCache &lt;/em&gt;ed &amp;egrave; particolarmente efficiente, perch&amp;eacute; permette al motore Asp.NET di riutilizzare l&amp;rsquo;html generato da una richiesta precedente senza eseguire nemmeno una riga di codice. Questa tecnica non &amp;egrave; per&amp;ograve; priva di effetti collaterali, che debbono essere accuratamente esaminati per capire se effettivamente si pu&amp;ograve; applicare alle proprie pagine e/o controlli. Si prenda ad esempio la pagina &lt;em&gt;page1.aspx &lt;/em&gt;contenuta nel codice accluso che contiene una semplice gridView collegata alla tabella customer del database northwind. L&amp;rsquo;unica particolarit&amp;agrave; &amp;egrave; la presenza di una colonna template che contiene un bottone il cui scopo &amp;egrave; cancellare un cliente dal database.&lt;/p&gt;
&lt;textarea class="xhtml:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;asp:TemplateField&amp;gt;
  &amp;lt;ItemTemplate&amp;gt;
    &amp;lt;asp:Button 
       ID=&amp;quot;DeleteButton&amp;quot; 
       CommandName=&amp;quot;DeleteRow&amp;quot; 
       CommandArgument=&amp;#39;&amp;lt;%# DataBinder.Eval(Container.DataItem, &amp;quot;CustomerID&amp;quot;) %&amp;gt;&amp;#39;
       Text=&amp;quot;Delete&amp;quot; 
       runat=&amp;quot;Server&amp;quot; /&amp;gt;
  &amp;lt;/ItemTemplate&amp;gt;
&amp;lt;/asp:TemplateField&amp;gt;
&lt;/textarea&gt; 
&lt;p&gt;Nell&amp;rsquo;esempio accluso la routine non effettua veramente la cancellazione ma indica semplicemente in una label l&amp;rsquo;id cliente che sarebbe stato cancellato, in questo modo non si alterano i dati nel database e l&amp;rsquo;esempio non perde di validit&amp;agrave;.&lt;/p&gt;
&lt;textarea class="vb.net:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) Handles GridView1.RowCommand
      Label1.Text = &amp;quot;Cancello elemento ID: &amp;quot; &amp;amp; e.CommandArgument
End Sub
&lt;/textarea&gt; 
&lt;p&gt;La pagina ha quindi un funzionamento molto semplice, vediamo ora cosa succede se si abilita la cache.&lt;/p&gt;
&lt;div class="subHeading"&gt;Abilitare la cache di pagina&lt;/div&gt;
&lt;p&gt;Sempre nell&amp;rsquo;esempio accluso, la pagina &lt;em&gt;page2.aspx&lt;/em&gt; contiene lo stesso codice visto in precedenza, con la semplice aggiunta della direttiva di abilitazione della cache&lt;/p&gt;
&lt;textarea class="xhtml:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;%@ OutputCache Duration=&amp;quot;60&amp;quot; VaryByParam=&amp;quot;none&amp;quot; %&amp;gt;
&lt;/textarea&gt; 
&lt;p&gt;Se si esegue la pagina si nota per&amp;ograve; che alla prima pressione del bottone il comportamento &amp;egrave; quello corretto e viene indicata la richiesta di cancellazione, ma alle pressioni successive non accade nulla e se si mette un breakpoint in modalit&amp;agrave; debug si pu&amp;ograve; verificare che la routine &lt;em&gt;GridView1_RowCommand&lt;/em&gt; viene chiamata solamente la prima volta.&lt;/p&gt;
&lt;p&gt;Chi conosce bene la cache di pagina non rimarr&amp;agrave; sorpreso da questo comportamento, ma analizziamo comunque in dettaglio cosa succede per avere un quadro della situazione.&lt;/p&gt;
Alla prima richiesta il server &lt;strong&gt;non ha la pagina in cache&lt;/strong&gt;, viene quindi generata la pagina in modo normale e l&amp;rsquo;html risultante viene salvato nella cache. Alla prima pressione di un bottone la richiesta arriva al server, anche questa volta viene controllata la cache di pagina e &lt;strong&gt;nuovamente si ha un cache miss perch&amp;eacute; questa volta la richiesta &amp;egrave; in POST&lt;/strong&gt; mentre precedentemente era in get. Alle successive pressioni del tasto la pagina viene trovata in cache, viene quindi restituito al chiamante l&amp;rsquo;html contenuto nella cache e &lt;strong&gt;nessun evento viene generato&lt;/strong&gt; perch&amp;eacute; non viene nemmeno creata un&amp;rsquo;istanza della classe che gestisce la pagina 
&lt;p&gt;Questo tipo di cache pu&amp;ograve; quindi aumentare di molto le prestazioni di un&amp;rsquo;applicazione Asp.NET perch&amp;eacute; evita completamente l&amp;rsquo;esecuzione di codice. Si consideri inoltre che la cache &amp;egrave; abilitabile anche per i singoli controlli utente e quindi &amp;egrave; possibile effettuare cache parziale del contenuto di una pagina.&lt;/p&gt;
&lt;p&gt;Purtroppo nel caso in cui si richieda un comportamento dinamico, come nell&amp;rsquo;esempio appena mostrato, questa tecnica non &amp;egrave; apparentemente utilizzabile perch&amp;eacute; purtroppo elimina la chiamata dei metodi lato server che eseguono logica di business.&lt;/p&gt;
&lt;div class="subHeading"&gt;Forzare l&amp;rsquo;esecuzione della pagina indipendentemente dalla cache&lt;/div&gt;
&lt;p&gt;Supponiamo che la pagina precedente venga utilizzata per il 99.99% delle volte in modalit&amp;agrave; sola lettura e solo in rarissimi casi venga richiesta una cancellazione. In questo scenario il cache di pagina &amp;egrave; legittimo, bisogna solamente trovare il modo di forzare un cache miss alla pressione di un bottone. Naturalmente per pagine fortemente interattive questa tecnica non &amp;egrave; assolutamente efficiente, perch&amp;eacute; si genererebbero troppe versioni nella cache e sarebbe quindi consigliabile adottare altre strategie di caching. &lt;/p&gt;
&lt;p&gt;La direttiva OutputCache permette di indicare come viene indicizzata la cache tramite vari attributi come &lt;em&gt;varyByParam&lt;/em&gt;, &lt;em&gt;varyByControl&lt;/em&gt; etc, ed &amp;egrave; proprio su questi che si deve agire per forzare un cache miss in maniera programmatica. In particolare il varyByParam permette di specificare come chiavi di indicizzazione nomi di parametri in GET o in POST. Supponiamo quindi di aggiungere la linea&lt;/p&gt;
&lt;textarea class="xhtml:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;VaryByParam=&amp;rdquo;param&amp;rdquo;
&lt;/textarea&gt; 
&lt;p&gt;Alla direttiva OutputCache. In questo caso se la pagina viene chiamata con &lt;strong&gt;&lt;em&gt;page2.aspx?param=1 &lt;/em&gt;&lt;/strong&gt;il motore di asp.net indicizzer&amp;agrave; l&amp;rsquo;output nella cache con il valore param=1. Se una successiva richiesta viene fatta ad esempio con &lt;strong&gt;&lt;em&gt;page2.aspx?param=2 &lt;/em&gt;&lt;/strong&gt;il risultato &amp;egrave; un cache miss e l&amp;rsquo;output viene inserito a fianco del precedente, indicizzato con il valore param=2. In questo scenario &amp;egrave; importante capire che per ogni differente combinazione dei parametri indicati viene mantenuta nel server una versione della pagina in cache.&lt;/p&gt;
&lt;p&gt;Il nostro problema &amp;egrave; comunque differente, quello che si desidera &amp;egrave; abilitare la cache, ma far si che alla pressione di determinati bottoni si abbia sempre un cache miss, perch&amp;eacute; siamo interessati all&amp;rsquo;esecuzione del codice lato server associato al bottone stesso. Almeno apparentemente non esiste per&amp;ograve; una direttiva varyByXxx che permetta di indicare ad asp.NET uno o pi&amp;ugrave; bottoni che invalidano la cache, ma il problema pu&amp;ograve; essere aggirato in maniera molto semplice.&lt;/p&gt;
&lt;p&gt;La soluzione &amp;egrave; contenuta nella &lt;em&gt;page3.aspx&lt;/em&gt;, se la si manda in esecuzione si pu&amp;ograve; vedere come sia stata aggiunta una label che riporta l&amp;rsquo;ora di generazione della pagina, necessaria per verificare che effettivamente le pagine siano nuovamente rigenerate e non prese dalla cache. Aprendo un secondo browser e navigando allo stesso indirizzo si pu&amp;ograve; notare come l&amp;rsquo;ora restituita sia quella del primo caricamento, questo banale esperimento ci mostra che la cache &amp;egrave; effettivamente funzionante. La differenza &amp;egrave; che questa volta i bottoni funzionano correttamente ed il codice dell&amp;rsquo;handler viene eseguito ad ogni click. &lt;/p&gt;
&lt;p&gt;Il trucco &amp;egrave; veramente banale, prima di tutto &amp;egrave; stato inserito un &lt;em&gt;HiddenField&lt;/em&gt; di nome forcePostBack il cui valore iniziale &amp;egrave; un guid, e poi la cache &amp;egrave; stata impostata in modo da variare sulla base del contenuto di questo controllo. Se si vuole che alla pressione di un bottone sia sempre eseguito il codice del corrispettivo handler &amp;egrave; sufficiente cambiare il contenuto dell&amp;rsquo;hiddenField con un altro valore prima di effettuare il postback, assicurandosi chiaramente che questo valore sia univoco. Per ottenere un nuovo guid ad ogni pressione di un bottone &amp;egrave; indubbiamente vantaggioso generare direttamente lato server il codice javascript associato all&amp;rsquo;evento OnClientClick di ogni bottone. Ecco ad esempio come vengono creati i bottoni della gridView.&lt;/p&gt;
&lt;textarea class="xhtml:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;asp:TemplateField&amp;gt;
  &amp;lt;ItemTemplate&amp;gt;
    &amp;lt;asp:Button 
       ID=&amp;quot;DeleteButton&amp;quot; 
       CommandName=&amp;quot;DeleteRow&amp;quot; 
       ...
&lt;/textarea&gt; 
&lt;p&gt;Nello snippet &amp;egrave; stato evidenziato come l&amp;rsquo;unica aggiunta sia l&amp;rsquo;attributo &lt;em&gt;OnClientClick&lt;/em&gt; il cui contenuto &amp;egrave; impostato da una funzione lato server chiamata ForcePostbackJs(). &lt;/p&gt;
&lt;textarea class="vb.net:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;Private newguid As Guid
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  newguid = Guid.NewGuid
  Label2.Text = &amp;quot;Generazione pagina A:&amp;quot; &amp;amp; Now.ToString
End Sub
   
Protected Function ForcePostbackJs() As String
  Return &amp;quot;BLOCKED SCRIPT forcePostback.value=&amp;#39;&amp;quot; &amp;amp; Guid.NewGuid.ToString &amp;amp; &amp;quot;&amp;#39;;return true;&amp;quot;
End Function
&lt;/textarea&gt; 
&lt;p&gt;Come si pu&amp;ograve; vedere ad ogni evento load la pagina genera un nuovo guid e alla pressione del bottone si associa un javascript che imposta il contenuto dell&amp;rsquo;hiddenfield al nuovo guid generato. In questo modo si ha la sicurezza che ad ogni pressione di un bottone il nuovo valore dell&amp;rsquo;hidden field sia univoco e generi sempre un cache miss.&lt;/p&gt;
&lt;p&gt;Il quadro non &amp;egrave; per&amp;ograve; ancora completo, se si inserisce la vera logica di cancellazione, dopo la pressione del bottone alle successive richieste della pagina verrebbe comunque restituita la versione contenuta nella in cache, in cui &amp;egrave; ancora presente l&amp;rsquo;elemento cancellato. In generale infatti se la pressione di un bottone provoca l&amp;rsquo;esecuzione di logica di business che modifica i dati sulla base dei quali &amp;egrave; generata la pagina, tutte le precedenti versioni in cache non sono pi&amp;ugrave; valide. La soluzione &amp;egrave; quindi invalidare la cache di pagina in maniera programmatica, inserendo l&amp;rsquo;istruzione seguente nell&amp;rsquo;handler del bottone&lt;/p&gt;
&lt;textarea class="vb.net:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;HttpResponse.RemoveOutputCacheItem(&amp;quot;/Example/Page3.aspx&amp;quot;)&lt;/textarea&gt; 
&lt;p&gt;In questo modo ogni volta che viene eseguita logica di business tutta la cache della pagina Page3.aspx viene invalidata e le successive richieste visualizzeranno dati corretti.&lt;/p&gt;
&lt;div class="subHeading"&gt;Conclusioni&lt;/div&gt;
&lt;p&gt;La cache di pagina &amp;egrave; una tecnica che permette di ottenere grandi incrementi di prestazioni per pagine statiche o che contengono piccole porzioni dinamiche, purtroppo &amp;egrave; necessario ricorrere a piccoli &amp;ldquo;trucchi&amp;rdquo; se si vuole che la logica lato server risponda sempre agli eventi utente. In generale comunque la possibilit&amp;agrave; di abilitare questa forma di caching anche per i singoli controlli la rende indubbiamente una tecnica di grande efficacia per le proprie applicazioni Asp.NET.&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=1045" width="1" height="1"&gt;</description><enclosure url="http://dotnetmarche.org/blogs/article/attachment/1045.ashx" length="5015" type="application/x-zip-compressed" /><category domain="http://dotnetmarche.org/blogs/article/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Creare un programma estendibile mediante plugin - Parte 1</title><link>http://dotnetmarche.org/blogs/article/archive/2006/10/30/Creare-un-programma-estendibile-mediante-plugin-_2D00_-Parte-1.aspx</link><pubDate>Mon, 30 Oct 2006 04:29:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:907</guid><dc:creator>Alkampfer</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://dotnetmarche.org/blogs/article/rsscomments.aspx?PostID=907</wfw:commentRss><comments>http://dotnetmarche.org/blogs/article/archive/2006/10/30/Creare-un-programma-estendibile-mediante-plugin-_2D00_-Parte-1.aspx#comments</comments><description>    &lt;div class="mainAuthor"&gt;
&lt;p&gt;Di: 	Ricci Gian Maria&lt;/p&gt;
    &lt;/div&gt;    
&lt;div class="subTitle"&gt;      
La tecnologia .NET consente di iniettare codice in maniera dinamica in un processo, rendendolo di fatto estendibile mediante unit&amp;agrave; di codice chiamate &lt;em&gt;plugin&lt;/em&gt;.
&lt;/div&gt;
&lt;div class="wlWriterSmartContent" id="57DB9511-4ED8-456d-8E06-AF9EC0A0BF46:81c6ad88-1f10-4d18-99e6-ea055b688b87" style="margin:0px;padding:0px;display:inline;"&gt;&lt;div class="subTitle"&gt;
    &lt;/div&gt;

    &lt;div class="subHeading"&gt;
&lt;p&gt;Minimizzare le dipendenze&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="Normal"&gt;
&lt;p&gt;Negli ultimi anni si &amp;egrave; molto studiato su come minimizzare le dipendenze tra gli oggetti, in modo da rendere le applicazioni molto pi&amp;ugrave; flessibili ed estendibili. Questo studio ha portato alla creazione di pattern particolari come quelli di Dependency Injection o Inversion of control, di cui il lettore pu&amp;ograve; trovare abbondanza di informazioni semplicemente tramite google. In questo articolo si vuole invece esaminare una tecnica particolare che permette non solo di minimizzare la dipendenza tra gli oggetti, ma anche di estendere un&amp;rsquo;applicazione senza ricompilare.&lt;/p&gt;

&lt;p&gt;Si consideri un semplicissimo esempio di un applicativo minimale che deve solamente salutare l&amp;rsquo;utente, sulla base del classico &lt;em&gt;hello world&lt;/em&gt;. Il programma &amp;egrave; costituito da una semplice classe chiamata &lt;strong&gt;standardGreeter&lt;/strong&gt; ed una form che esegue un semplice saluto alla pressione di un bottone&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;namespace Example1 
{
	class StandardGreeter 
	{
		public String Greet() 
		{
			return &amp;quot;hello!!&amp;quot;;
		}
	}
}
&amp;hellip;
//codice che gestisce il click del bottone.
private void btnGreet_Click(object sender, EventArgs e) 
{
	StandardGreeter sg = new StandardGreeter();
	MessageBox.Show(sg.Greet()); 
}
&lt;/textarea&gt;
&lt;p&gt;Il codice &amp;egrave; veramente banale, ma &amp;egrave; gi&amp;agrave; sufficiente per individuare una forte dipendenza con la classe StandardGreeter. Se ad esempio il nostro programma deve evolvere permettendo di eseguire un saluto pi&amp;ugrave; formale rispetto ad un semplice &lt;em&gt;hello!!&lt;/em&gt; si potrebbe semplicemente realizzare un&amp;rsquo;ulteriore versione della classe chiamata &lt;em&gt;FormalGreeter &lt;/em&gt;modificando contemporaneamente il codice dell&amp;rsquo;handler del bottone. &lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;namespace Example1 
{
	class FormalGreeter 
	{
		public String Greet() 
		{
			return &amp;quot;MoreFormalHello&amp;quot;;
		}
	}
}
&amp;hellip;
//codice che gestisce il click del bottone.
private void btnGreet_Click(object sender, EventArgs e) 
{
	FormalGreeter sg = new FormalGreeter();
	MessageBox.Show(sg.Greet()); 
}
&lt;/textarea&gt;
&lt;p&gt;Questo approccio ha un enorme punto debole, il codice eseguito alla pressione del bottone deve conosce il tipo concreto di classe da istanziare per chiamare il suo metodo Greet() e quindi dipende dal tipo di oggetto utilizzato. Per risolvere elegantemente questo tipo di problematiche si pu&amp;ograve; utilizzare un pattern di Abstract Factory, oppure utilizzare librerie come la Spring.NET per l&amp;rsquo;&lt;em&gt;Inversion of control&lt;/em&gt;, o contenitori come il picocontainer, etc etc. In questo articolo la soluzione proposta &amp;egrave; invece basata su plugin, una tecnica particolare per caricare dinamicamente il codice implementando cos&amp;igrave; un pattern di Inversion of Control.&lt;/p&gt;

&lt;div class="subHeading"&gt;Caricamento dinamico di codice&lt;/div&gt;
&lt;p&gt;Un plugin non &amp;egrave; altro che un blocco di codice che viene caricato a runtime dal programma per estendere il funzionamento base. Il primo requisito per poter creare un plugin &amp;egrave; definire la sua interfaccia, il programma host infatti non pu&amp;ograve; caricare arbitrarie parti di codice se poi non sa come utilizzarle e dunque il primo passo per poter gestire un plugin &amp;egrave; definirne l&amp;rsquo;interfaccia, proprio come se si stesse per realizzare una classica implementazione di Abstract Factory. Nell&amp;rsquo;esempio accluso &amp;egrave; stata definita a questo proposito l&amp;rsquo;interfaccia &lt;em&gt;IGreeter&lt;/em&gt; che comprende un&amp;rsquo;unica funzione e individua il contratto che deve essere implementato da un oggetto in grado di restituire un saluto. &lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;/// &amp;lt;summary&amp;gt;
/// Interfaccia per l&amp;#39;oggetto greeter
/// &amp;lt;/summary&amp;gt;
public interface IGreeter 
{
	String Greet();
}
&lt;/textarea&gt;
&lt;p&gt;La particolarit&amp;agrave; &amp;egrave; che l&amp;rsquo;interfaccia viene definita in un progetto esterno a quello principale. La ragione &amp;egrave; semplice dato che chi implementa un plugin deve avere un riferimento al progetto che contiene il contratto e quindi &amp;egrave; pi&amp;ugrave; logico che tutte le interfacce che possono essere implementate da plugin esterni si trovino in un assembly dedicato che pu&amp;ograve; essere cos&amp;igrave; referenziato da chiunque voglia scrivere un plugin.&lt;/p&gt;

&lt;p&gt;Nella solution di esempio si trovano infatti due implementazioni dell&amp;rsquo;interfaccia IGreeter, ognuna implementata in un differente assembly. Il progetto pi&amp;ugrave; interessante &amp;egrave; comunque il &lt;em&gt;PluginManager&lt;/em&gt; che contiene il codice per gestire il caricamento dinamico del codice. Dal punto di vista del programma principale un plugin &amp;egrave; una classe che implementa un interfaccia riconosciuta e contenuto in un assembly esterno sconosciuto in fase di compilazione. Durante l&amp;rsquo;esecuzione &amp;egrave; compito del PluginHandler scandire una particolare cartella in cui sono contenuti tutti i plugin al fine di identificare al suo interno tutti i tipi che implementano l&amp;rsquo;interfaccia richiesta ed occuparsi poi della creazione delle specifiche istanze. Il codice che effettua la scansione &amp;egrave; veramente semplice&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;public PluginManager( 
	String	pluginDirectory, 
	String	interfaceName) 
{
	ScanDirectory(pluginDirectory, interfaceName);
}
private void ScanDirectory( 
	String directoryName, 
	String interfaceName) 
{
	foreach (String fileName in System.IO.Directory.GetFiles(directoryName, &amp;quot;*.dll&amp;quot;)) 
	{
		AnalyzeAssemblyFile(fileName, interfaceName);
	}
}
private void AnalyzeAssemblyFile(
	String fileName, 
	String interfaceName) 
{
	try 
	{
		System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFrom(fileName);
		foreach (Type Ty in asm.GetTypes()) 
		{
			if (Ty.GetInterface(interfaceName) != null) 
			{
				mLoadedPlugins.Add(Ty.Name, new PluginInfo(Ty.Name, Ty));
			} 
		}
	} catch (Exception Ex) 
	{
		System.Diagnostics.Debug.WriteLine(Ex.Message);
	}
}
&lt;/textarea&gt;
&lt;p&gt;Come si pu&amp;ograve; vedere al costruttore dell&amp;rsquo;oggetto PluginManager viene semplicemente passata la cartella da esaminare e il nome dell&amp;rsquo;interfaccia cercata. La funzione che effettua tutto il lavoro si chiama &lt;em&gt;ScanDirectory()&lt;/em&gt; e itera semplicemente tra tutti i file con estensione dll presenti nella cartella invocando per ognuno di essi la funzione &lt;em&gt;AnalyzeAssemblyFile()&lt;/em&gt;, la quale non fa altro che tentare di caricare l&amp;rsquo;assembly in memoria, iterare in tutti i tipi contenuti e cercare con la funzione &lt;em&gt;GetInterface() &lt;/em&gt;i tipi che implementano l&amp;rsquo;interfaccia richiesta. Per ogni plugin trovato viene creato un nuovo oggetto &lt;strong&gt;PluginInfo&lt;/strong&gt; che viene poi inserito in un dizionario indicizzato con il nome del tipo stesso. L&amp;rsquo;oggetto PluginInfo mantiene infatti al suo interno tutte le informazioni sul plugin caricato; internamente la classe PluginInfo ha due sole propriet&amp;agrave;: il nome del plugin ed un riferimento al tipo di oggetto che lo implementa. Durante la creazione di un oggetto PluginInfo viene inoltre recuperato un riferimento al costruttore di default, utilizzato successivamente per creare nuove istanze.&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;public PluginInfo(
	String	name, 
	Type	pluginType) 
{		
	mPluginName = name;
	mPluginType = pluginType;
	mConstructorInfo = pluginType.GetConstructor(new Type[] {});
}
private ConstructorInfo mConstructorInfo; 
public object CreateInstance() 
{
	return mConstructorInfo.Invoke(new object[] {});
}
&lt;/textarea&gt;
&lt;p&gt;Come si pu&amp;ograve; notare il codice per gestire il plugin &amp;egrave; veramente minimale. Il programma chiamante &amp;egrave; anch&amp;rsquo;esso diverso dalla versione precedente, la form contiene infatti una combo in cui vengono listati tutti i plugin disponibili ed alla pressione del bottone viene utilizzato il greeter scelto dall&amp;rsquo;utente. Nel progetto incluso sono state inoltre aggiunte delle post build action ai due progetti in modo che, ad ogni compilazione, le dll con i plugin vengano inserite automaticamente nella sottocartella Plugins del programma principale.&lt;/p&gt;

&lt;p&gt;Per capire il vantaggio di questa tecnica si cancelli il file EducatedGreeter.dll dalla cartella plugins  e si esegua il programma; nella combo ora appare solamente lo StandardGreeter. A questo punto basta copiare nuovamente il file EducatedGreeter.dll nella cartella dei plugin, riavviare il programma e verificare che &amp;egrave; nuovamente possibile utilizzare entrambi i greeter, senza dover ricompilare nulla. Se in futuro sorger&amp;agrave; la necessit&amp;agrave; di un ulteriore Greeter non si deve fare altro che implementare un nuovo plugin e copiarlo nella cartella apposita.&lt;/p&gt;

&lt;div class="subHeading"&gt;Conclusioni&lt;/div&gt;
&lt;p&gt;L&amp;rsquo;utilizzo del caricamento dinamico di assembly e della reflection permette di implementare con veramente poche righe di codice una libreria che permette di gestire l&amp;rsquo;Inversion of Control con un ottica basata su caricamento dinamico di codice. Il programma finale &amp;egrave; infatti in grado di utilizzare i nuovi plugin senza necessit&amp;agrave; di dover ricompilare l&amp;rsquo;applicativo o modificare file di configurazione, &amp;egrave; sufficiente infatti copiare le nuove dll nella apposita cartella e &amp;ldquo;l&amp;rsquo;iniezione&amp;rdquo; del nuovo codice &amp;egrave; completamente automatica.&lt;/p&gt;
&lt;/div&gt;
    &lt;div class="mainAuthor"&gt;
      
&lt;p&gt;
						Biografia:
						&lt;a href="http://dotnetmarche.org/user/Profile.aspx?UserID=2105"&gt;http://dotnetmarche.org/user/Profile.aspx?UserID=2105&lt;/a&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt; &lt;div class="wlWriterSmartContent" id="57DB9511-4ED8-456d-8E06-AF9EC0A0BF46:a3632a25-3973-45d0-acf2-9f3a9c25ee59" style="margin:0px;padding:0px;display:inline;"&gt;
  
    

    &lt;/div&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=907" width="1" height="1"&gt;</description><enclosure url="http://dotnetmarche.org/blogs/article/attachment/907.ashx" length="154213" type="application/zip" /><category domain="http://dotnetmarche.org/blogs/article/archive/tags/Framework/default.aspx">Framework</category></item><item><title>Alcune considerazioni sull'Atlas.UpdatePanel</title><link>http://dotnetmarche.org/blogs/article/archive/2006/09/21/Alcune-considerazioni-sull_2700_Atlas.UpdatePanel.aspx</link><pubDate>Thu, 21 Sep 2006 01:09:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:559</guid><dc:creator>Alkampfer</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://dotnetmarche.org/blogs/article/rsscomments.aspx?PostID=559</wfw:commentRss><comments>http://dotnetmarche.org/blogs/article/archive/2006/09/21/Alcune-considerazioni-sull_2700_Atlas.UpdatePanel.aspx#comments</comments><description> &lt;div class="wlWriterSmartContent" id="57DB9511-4ED8-456d-8E06-AF9EC0A0BF46:c08a3e16-538a-4642-8a7b-859f18ba4577" style="margin:0px;padding:0px;display:inline;"&gt;
  
    

    
  
    &lt;div class="mainAuthor"&gt;
      
&lt;p&gt;Di:  
						Ricci Gian Maria&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="subTitle"&gt;
      
&lt;p&gt;Il nuovo framework AJAX per ASP.NET 2.0 nonostante sia ancora in beta &amp;egrave; indubbiamente un prodotto molto interessante. In questo articolo verranno esposte alcune particolarit&amp;agrave; interessanti del controllo UpdatePanel che presenta comportamenti anomali in alcune situazioni.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="Normal"&gt;
&lt;div class="subHeading"&gt;Creare un controllo che fa uso di UpdatePanel&lt;/div&gt;
&lt;p&gt;L&amp;rsquo;UpdatePanel &amp;egrave; senza dubbio uno dei controlli pi&amp;ugrave; utili di Atlas, purtroppo per&amp;ograve; ci sono alcune particolarit&amp;agrave; che &amp;egrave; bene conoscere, per evitare di incappare in spiacevoli inconvenienti.&lt;/p&gt;

&lt;p&gt;Spesso l&amp;rsquo;UpdatePanel viene inserito all&amp;rsquo;interno di controlli utente. Nell&amp;rsquo;esempio accluso si pu&amp;ograve; infatti vedere che il &lt;em&gt;Controllo1.ascx&lt;/em&gt;, ha due semplici combo per effettuare una selezione a cascata racchiuse da un UpdatePanel, il cui scopo &amp;egrave; essenzialmente quello di impedire che ad ogni selezione tutta la pagina venga nuovamente renderizzata. &lt;/p&gt;

&lt;p&gt;Naturalmente la pagina ospitante (&lt;em&gt;Page1.aspx&lt;/em&gt;) deve contenere un controllo ScriptManager ed abilitare il PartialRendering affinch&amp;eacute; tutto funzioni correttamente. Purtroppo come si pu&amp;ograve; vedere eseguendo la &lt;em&gt;Page2.aspx&lt;/em&gt; se il controllo utente viene utilizzato all&amp;rsquo;interno di un controllo Wizard si generano errori javascript quando si effettua il postback della pagina. Spendendo un po&amp;rsquo; di tempo debuggando il javascript dell&amp;rsquo;Atlas si scopre che l&amp;rsquo;errore &amp;egrave; dovuto al fatto che il controllo Wizard renderizza nella pagina solamente i controlli del tab corrente. Purtroppo Atlas esaminando il codice sorgente della pagina nota che sono presenti due istanze del Controllo1.ascx ed quindi nella pagina sono effettivamente presenti due controlli UpdatePanel. Questo fa si che durante il postback il codice javascript si aspetta che la pagina contenga entrambi gli UpdatePanel, purtroppo per&amp;ograve; quello relativo al tab non attivo del Wizard non &amp;egrave; in realt&amp;agrave; presente nel DOM della pagina ed ecco la sorgente dell&amp;rsquo;errore.&lt;/p&gt;
&lt;div class="subHeading"&gt;Risolvere il problema del wizard&lt;/div&gt;
&lt;p&gt;La soluzione &amp;egrave; nel &lt;em&gt;Controllo2.ascx&lt;/em&gt; e consiste semplicemente nell&amp;rsquo;utilizzo corretti dei trigger degli UpdatePanel, in modo da indicare al motore javascript di Atlas di aggiornare l&amp;rsquo;UpdatePanel solamente quando la prima combo genera l&amp;rsquo;evento di cambio indice. In questo a runtime durante il postback causato da un controllo Atlas cerca di aggiornare solamente l&amp;rsquo;UpdatePanel per cui il trigger &amp;egrave; stato attivato, ignorando quindi gli UpdatePanel che non sono effettivamente presenti nella pagina. &lt;/p&gt;

&lt;p&gt;Purtroppo i problemi non sono finiti. Nella pagina Page4.aspx un altro bug si genera quando si tenta di creare dinamicamente da codice un&amp;rsquo;istanza del Controllo2.ascx.&lt;/p&gt;
&lt;textarea class="csharp:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;protected void Page_Load(object sender, EventArgs e) {
	Control dynCnt = Page.LoadControl(&amp;quot;~/Controllo2.ascx&amp;quot;);
	Panel1.Controls.Add(dynCnt);
}
&lt;/textarea&gt;
&lt;p&gt;Purtroppo anche in questo caso a runtime Atlas va in errore, questa volta per&amp;ograve; non si genera un errore javascript, ma viene mostrata un educata messagebox in cui l&amp;rsquo;utente &amp;egrave; avvertito del fatto che il nome del controllo utilizzato per il trigger non &amp;egrave; valido. Per capire l&amp;rsquo;origine di questo altro problema bisogna confrontare ci&amp;ograve; che viene renderizzato nel caso di controllo incluso a design time (page1.aspx) con il DOM della pagina dinamica. Nel caso di inclusione a design time in particolare ecco come viene renderizzata la prima dropDownList del controllo utente.&lt;/p&gt;
&lt;textarea class="xhtml:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;select name=&amp;quot;Controllo1_1$DropDownList1&amp;quot; onchange=&amp;quot;BLOCKED SCRIPTsetTimeout(&amp;#39;__doPostBack(\&amp;#39;Controllo1_1$DropDownList1\&amp;#39;,\&amp;#39;\&amp;#39;)&amp;#39;, 0)&amp;quot; id=&amp;quot;Controllo1_1_DropDownList1&amp;quot;&amp;gt;
	&amp;lt;option selected=&amp;quot;selected&amp;quot; value=&amp;quot;NessunaSelezione&amp;quot;&amp;gt;NessunaSelezione&amp;lt;/option&amp;gt;
	&amp;lt;option value=&amp;quot;Fiat&amp;quot;&amp;gt;Fiat&amp;lt;/option&amp;gt;
	&amp;lt;option value=&amp;quot;Ferrari&amp;quot;&amp;gt;Ferrari&amp;lt;/option&amp;gt;
	&amp;lt;option value=&amp;quot;Ford&amp;quot;&amp;gt;Ford&amp;lt;/option&amp;gt;
&amp;lt;/select&amp;gt;
&lt;/textarea&gt;
&lt;p&gt; Mentre ecco quello che appare nella pagina che include dinamicamente il controllo.&lt;/p&gt;
&lt;textarea class="xhtml:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;select name=&amp;quot;ctl02$DropDownList1&amp;quot; onchange=&amp;quot;BLOCKED SCRIPTsetTimeout(&amp;#39;__doPostBack(\&amp;#39;ctl02$DropDownList1\&amp;#39;,\&amp;#39;\&amp;#39;)&amp;#39;, 0)&amp;quot; id=&amp;quot;ctl02_DropDownList1&amp;quot;&amp;gt;
	&amp;lt;option selected=&amp;quot;selected&amp;quot; value=&amp;quot;NessunaSelezione&amp;quot;&amp;gt;NessunaSelezione&amp;lt;/option&amp;gt;
	&amp;lt;option value=&amp;quot;Fiat&amp;quot;&amp;gt;Fiat&amp;lt;/option&amp;gt;
	&amp;lt;option value=&amp;quot;Ferrari&amp;quot;&amp;gt;Ferrari&amp;lt;/option&amp;gt;
	&amp;lt;option value=&amp;quot;Ford&amp;quot;&amp;gt;Ford&amp;lt;/option&amp;gt;
&amp;lt;/select&amp;gt;
&lt;/textarea&gt;
&lt;p&gt;In questo caso molto probabilmente il motore javascript di Atlas quando esamina la struttura della pagina genera il javascript corrispondente considerando che i nomi dei controlli nel DOM vengano generati sempre con lo stesso criterio. Purtroppo per i controlli dinamici il nome del controllo segue una regola di denominazione differente e da qui l&amp;rsquo;errore, perch&amp;eacute; si cerca nel DOM il nome di un controllo inesistente.&lt;/p&gt;
&lt;div class="subHeading"&gt;Generare trigger dinamicamente&lt;/div&gt;
&lt;p&gt;Il problema precedente &amp;egrave; derivato dal trigger e se il ragionamento fatto in precedenza &amp;egrave; corretto la soluzione &amp;egrave; semplicemente generare dinamicamente tutti i trigger nell&amp;rsquo;evento PreRender del controllo utente. Questa accortezza permette di indicare in modo corretto l&amp;rsquo;id del controllo.&lt;/p&gt;
&lt;textarea class="c#:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;protected void Page_PreRender(object sender, EventArgs e) {
	Microsoft.Web.UI.ControlEventTrigger trigger;
	trigger = new Microsoft.Web.UI.ControlEventTrigger();
	trigger.ControlID = DropDownList1.ClientID;
	trigger.EventName = &amp;quot;SelectedIndexChanged&amp;quot;;
	UpdatePanel1.Triggers.Add(trigger);
}
&lt;/textarea&gt;
&lt;p&gt;Se si esegue un run della pagina in modalit&amp;agrave; debug si pu&amp;ograve; notare che il vero id del controllo &amp;egrave; &lt;code&gt;MyId_DropDownList1 &lt;/code&gt;e dato che questa volta siamo direttamente noi da codice che lo indichiamo per il trigger, il problema viene aggirato.&lt;/p&gt;
&lt;div class="subHeading"&gt;Un ulteriore considerazione&lt;/div&gt;
&lt;p&gt;Talvolta accade che abilitando il partial rendering si generino errori javascript in linee che non esistono tipo 8.329.456 e che non &amp;egrave; possibile debuggare. Questi errori sono quasi sempre generati da javascript incluso in modo non corretto nella pagina. Cos&amp;igrave; come Microsoft stessa spiega nel punto 9 del documento &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASPNETusStan.asp"&gt;Building Asp.NET2.0 web sites Using Web Standards&lt;/a&gt; non &amp;egrave; possibile includere codice javascript nella pagina XHTML senza particolari accortezze, perch&amp;eacute; potrebbe alterare la struttura del documento. In sostanza la pagina html deve essere un documento XML valido, ma se nel javascript si utilizzano segni come &amp;lt; e &amp;gt; la validit&amp;agrave; del documento XML cade. A questo punto, dato che &amp;egrave; impossibile utilizzare le sequenze di escape &lt;strong&gt;&amp;amp;lt;&lt;/strong&gt; &lt;strong&gt;&amp;amp;amp; &lt;/strong&gt;perch&amp;eacute; altrimenti il codice javascript non funzionerebbe, la soluzione &amp;egrave; includere tutto in una sezione CDATA. In sostanza Microsoft consiglia di inserire uno script in questo modo&lt;/p&gt;
&lt;textarea class="js:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
/* &amp;lt;![CDATA[ */
function isLess(a, b) {
  if (a &amp;lt; b)
    return true;
}
/* ]]&amp;gt; */
&amp;lt;/script&amp;gt;
&lt;/textarea&gt;
&lt;p&gt;Talvolta nemmeno questo funziona e gli errori javascript continuano a presentarsi, un approccio pi&amp;ugrave; conservativo &amp;egrave; invece il seguente&lt;/p&gt;
&lt;textarea class="js:nogutter:nocontrols" cols="60" name="code" rows="20"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
&amp;lt;!--//--&amp;gt;&amp;lt;![CDATA[//&amp;gt;&amp;lt;!--
function isLess(a, b) {
  if (a &amp;lt; b)
    return true;
}
//--&amp;gt;&amp;lt;!]]&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/textarea&gt;
&lt;p&gt;Includendo tutti gli script della pagina in apposite sezioni CDATA si &amp;egrave; certi che la struttura XML del documento verr&amp;agrave; preservata e ATLAS non generer&amp;agrave; strani errori durante il PartialRendering.&lt;/p&gt;
&lt;div class="subHeading"&gt;Conclusioni&lt;/div&gt;
&lt;p&gt;Atlas &amp;egrave; sicuramente uno dei prodotti pi&amp;ugrave; interessanti per ASP.NET 2.0; &amp;egrave; gratuito, &amp;egrave; Microsoft e promette grandi funzionalit&amp;agrave;. Nonostante questo non bisogna mai dimenticare che &amp;egrave; ancora un prodotto in beta ed &amp;egrave; quindi inevitabile incontrare nello sviluppo qualche piccolo ostacolo, che per&amp;ograve; pu&amp;ograve; sempre essere superato con un po&amp;rsquo; di pazienza e una buona sessione di debugging. &lt;/p&gt;
&lt;/div&gt;
    &lt;div class="biblio"&gt;
      
&lt;p class="subHeading"&gt;Bibliografia&lt;/p&gt;
      
&lt;p&gt;Sito ufficiale dell&amp;rsquo;&lt;a href="http://atlas.asp.net/Default.aspx?tabid=47"&gt;Atlas&lt;/a&gt;&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="mainAuthor"&gt;
      
&lt;p&gt;
						Biografia:
						&lt;a href="http://dotnetmarche.org/user/Profile.aspx?UserID=2105"&gt;http://dotnetmarche.org/user/Profile.aspx?UserID=2105&lt;/a&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=559" width="1" height="1"&gt;</description><enclosure url="http://dotnetmarche.org/blogs/article/attachment/559.ashx" length="27213" type="application/zip" /><category domain="http://dotnetmarche.org/blogs/article/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Appunti su Community Server</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/CommunityServer-Notes.aspx</link><pubDate>Thu, 06 Jul 2006 11:26:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:154</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://dotnetmarche.org/blogs/article/rsscomments.aspx?PostID=154</wfw:commentRss><comments>http://dotnetmarche.org/blogs/article/archive/2006/07/06/CommunityServer-Notes.aspx#comments</comments><description>&lt;strong&gt;Installazione&lt;br /&gt;
&lt;/strong&gt;Fare riferimento alla documentazione riportata su &lt;a href="http://docs.communityserver.org/"&gt;http://docs.communityserver.org/&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://docs.communityserver.org/"&gt;&lt;br /&gt;
&lt;strong&gt;Siti con tips e articoli&lt;br /&gt;
&lt;/strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;font face="Tahoma" size="2"&gt;&lt;a href="http://soup.co.za/weblog/archive/category/1002.aspx" title="blocked::http://soup.co.za/weblog/archive/category/1002.aspx"&gt;http://soup.co.za/weblog/archive/category/1002.aspx&lt;/a&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;a href="http://richmercer.com/archive/2006/05/27/94.aspx" title="blocked::http://richmercer.com/archive/2006/05/27/94.aspx"&gt;http://richmercer.com/archive/2006/05/27/94.aspx&lt;/a&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&amp;nbsp;  (aggiunta di campi custom)&lt;/span&gt;&lt;/font&gt;&lt;br /&gt;
&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;strong&gt;Riduzione grandezza css&lt;/strong&gt;&lt;br /&gt;
&lt;/span&gt;In alcuni css (Themes/default/style/Common.css e Themes/default/style/common_print.css) ci sono, alla fine del file, molte righe vuote, che contribuiscono per circa met&amp;agrave; della grandezza dei file (da 80k a 40k ognuno circa). E&amp;#39; bene eliminare queste righe vuote.&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;strong&gt;Gestione cache&lt;/strong&gt;&lt;br /&gt;
&lt;/span&gt;Di default &amp;egrave; attiva la cache, a causa della quale le modifiche ai contenuti e al layout del sito non vengono visualizzate immediatamente.&lt;br /&gt;
Per disabilitare la cache si deve impostare cacheFactor=&amp;quot;0&amp;quot; nel file communityserver.config. &lt;br /&gt;
Per decidere se tenere la cache abilitata o meno, bisogna fare delle prove: a causa di file delle impostazioni (config, css, ...) piuttosto corposi, probabilmente pu&amp;ograve; essere conveniente lasciare la cache attiva.&lt;br /&gt;
&lt;span style="font-weight:bold;"&gt;&lt;/span&gt;&lt;strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;strong&gt;Aggiunta di voci al men&amp;ugrave; principale&lt;br /&gt;
&lt;/strong&gt;&lt;/strong&gt;Aggiungere nel file &lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;SiteUrl.config (nell&amp;rsquo;apposita sezione contentente anche gli alti elementi del  men&amp;ugrave;, contraddistinti dal tag xml &amp;#39;&lt;/span&gt;&lt;/font&gt;link&amp;#39;) una voce del tipo&lt;br /&gt;
&lt;br /&gt;
&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&amp;lt;link name=&amp;quot;&amp;lt;NOME_LINK&amp;gt;&amp;quot;  navigateUrl=&amp;quot;&amp;lt;URL_DI_DESTINAZIONE&amp;gt;&amp;quot; text=&amp;quot;&amp;lt;LABEL_MENU&amp;gt;&amp;quot; roles=&amp;quot;Everyone&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ovviamente su roles andranno specificati i ruoli abilitati a vedere la voce del men&amp;ugrave;.&lt;br /&gt;
L&amp;#39;url di destinazione, a causa di qualche sclero di Communty Server, &amp;egrave; bene specificarlo in modo assoluto e non relativo, altrimenti funzioner&amp;agrave; correttamente solo quando ci si trova nell&amp;#39;homepage (quando si &amp;egrave; dentro un&amp;#39;altra pagina, CS aggiunge una parte al path relativo, rendendolo incorretto)&lt;/span&gt;&lt;/font&gt;&lt;strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;strong&gt;&lt;br /&gt;
Link ad un articolo&lt;br /&gt;
&lt;/strong&gt;&lt;/strong&gt;Quando si crea un articolo, CS permette automaticamente di indirizzarlo tramite il path (relativo) content/&amp;lt;NOME_ARTICOLO&amp;gt;.aspx. Se, ad esempio, l&amp;#39;articolo si chiama FAQ, il path sar&amp;agrave; content/FAQ.aspx. &lt;br /&gt;
Fare attenzione a non utilizzare, se possibile, gli articoli, sostituendoli con il blog, in quanto non vengono indicizzati per le ricerche.&lt;strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Gestione poll&lt;br /&gt;
&lt;/strong&gt;&lt;/strong&gt;I poll possono essere creati direttamente da un post del forum. Occorre per&amp;ograve; avere i permessi adeguati per poterlo fare, altrimenti la tab &amp;#39;Poll&amp;#39; non sar&amp;agrave; visibile (esiste un&amp;#39;apposita voce nelle impostazioni generali del forum, accessibile dal pannello di amministrazione).&lt;br /&gt;
L&amp;#39;unica pecca &amp;egrave; che permettono la gestione di poll a sola scelta singola.&lt;br /&gt;
Se ci fosse l&amp;#39;esigenza, si pu&amp;ograve; integrare una libreria esterna (tipo &lt;a href="http://www.nsurvey.org/netpolls/"&gt;http://www.nsurvey.org/netpolls/&lt;/a&gt;)&lt;strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Fuso orario&lt;br /&gt;
&lt;/strong&gt;&lt;/strong&gt;L&amp;#39;orario che si trova nelle impostazioni generali non deve essere impostato a quello in cui ci si trova, ma a quello in cui si trova il server che ospita il sito.&lt;br /&gt;
&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;u&gt;Non&lt;/u&gt; &amp;egrave; invece necessario impostare nulla sul file web.config (sul forum di community server si fa riferimento ad una voce dbTimeZoneOffset da aggiungere, ma probabilmente si riferiva alla versione precedente di CS).&lt;/span&gt;&lt;/font&gt;&lt;strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;FCKEditor&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;Vedi file allegato &amp;quot;FCK Editor.zip&amp;quot; e relativo file Readme.txt (contenuto all&amp;#39;interno)&lt;strong&gt;&lt;br /&gt;
&lt;strong&gt;&lt;br /&gt;
WIKI&lt;/strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt; Se qualcuno volesse indagare, qua c&amp;rsquo;&amp;egrave; un thread interessante (anche se un po&amp;rsquo;  vecchio)&lt;/span&gt;&lt;/font&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;a href="http://communityserver.org/forums/thread/495747.aspx" title="blocked::http://communityserver.org/forums/thread/495747.aspx"&gt;http://communityserver.org/forums/thread/495747.aspx&lt;/a&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;
&lt;p class="MsoNormal"&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;con qualcosa da scaricare  all&amp;rsquo;indirizzo&lt;br /&gt;
&lt;a href="http://www.webdynamix.biz/products/wiki_build_0_1.zip" title="blocked::http://www.webdynamix.biz/products/wiki_build_0_1.zip"&gt;http://www.webdynamix.biz/products/wiki_build_0_1.zip&lt;/a&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;(e + aggiornato all&amp;rsquo;indirizzo &lt;a href="http://www.webdynamix.biz/products/wiki_build_0_2.zip" title="blocked::http://www.webdynamix.biz/products/wiki_build_0_2.zip"&gt;http://www.webdynamix.biz/products/wiki_build_0_2.zip&lt;/a&gt;)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Si tratterebbe (credo) di integrare FlexWiki in CS.&lt;strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&amp;nbsp;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;font face="Tahoma" size="2"&gt;&lt;span style="font-size:10pt;font-family:Tahoma;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=154" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/Community+Server/default.aspx">Community Server</category></item><item><title>[ABOUT US]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/ABOUT-US.aspx</link><pubDate>Thu, 06 Jul 2006 11:25:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:153</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>DotNetMarche è il primo, e per ora unico, .NET Users Group nato nelle Marche, e rappresenta un'aggregazione di utenti, prevalentemente professionisti del settore IT, accomunati dall’utilizzo del Microsoft .NET Framework e dalla passione per la programmazione...(&lt;a href="http://dotnetmarche.org/blogs/article/archive/2006/07/06/ABOUT-US.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=153" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item><item><title>[FAQ]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/FAQ-List.aspx</link><pubDate>Thu, 06 Jul 2006 11:24:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:174</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>&lt;p class="MsoBodyText"&gt;   &lt;span&gt;&lt;strong&gt;1. CHI SIETE ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Siamo un gruppo di persone che di mestiere (e per passione) fanno i programmatori e che dedicano molto del loro tempo allo studio ed allo sviluppo di tecnologie. Come molte altre persone di questo settore ci piace l'idea di confrontarci e condividere esperienze ed idee.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;2. CHE COS'È UNO USERS GROUP ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Uno Users Group è costituito da un gruppo di persone che condividono una passione nel suo complesso, e desiderano sostenerla, diffonderla e tutelarla. Le modalità di associazione, ritrovo ed organizzazione sono diverse per ogni singolo Users Group, ma il loro scopo è comune: condividere e diffondere la propria passione, creando un punto d'appoggio volontario, dove ognuno può dare il proprio contributo.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;3. COME È NATA L'IDEA DELLO USERS GROUP ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Durante una cena, conclusa con dei digestivi che qualcuno ha definito "criminali" ! :)&lt;br&gt;
&lt;br&gt;
In realtà l'idea nasce in parte, dall'esigenza di fondare un gruppo di utenti interessati alla programmazione in ambiente .NET con una zona di riferimento piuttosto limitata (la regione Marche), ed in parte sulla scia di quelle che sono le più conosciute realtà nazionali (vedi UGIdotNET).&lt;br&gt;
&lt;br&gt;
I motivi sono diversi: la presenza di un gruppo locale, ci offre la possibilità di incontrarci molto più facilmente, senza dover affrontare lunghi viaggi per assistere a delle conferenze.&lt;br&gt;
Anche se ormai esistono moltissimi mezzi per rimanere costantemente in contatto, i benefici (ed il piacere) che si possono ottenere da incontri "dal vivo", non sono a nostro avviso paragonabili.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;4. E' GIÀ STATO FONDATO LO USERS GROUP ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;Si, ed il suo nome, DotNetMarche, è stato scelto tramite un democratico &lt;a href="http://www.dotnetmarche.org/forums/thread/13.aspx"&gt;sondaggio&lt;/a&gt;!&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;5. PERCHÈ UN ALTRO USERS GROUP ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Nella nostra zona non esisteva ancora un gruppo di utenti appassionati di programmazione in .NET, per cui vorremmo sopperire alle esigenze già espresse nella domanda "Come è nata l'idea dello users group ?".&lt;br&gt;
Inoltre vorremmo sottolineare il fatto che non ci proponiamo come alternativa ad altre realtà ben più strutturate ed organizzate della nostra, ma semmai come una loro naturale trasposizione sul territorio.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;6. QUALI SONO LE ATTIVITÀ DI UNO USERS GROUP ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Se l’obiettivo principale dello users group è quello di condividere ed accrescere le proprie competenze e fare nuove conoscenze, le attività principali sono tutte quelle che in qualche modo ci danno la possibilità di perseguire questi scopi.&lt;br&gt;
&lt;br&gt;
Quindi largo spazio a tutte le attività di community (forum, blog, ecc..), ai workshop, magari allo sviluppo di piccoli progetti software, e perché no, anche qualche cena.&lt;br&gt;
Naturalmente alcune attività potrebbero nascere in seno allo users group, mentre in altri casi ci si limiterà a promuovere iniziative di realtà complementari, come gli users group “nazionali”.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;7. MA SI PARLERÀ SOLAMENTE DI .NET ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Non necessariamente. Lo sviluppo in .NET ed il Framework in genere, coinvolge una miriade di argomenti più o meno complessi: c’è la parte sistemistica, i tools di sviluppo, i linguaggi di programmazione e via dicendo.&lt;br&gt;
Si possono fare confronti con tecnologie concorrenti, o sbirciare le tecnologie future.&lt;br&gt;
Tutto dipenderà dalle proposte, dalla voglia di partecipare e contribuire.&lt;a href="http://www.dotnetmarche.org"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoBodyText"&gt;&lt;span&gt;&lt;br&gt;
&lt;strong&gt;8. CHIUNQUE PUÒ PARTECIPARE ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Chiunque sia interessato alla programmazione con il .NET Framework ed a tutto quello che gli ruota attorno, e si trovi nelle Marche o dintorni. &lt;br&gt;Alle attività svolte on-line tramite il sito, come lo sviluppo di progetti open-source, possono partecipare anche persone al di fuori delle Marche.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;9. MA VOI SIETE DEGLI "ESPERTI" ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Assolutamente no, non siamo dei guru che si occupano di consulenze o formazione a tempo pieno, ma dei programmatori che hanno imparato quello che sanno dall'esperienza sviluppata in anni di studio e lavoro.&lt;br&gt;
Nelle nostre intenzioni, c’è la voglia di creare un gruppo, non di fare una gara per stabilire chi sono i più bravi, e se qualcuno se la sentirà di affrontare un argomento per quello che la propria esperienza gli ha insegnato, questo sarà il benvenuto.&lt;br&gt;
Se capiterà di dover rispondere “non lo so” a qualche domanda, questo non costituirà un problema, ma anzi un punto d’incontro su cui crescere e migliorare.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;10. PERCHÈ ORGANIZZARE O PARTECIPARE ALLE ATTIVITÀ DI UNO USERS GROUP QUANDO CON GOOGLE HO GIÀ TUTTO QUELLO CHE MI SERVE ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Perché su Google o su internet le persone le incontri solo virtualmente, mentre noi vorremmo&lt;br&gt;
poterci incontrare nel vero senso della parola. Che Google sia uno strumento ormai fondamentale per molti, questo è fuori di ogni dubbio, ma questo soprattutto grazie a coloro che hanno dedicato del tempo prezioso a pubblicare nuovi contenuti o dare una mano ad altri, come magari in precedenza qualcun altro aveva già fatto con loro.&lt;br&gt;
&lt;br&gt;
Uno users group deve essere un "mezzo" per avere la possibilità di crescere INSIEME, imparando dagli altri e condividendo al tempo stesso le proprie conoscenze. Anche se non sei un esperto questo non significa che tu non abbia nulla di interessante da condividere, ed in ogni caso questa rimane una buona occasione per conoscere cose nuove.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;11. DEVO PAGARE QUALCOSA PER PARTECIPARE ?&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
Lo users group è una realtà no-profit, e non sono contemplate (almeno per ora) quote associative o cose del genere. L’idea è quella di rimanere sul gratuito, se poi ci saranno spese amministrative o altro vedremo in seguito.&lt;/span&gt;&lt;/p&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=174" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item><item><title>[COMMUNITY RULES]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/COMMUNITY-RULES.aspx</link><pubDate>Thu, 06 Jul 2006 11:23:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:152</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>&lt;p class="MsoBodyText"&gt;&lt;span&gt;Gli obiettivi della community DotNetMarche sono essenzialmente la promozione di incontri e attività tra i suoi membri: sono quindi interesse prioritario di DotNetMarche l'&lt;strong&gt;organizzazione di workshop&lt;/strong&gt; e la &lt;strong&gt;creazione di progetti software realizzati in modalità collaborativa&lt;/strong&gt;, tramite i quali approfondire le tematiche dello sviluppo software in ambiente .NET.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoBodyText"&gt;&lt;span&gt;Il sito DotNetMarche permette di gestire in modo organizzato le attività della community: le forme principali di aggregazione sono i &lt;strong&gt;forum di discussione&lt;/strong&gt; sugli eventi in programma e sulle attività di sviluppo intraprese dal gruppo, la &lt;strong&gt;mailing list &lt;/strong&gt;attraverso la quale i membri vengono avvisati riguardo gli avvenimenti più importanti e le &lt;strong&gt;news&lt;/strong&gt;.&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoBodyText"&gt;&lt;span&gt;Data la tipologia dello user group, le attività svolte al suo interno saranno gestite in modo tale da sfruttare ampiamente la sua &lt;strong&gt;presenza locale nel territorio&lt;/strong&gt;, cosa che permette di avere una conoscenza più "stretta" degli altri membri, nonché la possibilità di incontrarsi periodicamente di persona, cosa fondamentale per avere quel feeling e quella praticità che le tecnologie moderne di comunicazione, per quanto avanzate, non riescono ancora a dare.&lt;/span&gt;&lt;span&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoBodyText"&gt;&lt;span&gt;Non sarà invece questo il luogo ideale per altri tipi di attività per le quali hanno più senso organizzazioni a livello nazionale ed internazionale già esistenti (come UgiDotNet o i newsgroup ufficiali Microsoft), che offrono una maggiore disponibilità di risorse ed una visibilità ben superiore nel caso si vogliano, ad esempio, pubblicare dei contenuti. In questo modo evitiamo di frammentare le risorse che troverebbero una collocazione ideale in altri luoghi, e che senz’altro potrebbero interessare un bacino di utenza molto più vasto.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoBodyText"&gt;&lt;span&gt;Seguono una serie di linee guida a riguardo.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;&lt;span&gt;Blog personali: &lt;/span&gt;&lt;/strong&gt;&lt;span&gt;attualmente non viene offerta la possibilità agli utenti del gruppo di pubblicare dei &lt;strong&gt;blog personali&lt;/strong&gt;, al fine di incoraggiarne la &lt;strong&gt;gestione su siti che offrono questo servizio con portata nazionale o internazionale&lt;/strong&gt; come UGIdotNET, DevLeap, DotNetHell o altri: questo scelta, da una parte evita la duplicazione dei post da parte degli utenti che già gestiscono un proprio blog su altri .NET user group, dall'altra favorisce la promozione dell'attività del gruppo e consolida il rapporto con&lt;strong&gt; le altre comunità&lt;/strong&gt; già esistenti. &lt;br&gt;
    &amp;nbsp;&lt;br&gt;
    &lt;/span&gt;&lt;strong&gt;&lt;span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;span&gt;Pubblicazione di articoli&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: DotNetMarche promuove e pubblica tutti gli articoli in qualche modo legati alle esperienze concrete di sviluppo sui progetti e attività del gruppo stesso, come ad esempio tutorial sulla configurazione ed uso dei Microsoft Applications Block, oppure recensioni dei tools di sviluppo come TestDriven.NET; particolare riguardo sarà riservato inoltre agli articoli introduttivi verso argomenti di livello basilare, ma spesso trascurati, come ad esempio i Design Patterns (in particolare se con un'ottica rivolta verso l'applicazione pratica di questi strumenti e metodologie, e non solo teorica).&lt;/span&gt; &lt;br&gt;
    &lt;br&gt;
    &lt;span&gt;I membri della community che invece desiderano scrivere articoli non collegati direttamente alle attività della community, sono incoraggiati a valutare la possibilità di pubblicare il loro lavoro in siti più idonei, dove potranno godere di una maggiore risonanza e visibilità. I membri dello user-group che in precedenza hanno già avuto modo di scrivere articoli per siti istituzionali (vedi UgiDotNet) o per riviste specializzate, offrono il loro supporto e sostegno al fine di agevolarne la redazione e la pubblicazione. &lt;/span&gt;&lt;br&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;blockquote&gt;&lt;span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;&lt;span&gt;Forum: &lt;/span&gt;&lt;/strong&gt;&lt;span&gt;il suo scopo principale è quello di affrontare quei temi che toccano in qualche maniera le attività dello user-group. Questioni specifiche di programmazione possono essere risolte, con altissima probabilità, utilizzando strumenti più idonei, come i motori di ricerca, i newsgroup ufficiali Microsoft o Google Groups, che offrono una knowledge-base vastissima (ad esempio molti dei problemi sull'utilizzo del framework, in genere sono già stati affrontati e risolti). Inoltre queste risorse raggiungono molte più persone (tra cui vari MVP) disponibili a rispondere alle domande, permettendo di risolvere i problemi più rapidamente e con un minor margine di errore.&lt;br&gt;
    &lt;br&gt;
    &lt;/span&gt;&lt;span&gt;Il &lt;strong&gt;forum&lt;/strong&gt;, quindi, ha senso se utilizzato principalmente per discutere delle attività portate avanti dalla community; saranno in ogni caso bene accette discussioni sulle problematiche di programmazione generale che non hanno trovato una risposta altrove, oppure che possono risultare più idonee da affrontare tra "amici", i quali potranno "dirottarvi" verso altre risorse su internet o rispondere in base alla propria esperienza.&lt;/span&gt;&lt;br&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;blockquote&gt;&lt;span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span&gt; &lt;br&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class="MsoBodyText"&gt;&lt;span&gt;L’invito è di utilizzare gli strumenti di discussione offerti dal sito DotNetMarche per un’attiva &lt;strong&gt;collaborazione e discussione tra gli utenti del gruppo&lt;/strong&gt;, e leggere la sezione [&lt;a href="http://www.dotnetmarche.org/blogs/article/archive/2006/06/26/HOW_TO.aspx"&gt;HOW TO&lt;/a&gt;] per capire come ottimizzare le risorse offerte dal sito (e convivere meglio con gli altri membri), ed in quali casi focalizzare la propria attenzione altrove.&lt;/span&gt;&lt;/p&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=152" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item><item><title>[HOW TO]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/HOW-TO.aspx</link><pubDate>Thu, 06 Jul 2006 11:22:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:151</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>&lt;p class="MsoBodyText"&gt;&lt;strong&gt;&lt;u&gt;&lt;span&gt;Gestione Profilo Utente&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span&gt;Ogni membro della community è "caldamente invitato" a compilare il &lt;strong&gt;proprio profilo personale&lt;/strong&gt;: il sito offre una completa sezione dedicata alla gestione del profilo utente, in cui è possibile (doveroso, direi...) specificare contatti email/instant messenging. In particolare sarebbe opportuno &lt;strong&gt;firmare i post &lt;/strong&gt;sul forum, specificando ad esempio il link al proprio sito o blog personale, eventuali certificazioni e riconoscimenti o qualunque altro riferimento che permetta di facilitare il contatto tra gli utenti.&amp;nbsp; &lt;br&gt;
    &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span&gt;La community considererà il profilo “completo”, solo se personalizzato con un avatar ed una piccola &lt;strong&gt;biografia&lt;/strong&gt;: il campo bio del profilo utente, anche se a prima vista non sembra, consente di inserire alcuni tag HTML a supporto della scrittura del testo. Sono sufficienti poche righe, purché utili ad identificare le proprie competenze e\o esperienze.&lt;br&gt;
    &lt;br&gt;
    &lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;La DotNetiquette prescrive che tutti gli utenti che entro un mese dalla registrazione al sito non avranno provveduto a compilare la propria biografia, &lt;strong&gt;saranno ritenuti in debito rispetto&lt;/strong&gt; agli altri membri della community... il fio da pagare per espiare la colpa sarà stabilito collegialmente in una delle prossime sedute :).&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="MsoBodyText"&gt;  &lt;/p&gt;
&lt;p class="MsoBodyText"&gt;&lt;strong&gt;&lt;u&gt;&lt;span&gt;Gestione Forum, Newsgroup e Google Groups&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;&lt;u&gt;&lt;span&gt;Strumenti a disposizione&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;span&gt;: come specificato nella sezione [&lt;a href="http://www.dotnetmarche.org/blogs/article/archive/2006/06/26/Community_Rules.aspx"&gt;COMMUNITY RULES&lt;/a&gt;], per risolvere i problemi quotidiani relativi al .NET Framework ed alla programmazione in genere, ci sono degli strumenti più adatti rispetto al forum presente nel sito. É auspicabile dunque utilizzare queste risorse, prima di porre delle domande che non siano pertinenti le attività dello user group; la community rimane comunque a disposizione nel caso il problema non si presenti di facile risoluzione, e comunque in tutti quei casi in cui per difficoltà di formulazione o per approfondimenti la scelta prediliga comunque il forum. &lt;br&gt;
    &amp;nbsp;&lt;br&gt;
    &lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span&gt;Segue una breve lista di risorse consultabili in rete che permettono una risoluzione veloce e precisa dei problemi di programmazione più comuni:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;&lt;span&gt;Motori di ricerca (es. Google)&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: i search engine indicizzano miliardi di pagine, tra cui forum, articoli e blog presenti in tantissime community nazionali ed internazionali; è molto probabile che tra di esse siano già contenute soluzioni e chiarimenti ai problemi ricercati. Particolare attenzione deve essere dedicata all’impostazione dei criteri di ricerca: &lt;/span&gt;&lt;span&gt;più saranno precisi e limitati tanto più il motore fornirà risposte pertinenti. Per favorire la ricerca i motori mettono a disposizione degli algoritmi in grado di interpretare le più comuni espressioni del linguaggio parlato, ma se utilizzati con operatori di algebra booleana (AND, OR, ecc..) i risualti forniti saranno senz’altro più precisi. Una guida all’utilizzo di Google può esse&lt;font size="2"&gt;re &lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;a href="http://www.google.com/support?hl=it" target="_BLANK"&gt;a questo indirizzo&lt;/a&gt;&lt;span&gt;.&lt;br&gt;
        &lt;/span&gt;&lt;/font&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;&lt;span&gt;Newsgroup&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: concettualmente simili ai forum (si può porre una domanda e attendere che qualcuno dia delle risposte), hanno il vantaggio di essere gestiti con un protocollo dedicato (NNTP) che, similmente a quanto avviene per gli RSS, ci permette di aggregare e sincronizzare i post attraverso dei software più o meno dedicati, come Outlook Express. Per questi motivo, i newsgroup sono probabilmente molto più usati - e pratici da utilizzare - rispetto ai forum, anche se con l’avvento di RSS molti forum si sono adeguati ed hanno esteso il supporto a questo standard rendono di fatto questi due strumenti molto simili.&lt;br&gt;
        &lt;br&gt;
        &lt;/span&gt; &lt;span&gt;Tra le moltissime presenti, esiste una gerarchia di newsgroup ufficiali Microsoft divisi per tematiche (es. microsoft.public.it.dotnet.csharp e microsoft.public.it.dotnet.vb sono i gruppi italiani per C# e VB.Net) in cui porre domande alle quali, probabilmente, verrà data una risposta da persone competenti e disponibili a chiarimenti.&lt;br&gt;
        &lt;br&gt;
        &lt;/span&gt;&lt;span&gt;Per configurare i newsgroup Microsoft in Outlook Express seguire le seguenti istruzioni:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;span&gt;Andare su Tools -&amp;gt; Accounts -&amp;gt; Tab News -&amp;gt; Pulsante Add -&amp;gt; News. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;span&gt;Inserire nome ed indirizzo e-mail (va bene anche un nome fittizio se si vuole mantenere l’anonimato, ma non è una pratica consigliata visto che dall’altra parte ci sono persone disposte a dare un aiuto incondizionato).&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;span&gt;Inserire l’indirizzo del server NNTP (ad es. news.microsoft.com). &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;span&gt;Nel treeview con le varie cartelle verrà aggiunta una voce (es. news.microsoft.com): esplorare la gerarchia per ricercare e selezionare i gruppi di proprio interesse.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;span&gt;A questo punto è possibile porre nuove domande (New Post) o rispondere a quelle di altri (Reply), contribuendo così alla community.&lt;/span&gt;&lt;br&gt;
            &lt;span&gt;&lt;/span&gt;&lt;/li&gt;
            &lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;br&gt;
            &lt;/span&gt;          &lt;/ul&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
    &lt;blockquote&gt;&lt;blockquote&gt;&lt;span&gt;Oltre ad Outlook Express sono disponibili ovviamente una vasta gamma di software (aggregatori) per gestire i newsgroup, tra i più noti RSS Bandit e NewzCrawler.&lt;br&gt;
    &lt;br&gt;
    &lt;/span&gt;     &lt;span&gt;Un elenco dei principali indirizzi dei server NNTP è fornito da Google&lt;font size="2"&gt;. A &lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;a href="http://www.microsoft.com/communities/newsgroups/default.mspx"&gt;questo indirizzo&lt;/a&gt;&lt;/font&gt;&lt;span&gt;&lt;font size="2"&gt;&lt;span&gt; &lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font size="2"&gt;è pos&lt;/font&gt;sibile trovare tutti i newsgroup ufficiali Microsoft.&lt;br&gt;
    &lt;br&gt;
    &lt;/span&gt;&lt;/span&gt;     &lt;span&gt;&lt;span&gt;Alcuni newsgroup (ad es. UgiDotNet) richiedono un autenticazione costituita da username e password che generalmente vengono fornite dagli amministratori del sito. In questo caso, è possibile impostare questi dati nell'account creato in Outlook Express.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
    &lt;/blockquote&gt;&lt;/blockquote&gt;
    &lt;div&gt;     &lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;&lt;span&gt;Google Groups&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: questo strumento unisce la potenza di ricerca di Google al vastissimo repository di post creati nei newsgroup in più di 20 anni di storia. Una delle principali limitazioni dei newsgroup, ma sarebbe meglio dire del protocollo NNTP, è la possibilità di effettuare ricerche all'interno del corpo dei messaggi e di conseguenza nell'archivio dei post.&lt;br&gt;
            &lt;br&gt;
            &lt;/span&gt; &lt;span&gt;Google ha sopperito a questa mancanza attraverso Google Groups: una sezione del sito Google che indicizza e ricerca esclusivamente all'interno dei newsgroup (a differenza della sezione principale del sito, che non opera una ricerca completa in questi archivi). Tra le altre cose, Google ha acquisito il repository di post &lt;font size="2"&gt;di &lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;a href="http://it.wikipedia.org/wiki/Usenet"&gt;Usenet&lt;/a&gt;&lt;/font&gt;&lt;span&gt;&lt;font size="2"&gt;, do&lt;/font&gt;ve è possibile trovare annunci che hanno fatto la storia dell'informatica!&lt;br&gt;
            &lt;br&gt;
            &lt;/span&gt; &lt;span&gt;La potenza di questo strumento deve essere unita al buon senso di coloro che lo utilizzano, facendo in modo che prima di porre qualsiasi quesito, ne sia verificata un’eventuale presenza e le relative soluzioni.&lt;br&gt;
            &lt;br&gt;
            &lt;/span&gt;&lt;span&gt;L'utilizzo di Google Groups è molto semplice, e l’impostazione dei criteri di ricerca è analoga a quello del motore principale. E’ possibile inoltre sfruttare la ricerca avanzata per filtrare i messaggi di determinati gruppi o utenti (ad es. si può specificare microsoft.public.it.dotnet.csharp come nome del gruppo su cui cercare, oppure microsoft.public.it.dotnet.* per filtrare tra tutti i messaggi relativi ai gruppi italiani su .NET).&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;&lt;u&gt;&lt;span&gt;Utilizzo del forum di DotNetMarche&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;br&gt;
        &lt;br&gt;
        Segue una serie di tip utili ad una migliore gestione ed utilizzo del forum.&lt;/span&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;&lt;span&gt;Ricezione notifiche via e-mail&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: al fine di evitare un controllo sistematico dell’aggiornamento del forum, è possibile abilitare la notifica via e-mail. Le opzioni a disposizione permettono di decidere se ricevere &lt;strong&gt;tutti i post&lt;/strong&gt; o solamente quelli di apertura di nuovi thread (ma non le relative risposte).&lt;br&gt;
            &lt;br&gt;
            &lt;/span&gt; &lt;span&gt;&lt;/span&gt;&lt;span&gt;Di default le notifiche sono disabilitate per non intasare senza preavviso la casella di posta elettronica. Per attivarle è sufficiente entrare nella sezione di modifica del profilo personale, selezionare la scheda ‘E-Mail’ e impostare su ‘Yes’ la voce ‘Enable Email Notifications of forum/thread subscriptions and replies to my posts’. Successivamente, per selezionare la notifica sui forum, andare nel link '&lt;a name="ctl00_ctl01_rcr_Forumlinkbar1___Forumanc"&gt;&lt;/a&gt;Forum Subscriptions' che si trova nel pannello 'Shortcuts', e porre la spunta alla voce 'Subscribe' sui forum di maggior interesse. In questo modo, verrà abilitata la notifica di ogni post, anche quelli di riposta. Bisogna prestare attenzione nel caso in cui vengano creati nuovi forum: in questo caso infatti è necessario ripetere l’operazione.&lt;br&gt;
            &lt;br&gt;
            &lt;/span&gt;&lt;font size="2"&gt;&lt;span&gt;In alternativa, è possibile configurare singolarmente ciascun forum direttamente dal pulsante "Forum Options" presente in fondo alla pagina. &lt;/span&gt;&lt;span&gt;In questa maniera si può ottenere una maggiore flessibilità di configurazione a scapito però del tempo impegato per l’impostazione di tutte le opzioni.&lt;br&gt;
            &lt;/span&gt;&lt;/font&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
    &lt;div&gt; &lt;/div&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;&lt;span&gt;Ricezione notifiche via RSS&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: il forum dispone anche di un feed rss che permette di aggregare i nuovi thread. Per sottoscrivere il feed, cercare l'&lt;strong&gt;icona "RSS Available"&lt;/strong&gt; in coda all'elenco dei topics, e copiare ed incollare il collegamento associato, nel software utilizzato per aggregare i contenuti (Outlook, Thunderbird, RSS Bandit, ecc… )&lt;br&gt;
            &lt;br&gt;
            &lt;/span&gt; &lt;font color="#ff0000"&gt;&lt;strong&gt;&lt;u&gt;&lt;strong&gt;&lt;span&gt;Nota bene 1&lt;/span&gt;&lt;/strong&gt;&lt;/u&gt;&lt;span&gt;:&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i feed RSS, a differenza delle notifiche e-mail, emettono nel loro flusso solamente il post di apertura di uno nuovo thread, e non tutte le risposte che seguono.&lt;br&gt;
            &lt;/span&gt; &lt;span&gt;E’ comunque possibile seguire un thread via RSS attraverso una modalità descritta in seguito.&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &lt;br&gt;
            &lt;br&gt;
            &lt;span&gt;&lt;/span&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;&lt;span&gt;&lt;u&gt;Nota bene 2&lt;/u&gt;:&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anche se non è evidenziato, esiste un collegamento che permette di sottoscrivere un feed RSS contenente i post di &lt;font size="2"&gt;apertura di un nuovo thread di tutti i forum (pubblici ?) presenti nel sito. Il link è il seguente:&lt;br&gt;
            &lt;/font&gt;&lt;/span&gt;&lt;a href="/Forums/aggregaterss.aspx?Mode=2"&gt;&lt;font size="2"&gt;&lt;span&gt;http://www.dotnetmarche.org/Forums/aggregaterss.aspx?Mode=2&lt;/span&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;span&gt;&lt;/span&gt;&lt;/font&gt;&lt;br&gt;
            &lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
    &lt;div&gt; &lt;/div&gt;
    &lt;ul&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;&lt;span&gt;Ricezione notifiche per un singolo thread&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;: assieme alle notifiche d’apertura di un thread, è possibile in ogni caso abilitare la &lt;strong&gt;notifica di tutte le risposte al topic principale&lt;/strong&gt; aperto sul forum, al fine di avere un controllo continuo della discussione. Le notifiche via e-mail possono essere abilitate attraverso il bottone &lt;strong&gt;"Enable email subscription" &lt;/strong&gt;presente nel topic, mentre in alternativa è possibile &lt;strong&gt;sottoscrivere il feed rss del topic&lt;/strong&gt; copiando ed incollando il link associato all’icona &lt;strong&gt;"RSS Available" &lt;/strong&gt;– sempre all’interno del topic - nel proprio aggregatore di feed.&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;
    &lt;p class="MsoBodyText"&gt;  &lt;/p&gt;
    &lt;p class="MsoBodyText"&gt;&lt;strong&gt;&lt;u&gt;&lt;span&gt;Apertura di un Blog&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;span&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;span&gt;In questo momento non è offerta alcuna possibilità di aprire un blog personale in questo sito. Le motivazioni di questa scelta sono state già evidenziate e approfondite nella sezione [&lt;a href="http://www.dotnetmarche.org/blogs/article/archive/2006/06/26/Community_Rules.aspx"&gt;COMMUNITY RULES&lt;/a&gt;].&lt;/span&gt;&lt;br&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class="MsoBodyText"&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;br&gt;
    &lt;/span&gt;&lt;strong&gt;&lt;u&gt;&lt;span&gt;Scrittura di articoli e partecipazioni allo sviluppo di progetti&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;span&gt;&lt;span&gt;·&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Presto saranno rese note una serie di risorse - sotto forma di articoli, tutorial, link e quant’altro - su strumenti e regole per portare avanti questo tipo di attività, come chiarito nelle [&lt;a href="http://www.dotnetmarche.org/blogs/article/archive/2006/06/26/Community_Rules.aspx"&gt;COMMUNITY RULES&lt;/a&gt;]. Nel frattempo tutti coloro che sono interessati a questo tipo di iniziative sono invitati a discuterne sul forum.&lt;/span&gt;&lt;/li&gt;
    &lt;/ul&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=151" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item><item><title>[WE WANT YOU]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/WE-WANT-YOU.aspx</link><pubDate>Thu, 06 Jul 2006 11:21:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:150</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>&lt;ul&gt;
    &lt;li&gt;&lt;span&gt;Appartenere ad una community di utenti, piccola o grande che sia, &amp;egrave; sicuramente un impegno, e se, come tanti di noi, hai gi&amp;agrave; un lavoro che ti occupa molte risorse e ti stressa oltremodo, questo onere pu&amp;ograve; risultare in alcuni casi gravoso: di certo quel poco o tanto di tempo che verr&amp;agrave; rubato alle tue attivit&amp;agrave; o al tuo relax sar&amp;agrave; ampiamente ripagato dal bagaglio di conoscenze personali, professionali, tecniche ed umane che acquisirai.&lt;/span&gt;&lt;span&gt; Questo vale in particolare per le comunit&amp;agrave; legate alla tecnologia e all'informatica, in cui le novit&amp;agrave; si susseguono vorticosamente ed &amp;egrave; difficile, per non dire impossibile, rimanere aggiornato su tutte le novit&amp;agrave;.&lt;br /&gt;
    &lt;br /&gt;
    &lt;/span&gt;&lt;span&gt;Essere membro di una comunit&amp;agrave; di sviluppatori ti permetter&amp;agrave; di discutere ed imparare dagli altri utenti le novit&amp;agrave; del software e dell'hardware, le nuove metodologie di sviluppo, le nuove tecnologie all'orizzonte... in un ambiente lavorativo come il nostro in cui &amp;quot;chi si ferma &amp;egrave; perduto&amp;quot; tutto questo ha un'importanza capitale, e, fidati, vale almeno un p&amp;ograve; dell'impegno che ti si richiede per partecipare.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span&gt;Avere un blog oramai sembra una moda, tutti ce l'hanno e ci scrivono di tutto, quindi magari ti chiedi perch&amp;egrave; dovresti aprirne uno pure te, tanto pi&amp;ugrave; che come membro di DotNetMarche non ne hai i privilegi... ebbene, dovresti invece aprirlo, magari utilizzando gli strumenti delle community nazionali UGIdotNET, DevLeap, DotNetHell o altre!&lt;br /&gt;
    &lt;br /&gt;
    &lt;/span&gt;&lt;span&gt;Per chi fa il nostro lavoro, avere un blog aiuta enormente a condividere le proprie problematiche, e serve a far &amp;quot;circolare le idee&amp;quot;: lavorando quotidianamente nella programmazione .NET, sarai sicuramente incappato in alcuni problemi che poi avrai risolto tramite un misto di bravura-fortuna o dopo qualche minuto di ricerca su google, oppure avrai scritto un particolare algoritmo di dieci righe per sostituire un precedente algoritmo da 500 righe, scritto magari da un tuo collega o amico che non conosceva il framework .NET cos&amp;igrave; bene come te... ebbene, postare la tua esperienza su un blog permetter&amp;agrave; a chiunque di imparare dal tuo operato, in puro spirito &amp;quot;community&amp;quot; secondo cui la condivisione dell'informazione &amp;egrave; il bene pi&amp;ugrave; prezioso.&lt;br /&gt;
    &lt;br /&gt;
    &lt;/span&gt;&lt;span&gt;Se ritieni di non avere le capacit&amp;agrave; o l'esperienza necessarie per scrivere contenuti interessanti, beh, &amp;egrave; il momento di ripensarci! Ricorda, &amp;quot;nessuno nasce imparato&amp;quot;, e anche una scoperta che ritieni banale, per altri pu&amp;ograve; essere causa di notti insonni...&lt;br /&gt;
    &lt;br /&gt;
    &lt;/span&gt;&lt;span&gt;E&lt;font size="2"&gt;cco &lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;a href="http://blogs.ugidotnet.org/piyo/category/1723.aspx"&gt;un p&amp;ograve; di risorse&lt;/a&gt;&lt;/font&gt;&lt;span&gt;&lt;font size="2"&gt; &lt;/font&gt;per guidarti all'apertura di un blog di successo e alla gestione corretta dei contenuti.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span&gt;Ultime, ma non per importanza, un paio di regole generali:&amp;nbsp; &lt;br /&gt;
    &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;span&gt;Una community esiste se e solo se &amp;quot;esistono&amp;quot; i suoi membri, e vive dell'entusiasmo e della voglia di fare di chi si impegna per farla funzionare: nessuno prende uno stipendio o benefit di sorta per le attivit&amp;agrave; di DotNetMarche, anzi spesso paga di tasca propria i costi di esercizio; ci aspettiamo dai membri della community voglia di fare e di partecipare, entusiasmo nel discutere e nel condividere e, perche n&amp;ograve;, pure un p&amp;ograve; di incoscienza e di &amp;quot;spirito di avventura&amp;quot; nel lanciarsi nelle attivit&amp;agrave; del gruppo! &amp;nbsp;&lt;/span&gt;&lt;br /&gt;
        &lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;
        &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;span&gt;Se ritieni che l'attivit&amp;agrave; del gruppo sia in qualche modo meritoria, e meritevole di pubblicit&amp;agrave;, beh, allora pubblicizzala!&lt;/span&gt;&lt;span&gt;Puoi inserire un banner in fondo ai post del tuo blog (hai aperto un blog, vero?), puoi vantare la tua appartenenza a DotNetMarche nella firma della tua email o nei post nei newsgroup/forum, puoi &amp;quot;spargere la voce&amp;quot; tra i tuoi colleghi di lavoro o tra gli amici programmatori... ogni nuovo membro del gruppo spinge tutti gli altri a impegnarsi perch&amp;egrave; DotNetMarche cresca anche nella qualit&amp;agrave; dei suoi contenuti!&lt;br /&gt;
        &lt;/span&gt;&lt;span&gt;Se ritieni al contrario che l'attivit&amp;agrave; del gruppo non sia poi cos&amp;igrave; tanto valida da meritare la tua pubblicit&amp;agrave;, beh, &amp;egrave; il momento che ti impegni in prima persona per far cambiare le cose!&lt;/span&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/ul&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=150" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item><item><title>[SONDAGGIO PROFILO]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/SONDAGGIO-PROFILO.aspx</link><pubDate>Thu, 06 Jul 2006 11:20:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:149</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>Durante la prima cena del gruppo (25 Maggio 2006) sono stati fatti compilare dei questionari per tracciare un profilo dei partecipanti. &lt;br /&gt;
Questi sono i risultati dei 14 moduli pervenuti:&lt;br /&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Quale &amp;egrave; la tua attuale occupazione?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Lavoratore	93,0%&lt;br /&gt;Studente	7,0%&lt;br /&gt;Disoccupato	0,0% &lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Se sei lavoratore, che ruolo\i ricopri?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Titolare / Amministratore delegato &amp;nbsp; &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Amministratore di rete &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7,1%&lt;br /&gt;Project / Product Manager &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 14,3%&lt;br /&gt;Amministratore di database &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;14,3%&lt;br /&gt;Architetto &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;50,0%&lt;br /&gt;Sviluppatore &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;57,1%&lt;br /&gt;Web designer &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0,0%&lt;br /&gt;Altro (specificare) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Quali tecnologie\linguaggi utilizzi abitualmente?&lt;/strong&gt;&lt;br /&gt;
    &lt;pre&gt;C# &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;85,7%&lt;br /&gt;Java &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7,1%&lt;br /&gt;VB.Net &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;50,0%&lt;br /&gt;SQL &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 92,9%&lt;br /&gt;ASP.NET &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 64,3%&lt;br /&gt;VB6 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 35,7%&lt;br /&gt;COM / Win32 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 28,6%&lt;br /&gt;ASP / VBScript / VBA &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;21,4%&lt;br /&gt;.NET Framework &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;78,6%&lt;br /&gt;Delphi &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0,0%&lt;br /&gt;XML Web Services / SOAP / WSE &amp;nbsp; 50,0%&lt;br /&gt;C / C++ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 28,6%&lt;br /&gt;Remoting / DCOM / MSMQ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Enterprise Services (COM+) &amp;nbsp; &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Compact Framework &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 64,3%&lt;br /&gt;HTML / CSS / Javascript &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 71,4%&lt;br /&gt;Altro (specificare) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Quali sono le tue aree di maggior interesse e quali ti piacerebbe approfondire?&lt;/strong&gt;&lt;br /&gt;
    &lt;pre&gt;Object oriented design &amp;amp; patterns &amp;nbsp; &amp;nbsp; 71,4%&lt;br /&gt;Sviluppo mobile &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 50,0%&lt;br /&gt;Sviluppo web &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;71,4%&lt;br /&gt;Project management &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Sviluppo windows forms &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;42,9%&lt;br /&gt;Business intelligence &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 50,0%&lt;br /&gt;Tecnologie per l'accesso ai dati &amp;nbsp; &amp;nbsp; &amp;nbsp;57,1%&lt;br /&gt;Applicazioni distribuite &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;35,7%&lt;br /&gt;Developer tools &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 42,9%&lt;br /&gt;WinFx &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 28,6%&lt;br /&gt;Common Language Runtime &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 28,6%&lt;br /&gt;Computer graphics &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 14,3%&lt;br /&gt;Altro (specificare) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7,1% (Accessibilit&amp;agrave;)&lt;br /&gt;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Quali iniziative ti piacerebbe fossero intraprese dallo user group?&lt;/strong&gt;&lt;br /&gt;
    &lt;pre&gt;Workshop tecnici &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 			78,6%&lt;br /&gt;Community web (blog, forum, ecc..) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 			57,1%&lt;br /&gt;Organizzazione trasferte eventi (eventi microsoft, ecc..) &amp;nbsp; &amp;nbsp;			57,1%&lt;br /&gt;Sviluppo applicazioni open source, o comunque in&amp;nbsp; ambiente collaborativo	2,9%&lt;br /&gt;Cene e riunioni informali &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;			71,4%&lt;br /&gt;Altro (specificare) &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;			0,0%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Ti piacerebbe partecipare agli incontri del DotNetMarche?&lt;/strong&gt;&lt;br /&gt;
    &lt;pre&gt;Si &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;100,0%&lt;br /&gt;No &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Ci penser&amp;ograve; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Se hai risposto no o sei indeciso, ci sono particolari motivi?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Non mi interessa &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Mancanza di tempo &amp;nbsp; 0,0%&lt;br /&gt;Altro &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0,0%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Saresti interessato a fare degli interventi tecnici durante gli incontri?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Si &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;43,0%&lt;br /&gt;No &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7,0%&lt;br /&gt;Forse &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 50,0&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Se si, su quali tematiche?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Object oriented design &amp;amp; patterns &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 28,6%&lt;br /&gt;Sviluppo mobile &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7,1%&lt;br /&gt;Sviluppo web &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Project management &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;21,4%&lt;br /&gt;Sviluppo windows forms &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;14,3%&lt;br /&gt;Business intelligence &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7,1%&lt;br /&gt;Tecnologie per l'accesso ai dati &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7,1%&lt;br /&gt;Applicazioni distribuite &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;14,3%&lt;br /&gt;Developer tools &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7,1%&lt;br /&gt;WinFx &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 14,3%&lt;br /&gt;Common Language Runtime &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 28,6%&lt;br /&gt;Computer graphics &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Altro (specificare) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 21,4% (Sicurezza,Accessibilit&amp;agrave;,Collaboration)&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Con che frequenza vorresti venissero fatti degli incontri?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;30gg &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;14,3%&lt;br /&gt;45gg &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;21,4%&lt;br /&gt;60gg &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;35,7%&lt;br /&gt;75gg &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;14,3%&lt;br /&gt;90gg &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7,1%&lt;br /&gt;Non &amp;egrave; rilevante &amp;nbsp; &amp;nbsp;7,1%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Preferisci degli incontri serali o diurni?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Serali		93,0%&lt;br /&gt;Diurni		7,0%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Di quale durata?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;1-2 ore &amp;nbsp; &amp;nbsp; &amp;nbsp; 21,4%&lt;br /&gt;2-4 ore &amp;nbsp; &amp;nbsp; &amp;nbsp; 71,4%&lt;br /&gt;6-8 ore &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7,1%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Saresti disposto a partecipare anche il sabato?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Si &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;57,1%&lt;br /&gt;No &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Forse &amp;nbsp; &amp;nbsp; &amp;nbsp; 14,3%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Hai problemi a spostarti?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;No &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;64,3%&lt;br /&gt;Dipende dalla frequenza degli incontri &amp;nbsp; &amp;nbsp;28,6%&lt;br /&gt;Massimo 50 Km &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Massimo 100 Km &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0,0%&lt;br /&gt;Massimo 20 Km &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Si sempre &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7,1%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Ti piacerebbe partecipare allo sviluppo di applicazioni all'interno dello users group, o comunque in un ambiente condiviso, per approfondire certe tecnologie e/o tools di sviluppo?&lt;/strong&gt;&lt;br /&gt;
    &lt;pre&gt;Si &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;50,0%&lt;br /&gt;No &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0,0%&lt;br /&gt;Forse &amp;nbsp; &amp;nbsp; 50,0%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sei soddisfatto dell'incontro di oggi?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;pre&gt;Per niente &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Poco &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0,0%&lt;br /&gt;Abbastanza &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 14,3%&lt;br /&gt;Molto &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;57,1%&lt;br /&gt;Meglio di cos&amp;igrave; &amp;nbsp; &amp;nbsp; 28,6%&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Hai delle proposte, questioni o suggerimenti da sottoporre all'attenzione degli organizzatori e dei partecipanti? &lt;/strong&gt;&lt;br /&gt;
    &lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;ul&gt;
    &lt;li&gt;Fare degli incontri di taglio tecnico, sviluppo o sistemistico, in cui le persone possano rapidamente identificarsi&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=149" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item><item><title>[CONTATTI]</title><link>http://dotnetmarche.org/blogs/article/archive/2006/07/06/CONTATTI.aspx</link><pubDate>Thu, 06 Jul 2006 11:18:00 GMT</pubDate><guid isPermaLink="false">61321887-5500-4417-8b9e-633d632ef265:148</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><description>&lt;p class="MsoBodyText"&gt;   &lt;span&gt;Sito web:&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;  &lt;a href="http://www.dotnetmarche.org"&gt;www.dotnetmarche.org&lt;/a&gt;&lt;br /&gt;
e-mail:&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;a href="mailto:staff@dotnetmarche.org"&gt;staff@dotnetmarche.org&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puoi contattarci anche tramite il &lt;a href="/forums/default.aspx"&gt;forum&lt;/a&gt; presente in questo sito, qualcuno sicuramente risponder&amp;agrave;!&lt;br /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p class="MsoBodyText"&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p class="MsoBodyText"&gt;&lt;br /&gt;
&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://dotnetmarche.org/aggbug.aspx?PostID=148" width="1" height="1"&gt;</description><category domain="http://dotnetmarche.org/blogs/article/archive/tags/_5B00_DotNetMarche_5D00_/default.aspx">[DotNetMarche]</category></item></channel></rss>