web-dev-qa-db-ja.com

プロパティなしでWeb APIからJsonResultを返します

Web APIコントローラーがあり、そこからアクションからJSONとしてオブジェクトを返しています。

私はこれを次のようにしています:

public ActionResult GetAllNotificationSettings()
{
    var result = new List<ListItems>();
    // Filling the list with data here...

    // Then I return the list
    return new JsonResult { Data = result };
}

ただし、この方法では、Data属性を含むJsonResultオブジェクトがJSONとしてシリアル化されます。したがって、アクションによって返される最終的なJSONは次のようになります。

{
    "ContentEncoding": null,
    "ContentType": null,
    "Data": {
        "ListItems": [
            {
                "ListId": 2,
                "Name": "John Doe"
            },
            {
                "ListId": 3,
                "Name": "Jane Doe"
            },
        ]
    },
    "JsonRequestBehavior": 1,
    "MaxJsonLength": null,
    "RecursionLimit": null
}

JsonResultオブジェクトが他のすべての種類のプロパティを追加したため、このJSON文字列をシリアル化できません。私はListItemsにのみ興味があり、他には何も興味がありません。しかし、次のようなものが自動的に追加されました:ContentTypeMaxJsonLengthなど...

JSON文字列の他のすべてのプロパティのため、これは私にとってはうまくいきません...

var myList = JsonConvert.DeserializeObject<List<ListItems>>(jsonString);

アクションからJSONオブジェクトを送信して、必要のないすべてのプロパティを追加しないようにする方法はありますか?

19
Vivendi

ASP.NET APIを約3年間使用してきた人として、代わりにHttpResponseMessageを返すことをお勧めします。 ActionResultまたはIEnumerableを使用しないでください!

あなたが発見したようにActionResultは悪いです。

IEnumerable <>を返すのは、後で拡張してヘッダーなどを追加する必要があるためです。

JsonResultの使用は、将来の場合に備えてサービスを拡張可能にし、他の応答形式をサポートする必要があるため、不適切です。真剣に制限したい場合は、アクション本文ではなくアクション属性を使用して制限できます。

public HttpResponseMessage GetAllNotificationSettings()
{
    var result = new List<ListItems>();
    // Filling the list with data here...

    // Then I return the list
    return Request.CreateResponse(HttpStatusCode.OK, result);
}

私のテストでは、通常、以下のヘルパーメソッドを使用して、HttpResponseMessageからオブジェクトを抽出します。

 public class ResponseResultExtractor
    {
        public T Extract<T>(HttpResponseMessage response)
        {
            return response.Content.ReadAsAsync<T>().Result;
        }
    }

var actual = ResponseResultExtractor.Extract<List<ListItems>>(response);

このようにして、以下を達成しました。

  • また、アクションはエラーメッセージと404 not foundなどのステータスコードを返すことができるため、上記の方法で簡単に処理できます。
  • アクションはJSONのみに限定されず、クライアントのリクエスト設定とフォーマッターの設定に応じてJSONをサポートします。

これを見てください: http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation

46
Dynamic

APIはリクエストに応じてJSONまたはXMLを返すため、WebAPIを使用する場合は、Jsonを明確に返すのではなく、オブジェクトを返す必要があります。

WebAPIがActionResultを返す理由はわかりませんが、コードを次のように変更します。

public IEnumerable<ListItems> GetAllNotificationSettings()
{
    var result = new List<ListItems>();
    // Filling the list with data here...

    // Then I return the list
    return result;
}

AJAXコードから呼び出している場合、JSONになります。

P.S WebAPIはRESTfulであると想定されているため、コントローラーはListItemControllerと呼ばれ、メソッドはGetと呼ばれる必要があります。しかし、それは別の日です。

12
Tim B James

私は同様の問題を抱えていました(すでにjson文字列に変換されたオブジェクトを返したいと思っているので、コントローラーgetはIHttpActionResultを返します)

ここに私がそれを解決した方法があります。最初にユーティリティクラスを宣言しました

public class RawJsonActionResult : IHttpActionResult
{
    private readonly string _jsonString;

    public RawJsonActionResult(string jsonString)
    {
        _jsonString = jsonString;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var content = new StringContent(_jsonString);
        content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = content };
        return Task.FromResult(response);
    }
}

このクラスはコントローラーで使用できます。簡単な例を示します

public IHttpActionResult Get()
{
    var jsonString = "{\"id\":1,\"name\":\"a small object\" }";
    return new RawJsonActionResult(jsonString);
}
9
Joe King