しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC の HTML ヘルパーと null の関係

ASP.NET MVC に標準で用意されている HTML ヘルパーはオーバーロードが非常に多いです。

簡単な例を挙げると Html.BeginForm を使って GET として実行されるフォームを作成する場合は、以下のようにオーバーロードメソッドを使って書けますね。

@using (Html.BeginForm("Result", "Search", FormMethod.Get))
{
    <input type="submit" />
}

更に Html.ActionLink を使ってルーティングパラメータを持つアクションへのリンクを作成する場合は、同様にオーバーロードメソッドを使って書けます。

@Html.ActionLink("リンクテキスト", "Details", new { id = 42 });

それでは本題。

これから Html.BeginForm を使ってファイルアップロードを行いたい場合を考えます。POST 先は今のアクションと同じとしますが、form 要素の enctype 属性を修正しないとファイルアップロードは出来ません。

単純に考えると、現在のコントローラが Product でアクションが Update の場合は以下のように書けばいいですね。

@using (Html.BeginForm("Update", "Product", FormMethod.Post, new { enctype = "multipart/form-data" })
{
    <input type="file" name="photo" />

    <input type="submit" />
}

しかし、コントローラやアクションの名前を変えた場合など、存在しない URL に POST が実行されるようになってしまうので、あんまりビューには書きたくないですよね。

ということなので、以下のように書き換えてしまいます。

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="photo" />

    <input type="submit" />
}

コントローラとアクションの指定を null にしました。これで本当に動くの?と考える人は多いと思いますが、null になっているパラメータは自動的に現在のルーティングパラメータから補完されるのでちゃんと動きます。

続いて Html.ActionLink で SSL (https) へのリンクを作成したい場合を考えます。

Html.ActionLink はオーバーロードメソッドがめちゃくちゃ多いです。普段使いだと 3,4 引数までしか使わないと思いますが、実際には以下のようにプロトコルやホスト名まで指定可能なメソッドも用意されているのでこれを使います。

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes)

パラメータが多いので、値を入れるのがめんどくさそうですが大丈夫。使わないパラメータには null を入れておけばいいんです。

@Html.ActionLink("アカウント情報", "Index", "Account", "https", null, null, null, null)

これでホスト名が変わっても問題なく動作するリンクを作成できます。開発環境でも IIS Express で仮想サイトに複数のホスト名を割り当てる - しばやん雑記 と組み合わせるとテストしやすいですね。

残念なのが ASP.NET MVC はデフォルト引数が追加される前に開発されたので、全てのパラメータが必須となっている点です。実装されていたら以下のように書けるはずですね。

@* これは今のバージョンでは動作しない *@
@Html.ActionLink("アカウント情報", "Index", "Account", "https")

今回の記事は、何となく MSDN フォーラムを眺めていたら、以下のようなスレッドがあったので書きました。

[ASP.NET MVC]httpsで表示されているページからhttpのページへ移動したい

フォーラムに書けと言われそうですが、あそこは回答早押し選手権みたいな殺伐とした空気を感じるので遠慮しています。

ゆるふわなブログやツイッターで、僕は今まで通り活動し続けることにします。