ASP.NET Web APIでAPIのバージョニングを設定する
この記事は、ASP.NET Web APIを使用してAPIを作成する時に、バージョニングを設定する方法について記載したものです。
一般的にAPIでバージョニングを行う方法は以下のように複数ありますが、今回はURLにバージョンを指定する方法について紹介します。
- URLに指定する
https://api.sample.com/v1/users
- クエリパラメータに指定する
https://api.sample.com/users?version=1
- メディアタイプに指定する
Accept: application/json;v=1
- 独自のHTTPヘッダに指定する
X-API-Version: 1
設定の流れ
設定の流れとしては以下のような感じです。
1. NuGetでMicrosoftが公開しているAPIバージョニングのためのライブラリを自身のプロジェクトに追加する
2. WebApiConfig.csにAPIバージョニングの設定を追加する
3. 各コントローラークラスにApiVersionアノテーションを付ける
以下、設定の流れを詳細に見ていきます。
1. NuGetでMicrosoftが公開しているAPIバージョニングのためのライブラリを自身のプロジェクトに追加する
以下のURLに公開されている Microsoft.AspNet.WebApi.Versioning
をAPIバージョニングを設定したいプロジェクトに追加してください。
NuGet Gallery | Microsoft.AspNet.WebApi.Versioning 3.0.1
Visual Studioのソリューションエクスプローラーで対象のプロジェクトを右クリックし、NuGetパッケージの管理をクリックして検索ボックスに Microsoft.AspNet.WebApi.Versioning と入力し対象のライブラリが表示されたインストールしてください。
正常に追加されたらプロジェクトの参照に Microsoft.AspNet.WebApi.Versioning が表示されているはずです。
2. WebApiConfig.csにAPIバージョニングの設定を追加する
ASP.NET Web APIの設定を記載するWebApiConfig.csに以下のコードを追加してください。
// バージョニングの設定 var constraintResolver = new DefaultInlineConstraintResolver() { ConstraintMap = { ["apiVersion"] = typeof( ApiVersionRouteConstraint ) } }; config.MapHttpAttributeRoutes(constraintResolver); config.AddApiVersioning();
3. 各コントローラークラスにApiVersionアノテーションを付ける
最後に各コントローラークラスにApiVersionアノテーションを付ければ完了です。
SampleController.cs
namespace SampleApi.Controllers { [ApiVersion("1")] [RoutePrefix("api/v{version:apiVersion}/users")] public class SampleController { [HttpGet] [Route("")] public async Task<IHttpActionResult> GetUsers() { ..... } } }
上記の場合以下のようなエンドポイントでリクエスト可能となります。
https://sample.com/api/v1/users
最後に
ASP.NET Web APIにおけるAPIバージョニングの設定方法は、ここで紹介した以外にもいくつか方法があります。その他の方法については以下のページを参照ください。
https://github.com/microsoft/aspnet-api-versioning
https://github.com/microsoft/aspnet-api-versioning/wiki/New-Services-Quick-Start#aspnet-web-api
https://github.com/microsoft/aspnet-api-versioning/tree/master/samples/webapi
https://github.com/microsoft/aspnet-api-versioning/wiki/Configuring-Your-Application
情報処理安全確保支援士に一発合格した勉強法
平成30年度秋期試験で、情報処理安全確保支援士に合格しました。
この記事では、情報処理安全確保支援士に合格するために私がやった勉強内容をご紹介します。
ですがご覧の通り、午後はギリギリです。あんまり偉そうなことは言えません。
勉強期間
4か月
午前I、午前IIの勉強は、応用情報技術者試験ドットコムと情報処理安全確保支援士ドットコムをそれぞれ使ったのですが、その履歴を確認すると6月後半から開始していたので、期間としては4か月くらいみたいです。
勉強内容
午前試験と午後試験に分けて書いていきます。
はじめに
情報処理の高度試験は、午前試験は足切りのようなもので、本番は午後試験です。 勉強時間の配分も午前は最低限に済ませて、午後の勉強に時間を割いた方が良いかと思います。 試験勉強を始める前に、色々な人の合格体験記を読んだのですが、午後Iが1番の難関と言っている方が多かったです。確かに午後Iも難しかったのですが、私は得点にも表れているように午後IIが1番難しかったです。 何より試験問題が長いので。。。
午前試験
午前I
応用情報技術者試験ドットコムの過去問道場で、繰り返し過去問を解きました。主に電車に乗っている時に解いていました。 過去問と全く同じ問題も出るので、午前Iはこれだけやっていれば充分かと思います。 60%取れればいいので、ここは最低限に済ませます。 短い空き時間を使って少しずつ解いていけば良いと思います。
午前II
こちらも午前Iと同じ方法です。 情報処理安全確保支援士ドットコムの過去問道場で、繰り返し過去問を解きました。 午前IIはセキュリティ関係の問いが多く、午後試験を解くために必要な用語や知識も身に付きます。 午前Iの過去問は応用情報のものなので、1回の試験分でも80問あり、結構量が多いのですが、こちらは25問しかないのでペースが速くなると思います。
午後試験
まず、過去問を1回分解いて、どれぐらいできるか確かめました。 結果、合格点には遠く及ばなかったので、以下の書籍を読みつつ、過去問を新しいものから順にひたすら解いていきました。
- 作者: 上原孝之
- 出版社/メーカー: 翔泳社
- 発売日: 2018/11/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
過去問は、IPAのサイトにあるものを印刷して使用していました。 最初はPC上で見たのですが、問題文と設問を行き来するのにとても不便だったので、ちょっと量は多かったですがすべて印刷しました。
たくさん過去問を解くことで、ある程度の文量の文章を読むことに慣れ、問題構成や設問のパターンを把握します。 分からない用語があれば、ネットで調べて概要を把握してください。 私は、共通鍵暗号、公開鍵暗号、デジタル署名、証明書など、暗号関連の知識をつけるために以下の書籍を読みました。
- 作者: 結城浩
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2015/08/26
- メディア: 単行本
- この商品を含むブログ (19件) を見る
過去問を解く際は、必ず時間を測ってください。自分がどれぐらいの時間で問題を解けるのか把握するためです。 午後試験は時間が足りない可能性もあるので、時間配分も意識しながら解くようにすると本番でも慌てずに済むと思います。
試験を受けての感想
私は免除がなく、午前Iから受けたので、丸一日とても長かったです。 本番の午後試験で重要だと思ったことは、自分が解答する問題をいかに早く選ぶことができるかです。 この選択に迷うとその分時間を消費してしまいますし、後から解答する問題を変えると、とても慌ててしまいます。 得点配分の大きい長文の記入形式問題に解答できそうな問題を選べば良いのではないでしょうか。
最後に、私が使用した教材です
応用情報技術者試験ドットコム
情報処理安全確保支援士ドットコム
- 作者: 上原孝之
- 出版社/メーカー: 翔泳社
- 発売日: 2018/11/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
ポケットスタディ 情報処理安全確保支援士 (情報処理技術者試験)
- 作者: 村山直紀
- 出版社/メーカー: 秀和システム
- 発売日: 2017/03/25
- メディア: 単行本
- この商品を含むブログ (2件) を見る
上記のような勉強をすることで、私は1度目の挑戦で合格することができました。これから受験される方達の参考になれば幸いです。
LPIC 300 合格 LPIC Level 3 取得
LPIC 300に合格し、LPIC Level 3を取得しました。
取得点
570点
内訳
OpenLDAPの設定 | 75% |
---|---|
OpenLDAPの認証バックエンドとしての利用 | 100% |
Sambaの基礎 | 63% |
Sambaの共有の設定 | 88% |
Sambaのユーザとグループの管理 | 66% |
Sambaのドメイン統合 | 77% |
Sambaのネームサービス | 80% |
LinuxおよびWindowsクライアントの操作 | 40% |
受験回数・勉強期間
1回目。18日間です。
勉強に使ったもの
Ping-t
ping-t.com
勉強法
Ping-tの各問題をすべて金になるまで解きます。
次に模擬試験をひたすら行い、
模擬試験でコンスタントに90%以上取れるようになったら受験しました。
本番試験の感想
入力問題は12問でました。思っていたより多かったです。
だいたい30分くらいですべて解き終えて、
10分くらい見直しした後に終了。
Ping-tで見たような問題もありましたが、見たことのないような
問題の方が多かった印象です。
Ping-tだけでも合格できると思いますが、100%合格できるかは微妙ですね。
万全の状態で臨みたい方は、Ping-tと併せて他の対策もした方が良いかもしれません。
ImageToolsを使用してSilverlightアプリケーション上でGIFを再生する
ImageToolsというライブラリを使用して、Silverlightアプリケーション上でGIFを再生する方法を書きます。
ImageTools 公式サイト
imagetools.codeplex.com
使い方
- ImageToolsライブラリをダウンロードする。
上記公式サイトから、ライブラリをダウンロードしてください。
2.Silverlight アプリケーションのプロジェクトにImageToolsのDLLを参照設定する。
GIFを再生するために必要なDLLはおおよそ以下の4つ。
ImageTools.dll
ImageTools.Controls.dll
ImageTools.Utils.dll
ImageTools.IO.Gif.dll
3.参照設定後、xamlファイルに以下のように記述する。
namespaceにImageToolsを追加し、GIFを表示するためのImageToolsのAnimatedImageタグを定義する。
<UserControl x:Class="ImageToolsSampleApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:imagetools="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <imagetools:AnimatedImage x:Name="image" Height="100" Width="100" Stretch="Fill" MouseLeftButtonUp="image_MouseLeftButtonUp"></imagetools:AnimatedImage> </Grid> </UserControl>
4.上記xamlファイルのコードビハインドで以下のように記述する。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using ImageTools; using ImageTools.IO; using ImageTools.IO.Gif; namespace ImageToolsSampleApp { public partial class MainPage : UserControl { // GIFアニメーションの動いてるか止まっているかを持つフラグ private bool isAnimate = false; public MainPage() { InitializeComponent(); Decoders.AddDecoder<GifDecoder>(); ExtendedImage extendedImage = new ExtendedImage(); // GIF読み込み完了時の処理 extendedImage.LoadingCompleted += (sender, args) => { Dispatcher.BeginInvoke(() => { image.Source = extendedImage; isAnimate = true; // GIFの再生秒数を抽出 double totalDelayTime = 0F; for (int i = 0; i < extendedImage.Frames.Count; i++) { totalDelayTime += (extendedImage.Frames[i].DelayTime / 100.0) * 1000.0; } totalDelayTime += (extendedImage.DelayTime / 100.0) * 1000.0; }); }; // GIF読み込み extendedImage.UriSource = new Uri("Image/sample.gif", UriKind.Relative); } // GIFクリック時の処理 private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // GIFの状態をみて、再生するか止めるか行う if (isAnimate == false) { image.Start(); isAnimate = true; } else { image.Stop(); isAnimate = false; } } } }
以上
Rails チュートリアルでrails testした時に、「ActiveRecord::PendingMigrationError」が発生した時の対処
Railsチュートリアルをやっていてちょっとはまったところがあったので、同じことで困っている人のためにメモ。
【発生箇所】
Rails チュートリアルの第6章 6.3.1 ハッシュ化されたパスワード付近。
【現象】
6.3.1 ハッシュ化されたパスワードで、最初にusersテーブルにpassword_digestカラムを
追加するために、マイグレーションした後で、rails testコマンドを実行すると、以下のエラーが出る。
[vagrant@localhost sample_app]$ rails test
Running via Spring preloader in process 13972
/home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activerecord-5.0.1/lib/active_record/migration.rb:573:in `check_pending!': (ActiveRecord::PendingMigrationError)Migrations are pending. To resolve this issue, run:
bin/rails db:migrate RAILS_ENV=test
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activerecord-5.0.1/lib/active_record/migration.rb:586:in `load_schema_if_pending!'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activerecord-5.0.1/lib/active_record/migration.rb:592:in `block in maintain_test_schema!'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activerecord-5.0.1/lib/active_record/migration.rb:823:in `suppress_messages'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activerecord-5.0.1/lib/active_record/migration.rb:597:in `method_missing'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activerecord-5.0.1/lib/active_record/migration.rb:592:in `maintain_test_schema!'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/railties-5.0.1/lib/rails/test_help.rb:15:in `'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `block in require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `require'
from /home/vagrant/rails_tutorial_since_20170315/sample_app/test/test_helper.rb:3:in `'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `block in require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `require'
from /home/vagrant/rails_tutorial_since_20170315/sample_app/test/controllers/static_pages_controller_test.rb:1:in `'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `block in require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/activesupport-5.0.1/lib/active_support/dependencies.rb:293:in `require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/railties-5.0.1/lib/rails/test_unit/test_requirer.rb:11:in `block in require_files'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/railties-5.0.1/lib/rails/test_unit/test_requirer.rb:10:in `each'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/railties-5.0.1/lib/rails/test_unit/test_requirer.rb:10:in `require_files'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/railties-5.0.1/lib/rails/test_unit/minitest_plugin.rb:86:in `plugin_rails_init'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/minitest-5.10.1/lib/minitest.rb:80:in `block in init_plugins'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/minitest-5.10.1/lib/minitest.rb:78:in `each'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/minitest-5.10.1/lib/minitest.rb:78:in `init_plugins'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/minitest-5.10.1/lib/minitest.rb:129:in `run'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/railties-5.0.1/lib/rails/test_unit/minitest_plugin.rb:73:in `run'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/minitest-5.10.1/lib/minitest.rb:62:in `block in autorun'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /home/vagrant/.rbenv/versions/2.3.2/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from -e:1:in `'
【対処法】
まず、データベースをリセットするために以下のコマンドを実行。
[vagrant@localhost sample_app]$ rails db:migrate:reset
Dropped database 'db/development.sqlite3'
Dropped database 'db/test.sqlite3'
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
== 20170403115448 CreateUsers: migrating ======================================
- create_table(:users)
-> 0.0036s
== 20170403115448 CreateUsers: migrated (0.0037s) =============================== 20170408025509 AddIndexToUsersEmail: migrating =============================
- add_index(:users, :email, {:unique=>true})
-> 0.0039s
== 20170408025509 AddIndexToUsersEmail: migrated (0.0040s) ====================== 20170408091417 AddPasswordDigestToUsers: migrating =========================
- add_column(:users, :password_digest, :string)
-> 0.0023s
== 20170408091417 AddPasswordDigestToUsers: migrated (0.0023s) ================
次に、先ほどのエラーメッセージに表示されていた以下のコマンドを実行。
[vagrant@localhost sample_app]$ bin/rails db:migrate RAILS_ENV=test
== 20170403115448 CreateUsers: migrating ======================================
- create_table(:users)
-> 0.0023s
== 20170403115448 CreateUsers: migrated (0.0024s) =============================== 20170408025509 AddIndexToUsersEmail: migrating =============================
- add_index(:users, :email, {:unique=>true})
-> 0.0021s
== 20170408025509 AddIndexToUsersEmail: migrated (0.0025s) ====================== 20170408091417 AddPasswordDigestToUsers: migrating =========================
- add_column(:users, :password_digest, :string)
-> 0.0018s
== 20170408091417 AddPasswordDigestToUsers: migrated (0.0019s) ================
こうすると、rails testが実行できるようになる。
以上
SQL Serverに大量のテストデータを登録するときのコツ
アプリケーションのテストで、データベース(SQL Server)に十数万件のテストデータを登録する必要がありました。
SQLファイルに自動でINSERT文を生成して、SQL Server Management Studioでそのクエリを実行すると、メモリ不足のエラーになり、データ登録ができずに困っていたのですが、INSERT文のあとに「GO」を付けるとうまくいきました。
以下のようにひたすら、INSERT文を書き続けると、メモリ不足でエラーになる。
INSERT INTO テーブル名 VALUES(1, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(2, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(3, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(4, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(5, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(6, "Japan", 0, "TEST"); ・ ・ ・ ・(何十万行のINSERT文)
そこで、以下のように「GO」を付けるとメモリ不足にならずクエリが成功する。
INSERT INTO テーブル名 VALUES(1, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(2, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(3, "Japan", 0, "TEST"); GO INSERT INTO テーブル名 VALUES(4, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(5, "Japan", 0, "TEST"); INSERT INTO テーブル名 VALUES(6, "Japan", 0, "TEST"); GO ・ ・ ・ ・(何十万行のINSERT文)
まぁ、「GO」を付けることで、1つのステートメントが終了しましたよ〜と通知するみたいですね。
「GO」を付けないとずっと1つのステートメントが続いてしまって、メモリが解放されずにどんどん圧迫してしまい、失敗していたみたいです。
知らないとちょっと困るので、メモ。