はじめに
どうも、ATLのヴィリアスです。
ある日、 JavaScript から MVC のコントローラーのメソッドを呼び出そうとしたところ…

「メソッドが見つからないから、404エラーだよー!!」と怒られてしまいました。
それに対して、私は該当のコードを確認しましたが…
public class HomeController : Controller
{
public async Task<string> GetNewTokenAsync()
{
.
.
.
}
}
async function updateToken() {
$.ajax({
type: 'POST',
url: location.origin + '/Home/GetNewTokenAsync',
.
.
.
})
}
「ん?メソッド名あってね??」となり、一悶着してしまいました。
そこでいろいろ調べた結果、最終的に私が悪かったことが判明したので、
戒めと反省と謝罪として、そのときの解決策をここに記します。
※免責事項(必ず、ご一読ください)
本記事の情報により生じた、いかなる損害や損失についても、当社は一切の責任を負いかねます。
また、誤情報が入り込んだり、情報が古くなったりすることもありますので、
必ずしも正確性を保証するものではありません。ご了承ください。
まずは結論
こちらが正しい書き方でした。
async function updateToken() {
$.ajax({
type: 'POST',
// url: location.origin + '/Home/GetNewTokenAsync',
url: location.origin + '/Home/GetNewToken'
.
.
.
})
}
Ajaxで指定するメソッド名 (アクション名) にAsyncはいらなかったのです!
なぜAsyncが必要ないのか?
以下によると、MVC 3.0以降では
コントローラーのメソッド名の後ろに付随するAsyncは内部で削除される仕様になっているとのこと。
これに気が付かず、
「GetNewTokenAsyncが見つからないよ!」ということで404エラーが出てしまっていたんですね。
補足1: Asyncが削除されないようにするには
MVC のスタートアップ設定で、以下のコードを記述します。
services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
SuppressAsyncSuffixInActionNamesは直訳すると、
「アクション名のAsyncサフィックスを抑える」です。
つまり、「アクション名の後ろに付随するAsyncを削除する」かどうかを設定できます。
それをfalseに設定することで、Asyncの削除を無効化できるということですね。
補足2: なぜこの仕様になったのか?
Asynchronous .NET methods, by convention, end with the Async suffix. However, when a method defines an MVC action, it is generally not desirable to have the Async suffix.
「慣習的には、非同期 .NET メソッドはAsyncサフィックスをつけます。
ですが、MVC アクション名としてはAsyncサフィックスは望ましくないのです。」
とのことでした。
おわりに
うーん、これは初見殺しの罠ですね。さすがに許せない。
……
冗談はさておき、
「JavaScript などの外部からメソッドを呼び出す時、Asyncには要注意!」ですね。
それではまた、次の記事で。