Showing posts with label VS 2008. Show all posts
Showing posts with label VS 2008. Show all posts

Tuesday, April 21, 2009

Macro vs Visual Source Safe

. Tuesday, April 21, 2009
0 commenti

Recentemente ho avuto la “necessità” di creare una macro in Visual Studio che eseguisse delle operazioni di Replace in diversi file del progetto.
Come in genere accade in questi casi è sufficiente registrare la macro tramite:
Tools > Macros > Record TemporaryMacro
ed il gioco è fatto.

Anche se può sembrare assurdo, lanciando la macro non ottenevo il risultato sperato, bensì la seguente eccezione:
"The server threw an exception. (Exception from HRESULT: 0X80010105 (RPS_E_SERVERFAULT))"

ErrorMacro

A dir la verità ho subito pensato ad un bug nella macro - tale eventualità non è stata esclusa immediatamente anche se in realtà non avevo scritto neanche una riga di codice - o addirittura nell'IDE.
Il problema è causato, come mi è stato fatto notare da un mio collega, dalla mancata gestione in automatico del check out (il progetto è gestito tramite Visual SourceSafe) del file da modificare.
Sostanzialmente se i file sono preventivamente messi in check out allora la macro fa il suo lavoro - giustamente -.
A questo punto, è diventata una questione di principio, riuscire a risolvere il problema, nonostante la scarsa utilità della macro.
Nello caso specifico ho convertito, per semplicità, il tutto in tre macro distinte:

  1. eseguire una ricerca nei file del progetto tramite regular expression;
  2. eseguire il check out dei file in base ai risultati mostrati nella finestra Find Results 1, prodotti dal punto 1;
  3. eseguire la funzione di Replace per ogni file in check out.

Forse la cosa più interessante da mostrare è il codice che ho scritto per svolgere il secondo punto:

   1: DTE.Windows.Item(Constants.vsWindowKindFindResults1).Activate()
   2: Dim resultsWin As Window = DTE.Windows.Item(Constants.vsWindowKindFindResults1)
   3: Dim sel As TextSelection = resultsWin.Selection
   4: If Not sel Is Nothing Then
   5:   sel.EndOfDocument(True)
   6:   Dim countLine = sel.CurrentLine
   7:   sel.StartOfDocument()
   8:   Dim lineStr As String
   9:   While (sel.CurrentLine < countLine)
  10:    sel.StartOfLine(False)
  11:    sel.EndOfLine(True)
  12:    lineStr = sel.Text
  13:    Dim reg As Regex = New Regex("c:.*(?=\(\d)", RegexOptions.IgnoreCase)
  14:    Dim line As String = reg.Match(lineStr).Value
  15:    If line.Length > 0 And DTE.SourceControl.IsItemCheckedOut(line) = False Then
  16:      DTE.SourceControl.CheckOutItem(line)
  17:    End If
  18:    sel.LineDown(True)
  19:  End While
  20: End If
  21: Dim win As Window = DTE.Windows.Item(Constants.vsWindowKindOutput)
  22: Dim ow As OutputWindow = win.Object
  23: ow.ActivePane.Activate()
  24: ow.ActivePane.OutputString("Completo!!!")

Anche se il codice parla abbastanza da solo, alcune righe meritano di essere un minimo commentate.
In particolare le prime tre righe consentono di poter analizzare il testo presente nella finestra dei risultati: Find Results 1 frutto della ricerca precedentemente eseguita.
Dopo aver calcolato il numero di righe presenti (riga 5 e 6) eseguo un ciclo estrapolando per ognuna l'eventuale path tramite una regular expression costruita ad hoc per il mio caso(riga 13).
In caso di match eseguo il check out del file richiamando il metodo CheckOutItem (riga 16).
Per concludere nella finestra di Output mostro un messaggio di fine operazione (riga 21, 22, 23, 24).

Read More »»

Wednesday, March 11, 2009

Ottimizzazione Js

. Wednesday, March 11, 2009
0 commenti

L’ottimizzazione di una applicazione web passa anche dall’ottimizzazione dei singoli elementi script Js che la compongono.
Rimuovere spazi, commenti, righe vuote ecc può ridurre dal 20% al 30% la dimensione del nostro script con un bel risparmio per il browser che lo deve scaricare.
I modi per eseguire questo tipo di ottimizzazione sono diversi.
In Visual Studio non mi risulta ci sia un tool integrato, ma nulla ci vieta di aggiungerne uno specifico. Attraverso External Tools abbiamo accesso ad una serie di strumenti esterni che ci facilitano lo sviluppo/debug. Per esempio nella lista, di default, è disponibile Create Guid che consente di generare un identificatore GUID in base ai criteri specificati.
A questi strumenti possiamo aggiungerne altri come per esempio JsTrim, un compressor Js a riga di comando.
Il componente permette essenzialmente due livelli di compressione. Il primo, basic, esegue un'eliminazione di tutto ciò che può essere superfluo, come accennavamo ad inzio post. Il secondo invece utilizza l'algoritmo di Dan Edvards che permette di ottenere un’ottimizzazione con un risparmio di più del 40%. Quest'ultimo però, è più lento nel caricamento rispetto al primo, per via della decompressione che il browser deve attuare.
I passi per aggiungere JsTrim alla lista degli strumenti:
cliccare su Tools > External Tools


JsTrim

Indicare 1) un titolo nell'apposito campo, 2) il path dell'eseguibile (per uniformità si può copiare il punto exe di JsTrim nella cartella ...\Microsoft Visual Studio 8\Common7\Tools), 3) gli argomenti (per maggiori dettagli vi rimando alla documentazione).
Per chi fosse interessato a YUI Compressor segnalo il seguente post:
Compressing and obfuscating javascript and css files with YUICompressor in Visual Studio
Per chi invece non utilizza Visual Studio, funzionalità di ottimizzazioni sono presenti in molti applicativi. Giusto per citarne uno: Aptana che avevo già segnalato tempo fa al seguente post.
Esistono anche servizi web in cui è sufficiente indicare il file js da ottimizzare e il servizio fa il resto.
Per esempio in Javascript Utility Web Site è disponibile un JavaScript Compactor (il file deve essere maggiore di 1000 bytes).
Al completamento della procedura viene mostrata la percentuale di riduzione della dimensione del file.
Altro sito estremamente interessante è Bananascript che, come il precedente, mostra tutta una serie di statistiche a fine processo ma come si può leggere dalle faq:
"Besides the common removal of comments, tabs and spaces as seen in many other tools, this tool also performs "real" compression on the files. The idea is simple, replace long recurring byte sequences by shorter ones."
non si limita ad eliminare il superfluo ma esegue una compressione reale.bananascript1

Read More »»

Monday, February 16, 2009

Link .Net #15

. Monday, February 16, 2009
0 commenti

Quindicesimo appuntamento con Link .Net:

WPF : Circular Progress Bar

Stanchi della solita progress bar? C’è chi si è divertito nel realizzare uno UserControl in WPF a forma circolare. en

Adding SharePoint Intellisense to Visual Studio 2008
Come abilitare l'intellisense per SharePoint utilizzando Visual Studio 2008. en

SQL SERVER - Simple Example of Reading XML File Using T-SQL
Un semplice tutorial su come leggere tramite T-SQL un file XML. en

Microsoft Recite
Progetto Microsoft per Windows Mobile che consente di registrare note vocali. Da provare. en

Read More »»

Sunday, December 21, 2008

Un coniglio in Outlook 2007

. Sunday, December 21, 2008
0 commenti

Nel 2005 si registrava un boom di vendite di un oggetto tecnologico, a forma di coniglietto sempre connesso ad internet chiamato Nabaztag.
Sul tecno coniglio si trovano tantissime informazioni sulla rete, sono state create delle vere e proprie community, diventando in pochissimo tempo un oggetto fashion ma che presenta ancora oggi un bel pò di pecche.
L’intento di questo post è quello di parlare di un suo particolare aspetto cioè le API attraverso le quali possiamo inviare messaggi o fargli eseguire delle coreografie (luci e movimento delle orecchie) o dargli in pasto in stream un mp3.
Gli ingredienti di questo semplice tutorial sono Outlook 2007 e il Framework .Net.
Ma partiamo con ordine. Prima di tutto bisogna recuperare due informazioni importanti cioè il serial number del Nabaztag e il token cioè una serie di cifre con la funzione di essere un identificatore extra.
Queste due informazioni si possono recuperare dalla pagina di preferenze del coniglio:

nabaztag
Lo scopo è quello di poter usare Outlook per inviare un messaggio al coniglio e per far questo ho creato un progetto di tipo Add-in per Outlook 2007 tramite Visual Studio 2008:

nabaztag1 
Con Office 2007 è stata introdotta una nuova interfaccia utente chiamata Ribbon che ha innescato un notevole cambiamento nella programmazione per Office.
Aggiungo al progetto Add-in un nuovo item di tipo Ribbon:

nabaztag2
Per chi vuole approfondire l’argomento Ribbon segnalo questo articolo pubblicato su MSDN Magazine (Febbraio 2007):
Ampliare 2007 Office System con proprie schede e controlli Ribbon

Per semplicità e brevità mostrerò soltanto come sia possibile inviare con queste poche righe di codice un messaggio TTS.
Il primo passo consiste nella creazione di una classe Bunny che presenta una serie di property e un metodo Send che ha la funzione di impacchettare il messaggio da inviare al server. 
Inviare un evento al tecno roditore significa effettuare una richiesta al seguente indirizzo:
http://api.nabaztag.com/vl/FR/api.jsp
passando una serie di parametri che potete trovare nella documentazione delle API.
Nell’esempio oltre al serial e al token invio, il messaggio TTS, la lingua e la voce che leggerà il messaggio.
Quest’ultimo viene indicato tramite il parametro voice.
Alcuni esempi di voci che potete selezionare:

UK - Leonard UK - Mister muggles UK - Penelope
UK - Shirley US-Billye FR - Archibald

 

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Configuration;
   4: using System.Linq;
   5: using System.Text;
   6: using System.Net;
   7:  
   8: namespace LookNabaztag
   9: {
  10:   public class Bunny
  11:   {
  12:     private string url = "http://api.nabaztag.com/vl/FR/api.jsp?";
  13:  
  14:     private string tts;
  15:     public string TTS
  16:     {
  17:       get
  18:       {
  19:         StringBuilder sbTTS = new StringBuilder();
  20:         if (tts..Trim().Length > 0)
  21:           sbTTS.Append("&tts=" + tts.Trim().Replace(" ", "+"));
  22:         if (voice..Trim().Length > 0)
  23:           sbTTS.Append("&voice=" + voice.Trim());
  24:         return sbTTS.ToString();
  25:        }
  26:        set 
  27:        { 
  28:          tts = value; 
  29:        }
  30:      }
  31:  
  32:      private string voice;
  33:      public string Voice
  34:      {
  35:        get 
  36:        { 
  37:          return voice; 
  38:        }
  39:        set 
  40:        { 
  41:          voice = value; 
  42:        }
  43:     }
  44:  
  45:     public void SendMessage()
  46:     {
  47:       WebRequest request;
  48:       try
  49:       {
  50:         StringBuilder sbUrl = new StringBuilder();
  51:         sbUrl.Append(url);
  52:         sbUrl.Append("sn=");
  53:         //Recupero dall'app.config il seriale
  54:         sbUrl.Append(ConfigurationSettings.AppSettings["serial"]);
  55:         sbUrl.Append("&token=");
  56:         //Recupero dall'app.config il token
  57:         sbUrl.Append(ConfigurationSettings.AppSettings["token"]);
  58:         sbUrl.Append(TTS);
  59:         request = WebRequest.Create(sbUrl.ToString());
  60:         WebResponse response = request.GetResponse();
  61:       }
  62:       catch (Exception exc)
  63:       {
  64:         string error = exc.Message;
  65:       }
  66:     }
  67:   }
  68: }


Adesso ci possiamo concentrare sul Ribbon:


nabaztag3 
Ho evidenziato nell’immagine due aspetti importanti della configurazione del Ribbon:

1) il nome dell’etichetta dell’add-in,

2) la tipologia.

In questo caso le tipologie che ho indicato tramite il property RibbonType sono due: Microsoft.Outlook.Mail.Compose, Microsoft.Outlook.Mail.Read indicando che solo al momento di lettura o composizione del messaggio di posta elettronica l’add-in sarà visibile.

Nel Group1 ho inserito un semplice controllo Button assegnando un’immagine per dargli un aspetto più simpatico.

Sull’evento click del Button vado a recuperare il corpo dell’email tramite il property Body per poi instanziare la classe Bunny vista in precedenza:

   1: using Outlook = Microsoft.Office.Interop.Outlook;
   2: .....
   3: //Recupero testo email
   4: Outlook.MailItem mail = 
   5:   (Outlook.MailItem)Globals.ThisAddIn.Application.Inspectors[1].CurrentItem;
   6: if (mail != null)
   7: {
   8:   Bunny bunny = new Bunny();
   9:   bunny.TTS = mail.Body;
  10:   bunny.Voice = "UK-Shirley";
  11:   bunny.SendMessage();
  12: }


Non ci rimane che osservare il risultato finale:

nabaztag4 
Se non sono presenti i soliti disservizi dei server Violet allora cliccando il tasto Send verrà inviato al coniglio un messaggio contenente il corpo dell’email.

Read More »»

Sunday, December 14, 2008

Flex nel mondo .NET

. Sunday, December 14, 2008
0 commenti

L'innegabile crescente successo del framework open source Adobe Flex (per applicazioni RIA) ha portato, oltre al famoso Flex Builder, alla creazione di diversi ambienti utili allo sviluppo e al debugging.
Si pensi ad IntelliJ IDEA, un IDE Java, che recentemente ha aggiunto il supporto per Adobe Flex oppure alla recente partnership di Abobe con SAP.  SapphireSteel, che chi sviluppa in Ruby avrà sicuramente sentito nominare, ha presentato Ametista per lo sviluppo in Visual Studio usando Flex. Merita di essere segnalato anche un framework: WebORB in versione .NET per l'accesso ai dati da Flex/Flash.
Le feature sono diverse, si passa dal supporto per Silverlight, ai template per Visual Studio, supporto per MSMQ queue ecc.
Questa soluzione si affianca ad un altro framework: FluorineFx che implementa Flex/Flash Remoting, Flex Data Services sempre per il .NET Framework.

Ovviamente dal canto mio trovo più interessante osservare alcuni casi che riguardano più da vicino .NET. Nonostante non abbia mai scritto una riga di codice con le API di Flex, ho voluto provare a togliermi la curiosità di sapere se per noi sviluppatori .NET la scelta di Silverlight sia proprio scontata, quindi per eseguire qualche esperimento ho utilizzato Tofino, plugin per Visual Studio 2008 presentato da Ensemble.

Il setup del plugin pesa all'incira 83 MB e per funzionare necessita che Java sia installato. Tramite i template aggiunti possiamo creare facilmente un progetto Flex:

Tofino1 
Ed è qui che sono iniziati i "problemi".

Pur trattandosi di una plugin in beta, trovarsi senza supporto per l'intellisense per i file MXML o per l'ActionScript è stato un pò "sconfortante". Per il momento non è previsto neanche un editor visuale per MXML.  Con questo non voglio assolutamente sminuire il lavoro svolto, anzi sono certo che continuerò con interesse a seguire l'evolversi non solo di questo plugin ma di tutti gli esempi di integrazione del mondo Flash nel mondo .NET ma, trovo che per il momento, sviluppare tramite il framework Flex in ambiente .NET non sia praticabile o per meglio dire la strada da percorrere è sicuramente più in salita rispetto ad uno che si avvicina per la prima volta a Silverlight.

Read More »»

Wednesday, November 12, 2008

Ritornare valore da popup con JQuery

. Wednesday, November 12, 2008
0 commenti

Nello sviluppo di web application, può capitare di dover ritornare uno o più valori selezionati in una pagina di popup ad una pagina parent.  Per questo scopo userò lo strafamoso framework jQuery.
Tra gli strumenti di lavoro, oltre alla libreria, troverete Visual Studio 2008 SP1 con supporto per l'intellisense.
jQuery 1.2.6 (Visual Studio Autocomplete Documentation)
è il primo risultato visibile dell'accordo che Microsoft ha recentemente stretto con il team di jQuery per integrare completamente questa magnifica libreria nella versione 2010 di Visual Studio.
Per maggiori dettagli vi rimando al post di Rick Strahl.
Ma passiamo a dare uno sguardo ad un pò di codice.
Per il tutorial servono due web form:
Default.aspx
Popup.aspx
composte rispettivamente, dal punto di vista del markup, nel seguente modo:

   1: <body>
   2:   <form id="form1" runat="server">
   3:     <div>
   4:       <asp:TextBox ID="txtValue" runat="server" Text="Pagina 1"></asp:TextBox>
   5:       <input type="button" id="btnOpen" value="Open" onclick="Open()"/>
   6:     </div>
   7:   </form>
   8: </body>

   1: <body>
   2:   <form id="form1" runat="server">
   3:     <div>
   4:       <asp:TextBox ID="txtReturnValue" runat="server" Text=""></asp:TextBox>
   5:       <input type="button" id="btnReturn" value="Ritorno" onclick="SetValue()" />
   6:     </div>
   7:   </form>
   8: </body>

Entrambe le pagine presentano un controllo textbox e un input di tipo button.
Nello specifico, l'input con id btnOpen richiama una funzione javascript che si occupa di aprire la pagina Popup.aspx allo scatenarsi dell'evento onclick:


   1: <script type="text/javascript">
   2:   function Open() {
   3:     $(open("Popup.aspx", "external", "width=300;height=300;resizable=0"));
   4:   }
</script>

Non ci resta che inviare il valore del textbox con id txtReturnValue della pagina di Popup.aspx alla pagina chiamante, settando il valore del textbox con id txtValue:


   1: <script type="text/javascript">
   2:   function SetValue() {
   3:     window.parent.opener.$("#txtValue").val($("#txtReturnValue").val());
   4:     $(close());
   5:   }
</script>


Il linea di massima con tre linee di codice si è raggiunto l'obiettivo.
Vediamo di rendere l'esempio un pò più "appetitoso".
Supponiamo di avere una griglia con una lista di dati e supponiamo che dalla pagina di popup vogliamo indicare un valore su cui eseguire un filtro.
I passi per raggiungere lo scopo possono essere:


  • Dalla pagina Popup.aspx richiamare una funzione javascript nella pagina Default.aspx passando come parametro il valore di filtro.
  • La funzione sopra indicata invia tramite JQuery Ajax API il dato ad un Web Service.
  • Parsing dell'xml (che contiene i dati filtrati) ritornato dal Web Service.

Partiamo dal creare un Web Service: WSTest.asmx.
Per semplicità il metodo GetDati ritorna un DataSet:

   1: using System;
   2: using System.Data;
   3: using System.Collections.Generic;
   4: using System.Linq;
   5: using System.Web;
   6: using System.Web.Services;
   7:  
   8: namespace WebApplication2
   9: {
  10:   /// <summary>
  11:   /// Summary description for WSTest

  12:   /// </summary>
  13:   [WebService(Namespace = "http://tempuri.org/")]
  14:   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  15:   [System.ComponentModel.ToolboxItem(false)]
  16:   // To allow this Web Service to be called from script, using ASP.NET AJAX,   
uncomment the following line.
  17:   // [System.Web.Script.Services.ScriptService]
  18:   public class WSTest : System.Web.Services.WebService
  19:   {
  20:     [WebMethod]
  21:     public DataSet GetDati( string filter)
  22:     {
  23:       //Eseguo le operazioni di filtro e ritorno un DataSet
  24:     }
  25:   }
  26: }

Invece la funzione ajax che si occupa di richiamare il web service e di parserizzare l'xml è la seguente:

   1: function Filter( filterValue) {
   2:     $.ajax({
   3:         type: "POST",
   4:         url: "WSTest.asmx/GetDati",
   5:         data: "filter=" + filterValue,
   6:         dataType: "xml",
   7:         success: function(response) {
   8:             var table = "<table border=\"1\">";
   9:             $("DTDati", response).each(function() {
  10:             var tr = "<tr><td>" + $("Id", this).text() + "</td><td>" + 
$("Desc", this).text() + "</td></tr>";
  11:             table = table + tr;
  12:                 })
  13:             $("#dv").append( table);
  14:             },
  15:             error: function(resp) {
  16:                 alert(resp);
  17:                 }
  18:         });
  19: }

In parole molto semplici la funzione Filter riceve il valore su cui effettuare il filtro. Viene richiamato il metodo GetDati indicato come valore del parametro url. In caso di successo viene lanciata la funzione che accetta un argomento restituito dal server, formattato in base al paramento dataType.
Itero sugli elementi di DTTati (name del DataTable) per generare l'html della tabella da renderizzare.
Dalla pagina Popup.aspx per lanciare la funzione Filter inserisco il codice della riga 4):

   1: <script type="text/javascript">
   2: function SetValue() {
   3:   window.parent.opener.$("#txtValue").val($("#txtReturnValue").val());
   4:   window.parent.opener.Filter($("#txtReturnValue").val());
   5:   $(close());
   6: }
   7: </script>


Come sempre questa soluzione non è certo da considerarsi quella definitiva ma solo come uno spunto.
Infatti si potrebbero apportare delle significative modifiche per migliorare di molto l'esempio come l'uso di JSON in sostituzione dell'xml, l'uso di AJAX Data Controls invece di generare il markup della griglia oppure l'uso di WCF (Windows Communication Foundation) al posto del Web Services.

Read More »»