【问题标题】:Returning unescaped Json in MVC with Json.Net使用 Json.Net 在 MVC 中返回未转义的 Json
【发布时间】:2011-11-14 23:39:19
【问题描述】:

如何在 MVC 项目中使用 Json.Net 返回未转义的 Json?

到目前为止,我序列化了一个基本对象,并让 Json.Net 对其进行序列化:

public JsonResult GetTimelineJson()
{
    var result = new MyGraph([some data...]);

    return Json(JsonConvert.SerializeObject(result), JsonRequestBehavior.AllowGet);
}

结果:

"{\r\n  \"id\": \"myGraph\",\r\n  \"title\": \"Graph title\",\r\n [...]

任何将其包装为 HtmlString 等的尝试都会导致通过线路传递一个空集(尽管调试点显示它正确地未转义)。我检查了 HTTP 标头中的内容类型设置是否正确。

【问题讨论】:

  • 为什么要发送 JSON 序列化字符串作为 JSON 结果?要么直接使用带有 JSON 方法的模型(不需要 JSON.Net),要么使用带有正确 MIME 类型的Content() 返回您的序列化对象。
  • 我来这里是为了寻找从 Web API 方法返回的 Json 格式的结果,经过一番搜寻,我终于得到了预期的结果。看我的回答here

标签: c# asp.net-mvc json json.net


【解决方案1】:

您正在 Jsoning 两次,Json 方法正在 json 序列化您已经转换的字符串。如果您想使用 JsonConvert,则将其直接写入响应流。

【讨论】:

    【解决方案2】:

    对象已经被 Json.NET 序列化,当你将它传递给 Json() 时,它会被编码两次。如果您必须使用 Json.NET 而不是内置编码器,那么处理此问题的理想方法是创建一个自定义 ActionResult 接受对象并在内部调用 Json.net 以序列化对象并将其作为 application/json 结果返回.

    编辑

    此代码用于上述解决方案。它未经测试,但应该可以工作。

    public class JsonDotNetResult : ActionResult
    {
        private object _obj { get; set; }
        public JsonDotNetResult(object obj)
        {
            _obj = obj;
        }
    
        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.AddHeader("content-type", "application/json");
            context.HttpContext.Response.Write(JsonConvert.SerializeObject(_obj));
        }
    }
    

    然后在您的控制器中执行以下操作:

    return new JsonDotNetResult(result);
    

    【讨论】:

      【解决方案3】:

      你也可以这样做

      public ActionResult GetTimelineJson()
      {
          var result = new MyGraph([some data...]);
          return Content(JsonConvert.SerializeObject(result), "application/json");
      }
      

      请注意,您应该将返回类型从 JsonResult 更改为 ActionResult

      【讨论】:

      • 这是最好的答案。一般来说,如果想将未转义和未格式化的 JObject 返回给客户端,那么 JObject 类中有ToString(Formatting),可以这样使用:JObject o = JObject.Parse("{foo:1000, bar: 2000}"); return Content(o.ToString(Formatting.None), "application/json");
      【解决方案4】:

      为了让单元测试更容易,我对我的新类做了一点改动:

      public class JsonDotNetResult : ActionResult
      {
          public JsonDotNetResult(object data)
          {
              Data = data;
          }
      
          //Name the property Data and make the getter public
          public object Data { get; private set; }
      
          public override void ExecuteResult(ControllerContext context)
          {
              context.HttpContext.Response.AddHeader("content-type", "application/json");
              context.HttpContext.Response.Write(JsonConvert.SerializeObject(Data));
          }
      }
      

      }

      这更类似于 System.Web.Mvc 中的 JsonResult,并允许我使用通用方法进行单元测试...

      单元测试助手:

      public static TReturn GetDataFromJsonResult<TJsonType, TReturn>(this ActionResult result) where TJsonType : ActionResult
      {
          var jsonResult = (TJsonType)result;
      
          var data = jsonResult.GetType().GetProperty("Data").GetValue(jsonResult);
      
          return (TReturn)data;
      }
      

      单元测试示例:

      [TestMethod]
      public void ControllerMethod_WhenMethodCalled_ThenSomeRecordsAreReturned()
      {
          // arrange
          var records = new List<string> { "Record1", "Record2" };
          var expectedRecordCount = records.Count();
      
          myService.Setup(x => x.GetRecordsFromDatabase()).Returns(records);
      
          // act
          var result = myController.GetRecords(); //Assuming this controller method returns JsonDotNetResult
      
          // assert
          var jsonResult = result.GetDataFromJsonResult<JsonDotNetResult, IEnumerable<string>>();
          Assert.AreEqual(expectedRecordCount, jsonResult.Count());
      }
      

      如果控制器返回正常的 JsonResult,则可以更改此行:

          var jsonResult = result.GetDataFromJsonResult<JsonResult, IEnumerable<string>>();
      

      【讨论】:

        猜你喜欢
        • 2021-08-24
        • 1970-01-01
        • 2013-08-20
        • 1970-01-01
        • 2015-11-24
        • 1970-01-01
        • 2016-06-14
        • 1970-01-01
        • 2012-05-07
        相关资源
        最近更新 更多