【问题标题】:Web Api 2 deserialize LINQ2SQL object with collection propertyWeb Api 2 使用集合属性反序列化 LINQ2SQL 对象
【发布时间】:2015-01-28 05:43:22
【问题描述】:

上下文很长,所以我将从以下问题开始:为什么 InductionQAs 集合属性没有被重新水化?

在 Web API 2 方法中,LINQ 生成一个对象 ic,其集合属性为 InductionQAs。在我消除了一个巨大的不相关对象图并防止循环引用之后,该方法返回了ic。这是代码。为简洁起见,已删除错误处理。

// GET: api/InductionContent/5
[Authorize]
public object Get(int id)
{
  var dc = new Models.InductionsDataContext();
  var user = GetUser(dc);
  var ic = dc.InductionContents.Single(c => c.InductionContentID == id);
  ic.User.InductionContents.Clear(); //don't ship this it can be huge
  return ic;
}

这是调用 JS 代码。忽略授权头业务,一切正常。

var token, headers;
$.ajax({ //get session token
  url: "api/token",
  headers: { Authorization: "Basic " + btoa("username:password") },
}).done(function (result) {
  localStorage.setItem('access_token', token = result.access_token);
  var headers = { Authorization: "Session " + token };
  $.ajax({ //get an induction content object 
    url: "api/InductionContent/5",
    headers: headers
  }).done(function (ic) {
    //at this point we have an object graph
    var json = JSON.stringify(ic);
  });
});

这是 JSON.stringify(ic) 返回的内容:

{
    "InductionContentID": 5,
    "InductionTemplateID": 1,
    "InductionContent1": "<p>We recognise that it is ...(redacted)</p>",
    "InductionContentOrder": 301,
    "Caption": "Workplace Health and Safety",
    "OwnerId": 0,
    "ParentId": 0,
    "TopicId": 5,
    "InductionQAs": [
        {
            "InductionQAID": 1,
            "InductionContentID": 5,
            "Question": "Who is responsible for ...(redacted)",
            "Answers": "A|B|C|*D",
            "InductionQAOrder": 1
        }
    ],
    "User": null
}

一切顺利。现在我们来回它。

$.ajax({
  type: "post",
  url: "api/InductionContent",
  headers: headers,
  data: ic
});

这会调用以下网络方法:

// POST: api/InductionContent
[Authorize]
public void Post([FromBody]Models.InductionContent ic)
{
  //redacted
}

方法被调用并且ic 有一个值。 ic.User 包含数据,但检查 ic.InductionQAs 发现它尚未初始化。

序列化配置如下:

protected void Application_Start()
{
  GlobalConfiguration.Configure(WebApiConfig.Register);
  GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
    .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
  GlobalConfiguration.Configuration.MessageHandlers
    .Add(new AuthenticationHandler(CreateConfiguration()));
  FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  RouteConfig.RegisterRoutes(RouteTable.Routes);
  BundleConfig.RegisterBundles(BundleTable.Bundles);
}

【问题讨论】:

    标签: ajax json serialization asp.net-web-api2


    【解决方案1】:

    MVC 很聪明,但还不够聪明。它需要一个提示。 “往返”调用应该如下所示:

        $.ajax({
          type: "post",
          url: "api/InductionContent",
          contentType: "text/json",
          headers: headers,
          data: JSON.stringify(ic)
        }).done(function (result) {
          //etc
        });
    

    这里有两点需要注意。

    • 我们假设手动控制有效载荷编码
    • 我们已使用所使用的编码对帖子进行了注释

    另一件事......

    完成所有工作后,我决定该方法应返回新创建的数据库行的 id。将方法返回类型更改为int 并附加最后一行

    return nc.InductionContentId;
    

    应该已经足够了,但是 ajax 调用的 done 方法完全没有触发。与 Fiddler 的调查显示,确实返回了 id 值内容类型为 text/json

    当您为 jQuery ajax 调用指定内容类型时,响应将使用相同的内容类型。如果返回值是一个对象,这将正常工作。该对象将被序列化为 JSON,而在另一端,它将被解析以提供结果对象。

    但是对于像 int 这样的简单值,它在解析阶段就没有了。为解决此问题,使用 dataType 属性返回纯文本的内容类型。

    $.ajax({
      type: "post",
      url: "api/InductionContent",
      contentType: "text/json",
      dataType: "text",
      headers: headers,
      data: JSON.stringify(ic)
    }).done(function (result) {
      var id = result;
      //etc
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 2020-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多