Sharepoint 2007: Creazione di un Workflow rilevando un valore da una pagina Asp.Net (VB.Net e C#)

In questo articolo, vedremo come utilizzare un Workflow in Sharepoint 2007, utilizzando il nuovo framework 3.0. In tale Workflow utilizzeremo una pagina web (aspx) nella quale dovremmo rilevare il valore di una casella di testo.

il
Sviluppatore Microsoft .Net, Collaboratore di IProgrammatori

In questo articolo viene descritta la procedura per la creazione di un WorkFlow, il quale rileva e visualizza nel dettaglio del Workflow, il valore situato in una casella di testo di una pagina Asp.net.
Vedremo come utilizzare un workflow creato con Windows Workflow Foundation, da utilizzare in una pagina Aspx in Sharepoint 2007.

Creazione del progetto e progettazione Workflow
Da Visual Studio 2005 si crea un nuovo progetto di tipo sharepoint, selezionare il modello “Sharepoint Server Sequential Workflow Library”.
Il workflow sarà composto di un solo nuovo elemento e precisamente del controllo logToHistoryListActivity, tale controllo visualizzare a fine esecuzione del workflow il dato immesso nella casella di testo.
Il Workflow dovrà avere l’aspetto simile a quello della figura 1.

Figura 1

Per il controllo logToHistoryListACtivity, impostiamo la proprietà HistoryDescription, con un campo denominato (dalla finestra di questa proprietà, selezionare il tab “Bind To a new member”, opzione create Field ) HistoryDescription .
Mentre per la proprietà HistoryOutCome, impostiamo il seguente valore (di tipo field) HistoryOutcome
Fatto ciò aggiungiamo un metodo per l’evento MethodInvoking, in questo evento, visualizzeremo il testo che verrà riportato nel dettaglio del workflow, in particolare nella sezione “Cronologia flusso di lavoro”.
Il codice di tale operazioni è il seguente:

 

VB.Net
Private Sub logAttivita_MethodInvoking(ByVal sender As System.Object, ByVal e As System.EventArgs)
        HistoryDescription = "Valore passato: " & workflowProperties.InitiationData
        HistoryOutcome = "Workflow Terminato"
 
    End Sub
 
C#
private void logAttivita_MethodInvoking(object sender, EventArgs e)
        {
            HistoryDescription = "Valore Passato: " + workflowProperties.InitiationData;
            HistoryOutcome = "Workflow Terminato";
        }

 

 

Creazione dei file XM:
Terminata la fase per di modellazione del nostro workflow, non ci resta che impostare i file di configurazioni, quali feature.xml e workflow.xml, creati di default nel progetto, nel momento in cui si crea un nuovo progetto di Sharepoint.
Selezionare il file Feature.xml, inseriamo il code snippet denominato Feature.xml (Snippets->SharePoint Workflow).
Di seguito si riporta il file Feature.xml, completato in ogni sua parte.
 

 

 

<?xmlversion="1.0"encoding="utf-8"?>
<!-- _lcid="1033" _version="12.0.3111" _dal="1" -->
<!-- _LocalBinding -->
 
<!-- Insert Feature.xml Code Snippet here.  To do this:
1) Right click on this page and select "Insert Snippet" (or press Ctrl+K, then X)
2) Select Snippets->SharePoint Workflow->Feature.xml Code -->
<Feature Id="3A61C8FC-0986-443c-B9CF-DA5F187E09C8"
          Title="Rileva Valori"
          Description="questo  Workflow rileva il valore di una casella di testo e lo visualizza a video"
          Version="12.0.0.0"
          Scope="Site"
          ReceiverAssembly="Microsoft.Office.Workflow.Feature, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
          ReceiverClass="Microsoft.Office.Workflow.Feature.WorkflowFeatureReceiver"
          xmlns="http://schemas.microsoft.com/sharepoint/">
  <ElementManifests>
    <ElementManifestLocation="workflow.xml" />
  </ElementManifests>
  <Properties>
    <PropertyKey="GloballyAvailable"Value="true" />
 </Properties>
</Feature>

 

Terminata la fase di compilazione del file Feature.xml non ci resta che completare il file Workflow.xml.
Anche in questo caso, una volta selezionato il file Workflow.xml, inseriamo il code snippet, denominato Workflow.xml (Snippets->SharePoint Workflow).
Di seguito si riporta il file workflow.xml, completo in ogni sua parte, da ricordare che l’attributo publickeytoken si ottiene registrando la dll nella gac, la quale dll dev’essere compilata con una firma sicura.
File Workflow.xml

 

<?xmlversion="1.0"encoding="utf-8" ?>
<!-- _lcid="1033" _version="12.0.3015" _dal="1"   -->
<!-- _LocalBinding   -->
 
<!-- Insert Workflow.xml Code Snippet here.  To do this:
1) Right click on this page and select "Insert Snippet" (or press Ctrl+K, then X)
2) Select Snippets->SharePoint Workflow->Workflow.xml Code -->
<Elementsxmlns="http://schemas.microsoft.com/sharepoint/">
 <Workflow
       Name="Rileva Valore"
       Description="Il Workflow visualizza il valore di una casella di testo di una pagina"
       Id="E96182E2-8243-4e2f-8103-7C616B022D6A"
       CodeBesideClass="SPWFRilevaValore.Workflow1"
       CodeBesideAssembly="SPWFRilevaValore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dec95f95a7b44c08"
       InstantiationUrl="_layouts/PaginaValore.aspx">
 
    <Categories/>
    <!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
    <MetaData>
      <AssociateOnActivation>false</AssociateOnActivation>
    </MetaData>
  </Workflow>
</Elements>

 

Creazione della pagina Asp.Net
La creazione del nostro progetto sta giungendo alla fine, ora rimane sola la parte web, in particolare la creazione di una pagina Asp.Net, la quale conterrà una casella di testo, ed un pulsante, quest’ultimo avrà il compito di avviare il workflow.
Aggiungiamo nella soluzione, un nuovo progetto di tipo applicazione Web Asp.net.
A differenza della maggior parte dei progetti, in questo progetto web, la pagina web, non sarà gestita con il code behind, ossia di avere due file, un file con il codice ed un altro con la parte html della pagina, ma sarà tutto incluso in una pagina aspx.
La pagina web, farà parte di una masterpage (application.master) ed eredita dalla pagina Microsoft.SharePoint.WebControls.LayoutsPageBase , da cui derivano tutte le pagine per sharepoint 2007.
Utilizzeremo i namespace di sharepoint ossia Microsoft.SharePoint, Microsoft.SharePoint.Workflow, Microsoft.SharePoint.Utilities, Microsoft.SharePoint.WebControls

La pagina, avrà una tabella contenente un controllo di tipo casella di testo, un controllo pulsante ed controllo label.
Di seguito si riporta la pagina Aspx, con il relativo codice e script html

 

VB.Net
 
<%@ Assembly Name="Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@ Page Language="VB"Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase" MasterPageFile="~/_layouts/application.master"   EnableViewState="false" EnableViewStateMac="false"   %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.Workflow"%>
<%@ Import Namespace="Microsoft.SharePoint.Utilities"%>
<%@ Import Namespace="Microsoft.SharePoint.WebControls"%>
 
<script runat="server">
    'dichiarazioni campi
    'oggetto per la gestione del sito
    Protected List As SPList
    'oggetto elemento o riga di una lista
    Protected ListItem As SPListItem
    'classe che rappresenta l'assocazione di un workflow
    Protected WorkflowAssociation As SPWorkflowAssociation
    'oggetto che rappresenta un sito o un tipo di contenuto lista
    Protected CCType As SPContentType
   
   
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
       
        Dim paramList As String = Request.Params("List")
        Dim paramID As String = Request.Params("ID")
        List = Web.Lists(New Guid(paramList))
        ListItem = List.GetItemById(Convert.ToInt32(paramID))
        Dim WorkflowAssociationID As Guid = New Guid(Request.Params("TemplateID"))
        WorkflowAssociation = List.WorkflowAssociations(WorkflowAssociationID)
        'verifico che non sia nulla, altrimenti ritento un associazione
        If (WorkflowAssociation Is Nothing) Then
            'ottengo il riferimento al workflow
            Dim CTypeID As SPContentTypeId = CType(ListItem("ContentTypeId"), SPContentTypeId)
            CCType = List.ContentTypes(CTypeID)
            WorkflowAssociation = CCType.WorkflowAssociations(WorkflowAssociationID)
        End If
 
        If (WorkflowAssociation Is Nothing) Then Throw New SPException("Nessun Workflow trovato")
    End Sub
   
   
   
    Protected Sub BtnOk_Click(ByVal sender As Object, ByVal e As System.EventArgs)
       
        
        Try
           
            Dim valore As String = txtNome.Text
            Web.Site.WorkflowManager.StartWorkflow(ListItem, WorkflowAssociation, valore)
        
       
  
        Catch ex As Exception
            'nel caso che è un eccezione vado alla pagina degli errori
            SPUtility.Redirect("Error.aspx", _
                                   SPRedirectFlags.RelativeToLayoutsPage, _
                                   HttpContext.Current, _
                                   "ErrorText=" + "Errore")
        End Try
        SPUtility.Redirect(List.DefaultViewUrl, _
                   SPRedirectFlags.Default, _
                   HttpContext.Current)
    End Sub
</script>
 
<asp:Content ID="Main" ContentPlaceHolderId="PlaceHolderMain" runat="server">
 
      <table cellspacing="0" cellpadding="0" border="0" >
       <TR>
             <td valign=top><asp:Label Text="Nome:" ID="LblNome" runat=server></asp:Label></td>
             <td>  <asp:TextBox ID="txtNome" runat="server"></asp:TextBox></td>
    </tr>
      <tr>
      <td colspan="1">
      <asp:Button ID="BtnOk" runat="server" Text="OK"     OnClick="BtnOk_Click" /></td>
    </tr>
      </TABLE>
       
     
</asp:Content>
 
C#
<%@ Assembly Name="Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@ Page Language="C#" Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase" MasterPageFile="~/_layouts/application.master"   EnableViewState="false" EnableViewStateMac="false"   %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.Workflow"%>
<%@ Import Namespace="Microsoft.SharePoint.Utilities"%>
<%@ Import Namespace="Microsoft.SharePoint.WebControls"%>
 
<%--Codice C#--%>
<script runat="server">
    //dichiarazioni campi
    //oggetto per la gestione del sito
    protected SPList List;
    //oggetto elemento o riga di una lista
    protected SPListItem ListItem;
    //classe che rappresenta l'assocazione di un workflow
    protected SPWorkflowAssociation WorkflowAssociation;
    //oggetto che rappresenta un sito o un tipo di contenuto lista
    protected SPContentType CType;
   
    protected void Page_Load(object sender, EventArgs e)
    {
        string paramList = Request.Params["List"];
        string paramID = Request.Params["ID"];
        List = Web.Lists[new Guid(paramList)];
        ListItem = List.GetItemById(Convert.ToInt32(paramID));
        Guid WorkflowAssociationID = new Guid(Request.Params["TemplateID"]);
        WorkflowAssociation = List.WorkflowAssociations[WorkflowAssociationID];
        //verifico che non sia nulla, altrimenti ritento un associazione
        if (WorkflowAssociation == null)
        { // ottengo il riferimento al workflow
            SPContentTypeId CTypeID = (SPContentTypeId)ListItem["ContentTypeId"];
            CType = List.ContentTypes[CTypeID];
            WorkflowAssociation = CType.WorkflowAssociations[WorkflowAssociationID];
        }
 
        if (WorkflowAssociation == null)
            throw new SPException("Nessun Workflow trovato");
      
    }
 
 
 
    protected void BtnOk_Click(object sender, EventArgs e)
    {
        try
        {
            string valore = txtNome.Text;
            Web.Site.WorkflowManager.StartWorkflow(ListItem,
                                               WorkflowAssociation,
                                               valore);
        }
        catch (Exception ex)
        {
            //nel caso che è un eccezione vado alla pagina degli errori
            SPUtility.Redirect("Error.aspx",
                                   SPRedirectFlags.RelativeToLayoutsPage,
                                   HttpContext.Current,
                                   "ErrorText=" + "Errore");
        }
        SPUtility.Redirect(List.DefaultViewUrl,
                        SPRedirectFlags.Default,
                        HttpContext.Current);
       
    }
</script>
 
<asp:Content ID="Main" ContentPlaceHolderId="PlaceHolderMain" runat="server">
 
      <table cellspacing="0" cellpadding="0" border="0" >
       <TR>
             <td valign=top><asp:Label Text="Nome:" ID="LblNome" runat=server></asp:Label></td>
             <td>  <asp:TextBox ID="txtNome" runat="server"></asp:TextBox></td>
    </tr>
      <tr>
      <td colspan="1">
      <asp:Button ID="BtnOk" runat="server" Text="OK"     OnClick="BtnOk_Click" /></td>
    </tr>
      </TABLE>
       
     
</asp:Content>

 

 

Terminata la preparazione del workflow e della pagina web, non resta che copiare i file (dll, aspx, xml) nella macchina (nel nostro caso in una virtual machine) e testare il tutto.

 

 

Configurazione ed installazione
A questo punto non ci resta che installare e configurare il nostro progetto, copiando i file nel computer in questione (nel mio caso è una macchina virtuale virtual pc 2007), nella cartella FEATURES (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\) create una cartella (per esempio SPWFRilevaValore) in essa copiate i file xml (feature.xml e workflow.xml).
Copiante nella cartella assebly (C:\WINDOWS\assembly) la dll, in questo modo viene registrata nella GAC.
Ora non resta che copiare la nostra pagina Aspx, nella cartella delle pagine di sharepoint, e precisamente nella cartella layouts (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS ).
A questo punto occorre eseguire dal prompt dei comandi, l’installazione del file feature,xml.
La registrazione avviene tramite il file stsadm.exe di seguito si riporta il comando da eseguire
stsadm.exe -o installfeature -filename SPWFRilevaValore\feature.xml -force
Riavviamo il WebServer IIS, tramite il comando IISReset.

Attivazione del WorkFlow
Terminata la fase di registrazione del componente non ci resta che attivare il workflow, apriamo il portale di sharepoint, e selezioniamo la nostra applicazione web, dal menu azioni sito, selezionare la voce impostazioni sito, nella sezione Amministrazione raccolta siti, selezionare la voce “Caratterestiche raccolta siti”

 

Figura 2

Nella pagina che viene aperta, troviamo l’elenco dei vari Workflow disponibili, tramite il pulsante attiva, del nostro Workflow rendiamo attivo il Workflow, come mostrato in figura 2.
Ora che il workflow è attivo, dobbiamo aggiungerlo nella nostra raccolta ed elenchi sito, dalla pagina delle impostazioni sito, selezioniamo la voce “Raccolte ed elenchi del sito”, che si trova nella sezione “amministrazione sito”.
Selezioniamo il contenuto con la dicitura “Documenti” .
Nella pagina che viene aperta, selezioniamo la voce “Impostazioni flusso di lavoro” che si trova nella sezione “Autorizzazioni e gestione”, a questo punto aggiungiamo il nostro workflow, valorizzando i campi di tale pagina.

Esecuzione del Workflow.
Ora che nel nostro progetto è stato creato ed aggiunto il workflow, non ci resta che eseguirlo, nella cartella documenti, selezioniamo un documento e dal menu di scelta rapida, selezioniamo la voce “Flussi di lavoro”, nella pagina che viene aperta (figura 3) , facciamo click sul nostro workflow.

Figura 3

A questo punto verrà avviata la nostra pagina (figura 4), come illustrato precedentemente, il worfklow, avrà il compito di visualizzare il testo della casella di testo nella cronologia del flusso di lavoro (fate clic sulla voce completato). (figura 5)

Figura 4

Figura 5

Conclusioni:
In questo articolo è stato illustrata la tecnica di come eseguire un workflow da una pagina Asp.net, tramite la parola download è possibile scaricare il file di esempio.

Download