BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

ASP.NET MVC でパスワードの有効期限対応をする

さてさてVisual Studio2015リリース直前な時期ですが、Visual Studio2013でのASP.NET MVCな常にログインが必要な業務系アプリ想定で、以下の実装例をメモしておきます。

  • 新規ユーザー登録(&仮パスワード発行)後、ユーザーの初回ログイン時にパスワード変更画面へ強制遷移
  • ユーザーのパスワード有効期限を設定し、過ぎたらログイン時にパスワード変更画面へ強制遷移

> Environment

今回の開発環境はこんな感じです。

> OverView

ASP.NET MVCで個人認証のテンプレート使って、DBの接続はざっくりEntityFrameworkでアプリ作るところに、パスワード要件を実装と思ってください。
AuthorizeAttributeのFilterを作って、アプリに適用させることで実現します。

手順の全体像は、

  1. ASP.NET MVC5で、個人認証つきのプロジェクト作成
  2. Attribute作成前の準備
  3. 要件を満たすためのAttribute作成
  4. アプリに適用

です。

> Implimentation 1. ASP.NET MVC5、個人認証のプロジェクト作成

これはただの下準備なので、さっくり進めます。
Visual Studioで新規プロジェクトを作成します。テンプレートの選択は、もちろん[Web]です。
f:id:beachside:20150712145712p:plain

たまに[VisualStudio2012]を選択する方がいるのですが、選択するのは、上図の通りWebです。お間違えなく。

そして、MVCで個人認証で進めます。
f:id:beachside:20150712150704p:plain

> Implimentation 2. Attribute作成前の準備

パスワード変更の最終変更日を管理するので、DBにカラムを持ちます。
ASP.NET Identity2.2.1で個人認証すると、データベースに[AspNetUsers]ってテーブルできますよね。
f:id:beachside:20150712152313p:plain
このテーブルでパスワード変更の最終変更日も管理しようと思います。

話は脱線しますが、わからんことがあって放置している点を書いておくと、
MembershipプロバイダーのLastPasswordChangedDateあたりを使うべきなのかなーとかが??です。AspNetUsersテーブルもあるのにこっちも使うのは面倒では?と何も調べず知らずに書いてます。よいプラクティスをご存じなMVPさん方々、ご教授願いますm(_ _)m...


さて、話は戻ります。
[AspNetUsers]テーブルに[LastPasswordChangedDate]列を追加します。
パスワード変更の日付は、DBファーストでもコードファーストでもどちらで書いても構わないのですが、コードファーストでいきますか(いつもはコードファーストが嫌いなのでDBファーストで書いてます...)。

[ソリューションエクスプローラ]の[Models] > [IdentityModels.cs]を開きます。
以下のように、[ApplicationUser]クラスに[LastPasswordChangedDate]プロパティを追加します。

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // authenticationType が CookieAuthenticationOptions.AuthenticationType で定義されているものと一致している必要があります
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // ここにカスタム ユーザー クレームを追加します
        return userIdentity;
    }

    public DateTime? LastPasswordChangedDate { get; set; }

}

あとは、Migrationすればデータベース側に反映されます。個人的には、マイグレーションで面倒なことが起きるのでDBファーストが好みです。
しばらくMigrationなんてしてないのでどうするんだっけ感がありますが、パッケージマネージャーコンソールで、

enable-migrations

を実行して、Migrationを有効にします。
次は、こんな感じで適当に...

add-migration InitialCreate

最後に、

update-database

でデータベース側も反映されます。
f:id:beachside:20150712160030p:plain

migrationについて不明の方は、ここら辺をご参考いただければと。
www.asp.net

> Implimentation 3. 要件を満たすためのAttribute作成

それでは本題のAttribute作成です。
プロジェクトに適当にフォルダを追加します。今回は以下のようにフォルダと[PasswordExpirePeriodAtteribute]クラスを追加しました。
f:id:beachside:20150712160726p:plain

コードは以下のようにしています。

public class PasswordExpirePeriodAttribute : AuthorizeAttribute
{
    private static readonly int PasswordExpirePeriod = 90;

    public override void OnAuthorization(AuthorizationContext filterContext)
    {

        if (filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower() == "manage") return;

        var user = HttpContext.Current.User;
        if (user != null && user.Identity.IsAuthenticated)
        {
            using (var context = new ApplicationDbContext())
            {
                var passwordChangedDate = context.AspNetUsers.Find(user.Identity.GetUserId()).LastPasswordChangedDate;
                // NULLの場合=初回ログイン
                if (passwordChangedDate == null)
                {
                    filterContext.Controller.TempData["ExpirePeriodMessage"] = "初期パスワードの変更をしてください。";
                    filterContext.Result = new RedirectResult("~/manage/changepassword/");
                    return;
                }

                //期限切れの場合
                if (DateTime.Today >= passwordChangedDate.Value.AddDays(PasswordExpirePeriod))
                {
                    filterContext.Controller.TempData["ExpirePeriodMessage"] = "パスワードの有効期限が切れています。変更するまでここから逃げることはできませんよ?";
                    filterContext.Result = new RedirectResult("~/manage/changepassword/");
                }

            }
        }
    }
}


まず、[PasswordExpirePeriodAttribute]クラスは、[AuthorizeAttribute]を継承したクラスと定義し、フィルターとしての動作をさせます。
パスワードの有効期限は、staticな変数を持たせて90日を設定しました。多少真面目に書く場合は、webconfigとかにもたせて読み込む感じでしょうか。

動作のトリガーとして、[OnAuthorization]メソッドをoverrideします。
ここら辺が不明の場合は、"authorization filter asp.net mvc 5"あたりでググってみるとよいと思います。

次に、manageのコントローラーに来た場合は、このフィルターを抜けるようにしています。

 if (filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower() == "manage") return;

今回作っているASP.NET MVCのプロジェクトのパスワード変更が、[ManageController]の[ChangePassword]メソッド2つにリダイレクトするようにしています。
そのため、ManageControllerでも同様にフィルターを書けてしまうと無限リダイレクトループしてしまうからです。

次の処理は、DBにアクセスして[LastPasswordChangedDate]がnullだったら初期パスワード発行状態と判断し、パスワード変更画面へリダイレクトします。
そのため、ユーザーの登録時には、[LastPasswordChangedDate]を登録せずNULLにしておくという勝手なルールがあることはお察しくださいませ。
[LastPasswordChangedDate]の型がNullableな理由です。

ここで一点注意していただきたいのは、以下のコード部分です。

 using (var context = new ApplicationDbContext())
{
       var passwordChangedDate = context.AspNetUsers.Find(user.Identity.GetUserId()).LastPasswordChangedDate;
      ...

[ApplicationDbContext]は、私は勝手にカスタマイズしているので、デフォルトで同様のコードを書いても[AspNetUsers]のテーブルにアクセスできません!DbContextをちゃんと作って、そのcontextを呼ぶ必要があります。このEntityframeworkの入門としてweb上に溢れていると思うので省略しちゃいます。

それ以降のコードでは、パスワードの最終更新から90日過ぎたかをみて、リダイレクトを判断します。

> Implimentation 4. アプリに適用

さて、最後にアプリに適用です。
ものがものなので、今回の例ではGlobalFiltersに登録しちゃいます。
ソリューションエクスプローラーの[App_Start]フォルダ > [FilterConfig.cs]を開きます。
[RegisterGlobalFilters]メソッドに、以下のようにフィルターを追加します。

filters.Add(new PasswordExpirePeriodAttribute());

GlobalFiltersに登録するということは、アプリ全体に適用されるので、それが不適合な場合は、必要なクラスのみのフィルターをつけます。

これで動作しますが、パスワードを変更した際にLastPasswordChangedDateを更新させてあげる処理を追加する必要はありますのでお忘れなく。
あと、パスワード変更のView(~\Views\Manage\ChangePassword.cshtml)では、TempData["ExpirePeriodMessage"]に値があれば表示するみたいなことしてあげれば、メッセージを表示できます。


なんか泥臭いコードなのであまり満足度低めなのですが、取り急ぎメモということで...

さて焼肉食べに行こう...

ASP.NET Web API2.2で、Swagger(Swashbuckle 5.1.5)を使う

WebAPIを作る用事があったのでSwaggerの設定方法をメモしておきます。ちなみにIIS Hostedです。ということで面白味はありません...。

Swaggerとは、言語に依存せず様々なプラットフォームに実装することができるRESTful APIのドキュメント作成ツールといったところです。
詳しくは、みそ先生がまとめておられます。miso-soup3.hateblo.jp

コードをベースにドキュメントが作成されるので、便利で楽です。

> Environment

今回の開発環境はこんな感じです。

> OverView

手順の全体像は、

  1. WebAPIのプロジェクト作成
  2. Swaggerをインストール
  3. Swaggerを使うための設定
  4. WebAPIのコントローラーをさっと作ってSwaggerの動作を確認

です。

> Implimentation 1. WebAPIのプロジェクト作成

Visual StudioでWebAPIのプロジェクトを作ります。

説明するほどもないかもしれませんが...手順を追いましょう。
プロジェクトの新規作成します。
テンプレートは、左ペインの「Web」を選択します。プロジェクトの名前は適当に...(今回は「SwaggerDemo」しました。)
f:id:beachside:20150531192908p:plain
次の画面では、「WebAPI」を忘れずに選びます。
f:id:beachside:20150531202936p:plain

> Implimentation 2. Swaggerをインストール

プロジェクトが作成できたら、SwaggerのPackageをNuGetからインストールします。
上部メニューの「ツール」→「NuGetパッケージマネージャー」→「パッケージマネージャーコンソール」を開き、以下のコマンドを実行します。

Install-Package Swashbuckle

f:id:beachside:20150531192949p:plain
今回のバージョンは、「5.1.5」です。
バージョンによって若干設定方法が変わりますので、後述の設定で「あれ?」という場合はバージョン依存と思ってください。

インストールが完了すると、プロジェクトの「App_Start」ディレクトリ配下に「SwaggerConfig.cs」ができたりします。

> Implimentation 3. Swaggerを使うための設定

XMLコメントをファイルに出力する設定を行います。
XMLコメントについて知らない方は...にぃにさまのサイトとかで復習をして頂ければ...ufcpp.net


プロジェクトのプロパティをクリックして、左ペインで「ビルド」を選択し、「XML ドキュメント ファイル」のチェックボックスをオンにします。パスが自動で表示されます(このパスは後で使います)。
f:id:beachside:20150531203336p:plain


このファイルをSwaggerで読み込むための設定を行います。

余談ですが、
Swashbuckleのバージョンで多少設定が変わってきます。特にversion 4.1.0とかだと 「
Swashbuckle.Bootstrapper.Init(....」みたいな設定が必要です。今回のバージョン(Version5くらい)からは以下の設定だけでOKです。

本題に戻り、
「App_Start」ディレクトリ内の「SwaggerConfig.cs」を開きます。
コメントたくさんのコードが作られています。以下のコード(158行目あたり)のコメントをはずします。

c.IncludeXmlComments(GetXmlCommentsPath());

これでXMLコメントのドキュメントを読み込む設定がされます。といっても、GetXmlCommentsPathメソッドがないので作りましょう。

private static string GetXmlCommentsPath()
{
        return string.Format(@"{0}\bin\SwaggerDemo.XML", System.AppDomain.CurrentDomain.BaseDirectory);
}

「bin\...」の部分のパスは、プロジェクトのプロパティでチェックボックスをオンにしたときに表示されたパスを入力します。

念のための確認ですが、167行目あたりの

.EnableSwaggerUi(c =>

のコメントが外れていることも確認しておきます。以前(多分Swashbuckleの別のバージョン)でやった時は自分でコメントを外した記憶があるので..。


これでSwaggerの設定完了です。

> Implimentation 4. ...Swaggerの動作を確認してみる

以下の感じで適当にWebAPIのコントローラーをつくりました。(scaffoldingで作られたコードなだけですが...)
XMLコメントも書きます。

using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Description;

namespace SwaggerDemo.Controllers
{
    public class ValuesController : ApiController
    {
        /// <summary>
        /// 全てのvalueを返します。
        /// </summary>
        /// <returns></returns>
        [ResponseType(typeof(IEnumerable<string>))]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        /// <summary>
        /// 指定のidのvalueを返します。
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [ResponseType(typeof(string))]
        public string Get(int id)
        {
            return "value";
        }

        // POST api/<controller>
        public void Post([FromBody]string value)
        {
        }

        // PUT api/<controller>/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/<controller>/5
        public void Delete(int id)
        {
        }
    }
}

さてさてデバッグしてみましょう。
実行されたURLの後ろに「/swagger」と入力してアクセスすると、無事にSwaggerのUIが表示されます。
f:id:beachside:20150531194015p:plain

XMLコメントを付けたメソッドは、その内容が表示されています。
ここからAPIを呼んでレスポンスを確認できるので、すこぶる便利ですね。

Double SubmissionをActionFilterで制御する

仕事が派手にドッタンバッタンしたので更新が途切れましたなー。

WebでSubmitボタンを連打された時の防止策についてメモしておきます。

まず、この記載での開発環境は、ざっくり

  • Visual Studio2013update4
  • .NET Framework4.5
  • ASP.NET MVC5

です。


制御は、ActionFilterだけでよいといえばよい気もしますが、個人的には、クライアント側でもjavascriptで制御してます。この実装についてはここでは触れませんが、ここらへんを参考にしてやってます。
http://technoesis.net/prevent-double-form-submission-using-jquery/technoesis.net

Reference

さて、本題ですが、ActionFilterの実装は、この方のサイトを参考にしています。
rion.io


まず、ActionFilterの基本については、こちらのサイトを参照くらいでしょうか。
https://msdn.microsoft.com/ja-jp/library/dd381609(v=vs.100).aspx

ざっくりまとめると、

  • クラスを作ってActionFilterAttributeを継承させると、ActionFilterクラスの出来上がり。4つのオーバーライドメソッドをオーバーライドすることで制御を行う。
  • OnActionExecutingメソッドはActionが呼び出される直前に動く
  • OnActionExecutedメソッドは、Actionが終了したときに動く
  • OnResultExecuting メソッドは、アクションによって返された ActionResult インスタンスが呼び出される直前に動く
  • OnResultExecuted メソッドは、結果が実行された直後に動く

Overview

やりたいことは、Submitボタンを押された後、処理が終わる前にsubmitを連打されれいたら、検知して、無視するとかエラー返すとかです。

ActionFilterのOnActionExecutingメソッドで、以下のことを実装して実現します。

  • Requestがあったユーザーを特定する仕組みをつくる
  • ユーザーが最初のアクセス(=submit)から特定秒数の間にアクセスがあったら、検知して処理(エラーとか無視とか)を行う

Implimentation : 1

まず、検証するControllerとView作っちゃいます。

Controllerはこんな感じでざっくり。

public class DemoController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public async Task<ActionResult> DemoSubmit()
    {
        await Task.Delay(3000);

        TempData["SummittedTime"] = DateTime.Now.ToString("hh:MM:ss fff");
        return RedirectToAction("Index");
    }
}

submitしたら、3秒待って、Viewを表示するだけです。ただ、submitした時間を表示します。
今回の話題とは全く関係ない小ネタですが、理由なくRedirectToActionさせて時間を表示するのでViewBagではなくTempDataに時間を入れて、表示できるようにしています。
ViewBagに入れるとRedirectしたらデータ消えちゃいますよね...。

Viewは、Index.cshtmlをこんな感じでまったり作りました。

<h2>demo prevent doubl submittion</h2>

@if (TempData["SummittedTime"] != null)
{
    <p>@TempData["SummittedTime"] </p>
}

@using (Html.BeginForm("DemoSubmit", "Demo"))
{
    <input class="btn btn-warning" type="submit" name="DemoSubmit" value="3秒以内の連打禁止だおー" />
}

Implimentation : 2

では、本題のActionFilterです。
Propertyをいくつか用意してます。
まず、「DelayTimer」。同一ユーザーから一度Requestを受けたら、delayする時間を設定するプロパティ。秒で設定します。今回はデフォルトで3秒を設定しました。
後は、エラーメッセージだったり、RedirectするUrl(今回は全然触れてない...)。

using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web.Caching;
using System.Web.Mvc;

public class PreventDoubleSubmitAttribute : ActionFilterAttribute
{
    #region class header

    private int _delayTimer = 3;
    public int DelayTimer
    {
        get { return _delayTimer; }
        set { _delayTimer = value; }
    }

    private string _err = "DoubleSubmit occurred";
    public string ErrorMessage
    {
        get { return _err; }
        set { _err = value; }
    }

    public string RedirectUrl { get; set; }

    #endregion
}

では、コアとなるOnActionExecutingの処理です。
まず、ユーザーを一意に認識させるために、リクエストの中の"HTTP_X_FORWARDED_FOR"を取得します。nullだったら、UserHostAddressを取得します。
その情報に、リクエストのUserAgentを追加しています。
あと、リスエストのUrlとパラメータを取得します。
それらの情報からMD5ハッシュを生成して、ユーザーの一意となるキーを作ります。
そして、ハッシュがCacheに存在するかを確認します。
存在する場合は、Prevent対象と判断し、なんらかの処理を入れます。今回は、BadRequestを返してしまっています。

存在しなければ、初回のリクエストと判断し、Cacheに値をセットします。その際に、そのCacheの有効期限にDelayTimerプロパティの秒数をセットします。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var request = filterContext.HttpContext.Request;
    var cache = filterContext.HttpContext.Cache;

    //一意となるデータを取得
    var firstrequest = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;
    firstrequest += request.UserAgent;

    var current = request.RawUrl + request.QueryString;

  //ハッシュ生成
    var hash = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(firstrequest + current)).Select(s => s.ToString("x2")));
    if (cache[hash] != null)
    {
        //今回は、BadRequestをなげます。
        filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        base.OnActionExecuting(filterContext);

        //おもむろにログを出してみたり...。
        var controller = filterContext.RouteData.Values["controller"].ToString();
        var action = filterContext.RouteData.Values["action"].ToString();
        Trace.TraceWarning("Double Submit Occured: {0} - {1}", controller, action);
    }
    else
    {
    //存在しなければ、キャッシュに値をセットする
        cache.Add(hash, string.Empty, null, DateTime.Now.AddSeconds(DelayTimer), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
    }

    base.OnActionExecuting(filterContext);
}

Implimentation : 3

最後にControllerにAttributeを追加してあげれば完了です。

[HttpPost]
[PreventDoubleSubmit]
public async Task<ActionResult> DemoSubmit()
{
....

これで、一度Submitした後、3秒以内に連打するとBadRequestが出力されます。

DelayTimerの時間など、プロパティにアクセスしたい場合は、こんな感じで書いてあげればよいです。

[HttpPost]
[PreventDoubleSubmit(DelayTimer = 5)]
public async Task<ActionResult> DemoSubmit()

今回は、javascriptで制御しているのに、それを掻い潜って連打攻撃してきたのであればBadRequestで沈める想定なのですが、ModelStateにエラーメッセージを追加したいとかもあるでしょうか。

if (cache[hash] != null)
{
    filterContext.Controller.ViewData.ModelState.AddModelError("DoubleSubmit", ErrorMessage);
}
else
{
...

こうした場合、controller側でModelstateのエラーを拾ってあげればよいです。

if (ModelState.Values.Select(vals => ModelState["DoubleSubmit"]).Any(v => v != null))
{
    //なんかエラー処理を...
}


なんか色々ざっくり書いてしまったメモですが、今回はこの辺で...。

Entity Framework 6 での接続リトライの設定(Azure SQL Database向け)

最近の仕事で
(個人的にやや敬遠がちだった)EFを使ってAzureのSQL Databeseに接続するのに
「接続のリトライは実装してね」とお願いしてたら、大掛かりな実装をされた事件があり「おいおーい」と感じたので、メモっておきます。

前提として、現在の開発は

  • Visual Studio 2013 update4
  • .Net Framework4.5
  • Entity Framework6.1.2

そしてC#って感じでやってます。

Overview

MSDNとかみてると、MS用語的には、Connection の Resiliency とか RetryのLogicと言うようですね。
実装方法は、以下です。非常にシンプル。

  1. DbConfigurationクラスの派生クラスを作って、リトライの設定を持たせる(≒属性を作成する)。
  2. 対象のDbContextの派生クラスに、属性をつける。

Implimentation : 1

DbConfigurationの派生クラスを作って、そのコンストラクターでSetExecutionStrategyメソッドを呼んでごにょごにょすることで、リトライ回数と再試行間隔を設定します。
今回は、BaseDbConfigurationという名前でクラスを作っています。

public class BaseDbConfiguration : DbConfiguration
{
    public BaseDbConfiguration()
    {
        SetExecutionStrategy("System.Data.Sql",
              ()=>new SqlAzureExecutionStrategy());
    }
}

ここでの登場人物については、MSDNのリンクを...。

SetExecutionStrategyメソッドの2ndパラメーターについてはEntity Framework Connection Resiliency / Retry Logic (EF6 onwards)の「Execution Strategies」あたりを見ました。

今回は、Azure SQL Databaseに接続するので、SetExecutionStrategyメソッドの2ndパラメーターに”SqlAzureExecutionStrategy”を使っています。

上記コードのようにSqlAzureExecutionStrategyのコンストラクターでパラメータを設定しないと、リトライ回数と再試行間隔には既定値がセットされます。
(既定値は、こちらを確認っと。)

自分でリトライ回数と再試行間隔をセットしたい場合は、こんな感じです。

public BaseDbConfiguration()
{
    SetExecutionStrategy("System.Data.Sql",
        ()=>new SqlAzureExecutionStrategy(5,TimeSpan.FromSeconds(30)));
}

Implimentation : 2

前述で作ったBaseDbConfigurationクラスを、DbContextがらみのクラスに属性としてつけます。
今回は、MyDbContextというクラスに属性を付けました。

[DbConfigurationType(typeof(BaseDbConfiguration))]
public class MyDbContext : DbContext
{
    ....

完了。シンプルで簡単でした。
実際に使うときは、基本クラスに設定して、必要なクラスに継承させてあげて使えばよいかって感じでしょうか。

201604追記
beachside.hatenablog.com
事故らないためにはここら辺の知識も必要でした....



注意として、独自にトランザクションを利用するときは、多少の細かい実装は必要です。ここでは触れませんが、下の方に参考リンクつけてます。

ASP.NET MVC5で最初にやったこと2014冬のメモ

f:id:beachside:20150206222149j:plain
メモに残しておこうと思ってたら年越して2015年2月ですね。社畜業務でシャチークシャチークしていると時が経つのは早いものです。

開発する際に最初にやったことのメモで、この業界のメイド王と名高いしばやんさんの雑記の内容がほとんどです。

これを書いているときに使っているのは、

やりたいことは、

  • セキュアなごにょごにょ
  • ヘッダーのごにょごにょ
  • ごにょごにょ...

難しいことは何もやってないので、変更した設定などの意味についてはふれません。ただただ設定したことを書きます。

Global.asaxの編集

Application_Startメソッド内に以下の内容を追加します。
そして、Application_PreSendRequestHeadersメソッドを追加します。
ヘッダーの処理関連と他諸々...。

protected void Application_Start()
{
    // 上の方は略

    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new RazorViewEngine());
    AntiForgeryConfig.CookieName = "token";
    AntiForgeryConfig.SuppressXFrameOptionsHeader = true;
}

protected void Application_PreSendRequestHeaders()
{
    Response.Headers.Remove("Server");
    Response.Headers.Remove("X-AspNetMvc-Version");
}

App_Start/RouteConfigの編集

ここでは、RegisterRoutesメソッド内に以下のコードを追加します。
urlをlowercaseにするのと、トレイリングスラッシュ。

public static void RegisterRoutes(RouteCollection routes)
{
    // 上の方は略

    routes.LowercaseUrls = true;
    routes.AppendTrailingSlash = true;
}

WebConfigの編集

認証クッキー絡みの設定などです。

<system.web>
    <httpRuntime targetFramework="4.5" enableVersionHeader="false" />
    <authentication mode="Forms">
        <forms requireSSL="true" />
    </authentication>
    <httpCookies requireSSL="true" />

あと、 SSLはもちろん有効にしてます。

ヘッダー絡みの変更については、Application_PreSendRequestHeadersメソッドで一元管理しようかなーとかも思いましたが、「まいっか」という理由でやめました。
あと、
ASP.NET MVCでResponse Headerのサーバーバージョンをどうやって隠しますか? - のんきネコ - 博客园
で書いてある404エラー時にヘッダーにサーバーのバージョンがでちゃう事件は、現在の環境では起こらないので、どっかで誰かが改善してくれてたんだなと思ってます。
→2015/1追記ですが、結果として上のリンクのCustomHeaderModuleつくる対応、やるべきって判断になりました!。

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(3/3)

今回は、Visual Studio Advent Calendar 2014 - Qiita11日目のエントリーです。
今回もはりきっていきましょーか。

>OverView

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(1/3)

 1. Peek Help
 2. Solution Explorer Errors
 3. Structure Visualizer
 4. Double click to maximize windows
 5. Timestamp margin
 6. Quick tasks – Edit Present On

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(2/3)

 7. Ctrl + Click to Peek Definition
 7. Ctrl + Click to Peek Definition
 8. HTML Copy improvements
 9. Recently Closed Documents
 10.Match Margin
 11.Power Commands context menu cleanup
 12.Syntactic Line Compression

イマココ

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(3/3)

 その他諸々・・・

では、その他諸々について進めます。

・Quick Tasks

Visual Studioの右上にある「クイック起動」で入力してさっと呼び出すことができるタスクの拡張機能です。たくさんある中で、ほほーという機能を紹介します。

コマンド 概要
CollapseRegions Currentのエディター(現在コードが表示されているエディター)の#regionを全て閉じます。
ExpandRegion Currentのエディターの#regionを全て開きます。
LineNumOff エディターの行番号表示をOFFにします。
LineNumOn エディターの行番号表示をONにします。
PresentOff プレゼンモードをOFFにします。Present**の機能は前回をご参照ください。
PresentOn プレゼンモードをONにします。Present**の機能は前回をご参照ください。
PresentEdit プレゼンモードのフォントを設定します。Present**の機能は前回をご参照ください。
WordWrapOff エディターの[右端で折り返す]をOFFにします。
WordWrapOn エディターの[右端で折り返す]をOFFにします。

・Color Printing

エディターの内容ををハイライトされた状態=カラーでプリントアウトできます。うむ、印刷してコードをみるときに見やすい。
と言っても、印刷してコードを見るという地獄のようなプレイはしたくないものです。

この機能についていくつかのISSUEがあるようなので、ご利用の際は本家をご確認したほうがよいですが、ドバッと印刷するのであれば問題なく利用できます。

・Middle-Click Scrolling

ミドルクリック(マウスホイールのクリック)で、スクロールができますという機能です。
...ふむふむ。

・Column Guides 

エディター内で、カーソルが当たっている行をグレーの枠で囲む機能です。
こんな感じ。
f:id:beachside:20141204221726p:plain


>Summary

Visual Studio Advent Calendar 2014 - Qiitaの3連続モノとして進めてきましたが、拡張機能は生産性やUXの向上の手助けになるもの揃いなので、このProductivity Power Toolsに限らずどんどん導入していくことをお奨めします。*1

あと、私はJAZUG(Japan Azure User Group)の中の人ではないのですが、イベント告知。
Azure 史上最大のコミュニティ イベント
GoAzure 2015」が1月16日に開催します。
マイクロソフトUSA本社の Scott Hanselman きますので.NET界隈の方々も楽しめると思います。
もちろん無償イベントです。
お申込みにはJAZUGのサイト経由で...

*1:我ながら雑なまとめでした...

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(2/3)

今回は、Visual Studio Advent Calendar 2014 - Qiita10日目のエントリーです。
前回に引き続き、進めていきます。

> Overview

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(1/3)

 1. Peek Help
 2. Solution Explorer Errors
 3. Structure Visualizer
 4. Double click to maximize windows
 5. Timestamp margin
 6. Quick tasks – Edit Present On

イマココ

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(2/3)

 7. Ctrl + Click to Peek Definition
 8. HTML Copy improvements
 9. Recently Closed Documents
 10.Match Margin
 11.Power Commands context menu cleanup
 12.Syntactic Line Compression

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(3/3)

 その他諸々・・・

それでは本編へ。

7. Ctrl + Click to Peek Definition

エディター内で、右クリックして[定義をここに表示]で、定義をインライン表示するというデフォルトの機能は定番でしょうか。ショートカットキーだと[ALT]+[F12]で表示されます。
それをさらにショートカットして、[Ctrl]+クリックで表示できるのがこの機能です。
f:id:beachside:20141204195102p:plain

8. HTML Copy improvements

ブロガーさんには嬉しい、コードをHTML形式でコピーする機能です。てゆーかこの記事書いてて気づいた嬉しい機能だコレ。エディターでコピーしたい範囲を選択し、メニューバーの [編集] > [Copy HTML Markup]を選択します。

f:id:beachside:20141204200439p:plain

それを貼り付けた結果が以下。

private bool ExistsGeoInfoInFile(Bitmap bitmap){
    var tags = (int[])Enum.GetValues(typeof(ExifTag));
    return bitmap.PropertyItems.Where(c => tags.Contains(c.Id))
                                               .Count() == tags.Length;
}

出力されるHTML自体はかなりゴリゴリですが、貼り付けるだけなので見る側としては良いと思います。

9. Recently Closed Documents

Chromeでいう「閉じたタブを開く」機能です。
間違って閉じてしまったタブを、[Ctrl] + [Shift] + [Z]を押すことで開いてくれます。連打すると開きまくります。何回まで戻せるかは興味がないので調べません...。

10.Match Margin

エディターでハイライトされた部分を、スクロールバーで示してくれる機能です。
下図を例にすると、「cal」を選択すると同じ文字列である3箇所がハイライトされますが、スクロールバーで位置が表示されています。
f:id:beachside:20141204202413p:plain
広範囲で同じ単語が使われているときは、ひと目で把握できます。

11.Power Commands context menu cleanup

ソリューションエクスプローラー内で、ソリューションまたはプロジェクトの右クリックメニューに「PowerCommands」を表示します。その中で下図のメニューを実行することができます。
f:id:beachside:20141204203604p:plain
1つ取り上げると、「Remove and Sort Usings」は、「未使用のusingを削除」と「usingの並び替え」を全てのファイルを一括で実行してくれるので便利ですね。

12.Syntactic Line Compression

エディターの表示する行を圧縮して、より多くの行を画面に表示する機能です。ふむふむ。


さて、今回はここまで。
次回
【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(3/3)
に続きます。

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(1/3)

今回は、Visual Studio Advent Calendar 2014 - Qiita9日目のエントリーです。

以前、Visual Studio 2013で開発する前に準備しておきたい17のこと(2/3) - BEACHSIDE BLOGでさらっと紹介したProductivity Power Tools 2013の機能紹介をします。

> Introduction

Productivity Power Tools 2013とは...
Visual Studio拡張機能のひとつで、Nugetから取得できるものです。
作成者はMicrosoftで、無料で使える拡張機能ですが、Visual StudioのバージョンがProfessional以上という制約はあります。
EXPRESS版では導入できないのですが、今はVisual Studio Communityがあるので、誰でも導入できるものになったと思っています。
Visual Studio Communityに導入できるか試していないですが・・・・汗)

今更ではあるのですが、2013で追加された機能を中心にさらりとまとめておきます。

> Overview

3回に分けて紹介します。概要はこんな感じ。

今回

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(1/3)

 1. Peek Help
 2. Solution Explorer Errors
 3. Structure Visualizer
 4. Double click to maximize windows
 5. Timestamp margin
 6. Quick tasks – Edit Present On

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(2/3)

 7. Ctrl + Click to Peek Definition
 7. Ctrl + Click to Peek Definition
 8. HTML Copy improvements
 9. Recently Closed Documents
 10.Match Margin
 11.Power Commands context menu cleanup
 12.Syntactic Line Compression

【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(3/3)

 その他諸々・・・

> Contents

1.Peek Help

MSDNのヘルプを見るとき、デフォルトの機能では、エディター内のコードにカーソルを置いて[F1]キーを押すことで、ブラウザでMSDNが表示されますね。
ブラウザを開くほどでも無いときに、エディターにインラインでヘルプが表示されるPeek Helpを使うと良いです。操作は、コードにカーソルを置いて[ALT]+[F1]を押す。
f:id:beachside:20141203202110p:plain

2.Solution Explorer Errors

コンパイルのエラーや警告は、エラー一覧ウインドウに表示されますがちょっと見難いという方には必見。
ソリューションエクスプローラーに赤の波線が表示され、エラーの箇所がソリューションエクスプローラーで可視化できます。
また、エラーが発生しているクラスにカーソルをホバーするとエラー一覧ウインドウで表示される内容を表示してくれます。
f:id:beachside:20141203203742p:plain

ソリューションエクスプローラーのフィルター機能でエラーのみをフィルタリングすることもできます。
f:id:beachside:20141203204833p:plain
フィルタリングすると...
エラーが発生しているファイルのみを表示します。
f:id:beachside:20141203205005p:plain

この設定は、オプションウインドウ(メニューバーの[ツール] > [オプション]で開く)の[Productivity Power Tools] > [Solution Error Visualizer]から表示の設定ができます。
f:id:beachside:20141203205800p:plain

3.Structure Visualizer

クラスとか構文のブロック等、コードのスコープを見やすく(...?)してくれます。スコープを線で表示してくれるというか・・・うまく言葉で表現できませんが、下図の通りです。
ブロックの先頭がエディタの表示外のときにStructure Visualizerの線にカーソルをあてると、ツールチップを表示してくれます(下図の赤枠)。
f:id:beachside:20141203211604p:plain

スクロールバーにもスコープを表示してくれます。
使い始めた時はかなりウザく感じましたが、慣れると使いやすいかなと思います。

「こんなのいらん」派の方は、オプションウインドウで、非表示の設定もできます。
f:id:beachside:20141203213217p:plain

4.Double click to maximize windows

ドッキングウインドウのタブをダブルクリックすると、ウインドウが最大化します。
最大化したウインドの上部をダブルクリックすると、小さくなります。
普段、大きなディスプレイで操作しているときはほぼ使わないですが、ディスプレイの小さいモバイルPCなどで操作している時は、役にたちますね。

5.Timestamp margin

デバッグモードでデバッグする際に、出力ウインドウにタイムスタンプを表示してくれます。
f:id:beachside:20141203214558p:plain
デフォルトでは、「分:秒.ミリ秒」で表示されますが、これもオプションウインドウの[Productivity Power Tools] > [Other Extensions]内で、Timestampの非表示や、時間やミリ秒の表示・非表示が設定できます。

6.Quick tasks – Edit Present On

プロジェクターに接続してプレゼンテーションをしているときなど、Visual Studioのフォントの変更とかに使える機能です。
プレゼンテーション用のフォントをクイック起動「PresentEdit」と入力しして、[PresentEdit]を選択すると、XMLファイルが表示されます(下図ではPresentまでしか入力してませんが)。
f:id:beachside:20141203225149p:plain

f:id:beachside:20141203230250p:plain
プレゼンテーション用のフォントサイズを設定できます。設定は、ファイルの保存で反映されます。
いざ、このXMLで設定したフォントサイズを利用するときは、クイック起動で「PresentOn」を入力すればフォントが切り替わります。
f:id:beachside:20141203230442p:plain
ON!。
f:id:beachside:20141203230447p:plain
元に戻すときは、クイック起動で「PresentOff」を入力して、Taskの[PresentOff]を選択すれば戻ります。


今回はここまで。
【Visual Studio2013拡張】Productivity Power Tools 2013の機能まとめ(2/3) - BEACHSIDE BLOG
へ続きます。

Visual Studio 2013で開発する前に準備しておきたい17のこと(3/3)

ブログ作成始めたてて更新連発してるわけではなく、
のんびりしてるとVS2015でちゃいそうなので焦って更新してます。

Visual Studio 2013で開発する前に準備しておきたい17のこと(1/3)
Visual Studio 2013で開発する前に準備しておきたい17のこと(2/3)

の時はVisual Studio2013 Update3だったのに、自分の環境もUpdate4にしちゃったし。

このシリーズ最終回は、拡張系を少々と「操作の基本抑えとこう」な話題。
仕事で、たまーにビギナーな人をみてて気づいた程度のネタです。比較的皆さん知ってる操作と思われるところです。
ちなみに、c#をベースに書いてます。

11.コードスニペット使おう

良く使うのは、プロパティのスニペット「prop」。
操作をさっと解説。

「prop」と入力して、Tabを2回押すと自動プロパティのスニペットが出現。
f:id:beachside:20141118004824p:plain

型(int)にフォーカスが当たっているので、変更したい場合は入力します。
そのままマウスは持たずにTabを2回押すと、MyPopertyが全選択でフォーカス当たるので、
好みのプロパティ名を入力します。
Enter押したら入力完了。

スニペット使って入力するときの基本操作は、
「Tab使ってフォーカス移動してEnterで確定」

エヴァンゲリオン第参話 「鳴らない、電話」 】的には、
「目標をセンターに入れてスイッチ…目標をセンターに入れてスイッチ…目標をセンターに入れてスイッチ…」
と一緒です。

ifとかforでも同じパターンなので慣れるとコーディング速度UPUP!(と信じたい)。
Console.WriteLine()の「cw」、Constructorの「ctor」、デストラクターの「~」、「#region」とか「if」「for」「try」「propdp」などなど用意されているのだけでたーくさんあります。
C#だと、MSDNVisual C# のコード スニペットに載ってる。
また、自分で作ることもできます。

12.小技 - 操作関連

行選択
カーソルを下の図のあたりに持っていき、クリックすると行選択できます。
f:id:beachside:20141117234720p:plain
1行でも複数行でも選択してドラッグ&ドロップで移動可能。

選択といえば、Visual Studioは矩形選択ももちろんできます。操作は多くのエディタと一緒なので略。


次。
カーソル位置履歴
コードを解析してるときとかに、メソッドの「定義へ移動」しまくって深いとこまで潜ってしまったとき(この表現で意味通じるの?と不安を感じる)
Cntrl + [-](マイナス)を押すと、前にカーソル置いたところに戻ってくれる。
[-](マイナス)数回押せばもとのソースに戻ってくれるので便利。

「定義へ移動」といえば、
前回のVisualStudio 2013で開発する前に準備しておきたい17のこと(2/3)でちょっと触れましたが、Productivity Power Tools 2013を入れておけば、メソッドにカーソルあててCntrl + Clickすると、「定義をここに表示」が起動します。
(拡張してなくてもalt + F12で表示されるけど)

次、
クリップボードリング
エクセルでもいうクリップボードの履歴。
Ctrl+Cとかでコピーした後、Ctrl+Vでペーストするのではなく、
Cntrl + Shift + V でペーストすると発動します。
Cntrl + Shiftを押したまま、Vを押せばコピーした履歴をさかのぼってくれるから、
数個の値をコピーするときには有用。たくさんあるときは面倒と感じます。

13.小技 - **ウインドウ関連

まずは、「タスク一覧」かなー。
メニューバーの「表示」→「タスク一覧」を選択
f:id:beachside:20141118001953p:plain

タスク一覧が表示される。
ユーザータスクは、タスクを作成して管理できます。
コード内のコメントとタスクを紐づけることもできて、そっちを割とよく使ってますかね。
使い方は簡単。
こちらのMSDNで丁寧に説明しているので、説明省略。


ウインドウ関連といったものの、あと、特にないことに気づいてしまった・・・
超基本なところですが、
「イミディエイト」ウインドウ
「出力」ウインドウ
「ウォッチ」
あたりをデバッグの時によく使うのはいうまでもないところでしょうか。

最近あまり開発してないから使ってないけど、
「並列ウォッチ」
も数年前に見てたなと思い出した・・・。

14.デバッグの方法は抑えておこう

先人の偉大な記事があるので、そちらを紹介。Visual Studio 2008の頃の記事だけど、基本的なことは変わらないです。

あと、ブレークポイントは停止の条件を付けたり色々できる点はつけておきたい。
ブレークポイントを付けた後、右クリックで以下が表示されるので、選択してあとはお好きなようにと。
f:id:beachside:20141119010521j:plain

詳細は、MSDNのこちら参照ですかね。
Breakpoints: Use Hit Counts, Call Stack Functions, and Conditions to Break When and Where You Want in the Visual Studio Debugger

余談ですが、Visual Studio2015(PREVIEW)だと、ブレークポイントでログ出すとかも出来る。
原因不明なバグ調査するときとか、ログ出力コードを直接書き込まずに、ブレークポイントからログ出すとかできる、既存コードを汚さずに済むから良さそうですな。
関係ないけど画像貼っちゃった。どんどん便利になりますなー。
f:id:beachside:20141119000336j:plain

15.LINQは使おう 

もはや圧倒的なネタ切れ感が漂う15個目は、LINQは圧倒的に使おうよというお話。
C#好きな人の特徴の一つがLINQだと思い込んでいるのだが、エンタープライズ系の方は意外と知らないとか使ってないとか使えないとか。それくらいそっちの方々は遅れている傾向にある(私が仕事で出会った人の傾向なので、一般論ではないよ)。

ここでは説明しきれないが、
@ufcpp大先生の
LINQ - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
あたりから入っておけば間違いないだろう♪
LINQ is 神。

16.その他お薦め拡張 

有料の拡張ではあるが、C#界ではもはや必須?のReSharper

Unity使うなら、

17.最後に

世の中には、テスト駆動開発ドメイン駆動開発とかあるが、その中でも裏社会で最強と言われるのが萌え駆動開発(主観全開でごめんなさいごめんなさい)。

(ひよひよさん、リンクお借りしております!)

そのツールとして、Pronama-chan IDE extension
 ClaudiaIDE extension

というオチになったが、今後も活用できることを願って今回のブログを終えよう。

Visual Studio 2013で開発する前に準備しておきたい17のこと(2/3)

さて、前回の

Visual Studio 2013で開発する前に準備しておきたい17のこと(1/3) 

の続き。

前回と今回の間で、Connectってイベントがあって

.NET2015とかVisual Studio Community 2013の発表があって、VS2013もUpdate4出て、すごーく書き難くなってきたタイトルではあるが、どれでも共有できる情報と信じて書き続けようっと。

隔週くらいで更新予定と思ったが急ごう・・・

 

つぎは、

7.Microsoft謹製の便利ツール

Productivity Power Tools 2013。

本家サイトからダウンロードしてインストールすれば完了。

個人的に好みな機能のいくつか紹介。

  • ctrl + clickで、クリックしたメソッドを「ここに定義」のメニュー呼べる
  • メニューバーの「編集」→「undo close」で閉じたソース開く(ショートカットキー:ctrl+shift+z)、Chromeの「閉じたタブを開く」ってやつ
  • 色付きでコードを印刷できる!(使ったことないけど...汗)

ほかにも、便利なものからややうざいと感じるものまでたーくさんだ。本家を見たほうが早い。。翻訳してブログネタにしようかな・・・。

 

Microsoftで出してるんだからVisualStudioに最初っから入れればいーじゃんとか思ったり、Scott Hanselmanがここのブログの最初の方で言ってる

"...more pluggable, more open, more fun."

みたいなことのひとつなのかなーと妄想したり...

(HanselmanのブログはOne ASP.NETのこと言ってるんやけど、こーゆーのもその要素になってるのかなーってね)

はい、次。

 

8.派手にハイライトしまくるぜ

選択したところと同じ部分をハイライトしてくれるツール、Highlight all occurrences of selected word extension。

本家からダウンロードして使ってマース。

作成者がMicrosoftの開発者、ふむふむ。

 

 9.Gitと連携する何かを入れる

どうやら今はあまりいいものがないらしい。でも、ソース管理はきっと主流のGitでするからなんか入れないとね。

Microsoft謹製だと、

kekyoさんのブログでは、Git Source Control Provider推し。

私が仕事で使ってるやつは何をどういれたんだっけなー・・・記憶にない。

明日職場でみて確認すれってね、まーいいや。

そもそもGit使う準備も面倒だから、ちゃんとしないとね。

断固SVN派の人は、ギャラリーにVisual SVNがある。個人的には使わないけど一応書いとく。

2014/11/24追記

Gitとの連携については・・・既存でも十分なので、どれが使いやすいかを見極めて導入すべし。。。(今度、改めて確認しよう・・・)。

 

セットアップはこれくらいかな・・・

次回、

Visual Studio 2013で開発する前に準備しておきたい17のこと(3/3) 

へ続く。

 

更新急がないと・・・

続きを読む