Потоковые вложения из Microsoft Graph API в SOAP WebService - PullRequest
1 голос
/ 11 октября 2019

Сначала я хотел бы описать нашу архитектуру, она состоит из:

  • Outlook Web Addin (размещен на IIS on-prem)
  • ASP.NET Web API (размещенon-prem)
  • API-интерфейс REST Microsoft Graph в облаке
  • веб-сервис SOAP (не под моим контролем, on-prem).

Поток можетописать, выполнив следующие действия:

  1. Пользователь нажимает кнопку в надстройке Outlook Web
  2. Из веб-надстройки в веб-API выполняется запрос Ajax с идентификаторомсообщения в качестве параметра.
  3. Веб-API запрашивает сообщение от Graph с помощью GraphServiceClient
  4. . Веб-API упаковывает вложения из сообщения в запрос SOAP и отправляет их вSOAP сервис.

Вложения в Microsoft Graph возвращаются в виде байтового массива и сохраняются в памяти. Таким образом, мы можем столкнуться с проблемами памяти и производительности.

Мой вопрос: возможно ли потоковое вложение из Microsoft Graph непосредственно в службу SOAP?

Получение вложений из 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
    }
}

Следует ли извлекать байты вложения со вторым запросом? Как это может быть передано вниз?

Определение вспомогательной части в мыльной службе 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>

... создается в службессылка как

[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));
        }
    }
}

... и может быть создана следующим образом:

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; 

Как и где я могу передать байты вложения из RestAPI поверх «моего» веб-API, а затем и службы SOAP?

Я также был бы благодарен за совершенно иной подход к решению этой проблемы.

1 Ответ

0 голосов
/ 11 октября 2019

Учитывая количество задействованных слоев и вашу неспособность контролировать API на любом конце рабочего процесса, я не уверен, что этот подход будет работать. Более того, я подозреваю, что даже если вы сможете заставить это работать, вы найдете его чрезвычайно хрупким.

Я бы предложил что-то вроде этой статьи из документации: Получить вложения элемента Outlook с сервера . В этом примере используется веб-службы Exchange, а не Microsoft Graph, но общий процесс будет таким же:

  1. Пользователь нажимает кнопку в надстройке
  2. Надстройка передает userPrincipalName и сообщение id в Web API
  3. Web API загружает вложения во временное хранилище.
  4. Web API загружает вложения из временного хранилища в службу SOAP.

Для того, чтобы эта работа работала, вашему веб-API необходимо будет использовать Клиентские учетные данные для подключения к Microsoft Graph с использованием Mail.Read области приложения . Это позволит веб-API подключаться к любому почтовому ящику и загружать вложения.

...