Il presente articolo è stato tradotto automaticamente.

Fondamenti

Il controllo delle versioni dei flussi di lavoro

Matthew Milner

Download codice disponibile dalla Raccolta di codice di MSDN
Selezionare il codice in linea

Contenuto

I problemi
Il controllo delle versioni di .NET
Controllo delle versioni con le definizioni di flusso di lavoro XOML
Delle attività
Servizi flussi di lavoro il controllo delle versioni
Aggiornamento dinamico

In qualsiasi applicazione, è disponibile una cosa è possibile essere certi di: caso di modifica. Uno dei problemi più comuni che è possibile trovare gli sviluppatori ancora con è come gestire flussi di lavoro il controllo delle versioni e le classi correlate. In mese questo, verrà discutere i problemi principali correlati al controllo delle versioni del flusso di lavoro e fornisce i consigli per apportare modifiche a definizioni di flusso di lavoro, attività e servizi del flusso di lavoro.

fig01.gif

Figura 1 semplice flusso di lavoro che può persistenza

Se generare un'applicazione .NET oggi, pronunciare, un'applicazione Windows Presentation Foundation (WPF) o ASP.NET, si potrebbe pensare sul controllo delle versioni o potrebbe non. Quando si desidera distribuire gli aggiornamenti a un'applicazione ASP.NET, è possibile in genere un processo posto semplicemente copiare su tutti o alcuni dei componenti compresi pagine, i file binari e configurazione. In alcuni scenari, puoi avere problemi su questa distribuzione, ad esempio assicurandosi che nessuna richiesta è in esecuzione, ma questo processo è in genere gestibile. In questo caso perché la distribuzione di nuove versioni delle applicazioni del flusso di lavoro in modo rigidi?

I flussi di lavoro consentono di modello di processo aziendale a esecuzione prolungata o la logica business. Inoltre, Windows Workflow Foundation (WF) fornisce servizi di persistenza che consentono lo stato di singole istanze di un processo aziendale deve essere salvato in un archivio permanente, ad esempio un database di Microsoft SQL Server. Che lo stato salvato è costituito da oggetti .NET serializzati e di dati si trova il problema.

Si consideri un flusso di lavoro che utilizza alcuni tipi di .NET come dati, pronunciare, una classe Order. Il flusso di lavoro viene avviato con un oggetto ordine passato come un parametro, quindi inserito nel database, lo stato contenente l'oggetto serializzato di ordine. A questo punto modificare la classe di oggetto Order e rigenerare la libreria dell'applicazione. Nel caso che salvato in modo permanente del flusso di lavoro deve riprendere perché un ritardo è scaduto o un evento viene generato per il flusso di lavoro, l'oggetto Order deve essere deserializzato. Non Sfortunatamente, perché tale tipo è stata modificata, la deserializzazione riesce, generando un'eccezione.

Alcune modifiche causare problemi con la deserializzazione perché non riesce la serializzazione binaria .NET standard e altri problemi verificarsi l'implementazione di WF di serializzazione. Indipendentemente dalla loro causa, il risultato finale è lo stesso: un'eccezione quando si tenta di caricare un flusso di lavoro che fa riferimento a tipi che sono state modificate. Potrebbero essere questi tipi di classi o interfacce che crei oppure sia attività personalizzate che è stato scritto.

Per fornire un esempio concreto, prendere in considerazione il flusso di lavoro nella Figura 1 . Semplicemente scritto alcuni dati nella console utilizzando un'attività WriteLine personalizzata, ritardi (che consente anche per mantenere) e quindi scrive ulteriori dati nella console.

Ora, se si avviare un'istanza del flusso di lavoro e consentire l'esecuzione al punto di inattività, ovvero il ritardo, verrà mantenute nel database. È possibile arrestare il runtime e iniziare a lavorare sulla mia versione 1.1 del flusso di lavoro. È possibile semplicemente verrà aggiungere un'attività alla fine della definizione del flusso di lavoro per scrivere più dati nella console, come illustrato nella Figura 2 .

Avvio senza avviare un'altra istanza del flusso di lavoro Common Language runtime determinerà il servizio di persistenza eseguire il polling del database per i timer scaduti. Quando trova l'istanza esistente, il servizio di persistenza tenterà di caricare l'oggetto e verrà generata un'eccezione. È possibile rilevare l'errore registrando un gestore eventi per l'evento ServicesExceptionNotHandled su WorkflowRuntime. Che cosa vedrà è che il servizio di persistenza genererà un evento per l'eccezione con il messaggio "indice è esterno ai limiti della matrice".

fig02.gif

Nella figura 2 Modifica definizione flusso di lavoro

Il problema è che È stata modificata la definizione del tipo di flusso di lavoro e non corrisponde più alla definizione che esisteva nel caso il flusso di lavoro è stato salvato in modo permanente. Quando il servizio di persistenza tenta di deserializzare il flusso di lavoro, viene visualizzato eccezioni perché la nuova definizione di tipo contiene campi che non erano presenti quando l'istanza è stato serializzato. Il codice di deserializzazione è leggere i campi il nuovo tipo e il tentativo di caricare i valori da dati serializzati. Poiché alcuni campi non è stata esistere quando l'istanza è stato serializzato, viene generata un'eccezione durante il tentativo di accesso che i dati.

Il controllo delle versioni di .NET

Uno per risolvere i problemi di controllo delle versioni consiste per sfruttare il sistema di controllo delle versioni incorporato in .NET Framework. Sin dalla versione 1.0 di .NET Framework, il controllo delle versioni di assembly è stato supportato ed è l'unico modo per attivare il supporto per affiancata per più versioni di assembly. In breve, ciascun assembly possono avere un numero di versione collegato dopo assembly effettuati con una chiave, più versioni dello assembly poter distribuire e della cache di assembly globale (GAC). Per ulteriori informazioni su versioni di assembly e assembly dei nomi sicuri, vedere ilLa documentazione MSDN su assembly.

Questo consente di generare le flussi di lavoro e le attività in progetti con una versione di 1.0, firma e distribuirli Global Assembly Cache. A questo punto, quando si avvia un flusso di lavoro e il problema persiste, le informazioni sulla versione fa parte di stato serializzato. Se si modifica il flusso di lavoro, è importante modificare la versione di assembly e ad altri assembly che il flusso di lavoro varia a seconda se gli sono state modificate, troppo. Ad esempio, se è necessario che il flusso di lavoro dall'esempio precedente e si apportata una modifica per l'attività WriteLine e la definizione del flusso di lavoro, quindi è necessario incrementare il numero di versione per ogni progetto e distribuire gli aggiornamenti per Global Assembly Cache.

A questo punto, sarà necessario versione 1.0 e 1.1 del flusso di lavoro distribuito nella Global Assembly Cache. Quando un flusso di lavoro versione 1.0 viene caricato dall'archivio di persistenza, Common Language runtime potranno risolvere la definizione di tipo per la versione 1.0 e utilizzare le informazioni di tipo durante la deserializzazione del flusso di lavoro. Flussi di lavoro qualsiasi versione 1.1 che sono state mantenute anche funzionerebbe poiché Common Language runtime sarà in grado di trovare la definizione per la versione 1.1 tipi, troppo. Essenzialmente, purché l'assembly contenenti i tipi per il flusso di lavoro e le relative classi può essere risolto e corrisponde alla definizione originale, il flusso di lavoro verrà deserializzare correttamente e possibile continuare l'elaborazione. È possibile visualizzare il funzionamento di questo processo in figura 3 le diverse versioni vengono caricate dal database e i relativi tipi di risolvere correttamente quando trovato nella Global Assembly Cache.

fig03.gif

Nella figura 3 controllo delle versioni .NET di lato lato

Un importante punto da notare è che i flussi di lavoro versione 1.0 continuerà utilizzo e l'elaborazione, ma sono ancora basati sulla definizione versione 1.0 del flusso di lavoro. Ciò significa che le modifiche introdotte nella versione 1.1 del flusso di lavoro non sarà presente nella definizione del flusso di lavoro. In altre parole, qualsiasi attività è aggiunto, rimosso o modificato in caso contrario non è visibile nella definizione del flusso di lavoro e non verrà visualizzato l'impatto di tali modifiche nei flussi di lavoro versione 1.0. Tra breve, verrà discusso una funzionalità nota come aggiornamento dinamico che fornisce la possibilità di modificare i flussi di lavoro di versione 1.0 esistenti e nel processo.

Semplicemente con affiancata, versioni di flussi di lavoro e assembly correlati non significa che le cose rullo insieme bene, tuttavia. L'applicazione host probabilmente è basato su un particolare e probabilmente il più recente, versione dei flussi di lavoro in modo che è possibile interagire con essi. Questo può causare problemi come un host generato con la versione 1.1 del flusso di lavoro verrà verificarsi problemi durante il tentativo di interagire con persistenti flussi di lavoro versione 1.0 sono stati creati con la versione 1.0 di classi correlate.

Un'area viene in cui questo problemi spesso visualizzata per gli sviluppatori è quando si utilizza ExternalDataExchangeService in combinazione con le attività HandleExternalEvent e CallExternalMethod per le comunicazioni locali. Molte persone pensare che sta eseguendo la funzione destra per il controllo delle versioni, seguire i passaggi precedenti in modo che entrambe le versioni 1.0 e 1.1 siano disponibili. Tuttavia, quando l'host tenta di inviare dati al flusso di lavoro tramite un evento, il tipo dell'interfaccia utilizzata non corrisponda. L'host utilizza la versione 1.1 dell'interfaccia, mentre l'istanza del flusso di lavoro è stata creata con la versione 1.0.

Per comprendere pienamente perché si tratta di un problema, richiamare comunicazioni effettivamente funzionamento in WF. (Per le comunicazioni del flusso di lavoro in più vedere ilSettembre 2007 puntata di fondamenti.) L'attività HandleExternalEvent crea una coda per ricevere dati e il nome della coda che include le informazioni sul tipo per l'interfaccia. Quando i dati viene inviati dall'host, devono essere inviato alla coda corretti. ExternalDataExchangeService (EDS) utilizza le informazioni di tipo e il nome dell'evento per creare ciò che ritiene è il nome di coda appropriata. Sfortunatamente, poiché la coda è stata creata in base alla versione 1.0 dell'interfaccia e i report EDS sta creando il nome della coda basa versione 1.1, i due oggetti IComparable non corrisponderanno e non sarà possibile individuare la coda.

Per risolvere completamente il problema, l'applicazione host deve disporre di generare eventi per l'interfaccia versione 1.0. Due modi possibili per questo scopo sono reflection e l'ereditarietà. La prima opzione prevede l'utilizzo di reflection per caricare la versione originale del servizio locale e aggiungerlo EDS, dopo il quale è possibile generare un evento di tale interfaccia nuovamente tramite reflection.

La seconda opzione prevede la creazione di un nuovo assembly in cui la versione 1.1 di interfaccia vengono creati e che derivano da interfaccia versione 1.0, consente di aggiungere eventi al tipo derivato durante la modifica non il tipo di base. In questo modo, se si generare un evento che è stato definito nella versione 1.0 dell'interfaccia, il nome della coda corretto verrà ottenere creato e il messaggio recapitato anche se si richiama tale operazione tramite il tipo derivato. La chiave è che versione 1.0 dell'interfaccia deve rimanere invariato e distribuito e la nuova interfaccia e il servizio deve derivare dall'interfaccia versione 1.0. Nella figura 4 è illustrato questo approccio.

fig04.gif

Nella figura 4 derivate interfacce per Communications locale

Si noti che solo il servizio derivata e interfaccia vengano inseriti per il report EDS. In questo modo l'host interagire con un singolo servizio ma generare eventi in base alle più interfacce. L'obiettivo è di mantenere l'interfaccia di versione 1.0 intorno al e in uso, in modo che il report EDS crea nomi di coda che corrispondono a ciò che verrà da creare i flussi di lavoro. Si noti inoltre che implica creando un progetto completamente nuovo, anziché solo creando una nuova versione della libreria di comunicazione. Untenable è la parola che entrano presente quando si pensa di utilizzare questo approccio a lungo termine.

In genere, il consiglio intorno a comunicazioni è evitare le attività di comunicazioni locali per questo motivo molto e utilizzo delle attività personalizzate che creano code basate sui nomi più semplici, ad esempio stringhe, rimozione gran parte la dipendenza di tipo tra il flusso di lavoro e l'host. Il suggerimento di altri consiste nell'utilizzare servizi di flusso di lavoro che forniscono funzionalità aggiuntive intorno a ricezione delle richieste e routing la versione corretta del flusso di lavoro, come verrà illustrato a breve.

Controllo delle versioni con le definizioni di flusso di lavoro XOML

Il primo passaggio di rendere vita più facile per il controllo delle versioni consiste nell'utilizzare i flussi di lavoro basato XOML senza doverli. Questo modello dichiarativo veramente offre molti vantaggi oltre al controllo delle versioni. Visualizzare il numero di maggio 2008 di MSDN Magazine per informazioni dettagliate "Il caricamento di modelli di flusso di lavoro in WF"). MI concentrerò sui vantaggi per il controllo delle versioni di seguito.

Durante la creazione di flussi di lavoro tramite un approccio di codice, si definisce un nuovo tipo. Ad esempio, se si crea un nuovo flusso di codice con il modello di progetto o elemento Visual Studio, si è definizione di una nuova classe che deriva da un tipo negli assembly WF. Questo è il motivo principale per i problemi descritti in precedenza, poiché quando si modifica il flusso di lavoro aggiungendo o rimuovendo le attività, si sta cambiando il tipo. Il problema non verificarsi quando si genera XOML flussi di lavoro.

Un flusso di lavoro XOML che non viene compilata è semplicemente un documento XML che descrive un insieme di tipi esistenti. Questo può sembrare una differenza sottile, ma che descrivono tipi esistenti invece di creare un nuovo tipo rende una grande differenza.

Di seguito è una definizione di flusso di lavoro XOML:

<SequentialWorkflowActivity x:Name="Workflow2" 
    xmlns:ns0="clr-namespace:SimpleWorkflows" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/workflow">
  <ns0:WriteLineActivity x:Name="Hello" OutputText="Hello" />
  <DelayActivity TimeoutDuration="00:00:03" x:Name="SmallDelay" />
  <ns0:WriteLineActivity x:Name="World" OutputText="World" />
</SequentialWorkflowActivity>

Consente di verificare che l'elemento principale è SequentialWorkflowActivity, definita nell'assembly System.Workflow.Activities. Questo tipo sia versione come 3.0, nonchanging. Se si crea un flusso di lavoro utilizzando questo tipo come attività di primo livello e il flusso di lavoro venga serializzato e mantenuto, è possibile essere garantita che, quando il flusso di lavoro viene caricato e deserializzato, Common Language runtime sarà in grado di trovare versione 3.0 del SequentialWorkflowActivity nella Global Assembly Cache.

Cosa sta modifica la definizione del flusso di lavoro aggiungendo o rimuovendo le attività? In una definizione di flusso di lavoro XOML stai modificando semplicemente alcune XML, non modifica i tipi. Anche se si modifica l'elemento principale la definizione del flusso di lavoro in un altro tipo, non viene modificato un tipo in cui le istanze del flusso di lavoro esistenti variano. Infatti, una volta creato un flusso di lavoro dal XOML, tale XOML verrebbe fatto riferimento non a nuovamente utilizzando il runtime per tutta la durata di tale istanza.

Utilizzo di flussi di lavoro in base XOML significa che non devono alla versione flussi di lavoro perché non si siano definendo i tipi. Poiché non è necessario fortemente assegnare un nome e versione flussi di lavoro, si inoltre non dispone fortemente assegnare un nome e versione l'altro digita, ad esempio interfacce comunicazioni locali e di entità di business. È molto più semplice apportare modifiche unificatore, ad esempio aggiungendo metodi o i membri ai tipi, senza la quantità di lavoro nell'applicazione.

Lo svantaggio a lavorare con i flussi di lavoro XOML è che è non necessario piccola a Nessun accesso a codice, diverso da quello che cosa è incapsulata nelle attività, pertanto costretti ulteriori attività di scrittura. Ma poiché le attività sono semplicemente classi, non è un blocco principale e consente di acquisire i metodi che possono essere utilizzati per fornire la logica o la condizione di controllo delle attività in un flusso di lavoro XOML di gestione degli eventi.

Inoltre, poiché la classe SequentialWorkflowActivity non ha le proprietà per il business case definita di, non potrai passare parametri al metodo CreateWorkflow. Fortunatamente, è possibile creare proprio tipo di attività principale, derivazione da uno dei tipi del flusso di lavoro inclusi e aggiungere proprietà richiesta è, oppure iniziare un flusso di lavoro con una ricezione attività o la attività personalizzata per è possibile inviare i dati iniziali subito dopo l'avvio del flusso di lavoro.

Infine, completamente dichiarative flussi di lavoro basati su XAML ricerca in avanti, sono l'opzione di modellazione primaria provenienti in WF 4.0. Molti miglioramenti vengono apportati alle funzionalità, tra cui sostituire gli eventi con ciò che sono correntemente chiamati un ActivityAction. In pratica, questi verranno forniscono è un modo per modellare delegati utilizzando l'attività e avere l'attività eseguire le attività anziché richiamare un delegato.

Delle attività

I flussi di lavoro sono attività, in modo che ne consegue che molte dei problemi illustrati finora con flusso di lavoro tipi applicare tipi di attività. Infatti, come un tipo di flusso di lavoro causa problemi se si aggiungono le attività, se si aggiungono le proprietà per un'attività digitare ed eseguire tale assembly attività non versione, si otterrà le eccezioni al momento della deserializzazione del flusso di lavoro. Sfortunatamente, le attività devono essere classi e devono essere compilati tipi, in modo da non facile soluzione XOML come con i flussi di lavoro.

La risposta più ovvia per le attività è che è necessario versione tali utilizzando tecniche di controllo delle versioni di .NET quando si modifica l'interfaccia per l'attività in alcun modo. In questo modo i flussi di lavoro esistenti e nuovi flussi di lavoro per fare riferimento alla versione corretta ed eseguire correttamente. Tenere presente, tuttavia, che se si è correggere un difetto in un metodo all'interno dell'attività non modifica l'interfaccia, è possibile apportare la correzione e distribuire l'assembly con lo stesso numero di versione. Quando questa attività viene caricata ed eseguita da flussi di lavoro nuovi o esistente, si eseguirà il codice corretto.

La risposta lunga comporta una conoscenza approfondita del meccanismo di serializzazione in .NET Framework, esula dall'ambito di questo articolo. Tuttavia esistono due operazioni di chiavi È possibile condividere che può fornire il vantaggio la maggior parte dei con la minima quantità di investimento.

In primo luogo, si desidera aggiungere proprietà o campi per le attività, è possibile contrassegnare i campi con l'attributo NonSerialized per evitare l'eccezione indice fuori limite dopo la deserializzazione di flussi di lavoro creato con la versione precedente dell'attività.

In secondo luogo, è possibile eseguire l'override il metodo OnActivityExecutionContextLoad per inizializzare qualsiasi stato che non è stato deserializzato automaticamente. Questo metodo ottiene chiamato quando l'attività viene ricreata dallo stato salvato in modo permanente oppure quando viene creato un nuovo contesto di esecuzione. Entrambe queste tecniche di insieme consentono di apportare modifiche a attività senza che è fortemente denominarle e modificare i numeri di versione.

Servizi flussi di lavoro il controllo delle versioni

Servizi flussi di lavoro forniscono problemi simili per comunicazioni locali, nonché ulteriori opportunità per decoupling i messaggi provenienti da flussi di lavoro. Perché un servizio flusso di lavoro viene creato tramite un contratto di assistenza, le versioni del servizio o dati contratti significa che il flusso di lavoro dovrà essere rigenerato con le nuove versioni dei contratti di. Quando arriva un messaggio a un endpoint del servizio, verrà ricevuto da un servizio mediante un contratto di una particolare versione. Se il flusso di lavoro per cui può essere utilizzato il messaggio è stato creato con la stessa versione del contratto, quindi operazioni funzionino bene. Tuttavia, se il flusso di lavoro è stato creato con la versione precedente del contratto e quindi inserito, quindi il messaggio Impossibile recapitare. Per supportare due versioni di contratti, sarà necessario distribuire due versioni del servizio.

Sebbene sia unfortunata che è impossibile sfruttare le funzionalità di controllo delle versioni inerente in Windows Communication Foundation (WCF) che si attiva una nuova versione del servizio per l'elaborazione dei messaggi provenienti dai client generati con la versione precedente, WCF forniscono un meccanismo per gestire questo scenario. A livello di WCF, lo client e servizi sono semplicemente scambio di messaggi e tipi .NET non intersecano il cavo. Problemi di versione che sto parlando sull'sono puramente a livello di .NET e possono essere nascosto da client utilizzando un router di messaggistica.

Il vantaggio con i servizi del flusso di lavoro è che è possibile pubblicare due servizi affiancati, con indirizzi diversi endpoint, ma per pubblicare un façade che entrambi i servizi accessibili all'indirizzo stesso. In questo modo, quando si distribuisce la versione 1.0 del servizio, è possibile distribuire dietro un router WCF pass-through che semplicemente accetta nei messaggi e li passa al servizio. Quando si è pronti distribuire la versione 1.1 del servizio, è possibile aggiornare le informazioni di routing in modo che i messaggi ottenere inviati per il servizio versione 1.0 o il servizio di versione 1.1, in base al messaggio o il contesto in cui è stato ricevuto. Figura 5 Mostra questo concetto router con due versioni di un servizio dietro un router e un client di interagire con essi.

fig06.gif

Nella figura 5 tramite un router per servizi di controllo delle versioni

La chiave per garantire che una soluzione con un router funzionerà è per distribuire con la versione 1.0 del servizio. Quindi quando si sposta la versione successiva, il router non è qualcosa di nuovo sono aggiungere la distribuzione e test del processo. .NET Framework 3.5 SDK fornisce un router di esempio e inoltre può seguire unarticolo pratica sull'utilizzo di regole WF per prendere decisioni di routing.

Aggiornamento dinamico

Dopo tutte la discussione su come gestire meglio la definizione di flussi di lavoro di modificare e gestire con nuove e vecchie versioni in esecuzione affiancata, vi è spesso una domanda su come gestire i flussi di lavoro precedente. Apportate modifiche al flusso di lavoro per un motivo. Probabilmente è stata per risolvere un difetto di logica oppure forse era normative di conformità necessari per essere seguito. Qualsiasi il motivo, spesso è il caso consente tutti i flussi di lavoro esistente per completare sono stati definiti non è un risultato tenable. In questi casi, è consigliabile di sfruttare una potente funzionalità in WF: aggiornamento dinamico.

In breve, Aggiornamento dinamico consente di apportare modifiche a un'istanza del flusso di lavoro in esecuzione. Possono consistere in tali modifiche aggiungendo o rimuovendo le attività dalla struttura del flusso di lavoro. È sufficiente è possibile, ma è possibile modificare completamente la definizione di un flusso di lavoro. Ad esempio, in una macchina a stati, l'utente ha la possibilità di aggiungere stati intero, con gli eventi che sono ascoltare e le transizioni definite. È possibile modificare le transizioni di stato rimuovendo e re-adding SetState attività. Un flusso di lavoro sequenziali, è possibile aggiungere o rimuovere i passaggi quando il processo di business.

Per apportare modifiche a un flusso di lavoro, è innanzitutto necessario creare un oggetto WorkflowChanges basato su flusso di lavoro. A questo punto, l'oggetto WorkflowChanges fornisce un clone della struttura del flusso di lavoro che è possibile modificare mediante la relativa proprietà TransientWorkflow. È apportare modifiche per il clone aggiungendo e rimuovendo le attività. Quando le modifiche sono complete, chiamare il metodo ApplyChanges il WorkflowInstance classe, passando WorkflowChanges per rappresentare le modifiche desiderate per applicare l'istanza effettiva.

Di seguito è flusso di lavoro esempio illustrata in precedenza, quali contenuti due attività WriteLine separate da un'attività di ritardo, a un'attività WriteLine aggiuntiva aggiunta alla fine della sequenza. Questo codice viene eseguito quando il flusso di lavoro passa inattivo oppure quando l'intervallo inizia l'esecuzione.

WorkflowChanges changes = 
  new WorkflowChanges(instance.GetWorkflowDefinition());
CompositeActivity root = changes.TransientWorkflow;
WriteLineActivity wl = new WriteLineActivity {
  Name = "newWriteLine",
  OutputText = "dynamically added"
};
root.Activities.Add(wl);
instance.ApplyWorkflowChanges(changes);

Questo semplice esempio seguente viene illustrato ciò che è possibile, ma è possibile creare scenari più avanzati per applicare numerose modifiche diverse a un flusso di lavoro in esecuzione. Questo consente di richiedere un flusso di lavoro versione 1.0 è già stato avviato e apportare modifiche all'istanza in modo che più si funziona come un flusso di lavoro version1.1.

Inviare domande e commentimmnet30@Microsoft.com.

Matthew Milner è un membro del personale tecnico a Pluralsight, in cui lavora in particolare sulle tecnologie di sistemi connessi (WCF, WF Windows, BizTalk, "Dublino" e la piattaforma di servizi Azure). Matt inoltre è un consulente indipendente specializzato in Progettazione applicazioni di Microsoft .NET e sviluppo. Matt condivide regolarmente suo amore di tecnologia per a conferenze locali, internazionali e internazionali, ad esempio ed tecnologie. Microsoft ha riconosciuto Matt come un MVP per sua contributi della comunità intorno a sistemi connessi tecnologia. Contatta Matt tramite il suo blog all'pluralsight.com/community/blogs/matt.