c# asp.net-mvc json json.net

c# - Devolución de Json sin escaparse en MVC con Json.Net



asp.net-mvc (4)

El objeto ya está serializado por Json.NET, y cuando lo pasas a Json () se codifica dos veces. Si debe usar Json.NET en lugar del codificador incorporado, entonces la forma ideal de manejar esto sería crear un ActionResult personalizado que acepte el objeto y llame a Json.net internamente para serializar el objeto y devolverlo como un resultado de application / json .

EDITAR

Este código es para la solución mencionada anteriormente. No está probado, pero debería funcionar.

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)); } }

y en tu controlador solo haz:

return new JsonDotNetResult(result);

¿Cómo se puede devolver a Json unescaped, utilizando Json.Net en un proyecto MVC?

Hasta ahora, serializo un objeto básico y hago que Json.Net lo serialice:

public JsonResult GetTimelineJson() { var result = new MyGraph([some data...]); return Json(JsonConvert.SerializeObject(result), JsonRequestBehavior.AllowGet); }

Resultado:

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

Cualquier intento de envolverlo en un HtmlString, etc., dará como resultado que se pase un conjunto vacío a través del cable (aunque el punto de depuración muestra que no se ha escapado correctamente). He comprobado que el tipo de contenido está configurado correctamente en los encabezados HTTP.


Hice un ligero cambio en mi nueva clase para facilitar las pruebas de unidad:

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)); } }

}

Esto se asemeja más a JsonResult en System.Web.Mvc y me permite realizar pruebas de unidad con un método genérico ...

Ayudante de prueba unitaria:

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; }

Ejemplo de prueba unitaria:

[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()); }

Esta línea se puede cambiar si el controlador devuelve el JsonResult normal:

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


Lo está presionando dos veces, el método Json es json serializando su cadena ya convertida. Si desea utilizar JsonConvert, escríbalo directamente en el flujo de respuesta.


También puedes hacer esto

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

Tenga en cuenta que debe cambiar el tipo de retorno de JsonResult a ActionResult