2017年2月26日日曜日

オブジェクトのトランスレーション+VB.net

ビューア用に変換

バケットにアップロードしたオブジェクトを、ビューア用のデータであるSVF形式に変換します。使用するAPIは「Model Derivative API」の「POST job」です。

シナリオ

前回までのバケットの選択→オブジェクトIDの取得 の流れを利用して、オブジェクトを変換してみます。バケットを選択しオブジェクト一覧を表示するGridViewに「SVF変換」の列を設けて、選択したオブジェクトをSVFに変換します。
SVF変換

使用するAPI

アップロードしたオブジェクトの変換には、「Model Derivative API」の「POST job」を使います。

URI

https://developer.api.autodesk.com/modelderivative/v2/designdata/job

アクセストークン

変換には「data:read」と「data:write または data:create」でアクセストークンを取得します。data:createを使うと、同じオブジェクトでも上書きされず、次々新しい変換ができますので、今回は data:read data:write を使います。

リクエストボディ~JSON

こんかいちょっとややこしいのは、送信するボディにJSONを使用することです。このJSONの形式は以下の通りです。
{
   "input": {
     "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA",
     "compressedUrn": true,
     "rootFilename": "A5.iam"
   },
   "output": {
     "formats": [
       {
         "type": "svf",
         "views": [
           "2d",
           "3d"
         ]
       }
     ]
   }
 }
これを単に文字列を使って作成してもいいのですが、クラスとしてこのJSONを表現し、Newtonsoft.Json.JsonConvert.SerializeObjectを使ってJSON文字列にしてみましょう。まず、このJSONをクラスに置き換える方法ですが、こちらに大変便利なWebサイトがあります。こちらではJSONとC#クラスの変換を助けてくれます。上記JSONを貼り付けてGenerateボタンを押すと
public class Input
{
    public string urn { get; set; }
    public bool compressedUrn { get; set; }
    public string rootFilename { get; set; }
}

public class Format
{
    public string type { get; set; }
    public List<string> views { get; set; }
}

public class Output
{
    public List<Format> formats { get; set; }
}

public class RootObject
{
    public Input input { get; set; }
    public Output output { get; set; }
}
となり、クラスが4つ作成されました。VB.netでこのクラスを定義すると

Public Class Input
    Public urn As String
End Class

Public Class Format
    Public type As String
    Public views As List(Of String)
End Class

Public Class Output
    Public formats As List(Of Format)
End Class

Public Class RootObject
    Public input As Input
    Public output As Output
End Class

となります。これをプロジェクト内に定義して [RootObject]クラスを生成し、JSONにコンバートすれば、JSON文字列を生成できます。

バケットの内容一覧

バケットの内容一覧を表示する部分は、前回を参照してください。

SVF変換用ButtonField

WebFormをもう一つ追加して、下の図のように設定します。
Webフォーム
SVF変換用のButtonFieldをGridViewに付け加えます。
ButtonFieldを付けくわて、ButtonStyleをButtonにする
このボタンフィールドのハンドラにSVF変換のコードを記入します。

コードサンプル

    Protected Sub gdvObjects_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles gdvObjects.RowCommand

        '何行目がクリックされたのか?
        Dim index As Integer = Convert.ToInt32(e.CommandArgument)
        Dim row As GridViewRow = gdvObjects.Rows(index)

        'オブジェクトIDの取得
        Dim objKey As String = row.Cells(1).Text
        Dim objId As String = row.Cells(2).Text

        '*******************************************
        '     アクセストークンを取得
        '*******************************************

        Dim acToken As String = mdlUtils.GetToken("data:write data:read")
        If acToken = "" Then
            lblBucketkey.Text = "アクセストークンの取得に失敗しました。"
            Exit Sub
        End If

        '*******************************************
        '     URN(ObjectId)をBase64エンコード
        '*******************************************

        Dim bytes As Byte() = System.Text.Encoding.UTF8.GetBytes(objId)
        Dim convURN As String = Convert.ToBase64String(bytes, Base64FormattingOptions.None)

        '*******************************************
        '     変換リクエスト(RestSharp)
        '*******************************************
        'クライアント
        Dim strClient As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(strClient)

        'リクエスト
        Dim transReq As New RestSharp.RestRequest()
        transReq.Resource = "modelderivative/v2/designdata/job"
        'メソッド
        transReq.Method = RestSharp.Method.POST
        'ヘッダー
        transReq.AddHeader("Authorization", "Bearer " + acToken)
        transReq.AddHeader("Content-Type", "application/json")
        'ボディのJSON文字列
        '{
        '   "input" {
        '               "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA"
        '           },
        '   "output": {
        '               "formats": [
        '                            {
        '                              "type": "svf",
        '                              "views": ["2d","3d"]
        '                             }
        '                           ]
        '              }
        '}
        '送信するJSONをクラスで置き換えて作成
        Dim iInput As New Input
        iInput.urn = convURN

        Dim iFormat As New Format
        iFormat.type = "svf"
        iFormat.views = New List(Of String)
        iFormat.views.Add("2d")
        iFormat.views.Add("3d")

        Dim iOutput As New Output
        iOutput.formats = New List(Of Format)
        iOutput.formats.Add(iFormat)

        Dim iRootObj As New RootObject
        iRootObj.input = iInput
        iRootObj.output = iOutput

        'JSONオブジェクトに変換する
        Dim json As Object = Newtonsoft.Json.JsonConvert.SerializeObject(iRootObj)

        '変換したJSONオブジェクトをボディに追加する
        transReq.AddParameter("application/json", json, RestSharp.ParameterType.RequestBody)

        'リクエストを送信
        Dim result As RestSharp.IRestResponse = _client.Execute(transReq)

        '*******************************************
        '     応答
        '*******************************************
        If result.StatusCode = Net.HttpStatusCode.OK Then

            '200 成功した場合
            '戻り値のJSONは次の形式になっている
            '{
            '  "result": "success",
            '  "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA",
            '  "acceptedJobs": {
            '    "output": {
            '      "formats": [
            '        {
            '          "type": "svf",
            '          "views": [
            '            "2d",
            '            "3d"
            '          ]
            '        }
            '      ]
            '    }
            '  }
            '}
            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            'URNを取得
            Dim strURN As String = jsonObj("urn")
            lblStatus.Text = "変換を開始しました。"
            tbxURN.Text = strURN

        ElseIf result.StatusCode = Net.HttpStatusCode.Created Then
            '201 すでに作成されている場合
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            Dim strURN As String = jsonObj("urn")
            lblStatus.Text = "すでに変換されています。"
            tbxURN.Text = strURN

        ElseIf result.StatusCode = Net.HttpStatusCode.BadRequest Then
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"diagnostic"の値にエラーの詳細が記載されている。
            Dim strDiagnostic As String = jsonObj("diagnostic")
            lblStatus.Text = "変換に失敗しました。" + strDiagnostic
            tbxURN.Text = ""

        Else
            '何らかの失敗
            lblStatus.Text = "変換に失敗しました。"
            tbxURN.Text = ""
        End If
    End Sub
End Class

'JSONクラス
Public Class Input
    Public urn As String
End Class

Public Class Format
    Public type As String
    Public views As List(Of String)
End Class

Public Class Output
    Public formats As List(Of Format)
End Class

Public Class RootObject
    Public input As Input
    Public output As Output
End Class

実行してみる

まず、バケットの一覧を表示します。
バケットの一覧
バケットを選択すると、

が表示されます。ここで[SVF変換]ボタンを押して、変換します。
変換が開始されるとURNが表示されます
時間をおいて、再度SVF変換を押すと「すでに変換されています」となります。

このURNを使って、ビューアにオブジェクトを表示することができます。


2017年2月4日土曜日

バケット内のオブジェクト+VB.net

バケット内のオブジェクト

作成したバケットにどのようなファイルがアップロードされているかを表示してみます。APIはData Management APIの「GET buckets/:bucketKey/objects」です。

リファレンスによると、必要な情報は

  • data:readのアクセストークン
  • バケットキー

の二つです。

(1) バケットの一覧を取得し表示
(2) 表示された一覧からバケットを選択
バケットの一覧を表示し「選択」をクリック
(3)バケット内のオブジェクトの一覧を表示
バケット内のオブジェクトを表示
というシナリオで構成してみます。
ASP.net Webフォームでこのお題を解いてみます。

バケットの一覧を取得してGridViewに表示する


前回はListViewにバケットの一覧を表示しましたが、今回はGridViewに表示します。新なWebフォームを追加して、GridView(gdvBucket)とラベル(lblStatus)を追加します。FORGE APIの部分は前回と同じですが、GridViewにデータを表示するために、新たにデータセット(DataSet)を作成して、GridViewにバインドします。どうもGridViewはデータベースと結びつけないと作動しないようです。


サンプルコード


Public Class WebForm4
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        '**********************************
        '     アクセストークンを取得
        '**********************************

        Dim acToken As String = mdlUtils.GetToken("bucket:read")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     バケットを取得
        '**********************************

        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets"

            'メソッド
            .Method = RestSharp.Method.GET

            'ヘッダー
            .AddHeader("Authorization", "Bearer " + acToken)

        End With

        '送信
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = Net.HttpStatusCode.OK Then

            '200OKの場合


            'データセットを定義
            Dim dsBucket As New DataSet("BucketList")
            Dim tblBucket As DataTable = dsBucket.Tables.Add("Table1")
            tblBucket.Columns.Add("バケットキー", Type.GetType("System.String"))
            tblBucket.Columns.Add("作成日", Type.GetType("System.String"))
            tblBucket.Columns.Add("ポリシーキー", Type.GetType("System.String"))


            Dim responseString As String = result.Content

            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"items"を取得しjArrayオブジェクトとする
            Dim itemArray As Newtonsoft.Json.Linq.JArray = jsonObj("items")
            '配列を走査し、データテーブルにデータ行を充てんする
            For Each item As Newtonsoft.Json.Linq.JObject In itemArray
                'バケットキー
                Dim strBucketKey As String = item("bucketKey")
                '作成した日付(ミリセカンド)
                Dim strCreatedDate As String = item("createdDate")
                'ポリシーキー
                Dim strPolicyKey As String = item("policyKey")

                'タイムスタンプから日付へ変換
                Dim intTimeStamp As Int64 = Int64.Parse(strCreatedDate)
                Dim dtCreateDate As DateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(intTimeStamp)


                'データセット
                Dim rowBucket As DataRow = tblBucket.NewRow()
                rowBucket("バケットキー") = strBucketKey
                rowBucket("作成日") = dtCreateDate.ToLocalTime.ToString
                rowBucket("ポリシーキー") = strPolicyKey
                tblBucket.Rows.Add(rowBucket)


            Next
            lblStatus.Text = tblBucket.Rows.Count.ToString + "個のバケットが見つかりました。"
            gdvBucket.DataSource = New DataView(tblBucket)
            gdvBucket.DataBind()

        Else
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            lblStatus.Text = "取得に失敗しました。" + vbTab + jsonObj("reason")

        End If
    End Sub
End Class

データグリッドに選択列を追加

デザインビューでデータグリッドを選択し、GridViewタスクから「列の編集」を選択します。
HyperLinkFieldを追加し、
DataNavigateUrlFields  に バケットキー
DataNavigateUrlFormatString に ~/WebForm5.aspx?BucketKey={0}
HeaderText に 詳細表示
Text に 選択

を設定します。
選択列の追加
バケットを選択したときに、次のページを呼び出すときにGridViewに表示されているデータセットテーブルの 「バケットキー」の値を受け渡します。DataNavigateUrlFormatStringには、DataNavigateUrlFieldにカンマ区切りで設定した文字列を、{0} {1}の書式で受け渡すことができます。

バケット内オブジェクト一覧

あらたなWebフォームを追加し、ラベル(lblBucketKey)とGridView(gdvObjects)を追加します。ページが遷移するときのデータの受け渡しは HttpRequestの Request.QueryStringを使います。(サンプルコードの冒頭の部分)
また、バケットの一覧を取得する部分は、バケットキーを使ってURLを作成するだけなので比較的簡単といえるでしょう。

サンプルコード

Public Class WebForm5
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        '**********************************
        '     バケットキーを取得
        '**********************************
    
        Dim strBucketKey As String = Request.QueryString("BucketKey")
        lblBucketkey.Text = strBucketKey

        '**********************************
        '     アクセストークンを取得
        '**********************************

        'アクセストークンを取得す部分はこちらを参照してください。
        Dim acToken As String = mdlUtils.GetToken("data:read")
        If acToken = "" Then
            lblBucketkey.Text = "アクセストークンの取得に失敗しました。"
        End If

        '**********************************
        '     バケット内のオブジェクト
        '**********************************
        Dim strClient As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(strClient)

        Dim chkReq As New RestSharp.RestRequest()
        With chkReq
            .Resource = "oss/v2/buckets/" + strBucketKey + "/objects"
            .Method = RestSharp.Method.GET
            .AddParameter("Authorization", "Bearer " + acToken, RestSharp.ParameterType.HttpHeader)
            .AddParameter("Content-Type", "application/json", RestSharp.ParameterType.HttpHeader)
        End With

        Dim result As RestSharp.IRestResponse = _client.Execute(chkReq)

        '**********************************
        '     データグリッドに表示
        '**********************************
        If result.StatusCode = Net.HttpStatusCode.OK Then
            '成功した場合
            'データセットを定義
            Dim dsObjects As New DataSet("BucketList")
            Dim tblObjects As DataTable = dsObjects.Tables.Add("Table1")
            tblObjects.Columns.Add("オブジェクトキー", Type.GetType("System.String"))
            tblObjects.Columns.Add("オブジェクトID", Type.GetType("System.String"))
            tblObjects.Columns.Add("ロケーション", Type.GetType("System.String"))

            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"items"を取得しjArrayオブジェクトとする
            Dim itemArray As Newtonsoft.Json.Linq.JArray = jsonObj("items")
            '配列を走査する
            For Each item As Newtonsoft.Json.Linq.JObject In itemArray
                'オブジェクトキー
                Dim strObjectKey As String = item("objectKey")
                'オブジェクトID
                Dim strObjectId As String = item("objectId")
                'ロケーション
                Dim strLoacation As String = item("location")

                'データセット
                Dim rowObjects As DataRow = tblObjects.NewRow()
                rowObjects("オブジェクトキー") = strObjectKey
                rowObjects("オブジェクトID") = strObjectId
                rowObjects("ロケーション") = strLoacation
                tblObjects.Rows.Add(rowObjects)


            Next
            gdvObjects.DataSource = New DataView(tblObjects)
            gdvObjects.DataBind()

        End If

    End Sub

End Class

GridViewを使うことで、少し見栄えも改善されました。

2017年2月1日水曜日

ファイルのアップロード +VB.net

バケットにファイルをアップロードする


作成したバケットにファイルをアップロードします。必要な情報は

  • アクセストークン data:create または  data:write (既存のファイルは上書き)
  • バケットキー   ファイルをアップロードするバケット

です。ここでもRestSharpを使ってファイルをアップロードしてみます。ユーザーインターフェイスは前回のバケット一覧を少し改造して、下の図のようにしてみました。
WebForm3.aspx
[参照]ボタンを押して選択したファイルを、lbxBucketsで選択したバケットに[アップロード]ボタンでアップロードし、そのObjectIDを取得して表示する、というシナリオです。

サンプルコード


アップロードボタンのクリックイベントのハンドラを示します。

    Protected Sub btnUpload_Click(sender As Object, e As EventArgs) Handles btnUpload.Click

        '**********************************
        ' アップロードするファイルを取得
        '**********************************

        'ファイルが選択されているか?
        If FileUpload1.HasFile = False Then
            MsgBox("ファイルが選択されていません。", MsgBoxStyle.OkOnly)
            Exit Sub
        End If

        'バケットにアップロードするファイル
        'FileUploadで転送されたファイル
        Dim fileToUpload As HttpPostedFile = FileUpload1.PostedFile

        'ファイル名(インターネットエクスプローラはフルパスを返す)
        Dim strFullPath As String = fileToUpload.FileName

        'ファイル名だけ取り出す
        Dim strFileName As String = IO.Path.GetFileName(strFullPath)

        '①ファイル名をURLエンコードする
        Dim strObjectKey As String = System.Web.HttpUtility.UrlEncode(strFileName)

        'ファイルの内容を読んでByteの配列とする
        Dim fileData As Byte() = Nothing
        Using binaryReader As New IO.BinaryReader(fileToUpload.InputStream)
            fileData = binaryReader.ReadBytes(fileToUpload.ContentLength)
        End Using


        '現在選択しているバケットキーを取得
        Dim strBucketKey As String = lbxBuckets.SelectedValue

        '**********************************
        '     アクセストークンを取得
        '**********************************

        Dim acToken As String = mdlUtils.GetToken("data:write")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     ファイルをアップロード
        '**********************************
        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets/" + strBucketKey + "/objects/" + strObjectKey

            'メソッド
            .Method = RestSharp.Method.PUT

            'ヘッダー
            .AddHeader("Authorization", "Bearer " + acToken)

            'BODY
            .AddParameter("Content-Type", fileToUpload.ContentType)
            .AddParameter("Content-Length", fileToUpload.ContentLength)

            '②アップロードするファイルをリクエストボディに追加
            .AddParameter("requestBody", fileData, RestSharp.ParameterType.RequestBody)

        End With

        'リクエスト送信
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        '結果
        If result.StatusCode = Net.HttpStatusCode.OK Then

            'ObjectIdを取得する
            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            'objectId
            lblObjectId.Text = jsonObj("objectId")

        Else
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            lblObjectId.Text = jsonObj("reason")

        End If

    End Sub

ポイントは①のファイルの名前をエンコードすることを忘れないようにするところと、②のファイルをBODYにテンプルすところです。

大きなサイズのデータを送れるようにする


ASP.netのFileUploadコントロールは転送できるファイルサイズが4MB程度に制限されているので、これを300MB(300×1024=307200KB)に緩和します。

ソリューションエクスプローラで「Web.config」ファイルを開き、17行目あたりにある
<httpRuntime targetFramework="4.6"/>
の末尾の/の前をクリックし、maxRequestLength="307200"と追記します。4.6"の後ろにスペースを空けて、maxと打てばインテリセンスが働いて、maxRequestを探すことができます。

  <system.web>
    <authentication mode="None" />
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6" maxRequestLength="307200" />
    <pages>
      <namespaces>
     ・・・・

実行する


デバッグ起動してバケットと、アップロードするファイルを選択して「アップロード」ボタンを押すと、ファイルサイズによっては時間がかかりますが、うまくいけばオブジェクトIDが返ってきます。


2017年1月24日火曜日

バケットの一覧 +VB.net

現在のバケットの一覧を取得

バケットの一覧を取得するにはDataManagementAPIのGET Bucketを使います。前回のプロジェクトを利用して、WebFormでバケットの一覧を取得してみます。

WebFormの追加

WebFormを追加して、下の図のようにサーバーコントロールを配置します。
サンプルのWebForm

サンプルコード


以下はバケットの一覧を取得するサンプルコードです。ポイントは「apiの戻り値のJSONの配列を処理する部分です。レスポンスをNewtonsoft.Json.Linq.JArray型に変換して情報を取り出します。

Public Class WebForm3
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        '**********************************
        '     アクセストークンを取得
        '**********************************
    'この部分は前回の記事を参照してください。

        Dim acToken As String = mdlUtils.GetToken("bucket:read")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     バケットを取得
        '**********************************

        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets"

            'メソッド
            .Method = RestSharp.Method.GET

            'ヘッダー
            .AddHeader("Authorization", "Bearer " + acToken)

        End With

        '送信
        'POSTする
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = Net.HttpStatusCode.OK Then

            '200OKの場合

            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"items"を取得しjArrayオブジェクトとする
            Dim itemArray As Newtonsoft.Json.Linq.JArray = jsonObj("items")
            '配列を走査する
            For Each item As Newtonsoft.Json.Linq.JObject In itemArray
                'バケットキー
                Dim strBucketKey As String = item("bucketKey")
                '作成した日付(ミリセカンド)
                Dim strCreatedDate As String = item("createdDate")
                'ポリシーキー
                Dim strPolicyKey As String = item("policyKey")

                'タイムスタンプから日付へ変換
                Dim intTimeStamp As Int64 = Int64.Parse(strCreatedDate)
                Dim dtCreateDate As DateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(intTimeStamp)

                'リストボックスのアイテムを追加する
                lbxBuckets.Items.Add(New ListItem(strBucketKey + " / 作成日時 : " + dtCreateDate.ToLocalTime.ToString + " / ポリシーキー : " + strPolicyKey, strBucketKey))

            Next
            lblStatus.Text = itemArray.Count.ToString + "個のバケットが見つかりました。"
        Else
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            lblStatus.Text = "取得に失敗しました。" + vbTab + jsonObj("reason")


        End If
    End Sub
End Class

実行する

実行すると以下のようになります。
現在のバケットの一覧

2017年1月19日木曜日

バケット作成 + VB.net

バケットを作成する

バケットを作成するにはまずbucket:createスコープでアクセストークンを取得し、ポリシーキー(データの保持期間)とバケット名(bucketId)を決めてPOSTで取得するという手順でした。これをvb.netで実装してみます。

アクセストークン取得モジュール

アクセストークンは様々な場面で必要なので、モジュールで関数にしておきます。

プロジェクトにモジュールを追加して「mdlUtils.vb」とします。以下はコードサンプルです。

Imports System.Net


Module mdlUtils

    Public Const CLIENTID As String = "自分のクライアントID"
    Public Const CLIENTSECRET As String = "自分のクライアントシークレット"
    Private ENDPOINT As String = "https://developer.api.autodesk.com"-

    ''' <summary>
    ''' 目的に応じたアクセストークンを取得する
    ''' </summary>
    ''' <param name="scopeString">スコープ</param>
    ''' <returns></returns>
    Public Function GetToken(ByVal scopeString As String) As String

        'RestSharpでクライアントを作成
        Dim _client As New RestSharp.RestClient(ENDPOINT)
        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "authentication/v1/authenticate"

            'メソッド
            .Method = RestSharp.Method.POST

            'ヘッダー
            .AddHeader("Content-Type", "application/x-www-form-urlencoded")

            'ボディ
            .AddParameter("client_id", CLIENTID)
            .AddParameter("client_secret", CLIENTSECRET)
            .AddParameter("grant_type", "client_credentials")

            'スコープ
            .AddParameter("scope", scopeString)
        End With

        'POSTする
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = HttpStatusCode.OK Then

            '結果(json形式の結果が文字列で返ってくる)
            'このjsonは以下の形式となる
            '{
            '  "token_type": "Bearer",
            '  "expires_in": 1799,
            '  "access_token": "Ff387cyQXw1elOT3nldiFIKBqDOs"
            '}
            Dim responseString As String = result.Content
            'ここからaccess_tokenの値だけを取り出す

            '文字列を操作しても可能だが、Newtonsont.JsonのJSON解読メソッドを使うと便利です。
            '使い方はまず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)

            'アクセストークンをオブジェクトに引数を与えて取得します
            Dim acToken As String = jsonObj("access_token")

            'Label1の表示を変更
            Return acToken

        Else
            '失敗した場合
            Return ""
        End If
    End Function
End Module

WebFormの追加


WebFormを一つ追加して、下の図のようにリストボックスとテキストボックス、ラベルを追加します。
WebFormにコントロールを追加

ボタンアクションを追加

btnCreateBucketをダブルクリックして、コードを追加すします。RestSharpで送信するデータは今回はJSONです。

Public Class WebForm2
    Inherits System.Web.UI.Page

    Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles btnCreateBucket.Click

        '**********************************
        '     アクセストークンを取得
        '**********************************

        Dim acToken As String = mdlUtils.GetToken("bucket:create")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     バケットを作成
        '**********************************


        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets"

            'メソッド
            .Method = RestSharp.Method.POST

            'ヘッダー
            .AddHeader("Content-Type", "application/json")
            .AddHeader("Authorization", "Bearer " + acToken)

            'ボディ(JSON形式で送る場合には匿名型を使用します。)
            '{
            '     "bucketKey":"mybucket",
            '     "policyKey":"transient"
            '}
            .AddJsonBody(New With {
                         Key .bucketKey = tbxBucketKey.Text,
                         Key .policyKey = lbxPolicy.SelectedValue
                         })
        End With

        'POSTする
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = Net.HttpStatusCode.OK Then

            '結果(json形式の結果が文字列で返ってくる)
            '{
            '  "bucketKey":"apptestbucket",
            '  "bucketOwner":"RlKfGlAbb7N8VJwLllOvpfonB1Ex52qG",
            '  "createdDate":1463785698600,
            '  "permissions":[
            '    {
            '      "authId":"RlKffonB1Ex52GlAbb7N8VJwLllOvpqG",
            '      "access":"full"
            '    }
            '  ],
            '  "policyKey":"transient"
            '}
            Dim responseString As String = result.Content
            '文字列を操作しても可能だが、Newtonsont.JsonのJSON解読メソッドを使うと便利。
            '使い方はまず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            'バケットキーを取り出す
            Dim bucketKeyString As String = jsonObj("bucketKey")
            'ステータスに出力
            lblStatus.Text = bucketKeyString + "の作成に成功しました。"

        Else
            'エラーの場合は理由を示すJSONが返ってくる
            '            {
            '  "reason":"Valid field 'bucketKey' must be of the form  [-_.a-z0-9]{3,128}"
            '}
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            Dim reasonString As String = jsonObj("reason")
            lblStatus.Text = "バケットの作成に失敗しました。理由:" + reasonString

        End If
    End Sub
End Class

RestSharpでJSONを送る

RestSharpでBODYにJSON形式のデータをセットする場合は、赤字で示した部分のように.AddJsonBodyの引数に匿名型のオブジェクトをセットします。

実行してみる


ビルドして実行してみます。
ブラウザで実行
データ保存期間とバケットキーを指定して「バケット作成」を押すと
バケットが作成された
もう一度押すとすでに同じ名前のバケットがあることがわかります。
同じ名前のバケットは作成できない
バケットの名前に大文字のアルファベットを使うと、同じくエラーになります。
文字の制約のエラー


2017年1月15日日曜日

アクセストークン + VB.net

サーバーサイドでアクセストークンを取得する

ここまでで基本的な知識は手に入りました。ここからはASP.NET WebFormを使って、FORGEに取り組んでみます。ビューアのチュートリアルでは、JavaScriptに直接

  • オブジェクトID
  • アクセストークン

を書き込んでいました。また、アクセストークンを取得するには
  • クライアントID
  • クライアントシークレット
が必要です。しかし、クライアントサイドのJavaScriptはブラウザーの開発者ツールを使えば「もろばれ」状態なので、大事な情報をクライアントサイドに置くわけにはいきません。

今回はWebFormを使って、アクセストークンを取得してみます。Webフォームのアクションはサーバーサイドで実行されるので、大事な情報をクライアントサイドに置かなくて済みます。

まずはVisual Studioで新しいWebFormプロジェクトを作成します。

RestSharpを導入する

アクセストークンを取得するにはRESTを使って、交信を行う必要があることがわかりました。VBでこれを実装するのはなかなか骨が折れそうですが、RestSharpを使うことでこの難関を切り抜けることができます。プロジェクトにRestSharpを組み込みます。

(1) [ツール]-[NuGetパッケージマネージャ]-[パッケージマネージャコンソール]
(2) パッケージマネージャコンソールで
  PM> Install-Package RestSharp

WebFormを追加


(1) [プロジェクト]-[新しい項目の追加]
(2) [Webフォーム]を選択して[追加]
(3) 画面左下の[並べて表示]をクリック
(4) ボタンとラベルを追加

ボタンのアクションを追加

(1) 追加したボタンをダブルクリックして、コードを表示する
(2) コードは以下のようになります。

Imports System.Net

Public Class WebForm1
    Inherits System.Web.UI.Page


    Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        'ラベルをクリア
        Label1.Text = ""

        'クライアントIDとクライアントシークレット
        Dim client_id As String = "自分のクライアントIDで置き換え"
        Dim client_secret As String = "自分のクラインとシークレットで置き換え"

        'URL
        Dim strClient As String = "https://developer.api.autodesk.com"

        'RestSharpでクライアントを作成
        Dim _client As New RestSharp.RestClient(strClient)
        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "authentication/v1/authenticate"

            'メソッド
            .Method = RestSharp.Method.POST

            'ヘッダー
            .AddHeader("Content-Type", "application/x-www-form-urlencoded")

            'ボディ
            .AddParameter("client_id", client_id)
            .AddParameter("client_secret", client_secret)
            .AddParameter("grant_type", "client_credentials")

            'スコープはとりあえずdata:read
            .AddParameter("scope", "data:read")
        End With

        'リクエストを送信
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = HttpStatusCode.OK Then

            '結果(json形式の結果が文字列で返ってくる)
            'このjsonは以下の形式となる
            '{
            '  "token_type": "Bearer",
            '  "expires_in": 1799,
            '  "access_token": "Ff387cyQXw1elOT3nldiFIKBqDOs"
            '}
            Dim responseString As String = result.Content
            'ここからaccess_tokenの値だけを取り出す

            '文字列を操作しても可能だが、Newtonsont.Jsonの解読メソッドを使うと便利です。
            '使い方はまず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object =  Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)

            'アクセストークンをオブジェクトに引数を与えて取得します
            Dim acToken As String = jsonObj("access_token")

            'Label1の表示を変更
            Label1.Text = acToken

        Else
            '失敗した場合
            Label1.Text = "アクセストークンを取得できませんでした。"

        End If

    End Sub
End Class

ポイントはRestSharpのリクエストの作り方と、戻り値のJSONからaccess_tokenの値と取り出す部分です。Newtonsoft.Jsonは規定でASP.netに組み込まれているので、特に参照を操作する必要はありません。

実行してみる


ビルドして実行してみます。最初の画面はこうです。
ボタンを押してみましょう
ボタンを押すと
アクセストークンが取得できた!
アクセストークンが取得できました。
結構少ないコードで、安全にアクセストークンを取得できることがわかりました。

2017年1月6日金曜日

ビューアで表示する(2)~表示ビューの変更

3Dビューが表示されたのは偶然だった?

前回無事ビューアで表示できたので、今回はチュートリアルのStep3を解明してみます。考えてみれば、Revitのデータをアップロードして、2dと3dのビューを表示用に変換するように、命令をしたわけですから、前回のビューアで表示するように指定したビューには複数のビューがあったはずです。にもかかわらず、3Dビューが表示されたのは「単なる偶然」だったのですね。
運よく?表示された3Dビュー
Step3では画面上部に「Nextボタン」を表示して、クリックするごとに表示可能ビューを入れ変えるようにしてみます。

Step3 をフォローする

ボタンをつくる

まずビューアの上にボタンを作成します。これはHTMLファイルの<div>で区切られたビューアの
<div id="MyViewerDiv"></div>
の行の直後に
<button id="MyNextButton" onClick="loadNextModel()">Next!</button>
とボタンタグを加えます。
ボタンのIDはMyNextButtonで、onClickイベントにloadNextModel()関数を指定しています。
次にボタンのスタイルを指定するために、<head>~</head>内の<style>~</style>タグのなかに
#MyNextButton {
        position: absolute;
        top: 5px;
        left: 5px;
        z-index: 1;
        font-size: 40px;
        cursor: pointer;
    }
と付け加えます。従いまして、Visual Studioとしては下の図のようになります。
ボタンのスタイルとタグを追加

onClickイベント関数の追加

ボタンをクリックしたときに処理される関数を記述します。とりあえず
function loadNextModel() {
    console.log('TODO: Load Next Model');
}
を追加するのですが、問題はどこに追加するのか?ということです。HTMLファイルにJavaScriptを記述する場合、<script>~</script>タグの間に記述するので、とりあえず、下のほうの</script>の直上に入れておきます。
</script>の直上にいれる

グローバル変数の追加

すでに<script>タグの直後に var viewer; というグローバル変数が宣言されていますが、これにあと三つのグローバル変数を追加します。

        var lmvDoc;
        var viewables;
        var indexViewable;

したがって、以下の図の位置に入ります。
グローバル変数を追加

ロード成功時の関数(onDocumentLoadSuccess)の変更

既存のonDocumentLoadSuccess()を以下の内容で書き換えます。
function onDocumentLoadSuccess(doc) {

    // docにある2Dおよび3Dの表示可能なビューの配列をグローバル変数viewablesに格納
    viewables = Autodesk.Viewing.Document.getSubItemsWithProperties(doc.getRootItem(), {'type':'geometry'}, true);
  // 表示可能なビューがなければ終了
    if (viewables.length === 0) {
        console.error('Document contains no viewables.');
        return;
    }

    // ビューアを<div id=MyViewerDiv>に作成しグローバル変数viewerに格納
    var viewerDiv = document.getElementById('MyViewerDiv');
    viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
    var errorCode = viewer.start();

    // ビューアの初期化時のエラーを確認する
    if (errorCode) {
        console.error('viewer.start() error - errorCode:' + errorCode);
        return;
    }

    // グローバル変数indexViewableを0に初期化し、グローバル偏すlmvDocにdocを格納.
    indexViewable = 0;
    lmvDoc = doc;

    // loadModel関数を呼び出して、ビューアにモデルをロードする
    loadModel();
}


働きはコメントをつけておきましたが、そもそもなぜonDocumentLoadSuccessに引数(doc)があるのかがわかりませんね。この関数自体は、Document.Load関数の第二引数の「onSuccessCallback」なのですが、これが引数をとるなどという記述は、HELPにはどこにもないですから。

これらの謎は後日調べて報告します。

さて、この関数の最後にあるloadModel()を、onDocumentLoadSuccess関数の後に記入します。
function loadModel() {
    var initialViewable = viewables[indexViewable];
    var svfUrl = lmvDoc.getViewablePath(initialViewable);
    var modelOptions = {
        sharedPropertyDbPath: lmvDoc.getPropertyDbPath()
    };
    viewer.loadModel(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
}

そして最後に、onClickイベント関数 loadModel を次の関数で置き換えます。
function loadNextModel() {

    viewer.tearDown();
    viewer.setUp(viewer.config);

    // インデックスを+1して次のビューをロード。最後まで行ったら0に戻る
    indexViewable = (indexViewable + 1) % viewables.length;
    loadModel();
}

これで実行してみると、まず下の図のように3Dビューが表示されます。
左上のNEXTボタンを押す
が、左上に表示された[Next!]ボタンをクリックすると
2D図面が表示される
2D図面が表示されます。押し続けると次々と図面が表示されて、また最初の3Dビューに戻ります。

さて、関数とAPI Referenceと見比べてみますと、onDocumentLoadSuccess関数のviewerのインスタンスを作成する「Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);」は、リファレンスには見当たりません。代わりに

というnew関数がありますので、この部分を

viewer = new Autodesk.Viewing.Viewer3D(viewerDiv);

と書き換えて実行してみます。実行後は[F5]などで、キャッシュを除去してください。これでも問題なく動くはずです。


What's next?


おお!無事に表示されたぞ。と喜んでいると一番下のWhat's next?の段落に

ここに紹介されているコードの多くは、物事を稼働させるために必要な定型文です。 ViewingApplicationオブジェクトを使用すると、その一部を簡略化できます。

とあります。ここにあるのはbioplate(定型文・決まり文句)なので、次のチュートリアルをやってみましょう、と言っております。

さてさて、「ViewingApplication」とはどのようなものなのでしょうか?

でも、ここらでチュートリアルで習ったことを使って、自分でWebアプリケーションを作ってみようではないですか!