18

私はMVC4Web APIを使い始めたばかりで、それがどのように機能するかを誤解しているようです。

Web APIの前は、次のような単純なMVCアクションメソッドがありました。

public JsonResult User()
{
    return Json(new
    {
        firstName = "Joe",
        lastName = "Jacobs",
        email = "joe.jacobs@gmail.com"
    });
}

それはうまくいくでしょう。新しいWebAPIコントローラーで、私は同様のことをしようとしています。

public object User()
{
    return new
    {
        firstName = "Joe",
        lastName = "Jacobs",
        email = "joe.jacobs@gmail.com"
    }
}

これはシリアル化エラーで失敗します:

'ObjectContent`1'タイプは、コンテンツタイプ'application/xmlの応答本文をシリアル化できませんでした。charset =utf-8'。

内部例外:

タイプ'<>f__AnonymousType1`3 [System.String、System.String、System.String]'はシリアル化できません。DataContractAttribute属性でマークを付け、シリアル化するすべてのメンバーをDataMemberAttribute属性でマークすることを検討してください。タイプがコレクションの場合は、CollectionDataContractAttributeでマークすることを検討してください。サポートされている他のタイプについては、Microsoft.NETFrameworkのドキュメントを参照してください。

APIコントローラーから匿名型を返すことについて私は何を理解していませんか?

4

4 に答える 4

33

Fiddlerを見ると(ここのサンプルはFirefoxを使用しています)

ここに画像の説明を入力してください

デフォルトでは、ブラウザからのリクエストはapplication/jsonではなくapplication/xmlを受け入れます

ただし、ヘッダーを1つ追加することで、Fiddlerから偽のリクエストを作成できます。

Accept: application/json

それが動作します

リンクから:

XMLシリアライザーは、匿名型またはJObjectインスタンスをサポートしていません。JSONデータにこれらの機能を使用する場合は、この記事の後半で説明するように、パイプラインからXMLフォーマッターを削除する必要があります。

削除する方法XmlFormatter

  var configuration = GlobalConfiguration.Configuration;
  configuration.Formatters.Remove(configuration.Formatters.XmlFormatter);
于 2013-02-19T16:29:17.687 に答える
3

JsonMediaTypeFormatterを使用して、JSONObjectおよび関連するクラスを必要としないようにすることもできます。次に、コントローラークラスで動的型を返すことができます。

public static void Register(HttpConfiguration config)
{
    config.Formatters.Clear();            
    config.Formatters.Add(new JsonMediaTypeFormatter());
    config.MapHttpAttributeRoutes();
}

public class YourController : ApiController
{        
    [HttpGet, Route("getstuff/{stuffId}")]
    public dynamic Get(string stuffId)
    {
        var stuff = Model.Stuff.Get(stuffId);

        return new {
            success= stuff != null,
            stuffId = stuff.Id,
            name = stuff.Name
        };
    }
}

Jsonpもサポートしたい場合は、JsonMediaTypeFormatterを継承して、独自のJsonpMediaTypeFormatterを作成できます(stackoverflow:https ://stackoverflow.com/a/12492552/1138266にもあります)。

于 2013-12-13T13:51:09.037 に答える
0

APIは生のリストを返すのが好きではないことがわかりました。代わりに、オブジェクトを作成し、オブジェクトの値をリストとして設定する必要がありました。最初のreturnステートメントを参照してください。

例:

public IHttpActionResult GetMessages(int messageFeedId, int lastMessageId) {
    List<Message> messageDomainObjects = MessageService.GetMessages(messageFeedId, lastMessageId);

    if (messageDomainObjects.Any())
    {
        var messages = messageDomainObjects.Select(m => new MessageModel(
            m.Id,
            m.Message,
            m.CreatedDate,
            m.IsActive,
            new UserModel(
                m.User.Id,
                m.User.FirstName,
                m.User.LastName
            )
        ));

        return Ok(new { messages = messages });
    }
    else
    {
        return Ok(new { });
    }
}
于 2016-12-01T04:43:51.687 に答える
0

私も同様の問題を抱えていましたが、解決策は Global.asax.csファイルにスニペットを追加することでした。

追加するスニペットは次のとおりです。

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
            .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters
            .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

また、上記のコード行をApplication_Startメソッドの最上部に追加したため、メソッドは次のようになりました。

protected void Application_Start()
    {
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
            .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters
            .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
于 2019-09-21T11:50:54.323 に答える