URL エンコーディング

URL エンコーディングの定義と、それを扱うための .NET Framework のライブラリを検証しました。

パーセント エンコーディングと URL エンコーディング

パーセント エンコーディングとは、文字列を UTF-8 でエンコードし、各バイトをパーセント記号 % とその 16 進数を用いて表すことです。
例えば、"/""%2F" に、"あ""%E3%81%82" に変換されます。

URL エンコーディングとは、URI の中で使われている記号と混在しないように一部の文字列をパーセント エンコーディングにより
変換することです。両者の言葉を区別せずに使うこともあります。

URL エンコーディング

RFC 3986 では、文字は次のように分類されます。

  • 非予約文字
    • エンコードしなくても利用できる文字
    • アルファベット、数字、および 4 種類の記号 -._~
  • 予約文字
    • URI で意味を持つ記号
    • 18 種類の記号 !#$&'()*+,/:;=?@[]
  • その他の文字
    • エンコードが必要な文字
    • 11 種類の記号 " %<>\^`{|} 、その他のすべての文字 (日本語など)

URL エンコーディングは、主に次の 2 通りで利用されます。

  • URI の各セグメント (クエリ文字列を除く)
    • https://tempuri.org/messages/Hello%20World%21messagesHello%20World%21 の部分
    • 非予約文字以外をパーセント エンコーディング
      • ただし、Web フレームワーク個別の仕様により、パーセント エンコーディングしても使用を制限されることがある
  • URI のクエリ文字列や、POST などで送信するときの本文 (フォーム)
    • key=value&message=Hello+World%21keyHello+World%21 の部分
    • 非予約文字以外をパーセント エンコーディングし、さらに %20 (スペース) を + に変換
    • MIME タイプ application/x-www-form-urlencoded と定義されている

 

.NET Framework のライブラリ

.NET Framework では、URL エンコーディングのために次の方法が用意されています。

  • System.Uri.EscapeDataString メソッド
    • RFC 3986 に従って非予約文字以外をパーセント エンコーディング
  • System.Uri.EscapeUriString メソッド
    • RFC 3986 に従って非予約文字・予約文字以外をパーセント エンコーディング
    • 既に全体が URI の形式になっているときに利用する
      • クエリ文字列も同様の規則で変換される。application/x-www-form-urlencoded には変換されない
  • System.Uri インスタンスの AbsoluteUri プロパティ
    • 基本的に Uri.EscapeUriString メソッドと同じだが、下記の点が異なる
    • %XX の形式になっているかどうかで扱いが異なる
      • https://tempuri.org/%2https://tempuri.org/%252
      • https://tempuri.org/%25https://tempuri.org/%25 のまま
    • クエリ文字列でない部分の \/ に変換される
  • System.Net.WebUtility.UrlEncode メソッド
    • RFC 2396 (旧版) に近い仕様で非予約文字以外をパーセント エンコーディングし、さらに %20 (スペース) を + に変換
  • System.Web.HttpUtility.UrlEncode メソッド
    • System.Net.WebUtility.UrlEncode メソッドと同じだが、小文字になる
  • System.Net.Http.FormUrlEncodedContent クラス
    • key-value データをまとめて application/x-www-form-urlencoded に変換

 

Uri.AbsoluteUri

 

.NET では System.Uri.EscapeDataString メソッドSystem.Uri.EscapeUriString メソッド
System.Net.Http.FormUrlEncodedContent クラスを使えばよいでしょう。

アプリケーションから HTTP 接続をするために System.Net.Http.HttpClient クラスを使うことが多いと思いますが、
接続先の URI を string で渡しても、HttpClient の内部では Uri インスタンスで扱われます。
したがって、URI を HttpClient に渡す前に、セグメントもクエリ文字列も URL エンコーディングしておくのがよさそうです。

 

作成したサンプル

バージョン情報

  • .NET Framework 4.5

参照

広告
カテゴリー: .NET Framework, サービス. タグ: , . Leave a Comment »

ランダムなデータを生成する JSON API

Random Data Web API というものを作成しました (正確には、2014 年に作成したものを最近改修しました)。
ランダムなデータを生成するための JSON Web API です。以下のデータを生成できます。

  • アルファベット
  • アルファベットと数字
  • バイト列
    • 16進数形式、Base64 形式
  • UUID (GUID)
  • 時刻順の ID
    • 現在の時刻をもとに、並べ替え可能な GUID を生成
    • SQL Server の uniqueidentifier 型にも対応

内容自体はとくに変哲のない API です。時刻順の ID は少し珍しいかもしれませんが。
また、仕様が記述されたヘルプページ、および jQuery を利用したテストページが付属しています。

Test page

さて、従来の一般的な Web API の問題点として、利用する開発者の意思に反してサービスが終了してしまうということがよくあります。
無償・有償を問わずサービスが永久に提供されるとは限らないため、
なるべく自身のアプリをそれに依存させず、自身でサービスを運用することが望ましいでしょう。

そこでこの Web API では、ソースコードをオープンソース ライセンスのもとで提供し、
それを利用する開発者自身がサービスをホストすることを想定します。
例えば Azure Web App などの PaaS を利用すれば GitHub から直接ビルドおよびデプロイができるため、
簡単な手順でサービスの運用を開始させることができます。
またこの場合は継続的デプロイが構成され、fork したリポジトリが更新されれば Azure Web App も自動的に更新されます。

詳細の方法については Azure Web App にデプロイする手順にまとめてあります。
なお、randomdata.azurewebsites.net は配置例として提供しているものです。このサイトに保証・サポートはありません。

Deployment Option

技術的な特徴としては、以下が挙げられます。

  • ASP.NET Web API
    • XML Formatter を無効化して、JSON 形式のみをサポート
  • ASP.NET Web API Help Page
    • ソースコード内のコメントから自動生成
    • いろいろカスタマイズして利用
  • ASP.NET Web API Cross-Origin Support
    • CORS (Cross-Origin Resource Sharing)
  • HTTPS 必須化

ヘルプページの多言語対応については、ブラウザーの翻訳機能を利用すれば何とかなるでしょう。

Help Translation

バージョン情報

  • .NET Framework 4.5
  • ASP.NET Web API 5.2.3
  • ASP.NET Web API Help Page 5.2.3
  • ASP.NET Web API Cross-Origin Support 5.2.3
  • Blaze 1.1.10

参照

Cognitive Services の Face API の利用

前回の Cognitive Services の Computer Vision API の利用に引き続いて、
今回は Face API を .NET (C#) で試してみたいと思います。

Cognitive Services の各 API を利用するには、まずアカウントのページから
サブスクリプションを登録してサブスクリプション キーを入手します。

Visual Studio で新規のプロジェクトを作成して (ここでは WPF とします)、
NuGet で Microsoft.ProjectOxford.Face をインストールします。

画像から顔を検出するには、次のようなコードを記述します。
(これは完全なコードではなく、API を呼び出す部分のみです。)

FaceServiceClient.DetectAsync メソッドの第 1 引数で画像を指定します。
画像は、Web 上の URL で指定するか、Stream を介して直接送ります。
前回は URL を指定しましたが、今回は Stream を使っています。

また、returnFaceAttributes という引数で、何の判定をするか (年齢、性別、眼鏡の有無など) を
IEnumerable<FaceAttributeType> 型で指定します。
上のコードでは、すべての情報を取得するように指定しています。
目や鼻などの特徴点の座標を判定するには、returnFaceLandmarks 引数に true を指定します。

実行結果は Face[] 型で、人数分の顔情報が格納されています。

 

実際にサンプル アプリを作成して試してみましたが、以下の注意点があります。

  • Computer Vision API にも年齢・性別を推定する機能がありますが、同一の結果にはならないようです。
  • 20 回に 1 回くらいの割合でエラーとなることがあるため、try-catch ステートメントは必須です。
    アプリの要件によってはリトライも検討したほうがよいでしょう。
    画像ファイル自体が原因となる場合もあるようです (サイズが小さいなど)。
  • (本題の Face API とは直接関係ないですが) JPEG ファイルは DPI が異なる場合があり (既定では 96)、
    Image コントロールに直接読み込ませると DPI によりサイズが変化し、
    Face API から取得した座標のスケールと異なってしまいます。
    したがってこのサンプルでは、あらかじめ BitmapImage オブジェクトに画像を読み込ませて、
    その PixelWidth および PixelHeight プロパティを利用しています。

作成したサンプル
FaceWpf (GitHub)

FaceWpf

 

前回: Cognitive Services の Computer Vision API の利用

バージョン情報
.NET Framework 4.5
Microsoft.ProjectOxford.Face 1.1.0

参照
Face API
How to Detect Faces in Image
Face API (Reference)

Microsoft Cognitive Services を始める ~ 全21種のサービス概説と開発準備
de:code 2016 > DBP018-Microsoft Cognitive Services 入門 → サンプルコード解説

Cognitive Services の Computer Vision API の利用

カテゴリー: サービス. タグ: , . 1 Comment »

Cognitive Services の Computer Vision API の利用

Microsoft Cognitive Services には現在、Preview のものを含めて 21 の API が用意されています。
今回は Computer Vision API を .NET (C#) で使ってみることにします。

Cognitive Services の各 API を利用するには、まずアカウントのページから
サブスクリプションを登録してサブスクリプション キーを入手します。

Visual Studio で新規のプロジェクトを作成して (ここでは WPF とします)、
NuGet で Microsoft.ProjectOxford.Vision をインストールします。

画像の分析をするには、次のようなコードを記述します。
(これは完全なコードではなく、API を呼び出す部分のみです。)

VisionServiceClient.AnalyzeImageAsync メソッドで、指定された画像に対してさまざまな分析ができます。

第 1 引数で画像を指定します。Web 上の URL で指定するか、Stream を介して直接送ります。
第 2 引数では、何の判定をするか (顔の判別が必要か、アダルト コンテンツの判定が必要かなど) を
IEnumerable<VisualFeature> 型で指定します。
上のコードでは、すべての情報を取得するように指定しています。

結果は AnalysisResult 型で返ってきます。
AnalysisResult は、プロパティが存在するだけのシンプルなクラスです。

 

次に、OCR (光学文字認識) も試してみます。
(これは完全なコードではなく、API を呼び出す部分のみです。)

OCR をするには、VisionServiceClient.RecognizeTextAsync メソッドを利用します。
オプション引数で言語を指定することもできます。既定では自動判別のようです。

 

実際にサンプル アプリを作成して試してみましたが、以下の注意点があります。

  • OCR では、日本語の場合は 1 文字で 1 単語になってしまうようです (下図参照)。
    今後の改善に期待します。
  • 20 回に 1 回くらいの割合でエラーとなることがあるため、try-catch ステートメントは必須です。
    アプリの要件によってはリトライも検討したほうがよいでしょう。
    画像ファイル自体が原因となる場合もあるようです (サイズが小さいなど)。

作成したサンプル
ComputerVisionWpf (GitHub)

ComputerVisionWpf

 

次回: Cognitive Services の Face API の利用

バージョン情報
.NET Framework 4.5
Microsoft.ProjectOxford.Vision 1.0.296

参照
Computer Vision API
How to Call Computer Vision API
Computer Vision API (Reference)

Microsoft Cognitive Services を始める ~ 全21種のサービス概説と開発準備
de:code 2016 > DBP018-Microsoft Cognitive Services 入門 → サンプルコード解説

センサーのデータを SignalR でホストする (5)

前回のセンサーのデータを SignalR でホストする (4) までで、

  • ASP.NET SignalR サービス (コンソール アプリケーション)
  • ASP.NET SignalR クライアント (HTML)
  • ASP.NET SignalR クライアント (コンソール アプリケーション)

を作成しました。

今回は、コンソール アプリケーションとして作成した ASP.NET SignalR サービスを
タスクバーの通知領域に常駐させるように変更したいと思います。

 

(5) サービスをタスクバーの通知領域に常駐させる

Windows のタスクバーの通知領域を利用するには、アイコン ファイル (.ico) が必須です。
まず、以下の手順でアイコンをリソースに登録します。

(1), (2) で作成したプロジェクトのプロパティを開き、[リソース] タブを選択します。
中央のリンクをクリックして、リソース ファイルを作成します。

リソース 1

通知領域に表示させるアイコン ファイル (.ico) を用意し、
エクスプローラーから下図の中央部分にドラッグ アンド ドロップします。

リソース 2

名前を ServiceIcon に変更しておきます。

リソース 3

 

次に、プロジェクトのプロパティの [アプリケーション] タブを選択し、
[出力の種類] を [Windows アプリケーション] に変更します。
これにより、コンソール画面を出現させずにアプリケーションを実行できます。

出力の種類

 

プロジェクトに System.Windows.Forms.dll への参照を追加して、
次のように Program クラスを変更していきます。


class Program
{
    const string SelfHostUrl = "http://localhost:8080";
    const string AppName = "Sensors Host";
    static IDisposable webApp;
    static NotifyIcon notifyIcon;

    static void Main(string[] args)
    {
        webApp = WebApp.Start(SelfHostUrl);
        ShowNotifyIcon();
        Application.Run();
    }

    static void ShowNotifyIcon()
    {
        var exitMenu = new ToolStripMenuItem("終了(&X)");
        exitMenu.Click += (o, e) => ExitApp();
        var contextMenuStrip = new ContextMenuStrip();
        contextMenuStrip.Items.Add(exitMenu);

        notifyIcon = new NotifyIcon
        {
            ContextMenuStrip = contextMenuStrip,
            Icon = Properties.Resources.ServiceIcon,
            Text = AppName,
            Visible = true,
        };

        notifyIcon.ShowBalloonTip(3000, AppName, "サービスを開始しました。", ToolTipIcon.Info);
    }

    static void ExitApp()
    {
        webApp.Dispose();
        notifyIcon.Dispose();
        Application.Exit();
    }
}


サービスのセルフホストを開始したら、Application.Run メソッドを呼び出します。
これによりブロックが起き、アプリケーションの実行状態が保持されます。

NotifyIcon オブジェクトを生成して Visible プロパティを true に設定することにより、
タスクバーの通知領域にアイコンが表示されるようになります。
また、[終了] メニューを ContextMenuStrip オブジェクトに追加しておきます。

 

これを実行します。
タスクバーの通知領域にアイコンとメッセージが表示されます。

Sensors Host (開始)

アイコンを右クリックすると、[終了] メニューが表示されます。

Sensors Host (終了)

 

前: センサーのデータを SignalR でホストする (4)

作成したサンプル
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5

参照
NotifyIcon クラス

センサーのデータを SignalR でホストする (4)

前回のセンサーのデータを SignalR でホストする (3) では、
ASP.NET SignalR サービスに対するクライアントを HTML で実装しました。
今回は同様のクライアントをコンソール アプリケーションで実装します。

 

(4) コンソール アプリケーションからサービスにアクセスする

まず、[新しいプロジェクトの追加] でコンソール アプリケーション プロジェクトを作成します。

準備として、次のものを参照に追加する必要があります。

  • ASP.NET SignalR .NET Client (Microsoft.AspNet.SignalR.Client)

作成したプロジェクトを右クリックして [Nuget パッケージの管理] を選択します。
上記のパッケージを検索してインストールします。

ASP.NET SignalR .NET Client

 

Program.cs を、次のように実装します。


class Program
{
    static void Main(string[] args)
    {
        Task.Run(() => StartConnection());

        Console.WriteLine("Press [Enter] to exit.");
        Console.ReadLine();
    }

    async static void StartConnection()
    {
        var connection = new HubConnection("http://localhost:8080/");
        connection.ConnectionSlow += () => Console.WriteLine("Connection is slow.");
        connection.Error += ex => Console.WriteLine(ex);

        var lightSensor = connection.CreateHubProxy("LightSensorHub");
        lightSensor.On<float>("NotifyIlluminanceInLux", NotifyIlluminanceInLux);
        var compass = connection.CreateHubProxy("CompassHub");
        compass.On<double>("NotifyHeadingMagneticNorth", NotifyHeadingMagneticNorth);

        await connection.Start();

        var illuminanceInLux = await lightSensor.Invoke<float>("GetIlluminanceInLux");
        NotifyIlluminanceInLux(illuminanceInLux);
        var headingMagneticNorth = await compass.Invoke<double>("GetHeadingMagneticNorth");
        NotifyHeadingMagneticNorth(headingMagneticNorth);
    }

    static void NotifyIlluminanceInLux(float illuminanceInLux)
    {
        Console.WriteLine("Light: {0} lx", illuminanceInLux);
    }

    static void NotifyHeadingMagneticNorth(double headingMagneticNorth)
    {
        Console.WriteLine("Compass: {0} °", headingMagneticNorth);
    }
}


HubConnection.CreateHubProxy メソッドで、Hub のプロキシを作成します。

サービス側から直接呼び出せるメソッドを定義するには、On メソッドを使います。
逆に、サービス側で定義されたメソッドを呼び出すには、Invoke メソッドを使います。

なお、サービスのパスを明示的に指定するには、

var connection = new HubConnection("http://localhost:8080/signalr", false);

のようにします。

 

では、これを実行します。
端末に手をかざしたり端末を回転したりすれば、サービス側からそれぞれのデータがプッシュ送信されます。

SensorsConsole

 

次回は、サービス側のアプリケーションを通知領域に常駐させるように変更します。

つづく

前: センサーのデータを SignalR でホストする (3)
次: センサーのデータを SignalR でホストする (5)

作成したサンプル
WinRT-SignalR-Sample (GitHub) (今回までの分)
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5
ASP.NET SignalR .NET Client 2.0

参照
Hubs API Guide – .NET Client (C#)

センサーのデータを SignalR でホストする (3)

前回のセンサーのデータを SignalR でホストする (2) では、サービス側を実装しました。
今回はクライアント側となる Web アプリケーションを実装します。

 

(3) ブラウザーからサービスにアクセスする

まず、[新しいプロジェクトの追加] で [ASP.NET 空の Web アプリケーション] を選択し、
Web アプリケーション プロジェクトを作成します。

準備として、次のものを参照に追加する必要があります。

  • jQuery
  • ASP.NET SignalR JavaScript Client (Microsoft.AspNet.SignalR.JS)

通常、Web アプリケーション プロジェクトで ASP.NET SignalR のクライアント側もサービス側も実装する場合は
ASP.NET SignalR (Microsoft.AspNet.SignalR) をインストールしますが、
今回はクライアント側のみを利用するため、ASP.NET SignalR JavaScript Client をインストールします。

また、現在のところ、ASP.NET SignalR JavaScript Client をインストールすると、
古いバージョンである jQuery 1.6.4 が同時に入ってしまうため、先に jQuery を個別にインストールしておきます。

作成したプロジェクトを右クリックして [Nuget パッケージの管理] を選択します。
上記のパッケージを検索してインストールします。

jQuery

ASP.NET SignalR JavaScript Client

 

プロジェクトに [HTML ページ] を追加し、名前を index.html とします。
index.html を次のように実装して、サービスからセンサーのデータを取得します。


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Sensors Client</title>
    <script src="Scripts/jquery-2.0.3.min.js"></script>
    <script src="Scripts/jquery.signalR-2.0.0.min.js"></script>
    <script src="http://localhost:8080/signalr/hubs"></script>
</head>
<body>
    <script type="text/javascript">
        $(function () {
            $.connection.hub.url = "http://localhost:8080/signalr";
            var appModel = { light: 0, compass: 0 };

            var lightSensor = $.connection.lightSensorHub;
            lightSensor.client.notifyIlluminanceInLux = function (illuminanceInLux) {
                appModel.light = illuminanceInLux;
                console.log("Light: %f lx", appModel.light);
            };
            var compass = $.connection.compassHub;
            compass.client.notifyHeadingMagneticNorth = function (headingMagneticNorth) {
                appModel.compass = headingMagneticNorth;
                console.log("Compass: %f °", appModel.compass);
            };

            $.connection.hub.start()
                .done(function () {
                    lightSensor.server.getIlluminanceInLux()
                        .done(lightSensor.client.notifyIlluminanceInLux);
                    compass.server.getHeadingMagneticNorth()
                        .done(compass.client.notifyHeadingMagneticNorth);
                });
        });
    </script>
</body>
</html>


サービス側から直接呼び出せるメソッドを定義するには、lightSensor.client.notifyIlluminanceInLux のように、
hub の client プロパティに関数を設定します。

逆に、サービス側で定義されたメソッドを呼び出すには、lightSensor.server.getIlluminanceInLux のように、
hub の server プロパティを経由して呼び出します。

これを実行します。
端末に手をかざしたり端末を回転したりすれば、サービス側からそれぞれのデータがプッシュ送信され、
ブラウザーのコンソールに値がレポートされます。

Sensors Client (コンソール)

 

あとは、GUI を追加すれば変化が視覚的にわかりやすくなります。
この先のコードは index.html (GitHub) をご覧ください。

Sensors Client 1

Sensors Client 2

 

次回は、コンソール アプリケーションでクライアントを作成します。

つづく

前: センサーのデータを SignalR でホストする (2)
次: センサーのデータを SignalR でホストする (4)

作成したサンプル
WinRT-SignalR-Sample (GitHub) (今回までの分)
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5
jQuery 2.0
ASP.NET SignalR JavaScript Client 2.0

参照
Tutorial: SignalR Self-Host