I'm trying to write a C# method that will serialize a model and return a JSON result. Here's my code:
public ActionResult Read([DataSourceRequest] DataSourceRequest request)
{
var items = db.Words.Take(1).ToList();
JsonSerializerSettings jsSettings = new JsonSerializerSettings();
jsSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var converted = JsonConvert.SerializeObject(items, null, jsSettings);
return Json(converted, JsonRequestBehavior.AllowGet);
}
I got the following JSON result when I go to Words/Read in Chrome:
"[{\"WordId\":1,\"Rank\":1,\"PartOfSpeech\":\"article\",\"Image\":\"Upload/29/1/Capture1.PNG\",\"FrequencyNumber\":\"22038615\",\"Article\":null,\"ClarificationText\":null,\"WordName\":\"the | article\",\"MasterId\":0,\"SoundFileUrl\":\"/UploadSound/7fd752a6-97ef-4a99-b324-a160295b8ac4/1/sixty_vocab_click_button.mp3\",\"LangId\":1,\"CatId\":null,\"IsActive\":false}
I think the \" escaped quotes are a problem that occurs when you double serialize an object. From other questions: WCF JSON output is getting unwanted quotes & backslashes added
It definitely looks like I'm double serializing my object, since I first serialize using JSON.NET and then pass my result into the Json() function. I need to manually serialize to avoid referenceloops, but I think my View needs an ActionResult.
How can I return an ActionResult here? Do I need to, or can I just return a string?
JsonResult is an ActionResult type in MVC. It helps to send the content in JavaScript Object Notation (JSON) format.
For example, returning JsonResult returns JSON-formatted data. Returning ContentResult or a string returns plain-text-formatted string data.
JsonRequestBehavior. A value that indicates whether HTTP GET requests from the client are allowed.
I found a similar stackoverflow question: Json.Net And ActionResult
The answer there suggested using
return Content( converted, "application/json" );
That seems to work on my very simple page.
Instead of serializing using JSON.NET and then calling Json()
, why not instead override the Json()
method in your controller (or perhaps a base controller to enhance its re-usability)?
This is pulled from this blog post.
In your controller (or base controller):
protected override JsonResult Json(
object data,
string contentType,
System.Text.Encoding contentEncoding,
JsonRequestBehavior behavior)
{
return new JsonNetResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
}
And the definition for JsonNetResult:
public class JsonNetResult : JsonResult
{
public JsonNetResult()
{
Settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
};
}
public JsonSerializerSettings Settings { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet
&& "GET".Equals(
context.HttpContext.Request.HttpMethod,
StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("JSON GET is not allowed");
}
HttpResponseBase response = context.HttpContext.Response;
response.ContentType =
string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;
if (this.ContentEncoding != null)
response.ContentEncoding = this.ContentEncoding;
if (this.Data == null)
return;
var scriptSerializer = JsonSerializer.Create(this.Settings);
using (var sw = new StringWriter())
{
scriptSerializer.Serialize(sw, this.Data);
response.Write(sw.ToString());
}
}
}
By doing this, when you call Json()
in your controller, you will automatically get the JSON.NET serializing you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With