Questa volta ho voluto prendere il toro per le corna.
Mi sono ritrovato ad affrontare per l'ennesima volta il problema di passare un file a zero byte in BizTalk.
BizTalk non supporta l'acquisizione di file a zero byte, questo non lo dico io ma Microsoft, è by design.
Il mio cliente mi guarda stranito ed io gli spiego per quale ragione la cosa non sia attuabile.
Le soluzioni proposte in rete sono delle più disparate, la più simpatica che ho trovato consiste....
...prima di andare avanti a leggere sedetevi comodi
nel monitorare l'event viewer ed intercettare l' errore che restituisce BizTalk, successivamente....
basta così non sono andato avanti a leggere.
Altra e credo unica soluzione degna di considerazione è utilizzare un server FTP, l'adapter FTP legge i file a zero byte, ma chiaramente si è obbligati a usare un server FTP.
Per essere precisi, e devo esserlo, l'adapter file supporta file a zero byte ma solo in send, si tratterebbe quindi di avere un server FTP per la sola ricezione.
Bisogna anche aggiungere che avere un server FTP in ricezione porta a dover gestire problematiche di concorrenza e di lettura che sono facilmente risolvibili su file system.
A questo punto mi sono detto basta, vediamo di mettere fine a questa storia.
A tal scopo ho deciso di fare un adapter file custom in grado di ricevere zero byte, a dire il vero non ero sicuro che funzionasse.
Nell' SDK di BizTalk, precisamente sotto ROOT:\Program Files\Microsoft BizTalk Server 2006\SDK\Samples\AdaptersDevelopment, è possibile trovare un paio di esempi e quello che serve per la relativa compilazione.
Prendiamo appunto ,come esempio, l'adapter file.
Non voglio entrare nel merito di alcune scelte architetturali dell' esempio ma entrare nel merito del problema.
Il punto chiave dell' adapter è chiaramente la funzione CreateMessage che crea il fatidico IBaseMessage, il messaggio.
L'adapter originale altro non fa che leggere un file metterlo in un System.IO.Stream e passare lo stream al Body del messaggio
part.Data = fs;
IBaseMessage message = this.messageFactory.CreateMessage();
message.AddPart(MESSAGE_BODY, part, true);
Il problema che anche in questo caso si incorre nell' errore tanto temuto
The adapter "SticAdapter" raised an error message. Details "SubmitFiles was called with an empty list of Files".
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
Originale il nome dell' apadper , ma la situazione lo richiedeva.
mmmhhhh...
Idea risolutiva!
Passare un Byte a zero direttamete nel body del messaggio
byte[] bytes = new byte[1];
fs.Write(bytes, 0, 1);
Trace.WriteLine("[BizTalkia.com] Passa il byte");
part.Data = fs;
IBaseMessage message = this.messageFactory.CreateMessage();
message.AddPart(MESSAGE_BODY, part, true);
Chiaramente fs è lo stream dopo la lettura dal file.
Se Il file è a zero byte entra correttamente in BizTalk e quello risultante in uscita è assolutamente di zero byte.
Se è un file pieno rimane integro all'originale, ma è fantastica questa trovata hehehehe
Una volta modificato il codice si tratta di compilare il tutto e eseguire il deploy.
Il deploy è semplicissimo, bisogna creare le chiavi di registry per la registrazione dell' adapter, è possibile trovare in due file che vengono forniti con l' SDK:
DynamicAdapterManagement.reg
StaticAdapterManagement.reg
che trovate sotto ROOT:\Program Files\Microsoft BizTalk Server 2006\SDK\Samples\AdaptersDevelopment\File Adapter
Le modifiche riguardano essenzialmente le directory di riferimento dei vari componenti in gioco.
Nel caso di un adapter sono solitamente tre:
Quello di RunTime, nel caso del nostor adapter è Microsoft.BizTalk.SDKSamples.Adapters.DotNetFile.Runtime.dll
Quello di gestione, cioè la famosa finestra di impostazioni: Microsoft.BizTalk.SDKSamples.Adapters.DotNetFile.Designtime.dll
Quello delle librerie di base, Microsoft.Samples.BizTalk.Adapter.Common.dll, che va rigorosamente messo in GAC.
Infine dalla console di amministrazione di BizTalk, sul nodo Adapters, tasto destro del mouse, new, mettete il nome preferito e selezionate Static DotNetFile.
Avete il codice sorgente a disposizione perciò potete effettuare tutte le modifiche del caso, una molto simpatica sarebbe quella di portare la data e ora del file in una context property, cosa che non è reperibile
utilizzando un file adapter standard, che propone al massimo il CreationTime che si riferisce alla data e ora di creazione del messaggio e non a quello del file.
Beh credo di aver detto tutto e spero che questo possa esser di aiuto a tanti.