Office 開発 New (Office Add-ins)

Office アプリ開発の新機能についてのまとめです。

■ まず少し Office 開発についての説明から

  2013 から Office 開発の新しいモデルとして、Office 用アプリ (Apps for Office) が登場しました。
これまで Office 開発で行えていた VSTO (.NET 開発) や VBA がなくなるわけではありませんが、Office 開発を行う際の一つの選択肢として利用できるものです。

特徴は、

  • マルチ デバイス対応
      デスクトップ版の Office だけではなく、Office Online (ブラウザー版の Office) やモバイルアプリでも動作するよう開発可能。
      現在、Office 365 をはじめとするクラウドサービスの普及にも伴い、Office ファイルをさまざまなデバイスから開くことが当たり前になってきているので、開発した内容が同じコードで、さまざまな端末上でも動作できるようになるっていうのは、この開発モデルを利用するメリットの一つといえます。
  •  開発は HTML,JavaScript がメイン
     
    .NET コードによる開発ではなく、HTML と JavaScript により開発します。HTML と JavaScript により開発した Web ページを任意の Web サーバー (もしくはクラウド上でも) にホストし、Office からネットワーク経由でアクセスして動作させます。
     
    開発した Web ページと、Web ページをアプリとして実行中の Office ファイルとのデータのやりとりには、専用の API (Office.js) を利用します。
  • マーケットプレイスを利用してアプリ インストール/アプリ展開できる
     
    Office ストアっていうマーケットプレイスがあり、開発したアプリはそこで展開 (販売) できます。HTML+JS で開発可能であることと合わせて、マイクロソフト技術の開発者ではなくても、利用者の多い Office のアプリを開発し、そこで販売が行えますし、またユーザーにとっては自分にとって便利なアプリを Office ストアから購入・インストールし、利用できます。
      企業内のみでの展開を行いたい場合には、企業内カタログと呼ばれる専用ストアを社内に用意して利用可能。

■ 利用方法

   アプリは Office ストアもしくは企業内カタログから Office ファイル上に追加して利用するのが基本です。
   たとえば、Excel だと、リボンの [挿入] タブから [ストア] をクリックし、Office ストアから使いたいものを追加。

     OAddins1
    作業ウィンドウに表示されるタイプや、本文上に表示されるコンテンツっていうタイプがあります。
    もちろん開発者がどちらか選べるってことです。

     OAddins2
   Outlook の場合、下図のようにメールや予定の閲覧画面に表示するタイプもあれば。
    メールや予定の作成画面に表示するタイプも。

     OAddins3

■ 直近の UPDATE 情報

と、ここまでまず概要でしたが、先日 Chicago で開催された Ignite で聞いた Office 用アプリについての Update をまとめておきます。

① Apps for Office (Office 用アプリ) という名前が、Office Add-ins に変更

  呼び方が変わりました!
 
 
個人的には、Apps for Office、日本語だと Office 用アプリって、名前がようやく浸透し出したのに、ここで変えちゃうの? という気持ちもありますが、Office Add-ins って名前のほうが、Office のアドインとイメージしてもらいやすそう!と思います。

  まだまだ MSDN 等の日本語記事は Office 用アプリのままですし、英語記事でも Apps for Office 記載のものがいくつもあるので、しばらく両方の名前を知っておいたほうがよさそうですね。Visual Studio の開発テンプレートも、Apps for Office って名前ですし。いまんとこ。

② Excel for iPad

  いままで Excel for iPad では Office Add-ins は動作しませんでしたが、サポート対象となったようです。まだ私も試せていませんが、近々テストしてみたいと思います。テストした結果これは!って内容があればまた Blog UP します。

引き続き iPad 版の他の Office もどんどん対応してほしいですね。

③ Word Online に対応

  Office Online (ブラウザー版の Office) では、Excel、PowerPoint、Outlook、あと Access (SharePoint 上で動作する Access アプリ) のみが対応していましたが、Word も対応の仲間入り。

④ Office.js のバージョンがシンプルに

  Office.js は Office Add-ins 開発時に利用する API で、Office Add-ins の実体となる開発した Web ページと、Web ページを Office Add-ins として実行中の Office ファイルとのデータのやりとりに利用するものです。

  これまで Office 2013 が出たタイミングだと、1.0 バージョン。Office 2013 SP1 が出たタイミングで 1.1 バージョンとなり、もちろん利用できる API 機能が増えました。今後も増えていくことが想像できます。

  CDN 参照する際には、https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js を利用しますが、1.0 のときはこれが、https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js としていたのですが、シンプルに https://appsforoffice.microsoft.com/lib/1/hosted/office.js で利用できるように。

 

以上、また目だった UPDATE があればまとめたいと思います。
あ、
dev.office.com もちょっと内容新しくなりましたね。JavaScript API Tutorial が、これから開発をはじめるかたには便利かとー

奥田 うさぎ

de:code フォローアップ② Office アプリでの SharePoint Online アクセス (Common Consent Framework 利用)

先日 開催された de:code で担当させていただいた Office アプリ開発 SP1 新機能セッションフォローアップ記事の第2弾です。

セッションの一番最後に、デモで動作を見ていただき、処理内容を解説させていただいた、Office 用アプリで、Office 365 API で提供される Common Consent Framework を利用し、SharePoint Online へアクセスする内容のサンプルコード紹介です。コードを作成する際の、詳細手順はフォローアップ記事① でふれていますので、あわせて参考にしていただければと思います。

また、Office 365 の新しい API や Common Consent Framework については、MS 松崎さんのステキ濃ゆい Blog で解説されていますので、そちらをぜひ~。

   ・ 松崎さん Blog 「Office 365 API 入門
                          「Azure Active Directory の Common Consent Framework (Service 側)

■  Azure Active Directory にアプリを登録

   ●  Office 365 テナントのアカウントで、Azure 管理ポータルにサインアップ
        (初回はユーザー情報の登録が必要)

   ●  アプリを登録

       1. [アプリケーション] を開き、[追加] をクリック

           MailApp1

       2. [組織で開発中のアプリケーションを追加]

          MailApp2

       3. 名前を指定し、[Web アプリケーションや Web API] を選択 

       4. サインオン URL、アプリケーション ID にアプリ内のリダイレクト HTML ページの URL を指定

       5. 登録されたら、構成画面で、クライアント ID とキーをひかえておく

         MailApp3

       6. 同じく構成画面で、[他のアプリケーションに対するアクセス許可] でアクセスしたい内容を指定

         MailApp4

コード例 (メールアプリで取得した添付ファイルを、OneDriveに保存するメール表示フォームの例)
    ※ 各ファイルやクラス等の名前は、任意に変更ください。

   ● Manifest でのアクティブ化ルール

        MailApp5

   ● 添付ファイル処理 コントローラークラス (GetAttachmentController クラス)

    // POST 処理
    [HttpPost()]
    public string SaveAttachment(AttachmentRequest request)
    {
      try
      {
        Attachment attachment = GetAttachmentFile(request.AttachmentId,
            request.AuthToken, request.EwsUrl);
        return SaveTOSP(attachment);
      }
      catch (Exception e)
      {
        return "エラー発生: " + e.Message + "\n\n" + e.StackTrace;
      }
    }

    // EWS よびだしを行い、添付ファイルを取得
    private Attachment GetAttachmentFile(string attachmentId,
        string authToken, string ewsUrl)
    {
      // GetAttachment SOAP リクエスト用に文字列作成
      string getAttachmentRequest =
          @"<?xml version=""1.0"" encoding=""utf-8""?>
           <soap:Envelope xmlns:xsi=""
http://www.w3.org/2001/XMLSchema-instance"&quot;
            xmlns:xsd=""http://www.w3.org/2001/XMLSchema"&quot;
            xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"&quot;
            xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types"&quot;>
                <soap:Header>
                <t:RequestServerVersion Version=""Exchange2013"" />
                </soap:Header>
                    <soap:Body>
           <GetAttachment   
           xmlns="
http://schemas.microsoft.com/exchange/services/2006/messages&quot;
           xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types"&quot;>
                        <AttachmentShape/>
                        <AttachmentIds>
                        <t:AttachmentId Id=""{0}""/>
                        </AttachmentIds>
                    </GetAttachment>
                    </soap:Body>
                </soap:Envelope>";
      getAttachmentRequest = String.Format(getAttachmentRequest, attachmentId);

      // Web リクエストオブジェクトの作成
      HttpWebRequest webRequest = WebRequest.CreateHttp(ewsUrl);
      webRequest.Headers.Add("Authorization",
          string.Format("Bearer {0}", authToken));
      webRequest.PreAuthenticate = true;
      webRequest.AllowAutoRedirect = false;
      webRequest.Method = "POST";
      webRequest.ContentType = "text/xml; charset=utf-8";
      byte[] bodyBytes
        = System.Text.Encoding.UTF8.GetBytes(getAttachmentRequest);
      webRequest.ContentLength = bodyBytes.Length;

      Stream requestStream = webRequest.GetRequestStream();
      requestStream.Write(bodyBytes, 0, bodyBytes.Length);
      requestStream.Close();

      // EWS リクエスト
      HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();

      // XML ドキュメントをレスポンスから取得
      if (webResponse.StatusCode == HttpStatusCode.OK)
      {
        Stream responseStream = webResponse.GetResponseStream();
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(responseStream);

        string fileName = xmlDocument.
            GetElementsByTagName("t:Name")[0].InnerText;
        byte[] bytes = Convert.FromBase64String(xmlDocument.
            GetElementsByTagName("t:Content")[0].InnerText);

        // レスポンス クローズ
        responseStream.Close();
        webResponse.Close();

        return new Attachment()
        {
          AttachmentBytes = bytes,
          AttachmentName = fileName
        };
      }
      return null;
    }

    // SharePoint ライブラリにファイル保存
    private string SaveTOSP(Attachment attachment)
    {
      string ResourceId =
https://****-my.sharepoint.com/;
      string ApiEndpoint = https://*****-my.sharepoint.com/personal/***/_api;
      string accessToken = OAuthController.GetAccessToken(ResourceId);

      // HTTP リクエスト (新しい File API 利用)
      HttpWebRequest webRequest = WebRequest.CreateHttp(ApiEndpoint
          + "/files/Add(name=’" + attachment.AttachmentName
          + "’, overwrite=true)");
      webRequest.Accept = "application/json;odata=verbose";
      webRequest.Headers.Add("Authorization",
          string.Format("Bearer {0}", accessToken));
      webRequest.Method = "POST";
      webRequest.ContentLength = attachment.AttachmentBytes.Length;
      webRequest.ContentType = "application/octet-stream";

      Stream requestStream = webRequest.GetRequestStream();
      requestStream.Write(attachment.AttachmentBytes, 0,
          attachment.AttachmentBytes.Length);
      requestStream.Close();

      // SharePoint へリクエスト送信
      HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
      if (webResponse.StatusCode == HttpStatusCode.OK)
      {
        Stream responseStream = webResponse.GetResponseStream();
        StreamReader reader = new StreamReader(responseStream);
        return reader.ReadToEnd();
      }
      return "エラー";
    }

    public class Attachment
    {
      public byte[] AttachmentBytes { get; set; }
      public string AttachmentName { get; set; }
    }

    public class AttachmentRequest
    {
      public string AuthToken { get; set; }
      public string AttachmentId { get; set; }
      public string EwsUrl { get; set; }
    }

   ● OAuthController クラス内容

     // AAD のクライアントID 指定
    private static readonly string ClientId = "クライアントID";
    // AAD のクライアントシークレット指定
    private static readonly string ClientSecret = "キー";
    private const string OAuthUrl = "
https://login.windows.net/{0}";
    private static readonly string AuthorizeUrl
      = string.Format(CultureInfo.InvariantCulture, OAuthUrl,
        "common/oauth2/authorize?response_type=code&client_id={0}&resource={1} 
        &redirect_uri={2}");
    private static readonly Uri RedirectUrl = new Uri(
        System.Web.HttpContext.Current.Request.Url,"/リダイレクトページ.html");

    [HttpPost()]
    public string GetAuthorizationUrl(AuthorizationRequest request)
    {
      return String.Format(CultureInfo.InvariantCulture, AuthorizeUrl,
          Uri.EscapeDataString(ClientId), Uri.EscapeDataString(request.ResourceId),
          Uri.EscapeDataString(RedirectUrl.ToString())
      );
    }

    [HttpPost()]
    public string OAuthFlow(AuthorizationParameters parameters)
    {
      try
      {
        ClientCredential credential = new ClientCredential(ClientId, ClientSecret);
        string authority =
          string.Format(CultureInfo.InvariantCulture, OAuthUrl, "common");
        AuthenticationContext authContext = new AuthenticationContext(authority);
        AuthenticationResult result
          = authContext.AcquireTokenByAuthorizationCode(parameters.Code,
            new Uri(RedirectUrl.GetLeftPart(UriPartial.Path)),credential);
        // トークンのキャッシュ
        SSInfo.RefreshToken = result.RefreshToken;
        return "OAuth 認証終了";
      }
      catch (ActiveDirectoryAuthenticationException ex)
      {
        return "OAuth 失敗" + ex.ToString();
      }
    }

    public static string GetAccessToken(string resourceId)
    {
      try
      {
        string refreshToken = Storage.SSInfo.RefreshToken;
        ClientCredential credential = new ClientCredential(ClientId, ClientSecret);
        string authority =
          string.Format(CultureInfo.InvariantCulture, OAuthUrl, "common");
        AuthenticationContext authContext = new AuthenticationContext(authority);
        AuthenticationResult result = authContext.AcquireTokenByRefreshToken(
            refreshToken, ClientId, credential, resourceId);
        return result.AccessToken;
      }
      catch (ActiveDirectoryAuthenticationException)
      {
        return null;
      }
    }

    public class AuthorizationRequest
    {
      public string ResourceId { get; set; }
    }
    public class AuthorizationParameters
    {
      public string Code { get; set; }
    }
   public class SSInfo
    {
      public static string RefreshToken { get; set; }
      public static string ClientId { get { return ""; } }
      public static string ClientSecret { get { return ""; } }
    }

   ● リダイレクト HTML ページの内容

    
       app.initialize();
       var oauthToken = {
           Code : getUrlParameter(‘code’)
       };

       $.ajax({
           url: ‘../../api/OAuth/OAuthFlow’,
           type: ‘POST’,
           data: JSON.stringify(oauthToken),
           contentType: ‘application/json;charset=utf-8’
       }).done(function (data) {
           app.showNotification(JSON.stringify(data));
           window.close();
       }).fail(function (status) {
           app.showNotification(‘エラー’, JSON.stringify(status));
       });

       function getUrlParameter(parameterName) {
           var pattern = “[\\?&]” + parameterName + “=([^&#]*)”,
               regularExpression = new RegExp(pattern),
               results = regularExpression.exec(window.location.href);

           return results ? results[1] : null;
       }
  

   ● アプリの HTML

      <button id="providePermission">① アクセス許可取得</button>
      <button id="saveToSP">② 添付ファイルを OneDrive へ保存 </button>

   ● アプリの HTML から参照する js

      – Initialize

          $(‘#providePermission’).click(To365OAuthFlow); 
          $(‘#saveToSP’).click(saveToSP);

     
      – 関数追加

    // OAuth フローのはじまり
     function To365OAuthFlow() {
        var dataToSend = {
            ResourceId: "Microsoft.SharePoint"
        }

        $.ajax({
            url: ‘../../api/OAuth/GetAuthorizationUrl’,
            type: ‘POST’,
            data: JSON.stringify(dataToSend),
            contentType: ‘application/json;charset=utf-8’
        }).done(function (data) {
            window.open(data);
        }).fail(function (status) {
            app.showNotification(‘エラー’, JSON.stringify(status));
        }).always(function () {
            $(‘.disable-while-sending’).prop(‘disabled’, false);
        });
    }

    // OneDrive へ保存
    function saveToSP() {
        var attachmentId = Office.context.mailbox.item.attachments[0].id;
        var ewsUrl = Office.context.mailbox.ewsUrl;
        Office.context.mailbox.getCallbackTokenAsync(function (ar) {
            var attachmentData = {
                AuthToken: ar.value,
                AttachmentId: attachmentId,
                EwsUrl: ewsUrl
            };

            sendRequest("GetAttachment/SaveAttachment", attachmentData);
        });
    }
   
  
    // ヘルパー関数 コントローラークラス内の API 呼び出し
     function sendRequest(method, data) {
        $.ajax({
            url: ‘../../api/’ + method,
            type: ‘POST’,
            data: JSON.stringify(data),
            contentType: ‘application/json;charset=utf-8’
        }).done(function (data) {
            app.showNotification("成功", "");
        }).fail(function (status) {
            app.showNotification(‘エラー’, JSON.stringify(status));      
        });
     }  

 

以上、コード内で行っている処理はセッション中に解説させていただいたとおりです。

上記サンプルでは、OneDrive へファイルを Add する REST コールを行っていますが、同様に、サンプルコード内の OAuthController.GetAccessToken で取得できるトークンをリクエストヘッダーで利用し、365 コンテンツへの REST アクセスが行っていただけます。

以上、参考にしていただければと思います。

奥田 うさぎ

de:code フォローアップ① Outlook メールアプリ での添付ファイル操作

こんにちは、奥田です。先日 de:code で Office アプリ開発 SP1 新機能についてのセッションを担当させていただきましたが、そのフォローアップ記事第1弾です。

少し前にリリースされた Office 2013 SP1 にて、Office 用アプリ開発においても新機能がたくさんあります。セッションでは、特に注目すべき変更点として Outlook のメールアプリについて、メインにお話させていただきました。

この記事では、その中で解説させていただいた添付ファイル操作について、サンプルコードの作成方法を補足させていただきます。

添付ファイル操作は、1.1 で追加された新しい API の利用で、ReadItem (項目の読み取り) 以上のアクセス許可レベルで可能となり、また OWA だけではなく、Outlook クライアントでもサポートされるようになりました。

参考:方法: Exchange サーバーから Outlook アイテムの添付ファイルを取得する

上記記事にあるサンプルコードを参考に、添付ファイルを操作するメールアプリを作成する際の参考手順です。
サーバーサイドコードの部分は、API コントローラーにより REST サービスとして用意したいと思います。

  ※  JSAPI 1.1 機能を利用するため、Microsoft Office Developer Tools for Visual Studio 2013 -  
       March 2014 Update パッケージ をインストールした環境で試していただけます。

1.VS でメールアプリプロジェクトを作成
     ●
メールの表示フォーム
     ●
[項目の読み取り] アクセス許可 (Manifest で設定)
     ●
メールボックスの要件セット 1.1 (Manifest で設定)

2.Web API コントローラー実装
     ●
[Webプロジェクト] を右クリック – [追加] – [Web API コントローラー クラス] を選択
         ※
メニューがでてこないときは、NuGet Microsoft ASP.NET Web API パッケージを入れるとよいかと

     ● クラス名を [***Controller] とします。
         ※ 
このあと、ASP.NET ルーティングでURLを構成するため、クラス名のおしりに、"Controller"
             とつけときます。

     ● コントローラークラス内の既定のコードを全部消して、次のコードを記述

    // Post アクションメソッド
    [HttpPost()]
    public string GetAttachment(AttachmentRequest request)
    {
      try
      {
        // EWS よびだしで、添付ファイル取得
        Attachment attachment = GetAttachmentFile
            (request.AttachmentId, request.AuthToken, request.EwsUrl);
        // 取得した添付ファイルをローカル保存 (パスは任意に変更を)
        System.IO.File.WriteAllBytes(@"c:\shared\"
            + attachment.AttachmentName, attachment.AttachmentBytes);
      }
      catch (Exception e)
      {
        return "エラー発生: " + e.Message + "\n\n" + e.StackTrace;
      }
      return "保存完了しました!";
    }

    // EWS よびだしを行い、添付ファイルを取得
    private Attachment GetAttachmentFile(string attachmentId,
        string authToken, string ewsUrl)
    {
      // GetAttachment SOAP リクエスト用に文字列作成
      string getAttachmentRequest =
          @"<?xml version=""1.0"" encoding=""utf-8""?>
              <soap:Envelope xmlns:xsi=""
http://www.w3.org/2001/XMLSchema-instance""
                xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
                xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/
              xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types"">
                <soap:Header>
                <t:RequestServerVersion Version=""Exchange2013"" />
                </soap:Header>
                    <soap:Body>
                    <GetAttachment
              xmlns=""
http://schemas.microsoft.com/exchange/services/2006/messages""
              xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types"">
                        <AttachmentShape/>
                        <AttachmentIds>
                        <t:AttachmentId Id=""{0}""/>
                        </AttachmentIds>
                    </GetAttachment>
                    </soap:Body>
                </soap:Envelope>";

      getAttachmentRequest = String.Format(getAttachmentRequest, attachmentId);

      // Web リクエストオブジェクトの作成
      HttpWebRequest webRequest = WebRequest.CreateHttp(ewsUrl);
      webRequest.Headers.Add("Authorization",
                        string.Format("Bearer {0}", authToken));
      webRequest.PreAuthenticate = true;
      webRequest.AllowAutoRedirect = false;
      webRequest.Method = "POST";
      webRequest.ContentType = "text/xml; charset=utf-8";
      byte[] bodyBytes
        = System.Text.Encoding.UTF8.GetBytes(getAttachmentRequest);
      webRequest.ContentLength = bodyBytes.Length;

      Stream requestStream = webRequest.GetRequestStream();
      requestStream.Write(bodyBytes, 0, bodyBytes.Length);
      requestStream.Close();

      // EWS リクエスト
      HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();

      // XML ドキュメントをレスポンスから取得
      if (webResponse.StatusCode == HttpStatusCode.OK)
      {
        Stream responseStream = webResponse.GetResponseStream();

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(responseStream);

        string fileName = xmlDocument.
            GetElementsByTagName("t:Name")[0].InnerText;
        byte[] bytes = Convert.FromBase64String(xmlDocument.
            GetElementsByTagName("t:Content")[0].InnerText);

        // レスポンス クローズ
        responseStream.Close();
        webResponse.Close();

        return new Attachment()
        {
          AttachmentBytes = bytes,
          AttachmentName = fileName
        };
      }
      return null;
    }

    public class Attachment
    {
      public byte[] AttachmentBytes { get; set; }
      public string AttachmentName { get; set; }
    }

    public class AttachmentRequest
    {
      public string AuthToken { get; set; }
      public string AttachmentId { get; set; }
      public string EwsUrl { get; set; }
    }

3.Global.asaxを作成し、API がよびだされるようルーティング規則を指定
    ●
[Webプロジェクト] を右クリック – [追加] – [グローバルアプリケーション クラス] を選択
         名前は Global のままにする

    ● Application_Start メソッド内に、次のコードを記述

          RouteTable.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

        (System.Web.Http と System.Web.Routing を using 追加)

4. メールアプリの表示フォームとして利用する html ファイルに、下記ソースを追加

      <button id="getAttachment">添付ファイル保存</button>

5.参照する js ファイルに、下記ソースを追加
     ●
Initialize メソッド内に、クリック操作追加

         $(‘#getAttachment’).click(getAttachment);

     ● 次のメソッド追加

   // 添付ファイル保存
    function getAttachment() {
        // 添付ファイル ID を JSAPI 利用して取得
        var attachmentId = Office.context.mailbox.item.attachments[0].id;
        // EWS EndPoint URL を JSAPI 利用して取得
        var ewsUrl = Office.context.mailbox.ewsUrl;
        // コールバックトークンを取得
        Office.context.mailbox.getCallbackTokenAsync(function (ar) {
            var attachmentData = {
                AuthToken: ar.value,
                AttachmentId: attachmentId,
                EwsUrl: ewsUrl
            };
            // コントローラークラス (サーバーサイドコード) の
            // GetAttachment を呼び出し (添付ファイルID、EWS URL、Token を渡す)
            sendRequest("コントローラー名/GetAttachment", attachmentData);
        });
    }

    // ヘルパー関数 コントローラークラス内の API 呼び出し
     function sendRequest(method, data) {
        $.ajax({
            url: ‘../../api/’ + method,
            type: ‘POST’,
            data: JSON.stringify(data),
            contentType: ‘application/json;charset=utf-8’
        }).done(function (data) {
            app.showNotification("成功", "指定の場所に保存しました。");
        }).fail(function (status) {
            app.showNotification(‘エラー’, JSON.stringify(status));
        });
     }

以上、コード内で行っている処理はセッション中に解説させていただいたとおりです。
参考にしていただければと思います。

奥田  うさぎ