1. ホーム
  2. c#

[解決済み】ASP.NET Coreがステータスコード付きのJSONを返す

2022-04-17 19:21:58

質問

.NET Core Web APIコントローラで、HTTPステータスコード付きのJSONを返す正しい方法を探しています。私はこのようにそれを使用しています。

public IHttpActionResult GetResourceData()
{
    return this.Content(HttpStatusCode.OK, new { response = "Hello"});
}

これは4.6のMVCアプリケーションにあったものですが、.NET Coreではこれがないようです。 IHttpActionResult 私は ActionResult で、このような使い方をしています。

public ActionResult IsAuthenticated()
{
    return Ok(Json("123"));
}

しかし、サーバーからの応答は、以下の画像のように変です。

Web APIコントローラは、Web API 2でやったように、HTTPステータスコード付きでJSONを返すようにしたいだけなんです。

どのように解決するのですか?

で応答する最も基本的なバージョンです。 JsonResult となります。

// GET: api/authors
[HttpGet]
public JsonResult Get()
{
    return Json(_authorRepository.List());
}

しかし、これはあなたの問題には役立ちません。なぜなら、あなた自身のレスポンス・コードを明示的に扱うことができないからです。

ステータスの結果を制御する方法ですが、これは ActionResult を利用することができます。 StatusCodeResult という型があります。

例えば

// GET: api/authors/search?namelike=foo
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authorRepository.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

上記の2つの例は、Microsoft Documentationから入手できる素晴らしいガイドから得たものであることに注意してください。 レスポンスデータの書式設定


エクストラスタッフ

私がよく遭遇する問題は、VSの"New Project"テンプレートからデフォルトの構成で行くのではなく、WebAPIをより詳細に制御したいことです。

基本的なことを確認しておきましょう...。

ステップ1:サービスを設定する

ASP.NET Core WebAPI がステータス コードを完全に制御しながら JSON シリアライズ オブジェクトで応答するようにするには、最初に AddMvc() サービスを ConfigureServices メソッドは、通常 Startup.cs .

重要なのは AddMvc() は、他のリクエストタイプへの応答と同時に、JSON 用の Input/Output Formatter を自動的に含めます。

プロジェクトで フルコントロール を含む様々なリクエストタイプに対してWebAPIがどのように動作するかなど、サービスを厳密に定義したい場合。 application/json で、それ以外のリクエストタイプ(標準的なブラウザのリクエストなど)には応答しないようにするには、以下のコードで手動で定義します。

public void ConfigureServices(IServiceCollection services)
{
    // Build a customized MVC implementation, without using the default AddMvc(), instead use AddMvcCore().
    // https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs

    services
        .AddMvcCore(options =>
        {
            options.RequireHttpsPermanent = true; // does not affect api requests
            options.RespectBrowserAcceptHeader = true; // false by default
            //options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();

            //remove these two below, but added so you know where to place them...
            options.OutputFormatters.Add(new YourCustomOutputFormatter()); 
            options.InputFormatters.Add(new YourCustomInputFormatter());
        })
        //.AddApiExplorer()
        //.AddAuthorization()
        .AddFormatterMappings()
        //.AddCacheTagHelper()
        //.AddDataAnnotations()
        //.AddCors()
        .AddJsonFormatters(); // JSON, or you can build your own custom one (above)
}

他のシリアライズ形式(protobuf、thriftなど)に対応するために、独自のカスタム入出力フォーマッタを追加する方法も含まれていることにお気づきでしょう。

上のコードの塊は、ほとんど AddMvc() メソッドを使用します。ただし、テンプレートであらかじめ用意されているサービスを利用するのではなく、各サービスを独自に定義して、quot;default"サービスを実装しています。コードブロックにリポジトリリンクを追加しました。 AddMvc() をGitHubのリポジトリからダウンロードします。 .

そもそも実装しないのではなく、デフォルトを元に戻すことで解決しようとするガイドもあることに注意してください...。私たちが今オープンソースで作業していることを考慮すると、これは冗長な作業であり、悪いコードであり、率直に言ってすぐに消えてしまう古い習慣です。


ステップ2:コントローラの作成

あなたの疑問を解決するために、本当に簡単なものをお見せします。

public class FooController
{
    [HttpPost]
    public async Task<IActionResult> Create([FromBody] Object item)
    {
        if (item == null) return BadRequest();

        var newItem = new Object(); // create the object to return
        if (newItem != null) return Ok(newItem);

        else return NotFound();
    }
}


ステップ3: 確認 Content-TypeAccept

を確認する必要があります。 Content-TypeAccept ヘッダを リクエスト が正しく設定されていることを確認します。あなたの場合(JSON)、次のように設定したいでしょう。 application/json .

リクエストヘッダが何を指定しているかに関係なく、WebAPIがデフォルトでJSONとして応答するようにしたい場合、それを いくつかの方法 .

ウェイ1 先ほどのおすすめ記事にもあるように( レスポンスデータの書式設定 ) を使えば、Controller/Action レベルで特定の書式を強制することができます。個人的にはこの方法は好きではありませんが...念のためここに書いておきます。

特定のフォーマットを強制する 特定のアクションのレスポンスフォーマットを制限したい場合は、以下のようにします。 [Produces]フィルタです。Produces] フィルタはレスポンス(応答)を指定します。 のフォーマットは、特定のアクション (あるいはコントローラ) のために用意されています。他のフィルタと同様、このフィルタも は、アクション、コントローラ、またはグローバルスコープで適用することができます。

[Produces("application/json")]
public class AuthorsController

[Produces] フィルタは AuthorsController はJSON形式のレスポンスを返すようにします。 フォーマッタが設定され、クライアントから である。 Accept ヘッダは、別の利用可能なフォーマットを要求します。

ウェイ2 私が望む方法は、WebAPIがすべてのリクエストに対して、要求されたフォーマットで応答することです。しかし、要求されたフォーマットを受け入れない場合、次に フォールバック をデフォルト(例:JSON)に変更する。

まず、それをオプションに登録する必要があります(先に述べたように、デフォルトの動作を作り直す必要があります)。

options.RespectBrowserAcceptHeader = true; // false by default

最後に、サービスビルダーで定義したフォーマッタのリストを並べ替えるだけで、ウェブホストはリストの一番上 (つまりポジション 0) に配置したフォーマッタをデフォルトとして使用するようになります。

より詳細な情報はこちらをご覧ください。 .NET ウェブ開発・ツール ブログエントリー