dicembre 2006 - Posts
Qualche
informazione utile dal team di SharePoint sulla definizione di form ASPX per la gestione dei workflow.
Segnalo
questo articolo, decisamente interessante, in merito a come creare delle macchine fisiche e non virtuali per demo particolarmente esose dal punto di vista dell'hardware, dove un PC virtuale non è la risposta giusta.
Così lo scorso anno chiudevo il 2005.
Niente buoni propositi per il 2007, come è stato nel 2006, perchè tanto poi non li rispetterei :-). Anche nel 2006 infatti mi sono ammazzato di lavoro, in palestra ci sono andato solo fino ad aprile. Sì beh il punto 10 (matrimonio) in effetti c'è stato anche se con 2 anni di ritardo, ma su quello arrivare in ritardo non è mai un male ;-) ... In compenso non ho ridotto né gli orari di lavoro, né l'impegno professionale, anzi! Proprio oggi, nel fare i vari conteggi di fine anno, ho scoperto che solo nell'ultimo trimestre 2006 ho macinato quasi 12.000 Km in auto per trasferte presso clienti ... sarebbe proprio il caso di trovare dei mezzi di locomozione più rapidi e che non sospendano la produttività :-).
Il 2007 non sarà da meno, a parte una parentesi iniziale in cui dovrò chiudere un paio di progetti software e completare un progetto molto importante che mi impegnerà gran parte del tempo fino a marzo.
Intanto auguro a tutti buon anno e vi raccomando di stare in allerta, perché DevCon 2007 sta arrivando e, a giudicare dalle versioni beta dell'agenda, varrà proprio la pena di esserci!
In un progetto che stiamo seguendo (nel quale è coinvolto anche
RoB), facciamo un pesante uso di WF. Siamo per ora molto soddisfatti del risultato e contenti di averci pensato (a WF intendo :-) ...). Abbiamo però incontrato un problema non banale, che ci ha fatto perdere diversi giorni per essere individuato e risolto. Per questo preferisco lasciarne traccia su questo blog.
In sostanza abbiamo diversi workflow che riutilizzano le stesse Activity custom, come è normale che sia in progetti che usano WF.
In particolare abbiamo creato delle custom composite activity, per utilizzare le nostre stesse activity custom in dei blocchi più complessi, tipicamente delle WhileActivity e dei Replicator, con anche una gestione sempre "fissa" delle eventuali eccezioni durante il flusso.
Questo ci consente di avere comportamenti uniformi tra i vari workflow, oltre ad una migliore mantenibilità del codice.
Il problema riscontrato è che queste composite activity custom, che sono scritte solo da codice, referenziano al loro interno delle Activity che hanno delle ActivityCondition (CodeCondition o RuleConditionReference). Nel nostro caso sono solo RuleConditionReference.
In fase di caricamento (durante la CreateWorkflow) e di validazione delle activity, il motore di WF cerca il riferimento al contenitore delle Rules a livello di RootActivity, ma nel nostro caso questo non è vero. Purtroppo il motore di WF non impedisce la definizione di Activity custom che ne contengono altre che a loro volta usano delle Rules, però in fase di load e di validation, si blocca con una bella NullReferenceException perché cerca la RuleDefinition a livello di RootActivity, non trovandola.
Nel nostro caso abbiamo aggirato il problema, però non è stato per nulla facile trovarne la causa, lo sa bene
Cristian che ci ha litigato per diversi giorni, lavorando di Reflector e debugger.
Questo problema sembra non manifestarsi per le composite disegnate dal designer, ma potrebbe capitare anche a voi di lavorare con composite da codice, quindi è meglio saperlo.
Un altro "problema" (diciamo così) che abbiamo riscontrato è il fatto che non è per nulla banale svolgere Unit Testing dei worfklow.
Infatti non è così semplice testare le singole Activity e ancor di più i flussi.
La strada che abbiamo scelto è stata di creare da codice dei TestMethod che creano dei "mini-workflow" con i quali eseguiamo le singole Activity. Sempre in questi TestMethod verifichiamo l'esito appoggiandoci ai componenti Biz, per controllare che il flusso abbia effettivamente fatto il suo lavoro.
Più semplice è stato invece testare le Rule usate nei workflow (dalle RuleConditionReference di prima) perché quelle alla fine sono dei normalissimi metodi di oggetti di business, quindi dei comuni TestMethod sono più che sufficienti.
Ora abbiamo la possibilità di fare UnitTesting di tutto il progetto, compresi i workflow, e questo non è affatto male per monitorare la correttezza di eventuali interventi di manutenzione/modifica del codice.
Come sempre quando si usano strumenti nuovi e tecnologie appena nate, c'è da trovare da soli soluzioni a problemi che con tecnologie più diffuse e consolidate, si trovano semplicemente con Google :-).
L'altro giorno ho pagato le spese di un problema legato all'istanziazione di componenti COM, via COM-Interop, da assembly .NET su piattaforma a 64bit.
Questo è in sintesi il problema. A me si è verificato nella chiamata ad un SOAP Service ASP.NET (un ASMX) che girava su piattaforma 64bit, in IIS a 64bit, con .NET 2.0 sempre a 64bit. Il servizio si limita a chiamare le library dell'API di SharePoint 2003, per creare una cartella e/o un site da codice, via API appunto.
Il guaio è che ho tentato in tutti i modi di aggirare il problema, sia come descritto nel post (forzando la compilazione a 32bit per piattaforme x86) sia forzando IIS a girare per intero (penalizza le performance ma a mali estremi ....) a 32bit, come indicato
qui.
Il problema però non è stato superato. La cosa "antipatica" è che invece in applicazioni classiche compilate per la piattaforma x86, ho fatto un test con un'applicazione console, il problema non sussiste, come indicato dal workaround del blog. Pare quindi che nel caso di IIS e ASP.NET 2.0 ci sia anche qualcos'altro da fare. Indagherò meglio, sperando di trovare una soluzione, sia per il mio caso specifico, che per altri che potrebbero avere le stesse esigenze.
Nel frattempo penso che aggirerò il "side effect" dei 64bit con un servizio WCF, anziché ASP.NET, compilato per x86, così da avere io il pieno controllo del processo host.
Ovviamente se qualcuno ci è già passato e ha dei suggerimenti ...
Oggi, lavorando con RoB ad un'applicazione che stiamo implementando, siamo
"cascati" in un problema che non saprei bene come definire.
Sicuramente è un comportamento "non immediato" dei web service ASMX, non lo definirei
semplicisticamente bug per scaricare la responsabilità su Microsoft, semplicemente è un
qualcosa che non avevo trovato documentato.
Se definiamo un WebMethod asincrono server-side, come spiego anche nel mio ormai vetusto :) libro
Full Contact XML & Web Services.
Se utilizziamo degli attributi di serializzazione, per esempio perché abbiamo correttamente usato un
approccio Contract First e con WSCF o WSDL.EXE abbiamo generato il codice server, gli attributi
devono essere tutti definiti sul metodo di Begin*, anche quelli relativi al return value, benché
il return value del Begin* method sia in realtà un IAsyncResult.
Questo comportamento è dovuto dal fatto che il motore di ASMX genera la signature dell'operazione
leggendo solo gli attributi di serializzazione del metodo di Begin* e non fonde gli attributi del
Begin* e End*.
Quindi in pratica, dobbiamo scrivere una cosa di questo tipo:
[System.Web.Services.Protocols.SoapHeaderAttribute("ActionSoapHeaderValue", Direction = System.Web.Services.Protocols.SoapHeaderDirection.InOut)]
[System.Web.Services.WebMethodAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("urn:sendActionStep", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Bare, Binding = "mauiActionsServiceBinding")]
[return: System.Xml.Serialization.XmlElementAttribute("SendActionStepOutputMessage", Namespace = "http://schemas.devleap.it/Actions")]
public virtual IAsyncResult BeginSendActionStep([System.Xml.Serialization.XmlElementAttribute(Namespace = "http://schemas.devleap.it/Actions", ElementName = "SendActionStepInputMessage")] SendActionStepInputMessage sendActionStepInputMessage, AsyncCallback callback, Object state)
{
return (beginSendActionStepInternal(sendActionStepInputMessage, callback, state));
}
[System.Web.Services.WebMethodAttribute()]
public virtual SendActionStepOutputMessage EndSendActionStep(IAsyncResult ar)
{
return(endSendActionStepInternal(ar));
}
dove come si vede l'attributo [return:] è stato definito sul WebMethod di BeginSendActionStep,
anche se è relativo al risultato del WebMethod di EndSendActionStep. L'operazione in quanto tale
che verrà esposta sarà poi SendActionStep che solo a livello di architettura server sarà eseguita
in asincrono.
Ho rilevato che anche nella versione definitiva di WCF non è possibile avere la
generazione automatica delle policy per i custom token creati. Accadeva anche nelle beta, ma speravo che poi qualcuno di buona volontà in quel di Redmond, fornisse una soluzione al problema. Invece anche nella RTM è rimasto tale.
Questo significa di fatto non poter pubblicare il WSDL autogenerato di un servizio
che utilizzi un token custom, come ad esempio uno UsernameSecurityToken con delle
informazioni aggiuntive (i tipici environment, site, ecc.).
Sono d'accordissimo con chi può farmi presente che il WSDL dovremmo crearlo noi e non
farcelo creare (nemmeno da WCF!), infatti sono il primo a predicarlo, ma è altrettanto
vero che il WSDL possiamo generarlo noi (approccio contract-first) e poi da questo
creare il contratto (ServiceContract) e farci poi creare (questa sì) la policy da WCF
in funzione della configurazione di servizi infrastrutturali che scegliamo.
Comunque, tornando al problema del WSDL e dell'emissione delle policy, per aggirarlo
dovremmo implementare dei nostri SecurityBindingElement supportando l'interfaccia
IPolicyExportExtension e poi definire noi quella parte di policy.
Quale periodo migliore del Natale :-) per dedicare una giornata a questo tipo di
estensioni e personalizzazioni dell'ambiente di WCF? :-)
Rimando quindi al periodo Natalizio la soluzione del problema e un post che dia qualche
indicazione su come aggirare l'inconveniente, intanto teniamo però tutti presente che
eventuali custom token inibiscono la possibilità di gerare dinamicamente le policy. In questo periodo siamo infatti tutti troppo impegnati a chiudere gli ultimi progetti operativi e ad organizzare DevCon 2007.