Windows Workflow Foundation - abilitare la persistenza

by Andrea 06 October 2009 05:10

In rete si trova parecchia documentazione riguardante Windows Workflow Foundation, ma spesso nei vari esempi o articoli non viene descritta una parte fondamentale, come nel caso della persistenza, ho dovuto sfogliare parecchi link prima di trovare il come creare il database per poter utilizzare il provider SqlWorkflowPersistenceService.

Questo provider è il provider che viene fornito di default per persistere un workflow in un database SQL Server. (E' comunque possibile creare un provider custom seguendo le indicazioni che trovate a questo link)
Mantenere un workflow solo in memoria ha parecchie limitazioni, e nel caso di operazioni lunghe, o crash/recycle del processo, questo potrebbe essere un problema non da poco. Ecco che il servizio di persistenza permette di ovviare a questi problemi, mantenendo persistente lo stato, e quindi permettendo il recupero del workflow.
Il runtine del workflow, nel caso abbia un sevizio di persisteza presente, si occupa di salvare in automatico (o volendo anche in modo manuale) il proprio stato, in particolari condizioni:

  • alla fine di una transazione atomica
  • sull'evento di Idle entrando in una Delay Activity
  • quando l'host chiama WorkflowInstance.Unload sull'istanza del flusso di lavoro
  • quando un'istanza del flusso di lavoro viene terminata o si conclude

Ovviamente è in grado di ripristinare il proprio stato in modo automatico, o volendo anche di forzarlo in manuale.

Prima di procedere a scrivere del codice si dovrà predisporre il database all'uso di questo servizio.
Sarà necessario quindi creare un database vuoto (CREATE DATABASE WorkflowPersistenceStore)
e poi lanciare gli script
SqlPersistenceService_Logic.sql e SqlPersistenceService_Schema.sql
che si trovano in
C:\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\en (ovviamente all'interno del database appena creato).

Nell'applicazione, una volta referenziati gli assembly di Windows Workflow Foundation, si potrà aggiungere il servizio da codice nel seguente modo:

   1: // Create the runtime and SqlWorkflowPersistenceService objects.
   2: WorkflowRuntime runtime = new WorkflowRuntime();
   3: SqlWorkflowPersistenceService persistenceService = new SqlWorkflowPersistenceService("connectioString");
   4:  
   5: // Add the SqlWorkflowPersistenceService and start the runtime.
   6: runtime.AddService(persistenceService);
   7: runtime.StartRuntime();
   8:  
   9: ...
  10: // Stop the runtime and remove the SqlWorkflowPersistenceService.
  11: runtime.StopRuntime();
  12: runtime.RemoveService(persistenceService);

Per maggiori informazioni a riguardo di come preparare l'applicazione all'uso del servizio di persistenza, ecco qui il link alla pagina su MSDN: Using SqlWorkflowPersistenceService

Tags:

.NET | Microsoft

Windows Workflow Foundation…da dove partire

by Andrea 06 October 2009 05:02

Dopo parecchio tempo dalla sua uscita, finalmente è capitata l'occasione di potermi studiare (e forse applicare) Windows Forkflow Foundation.

Per chi non lo conoscesse, si tratta di un framework e un engine che permettono di gestire dei processi secondo un preciso flusso. Esistono diverse tipologie di workflow che rispondono a differenti esigenze: nella versione attuale si ha la possibilità di scelta tra sequential workflow e state machine, ma quest'ultimo, nella prossima versione del framework, verrà sostituito dal flow chart).

Windows Workflow Foundation...
provides a programming model, in-process workflow engine and rehostable designer to implement long-running processes as workflows within .NET applications.

Per chi deve iniziare a studiarsi questa tecnologia, i punti di partenza sono i seguenti link:
MSDN Library: Windows Workflow Foundation
.NET Framework Developer Center: Windows Workflow Foundation

Suggerisco anche di scaricare le slide e il codice dell'evento che Raffaele Rialdi ha tenuto a XeDotNet, e che trovate a questo link:
Community Meeting: Workflow Foundation - 11 Maggio 2007

Un ulteriore consiglio a chi stà iniziando ora (come nel mio caso) a conoscere questa tecnlogia, è quello di documentarsi a riguardo delle novità/cambiamenti che verranno introdotti nella prossima versione del Framework, in modo da predisporre l'applicazione per eventuali cambiamenti/migliorie ed evitare quindi di buttare all'aria codice appena prodotto.
Upcoming Changes to .NET Framework 4: Windows Workflow Foundation (WF)

Tags:

.NET | Microsoft

Microsoft MVP ASP.NET…rinnovato!!

by Andrea 01 October 2009 07:51

MVP_logo

Da pochi minuti ho ricevuto la conferma del mio rinnovo come Microsoft MVP ASP.NET.

E' il mio secondo award, e quindi il mio primo rinnovo…ma ho vissuto la giornata esattamente come un anno fa…in trepidante attesa di quella mail, che poteva anche non arrivare mai. E credetemi che è un'attesa infinita.

MVP Open Days 2009Sono veramente felice di essere stato rinnovato, perchè in quest'ultimo anno ho avuto modo di crescere ulteriormente grazie anche a questo premio e alle persone che il programma MVP riesce ad unire.

Un grazie sincero a tutte le persone che mi fanno capire quanto sono appassionato a questo mondo...da chi incontro agli eventi di XeDotNet, a chi scrive nei forum e nei newsgoup…in modi differenti, ma avete sempre stimolato la mia voglia di crescere e di diffondere quel poco che so. ;-)

Ma il più importante ringraziamento (doveroso) va a Maria Elena (la mia fidanzata), per la pazienza che ha nei miei confronti nel permettermi di seguire le mie innumerevoli attività ed impegni.

Grazie!!

Tags: , ,

Microsoft | +1 | .NET | ASP .NET

DynamicData e ColorPicker FieldTemplates

by Andrea 16 September 2009 03:17

Con i Dynamic Data la velocità di realizzare l'applicazione aumenta notevolmente (ovvio che dipende sempre dal tipo di applicazione che si deve realizzare) e con la creazione di FieldTemplates di ha la possibilità di migliorare l'iterazione tra applicazione e utente.

Una delle necessità che ho avuto è stata quella di dover far inserire il valore in esadecimale di un colore (es: #FFFFFF), e consapevole del fatto che un utente non potesse conoscere i valori a memoria, mi sono adoperato per realizzare un opportuno FieldTemplate.
L'ultima versione degli AJAX Control Toolkit mi è venuta in aiuto grazie al controllo ColorPicker che è stato recentemente incluso, ed ecco qui il risultato ottenuto:

ColorFieldTemplate

Il codice del FieldTemplate è il seguente:

   1: public partial class Color_EditField : FieldTemplateUserControl
   2: {
   3:     protected override void ExtractValues(IOrderedDictionary dictionary)
   4:     {
   5:         dictionary[Column.Name] = ConvertEditedValue(txtColor.Text);
   6:     }
   7:  
   8:     public override Control DataControl
   9:     {
  10:         get { return txtColor; }
  11:     }
  12: }
   1: <%@ Control Language="C#" CodeBehind="Color_Edit.ascx.cs" Inherits="DynamicData.FieldTemplates.Color_EditField" AutoEventWireup="True" %>
   2:  
   3: <asp:ImageButton 
   4:     runat="Server" 
   5:     ID="btnOpenColorPicker" 
   6:     style="float:left;margin:0 3px" 
   7:     ValidationGroup="none" 
   8:     ImageUrl="~/images/cp_button.png" 
   9:     AlternateText="Click to show color picker" />
  10: <asp:Panel 
  11:     runat="server"
  12:     ID="pnlColor" 
  13:     style="width:18px;height:18px;border:1px solid #000;margin:0 3px;float:left" />
  14: <atk:ColorPickerExtender 
  15:     runat="server"
  16:     ID="colorPicker"     
  17:     TargetControlID="txtColor" 
  18:     PopupButtonID="btnOpenColorPicker" 
  19:     SampleControlID="pnlColor" 
  20:     PopupPosition="Absolute" />
  21: <asp:TextBox ID="txtColor" 
  22:     runat="server" 
  23:     Text='<%# FieldValueEditString %>' 
  24:     style="visibility:hidden;" />

Nella mia applicazione non avevo la necessita di visualizzare il codice del colore (che compare nella TextBox), ma nel caso a qualcuno interessasse, sarà sufficiente togliere lo stile "visibility:hidden;" dalla TextBox txtColor.

Tags: ,

ASP.NET AJAX | ASP .NET | .NET

Code Snippet plugin per Windows Live Writer

by Andrea 14 September 2009 07:21

Ogni volta che installo Windows Live Writer mi dimentico sempre quale dei tanti Code Snippet plugin fosse quello che utilizzavo.

Ne ho provati diversi, ma il mio preferito rimane sempre quello scritto da Leo Vildosola che potete scaricare partendo da questo link: Code Snippet plugin for Windows Live Writer

csdlg_full 

Mi sono deciso a scrivere questo post dopo che per l'ennesima volta ho chiesto ad Andrea (visto che lui utilizza lo stesso plugin) se si ricordava il nome del plugin, e da dove poterlo scaricare...e così le prossime volte cercherò qui nel blog. ;-)

Tags: ,

Internet | Microsoft | Tempo libero | Sito

ASP.NET Ajax Control Toolkit e DynamicPopulateExtenderControlBase

by Andrea 14 September 2009 06:51

Stavo introducendo il controllo HoverMenuExtender all'interno di uno UserControl e nell'intellisense mi compaiono alcune proprietà che mi risultano "anomale" per il controllo che stavo per utilizzare. Anomale nel senso che non mi aspettavo proprio di trovare tali proprietà in questo controllo.
HoverMenuExtender 
Le proprietà in questione sono quelle che hanno il suffisso Dynamic: DynamicContextKey, DynamicControlID, DynamicServiceMethod e DynamicServicePath.

Visto che (dal nome) potevano fare al caso mio, guardo la documentazione online, e scopro che non esiste documentazione a riguardo. Allora, come spesso accade, scarico i sorgenti degli ajax control toolkit e do un'occhiata al codice per capire dove fossere utilizzate e a cosa servissero. Ed è qui che sono rimasto sorpreso.

I controlli HoverMenuExtender, DropDownExtender, ModalPopupExtender e PopupControlExtender derivano dalla classe base DynamicPopulateExtenderControlBase, che contiene per l'appunto queste proprietà:

  • DynamicServicePath: url del web service che conterrà il metodo da chiamare. (lasciare vuoto se si intende chiamare un page method)
  • DynamicServiceMethod: metodo del web service da chiamare.
  • DynamicContextKey: permette di definire un parametro opzionale per parametrizzare il metodo chiamato. (parametro opzionale)
  • DynamicControlID: id del controllo che verrà utilizzato come container per iniettare il codice HTML restituito dal metodo.

Utilizzando queste proprietà è possibile utilizzare un metodo (DynamicServiceMethod) di un web service (DynamicServicePath) per farsi ritornare una porzione di condice HTML, che verrà poi iniettato in un preciso controllo (DynamicControlID).

Per provare se il tutto funziona correttamente, la via più semplice è quella di provare il tutto.
Creo un metodo in un web service che restituisca una porzione di codice HTML:

   1: [WebMethod]
   2: [ScriptMethod]
   3: public string GetHoverMenuContent(string contextKey)
   4: {
   5:     return String.Format("<span style='{0}'>Hello World!</span>", contextKey);
   6: }

e nella pagina vado a inserire il controllo, con le proprietà correttamente valorizzate:

   1: <ajax:HoverMenuExtender 
   2:     ID="hoverMenuExtender"
   3:     runat="server"
   4:     TargetControlID="linkButton" 
   5:     PopupControlID="Panel1" 
   6:     PopupPosition="Right" 
   7:     DynamicControlID="Panel2"
   8:     DynamicContextKey='font-weight:bold' 
   9:     DynamicServiceMethod="GetHoverMenuContent" 
  10:     DynamicServicePath="~/ajax.asmx" />
  11:  
  12: <asp:Panel ID="Panel1" runat="server" style="display:none;">
  13:   <asp:Label ID="Panel2" runat="server" />
  14: </asp:Panel> 

Il risultato che ho ottenuto è stato esattamente quello voluto, e quindi che al passaggio del mouse sopra al linkButton (o al controllo definito nella proprietà TargetControlID), è stato chiamato il metodo del web service, passando nel parametro contextKey il valore specificato nella prorietà DynamicContextKey (in questo caso il valore è fisso a font-weight:bold), e una volta ritornato il codice HTML, questo è stato inserito come innerHTML del controllo Panel2, e il Panel1 reso visibile.

In poche parole, tramite queste proprietà si ha la possibilità di popolare i controlli con maggiore dinamicità, e delegando la creazione di parte del contenuto HTML ad un metodo esterno. Questo in molti casi risulta veramente utile, permettondo con poche righe di codice di ottenere il comportamento/effetto voluto, e dimostrando per l'ennesima volta la flessibilità dei controlli contenuti negli AJAX Control Toolkit.

Tags: ,

ASP.NET AJAX | ASP .NET | .NET

Pubblicata agenda XeDotNet

by Andrea 27 August 2009 05:34

logo_xedotnet E' stata pubblicata l'agenda con i Community Meeting del prossimo semestre di XeDotNet.

  • 25 Settembre 2009 – PATTERN TRACK
    • Model-View-ViewModel Applied: real world WPF application
    • Model-View-ViewModel e la UI Composition: WPF Power
  • 16 Ottobre 2009 – TFS TRACK
    • Team Foundation Server Database Edition
    • Scrum for Team System, non solo teoria
  • 6 Novembre 2009 – WEB TRACK
    • Windows Communication Foundation: normalizzare e controllare i servizi WCF
    • Silverlight do it better: Silverlight, Ria Services e le LOB Applications
  • 11 Dicembre 2009 – DATA TRACK
    • Entity Framework 4.0: Promessa mantenuta?
    • Dynamic Data 4.0 

Per informazioni e registrazione:
http://www.xedotnet.org/nextmeetings.aspx

Per quanto mi riguarda, terrò la sessione relativa ai Dynamic Data 4  l'11 Dicembre 2009.
La sessione sarà dedicata a casi reali (come è già emerso da chiacchere con alcuni di voi), ma prima di iniziare a preparare il materiale, sarei curioso di sapere come preferireste fosse trattato l'argomento, o quali particolari problematiche vorreste fossero affrontate. 
E mi raccomando, non esitate a contattarmi, proponendo argomenti/esempi di vostro interesse su questa tecnologia, perchè potrebbero essere di interesse comune.

Technorati Tags: ,

Tags: ,

XeDotNet | .NET

Gestione commenti su BlogEngine.NET

by Andrea 20 August 2009 08:26

Una mancanza che ho sempre trovato in BlogEngine.NET era di non avere una gestione centralizzata dei commenti. Per cancellare o approvare un commento si doveva necessariamente farlo dalla pagina del post, che comportava il conoscere esattamente dove fosse stato postato quel commento (link che viene comunicato via mail).

Scaricando l'ultima versione presente in codeplex, nella sezione Source Code(in quanto non è ancora stata rilasiata una release ufficiale) è stata aggiunta la possibilità di visualizzare e gestire i commenti direttamente dalla sezione Admin del proprio blog.
Da questa sezione è possibile infatti visualizzare tutti i commenti, approvarli in caso di moderazione attiva, cancellarli e modificarli (cosa che invece non approvo molto).

La sezione è ancora in fase di sviluppo, me devo ammenttere che funziona perfettamente ed è una grande comodità.

La versione iniziale di BlogEngine.NET che include questa funzionalità è la 1.5.1.17.

Technorati Tags: ,

Tags:

ASP .NET | .NET | Sito

Italian Agile Day

by andrea 30 July 2009 03:14

Anche quest'anno ritorna l'Italian Agile Day, il 20 novembre 2009 a Bologna.

Italian Agile Day 2009!

IAD120Venerdi’ 20 Novembre 2009 si terrà a Bologna il sesto Italian Agile Day. Si tratta di una conferenza gratuita di un giorno dedicata alle metodologie Agili per lo sviluppo e la gestione dei progetti software rivolta agli sviluppatori, project leaders, IT managers, tester, architetti e coach che hanno esperienze da condividere o che iniziano solo ora ad interessarsi a queste tematiche. La giornata ha come obiettivo la conoscenza pratica, le esperienze sul campo e un attivo coinvolgimento di tutti i partecipanti. L’accesso è libero previa registrazione, i posti sono limitati. L’evento, per la quarta volta consecutiva, si auto-finanzierà.

L'evento, come specificato, è GRATUITO, e si auto-finanzierà. E anche quest'anno ho dato il mio contributo, sperando questa volta di riuscire ad esserci (e che non capitino i soliti lavori urgenti).
Per chiunque creda in questo tipo di eventi, e voglia dare il suo contributo, trova informazioni in questa pagina http://www.agileday.it/front/sponsor, mentre, per il programma e l'apertura delle iscrizioni dovremmo attendere ancora un pò.
Link: http://www.agileday.it/front/2009/italian-agile-day-2009/

Technorati Tags:

Tags:

Generale

Reporting Services - report snapshots

by andrea 23 July 2009 02:31

Una funzionalità che trovo molto utilie di Reporting Services sono gli Report Snapshots.

Cos'è un report snapshot?

Uno Report Snapshot non è altro che una copia del report, eseguito in un preciso istante. Questa copia conterrà tutte le informazioni necessarie per permettere di visualizzare il report in un secondo momento, e avere lo stato al momento della sua creazione.

Quando viene chiesto di salavare uno snapshots, Reporting Services esegue il report in questione e immagazzina tutte le informazioni che vanno a popolare i dataset utilizzati nel report stesso (e anche il layout del report). In questo modo, quando viene richiesta la visualizzazione di un preciso Snapshot, si hanno a disposizione i dati già elaborati, che erano presenti in quel preciso istante (data + ora).
Ecco cosa viene salvato nel server di Reporting Services:

  • The result set (that is, the data in the report, retrieved through the credentials specified in the Data Sources properties page of the report).
  • The underlying report definition, as it exists at the time the snapshot was created. If the report definition was subsequently modified after the snapshot was generated, those changes are not reflected in the snapshot.
  • Parameter values that are used to obtain or filter the result set.
  • Embedded resources, such as images. External resources that are linked to a report are not stored with the report snapshot.

Un enorme vantaggio, che porta all'uso dei Report Snapshots, è il fatto di poter essere schedulati, ed esistono molte impostazioni possibili a riguardo. (esecuzione a intervalli prestabiliti, in precisi giorni, una sola volta, ...)

I Report Snapshots hanno però anche delle limitazioni, una di queste, è dovuta al fatto che vengono salvanti anche i valori dei parametri, e questo comporta che se vogliamo Snapshot con parametri differenti, si dovranno creare differenti Report (o Linked Reports), ma questo è anche capibile.
In alcune condizioni però, è possibile utilizzare un parametro (visibile) all'interno del report per filtrare i dati. Infatti, il filtro dei dati all'interno del report è una prassi consentita, in quanto viene applicato ai dati che popolano i DataSet (e quindi immagazzinati nello snapshot)

Quando utilizzare i report snapshots?

Possono essere utilizzati prevalentemente per due motivazioni:

  • Si vuole avere uno storico di un determinato report.
    Schedulando la creazione di snapshot a determinati intervalli, permettono di avere esattamente la situazione (il risultato del report) in quel dato momento, e quindi poter eseguire a posteriore una visualizzazione di tali dati.
  • Esecuzione di report che richiedono molto tempo di elaborazione.
    E' possibile schedulare l'esecuzione di snapshot per ovviare al problema dell'attesa per l'elaborazione di report che richiedono un lungo tempo di caricamento. In questo modo, l'utente può visualizzare l'ultimo snapshot eseguito, che verrà caricato velocemente in quanto i dataset sono già stati popolati durante la creazione dello snapshot, risparmiando così l'attesa all'utente.

Come visualizzare uno snapshot nel controllo ReportViewer

Per visualizzare uno snapshot di un preciso report nel controllo ReportViewer è sufficiente impostare la proprietà HistoryId del controllo, con l'ID dello snapshot che si vuole visualizzare.

reportViewer.ServerReport.HistoryId = historyID;

Utilizzando il web service esposto da Reporting Services (Consumare il web service di Reporting Services) è possibile recuperare la lista di Snapshots di un determinato report, e utilizzare i dati ricevuti per recuperare l'identificativo dell'ultimo Snapshot eseguito.
Ecco come poter recuperare la lista di tutti gli snapshot di un determinato report:

   1: public ReportHistorySnapshot[] GetReportHistory(string reportFullPath)
   2: {
   3:   using (ReportingService2005SoapClient rs = ReportingService2005SoapClient())
   4:   {
   5:       rs.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
   6:       rs.ClientCredentials.Windows.ClientCredential.UserName = "username";
   7:       rs.ClientCredentials.Windows.ClientCredential.Password = "password";      
   8:  
   9:       ReportHistorySnapshot[] snapshots = null;
  10:       rs.ListReportHistory(reportFullPath, out snapshots);
  11:  
  12:       return snapshots;
  13:   }
  14: }

Link:

Tags: ,

SQL Server | .NET | Reporting Services