2

In my current MVC application I perform an AJAX call to the controller. The controller gets an object from the database and returns it in the form of a JSON response. My confusion is between using the Controller.Json method vs JavaScriptSerializer.Serialize(object). My object I am converting is a simple class called PhoneSerializable with a few public properties of type string and int.

I have the following:

var serializedPhone = jsSerializer.Serialize(new PhoneSerializable(phone));
return new ContentResult {Content = serializedPhone, ContentType = "application/json"};

This works correctly and I get a JSON response that my AJAX caller can parse. Yet some online examples I have seen use this instead:

return Json(new PhoneSerializable(phone));

The response of this has mostly null properties and a DenyGet header which means it failed parsing or something. The documentation for the Json(object) method states that it uses the same javascript serializer for the object yet it fails to convert my simple object to JSON.

What am I missing? I would like to use Json(object) since it is much cleaner but I cannot seem to get it to work.

EDIT WITH ANSWER:

The Json() method was defaulting to "DenyGet" adding more parameters fixed the issue and it now works:

return Json(new PhoneSerializable(phone), 
            "application/json", 
            JsonRequestBehavior.AllowGet);

1 Answer 1

2

Using the Json method from the Controller base class simply returns a new object of type JsonResult, using the following overload:

protected internal JsonResult Json(object data)
{
    return this.Json(data, null, null, JsonRequestBehavior.DenyGet);
}

protected internal virtual JsonResult Json(
                       object data, 
                       string contentType, 
                       Encoding contentEncoding,
                       JsonRequestBehavior behavior)
{
    return new JsonResult
    {
        Data = data,
        ContentType = contentType,
        ContentEncoding = contentEncoding,
        JsonRequestBehavior = behavior
    };
}

After you return Json(new PhoneSerialize(phone));, the controller eventually invokes a method called ExecuteResult(ControllerContext context), which internally does the same serialization with JsonSerializer:

public override void ExecuteResult(ControllerContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context");
    }
    if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
                            string.Equals(context.HttpContext.Request.HttpMethod,
                                          "GET",
                                          StringComparison.OrdinalIgnoreCase))
    {
        throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
    }
    HttpResponseBase response = context.HttpContext.Response;
    if (!string.IsNullOrEmpty(this.ContentType))
    {
        response.ContentType = this.ContentType;
    }
    else
    {
        response.ContentType = "application/json";
    }
    if (this.ContentEncoding != null)
    {
        response.ContentEncoding = this.ContentEncoding;
    }
    if (this.Data != null)
    {
        JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
        if (this.MaxJsonLength.HasValue)
        {
            javaScriptSerializer.MaxJsonLength = this.MaxJsonLength.Value;
        }
        if (this.RecursionLimit.HasValue)
        {
            javaScriptSerializer.RecursionLimit = this.RecursionLimit.Value;
        }
        response.Write(javaScriptSerializer.Serialize(this.Data));
    }
}

This basically means you're passing both DenyGet as a default parameter, yet your method is a "GET", which ends up throwing an InvalidOperationException. You should specify the "AllowGet" explicitly to avoid this:

return Json(new PhoneSerializable(phone), 
            "application/json", 
            JsonRequestBehavior.AllowGet);
Sign up to request clarification or add additional context in comments.

1 Comment

I see. So the Json method was simply defaulting to "DenyGet". It works now after using this return statement instead: return Json(new PhoneSerializable(phone), "application/json", JsonRequestBehavior.AllowGet); Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.