Потоковые вложения из Microsoft Graph API в SOAP WebService

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

  • Надстройка Outlook Web (размещается на IIS локально)
  • веб-API ASP.NET (размещенный локально)
  • REST API Microsoft Graph в облаке
  • SOAP WebService (не под моим контролем, локально).

Процесс можно описать следующими шагами:

  1. Пользователь нажимает кнопку в надстройке Outlook Web
  2. Запрос Ajax выполняется из веб-надстройки к веб-API с идентификатором сообщения в качестве параметра.
  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; 

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

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


person Mario Semper    schedule 11.10.2019    source источник


Ответы (1)


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

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

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

Чтобы это работало, ваш веб-API должен будет использовать Учетные данные клиента для подключения к Microsoft Graph с помощью _ 3_ область применения. Это позволит веб-API подключаться к любому почтовому ящику и загружать вложения.

person Marc LaFleur    schedule 11.10.2019