First I would like to describe our architecture, it consists of:
- Outlook Web Addin (hosted on IIS on-prem)
- an ASP.NET Web API (hosted on-prem)
- the Microsoft Graph REST API in the cloud
- a SOAP WebService (not under my control, on-prem).
The flow can be described with these steps:
- User clicks a button in the Outlook Web Add-in
- An Ajax request is made from the Web Add-in to the Web API with the ID of the message as a parameter.
- The Web API requests the message from Graph via
GraphServiceClient
- The Web API packs the attachments from the message into a SOAP request and sends submits it to the SOAP service.
The attachments in Microsoft Graph are returned as a Byte Array and stored in memory. So we can get run into memory and performance issues.
My question is, would it be possible to stream the attachments from Microsoft Graph directly to the SOAP service?
Getting attachments from MS Graph Rest API
var mail = graphClient
.Users["mailbox"]
.Messages["id"]
.Request()
.Expand("attachments");
foreach (var attachment in message.Attachments)
{
if (attachment.GetType() == typeof(FileAttachment))
{
var fileAttachment = (FileAttachment) attachment;
// ==> fileAttachment.ContentBytes already contains the bytes of the attachment
}
}
Should the bytes of the attachment be fetched with a second request? How can it be streamed down?
The definition of the attachment part in the soap service wsdl
<xsd:complexType name="DocumentData">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="extension" type="xsd:string"/>
<xsd:element name="content" type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
... is generated in the service reference as
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3062.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://is.uniqa.at/UniqaDocumentWF.WS:startDoWFProcess")]
public partial class DocumentData : object, System.ComponentModel.INotifyPropertyChanged
{
private string nameField;
private string extensionField;
private byte[] contentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
this.RaisePropertyChanged("name");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 1)]
public string extension
{
get
{
return this.extensionField;
}
set
{
this.extensionField = value;
this.RaisePropertyChanged("extension");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, DataType = "base64Binary", Order = 2)]
public byte[] content
{
get
{
return this.contentField;
}
set
{
this.contentField = value;
this.RaisePropertyChanged("content");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null))
{
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
... and can be created like this:
DoWF.DocumentData data = new DocumentData();
data.name = name;
data.extension = extension;
// At the moment content is set to
// "fileAttachment.ContentBytes" before
// the request is send to the soap service
data.content = content;
How and where can I stream the attachment bytes from Rest API over "my" Web API and then to the SOAP service?
I would also be grateful for a completely different approach to solve this problem.