はじめに
どうも、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
には要注意!」ですね。
それではまた、次の記事で。