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 »

dotnet コマンドによるビルド

前回の .NET Core と .NET Standard に引き続き、今回はコマンドラインでアプリやライブラリをビルドする方法を検証しました。
まず、ビルドに関連する dotnet コマンドの一覧を挙げます。
基本的にはプロジェクト フォルダー上で実行しますが、build や pack などは ソリューション フォルダー上でも実行できます。

  • dotnet restore
    • NuGet 参照を解決する
  • dotnet build
    • MSBuild.exe を実行する
    • 内部で restore する (ソースコードしかない状態でも実行できる)
  • dotnet msbuild
    • MSBuild.exe と同じ引数を指定する
    • 内部で restore しない (ソースコードしかない状態では失敗)
  • dotnet publish
    • publish フォルダーに発行する
    • 内部で build する (ソースコードしかない状態でも実行できる)
  • dotnet pack
    • NuGet パッケージを作成する
    • 参照先の DLL は含まれず、依存関係が設定される
    • 内部で build しない (ソースコードしかない状態では失敗)
  • dotnet clean
    • 前回のビルド結果を消去する
    • restore の結果は残る
  • dotnet run
    • ソースコードからアプリを実行する
    • 内部で build する
  • dotnet App1.dll
    • ビルド済みのアプリを実行する

 

以下、詳細について記述していきます。

dotnet msbuild と msbuild

dotnet msbuild と msbuild の動作は同じです。

dotnet msbuild /p:Configuration=Release /t:Rebuild
msbuild /p:Configuration=Release /t:Rebuild

ただし、msbuild は環境変数の PATH に設定されていないため、
cmd や PowerShell で実行するにはそのパスを指定しなければなりませんが、
dotnet は PATH に設定されているため cmd や PowerShell でそのまま実行できて便利です。

アセンブリのビルド・発行

リビルドするには --no-incremental を指定します。

dotnet build -c Release --no-incremental

ただし build では、.NET Core を対象とする場合、NuGet 参照の DLL がコピーされません。
build では開発環境が想定されており、.dev.json ファイルに NuGet 参照が記述されます。
(.NET Framework を対象とする場合は NuGet 参照の DLL もコピーされます。)

配置用にすべての DLL を含めるには publish を使います。
プロジェクトに対象のフレームワークが複数ある場合、-f で一つだけ指定します。

dotnet clean -c Release
dotnet publish -c Release -f netcoreapp2.0

なお、publish 単独ではリビルドができないため、先に clean を実行しています。

NuGet パッケージ作成

出力先のディレクトリを変更するには -o を指定します。

dotnet pack -c Release -o pkg

または、

dotnet msbuild /p:Configuration=Release /t:pack

[構築時に NuGet パッケージを生成する] (.csproj では GeneratePackageOnBuild) を設定して build する方法もあります。

dotnet build -c Release --no-incremental

GeneratePackageOnBuild

 

前回: .NET Core と .NET Standard
次回: ASP.NET Core Web API の Tips

作成したサンプル

バージョン情報

  • .NET Core 2.0

参照

カテゴリー: .NET Core, .NET Framework, ツール. タグ: . 2 Comments »

.NET Core と .NET Standard

.NET Core の登場以降、Visual Studio で新しいプロジェクトを作成しようとすると、
従来の .NET Framework のほかに .NET Core と .NET Standard 向けのプロジェクト テンプレートが現れます。

NewProject

それぞれのプロジェクトにおけるアセンブリの参照可否をまとめると次のようになります。

  • .NET Framework 向けプロジェクト
    • .NET Framework アセンブリを参照可能
    • .NET Core アセンブリを参照不可
    • .NET Standard アセンブリを参照可能
  • .NET Core 向けプロジェクト
    • .NET Framework アセンブリを参照不可
    • .NET Core アセンブリを参照可能
    • .NET Standard アセンブリを参照可能

.NET Framework と .NET Core はランタイムが異なるため、
両方に対応するクロスプラットフォームのクラス ライブラリを作成するには .NET Standard をターゲットにします。
なお、.NET Standard 2.0 アセンブリは .NET Framework 4.6.1 以上で参照可能です。

.NET Core および .NET Standard のプロジェクト テンプレートには、次の特徴があります。

  • .csproj ファイルの記述が簡略化されている
    • アセンブリ情報は .csproj ファイルに含まれ、AssemblyInfo.cs は不要
  • NuGet パッケージを簡単に作成できる
    • ビルド時に作成するように設定できる

クラス ライブラリの .csproj ファイルの内容は次のようになっています。


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

</Project>


TargetFramework を TargetFrameworks に変更すれば、対象のフレームワークをセミコロン区切りで複数指定できます。
ここで指定する netstandard2.0net40 は、Target Framework Moniker と呼ばれます。

<TargetFrameworks>netstandard2.0;net40</TargetFrameworks>

これで複数のフレームワークを対象にしたアセンブリを一度にビルドできます。

TargetFrameworks

.NET Framework 向けのみのアセンブリを作成したい場合であっても、
.NET Core 向けのテンプレートから作成して TargetFramework を変更する方法が有効です。

次に、OutputTypeExe を指定すればコンソール アプリになります (指定がなければクラス ライブラリ)。

<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks>

コンソール アプリをビルドすると、.NET Framework 向けでは .exe が生成されますが、.NET Core 向けでは .dll となります。
(自己完結型デプロイにより、各プラットフォーム向けの実行可能ファイルを生成することもできます。ただし 60MB 前後になります。)

NetCoreConsole

DLL の状態の .NET Core 向けアプリを実行するには、dotnet コマンドを実行します。

dotnet ConsoleApp1.dll

その他の注意点

  • 例えば System.Security.Cryptography 名前空間は .NET Standard で利用可能ですが、
    .NET Framework と .NET Core ではクラス構成に差異があります。
    ビルドできても実行時にエラーとなることもあります (HashAlgorithm.Create メソッドなど)。

 

次回: dotnet コマンドによるビルド

作成したサンプル

バージョン情報

  • Visual Studio 2017
  • .NET Core 2.0

参照

ASP.NET で HTTP ハンドラーを作成する

以前に投稿した静的コンテンツへの要求を動的に処理するという記事に関連して、
今回は HTTP ハンドラーを作成する方法を紹介します。

ASP.NET で HTTP 要求に対して応答を返す方法としては、
IHttpHandler インターフェイスを実装したクラスを作成する方法があり、
.aspx や MVC を使うよりも原始的です (最も原始的な方法は Global.asax)。
ProcessRequest メソッドの引数で HttpContext オブジェクトが渡されます。
HTTP 要求の情報はここからすべて取得でき、応答もこのオブジェクトに格納します。
これにより、任意の処理を実装できます。

IHttpHandler インターフェイスを利用する方法として、
.ashx ファイルを作成する方法もありますが、これでは拡張子が .ashx に固定されてしまいます。
任意の拡張子を利用するには、通常のクラスとして IHttpHandler インターフェイスを実装し、
Web.config で拡張子や HTTP メソッド (GET など) とのマッピングを指定します。

以下では、.txt へのアクセスに対する HTTP ハンドラーを実装します。

サンプルの全体は HttpHandlerWeb (GitHub) にあります。
なお、このサンプルでは Web アプリケーション プロジェクトではなく、Web サイトを利用しています。
そのため、App_Code フォルダーの下にクラスを配置しています。

これで、.txt へのアクセスを受け付けられるようになりました。

file1.txt

 

以前のバージョン (IIS 6.0 以前?) では、Web.config の system.web/httpHandlers セクションで設定していました。

 

前回:静的コンテンツへの要求を動的に処理する

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

バージョン情報
.NET Framework 4.5

参照
チュートリアル : 同期 HTTP ハンドラーの作成 (MSDN)

カテゴリー: .NET Framework. タグ: . 1 Comment »

ASP.NET Web API の Tips (2)

ASP.NET Web API を利用する際の注意点や備忘録です。ほぼ箇条書きです。
基本的な説明は省略しています。
(ASP.NET Core Web API 版も書きました。)

例外処理

  • 戻り値が HttpResponseMessage または IHttpActionResult の場合、Request.CreateErrorResponse メソッドなどで HttpResponseMessage を生成する
  • 戻り値が HttpResponseMessage でも IHttpActionResult でもない場合、HttpResponseException を返すことで同様の効果が得られる
  • HttpError を利用して、JSON のエラー メッセージを含めることができる

公式解説: Exception Handling in ASP.NET Web API

Help Page

コードの XML ドキュメントから、ユーザー向けのヘルプ ページを自動的に生成する機能です。
Visual Studio でプロジェクトを作成するときに Web API を選択すると、Help Page もインストールされます。
あとから追加するには、NuGet で Microsoft.AspNet.WebApi.HelpPage をインストールします。

ただし、既定では機能が有効になっていません。

  • 有効にする手順:
    • プロジェクトのプロパティで、XML ドキュメントの出力を有効にする
    • HelpPageConfig.cs のコメントアウトを解除する ( // を取る)

SetDocumentationProvider

  • アクション メソッドの戻り値が HttpResponseMessage または IHttpActionResult の場合、
    [ResponseType(typeof(string))] のように属性でデータの型を指定する
  • Areas\HelpPage にソースコードがあるため、カスタマイズ可能
  • ヘルプ ページ (Help/Index) を既定のページに設定するには、HelpPageAreaRegistration.cs でルーティングの設定を追加するとよい
  • ASP.NET Core Web API では、Help Page を使えない
    • Swashbuckle (Swagger の .NET 向け実装) を使う

HelpPage

公式解説: Creating Help Pages for ASP.NET Web API

Web API の呼び出し

.NET アプリケーションから Web API を呼び出すには、HttpClient クラスを利用するとよいでしょう。
また、サービス側で実装されたカスタム データ型も、サービス コントラクトとして利用できます。
すなわち、応答メッセージに対して response.Content.ReadAsAsync<T>() を呼び出せば T 型としてデシリアライズできます。

公式解説: Call a Web API From a .NET Client (C#)

CORS

  • NuGet で Microsoft.AspNet.WebApi.Cors をインストールする
  • WebApiConfig.cs で config.EnableCors メソッドを呼び出すことで機能を有効にする
    • 引数に EnableCorsAttribute を渡すとグローバルに設定できる
    • コントローラー、アクションのレベルでは [EnableCors] を指定する

CORS が機能しているかどうかをテストする方法については ASP.NET Core Web API の Tips に書きました。

公式解説: Enabling Cross-Origin Requests in ASP.NET Web API 2

JSONP

未検証。

  • MediaTypeFormatter を利用する
    • WebApiContrib.Formatting.Jsonp など

フォーマット

ASP.NET Web API は、既定で JSON と XML をサポートします。
要求の Accept ヘッダーに何が指定されているかで結果のフォーマットが変わります。
Google Chrome 上で Web API を直接呼び出すと結果が XML 形式で返ってきます。
これは、要求の Accept ヘッダーに application/xml が含まれているためと考えられます。
これを JSON 形式にするには、text/html が含まれている場合に JSON を返す設定や XML 形式を無効にする設定が考えられます。

解説: How do I get ASP.NET Web API to return JSON instead of XML using Chrome?

 

前回: ASP.NET Web API の Tips (1)

作成したサンプル

バージョン情報

  • .NET Framework 4.5
  • ASP.NET Web API 5.2.3
  • ASP.NET MVC 5.2.3
  • ASP.NET Web API Help Page 5.2.3
  • ASP.NET Web API CORS 5.2.3

参照

カテゴリー: .NET Framework. タグ: , . 1 Comment »

ASP.NET Web API の Tips (1)

ASP.NET Web API を利用する際の注意点や備忘録です。ほぼ箇条書きです。
基本的な説明は省略しています。
(ASP.NET Core Web API 版も書きました。)

ルーティング

WebApiConfig.cs にルーティングの設定が記述されています。
既定のテンプレートは api/{controller}/{id} となっており、REST スタイルを想定したものとなっています。
ただし、ASP.NET MVC と同様に {action} も利用可能であり、RPC スタイルの API も構成できます。

  • [RoutePrefix], [Route], [ActionName] などの属性を利用することで柔軟に構成できる
  • [Route] を複数設定できる

公式解説: Web API Routing

HTTP メソッド

  • 主に REST スタイルの場合、Get、Post などのメソッド名で解決される (CoC)。
    この場合、[HttpGet] などの属性を指定する必要はない
  • 主に RPC スタイルで任意のアクション名を利用するには、[HttpGet] などの属性を指定する

引数

  • DateTime, Guid などの型も扱える
  • 引数の [FromBody] は、エンティティ型なら付ける必要はない
  • ルーティングで {i:int:range(0,100)} のような制約を追加できる
  • 引数に既定値を指定すると、URL のパラメーターを省略可能
    • ルーティングで指定する場合は {i:int?} のようにする
    • range などを使う場合、省略可能にできない
      • int? と range は同時に指定できない
  • 引数で / を使う場合、引数名の前に * を指定する (下の DateTime 型の例)

公式解説: Attribute Routing in ASP.NET Web API 2

戻り値

戻り値として、通常のデータ型以外に次のものを指定できます。

  • HttpResponseMessage
    • 生の応答データ
  • IHttpActionResult
    • HttpResponseMessage をラップしたインターフェイス

これらを利用することにより、応答データを柔軟に設定できます。

  • JSON や XML に限らず、テキストや画像などの任意の形式のコンテンツを返せる
  • 主な IHttpActionResult の実装は System.Web.Http.Results 名前空間で定義されている

以下は、テキスト (Content-Type: text/plain) を返す例です。

公式解説: Action Results in Web API 2

 

次回: ASP.NET Web API の Tips (2)

作成したサンプル

バージョン情報

  • .NET Framework 4.5
  • ASP.NET Web API 5.2.3

参照

カテゴリー: .NET Framework. タグ: , . 3 Comments »

メソッドチェーンでアスペクト指向プログラミング

透過プロキシでアスペクト指向プログラミング (1) では、ログ出力やデータベース トランザクションなどの横断的関心事を、

public class NorthwindBusiness : MarshalByRefObject
{
    [TraceLog]
    [TransactionScope]
    public short SelectUnitsInStock()
    {
    }
}

のように、属性として記述することができました。
今回は属性を使わずに、LINQ と同様にメソッドチェーンを使って横断的関心事を記述してみます。

まず、戻り値を持つ (Func<TResult> に相当する) 処理を IProxyable<TResult> インターフェイスとして定義して、
後ろにメソッドチェーンを追加することで処理を上書きできるようにします。

これを実行すると出力は次のようになり、元の処理の前後に処理が追加されていることがわかります。

Before
Body
After

次に、戻り値を持たない (Action に相当する) 処理を表す IProxyable インターフェイスを、
IProxyable<TResult> インターフェイスの特別な場合とみなして継承させます。

あとは、ログ出力やデータベース トランザクションなどの横断的関心事を拡張メソッドとして作成すれば完成です。

実行結果です:

ProxyableConsole

 

使い道としては、

  • .NET で透過プロキシを使いたくないとき (処理速度を上げたい、など)
  • .NET の属性のような仕組みを持たない別のプラットフォーム

などの場合が考えられるでしょう。

前回:透過プロキシでアスペクト指向プログラミング (2)

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

バージョン情報
C# 7.0
.NET Framework 4.5

参照
アスペクト指向プログラミング

カテゴリー: .NET Framework, データベース. タグ: . 1 Comment »