使用Json(对象)与JavaScriptSerializer()编码JSON的MVC控制器.Serialize(object)

时间:2015-07-01 17:19:44

标签: c# json asp.net-mvc

在我当前的MVC应用程序中,我对控制器执行AJAX调用。控制器从数据库中获取一个对象,并以JSON响应的形式返回它。我的困惑在于使用Controller.Json方法与JavaScriptSerializer.Serialize(对象)之间的混淆。我转换的对象是一个名为PhoneSerializable的简单类,其中包含一些类型为stringint的公共属性。

我有以下内容:

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

这可以正常工作,我得到一个我的AJAX调用者可以解析的JSON响应。 然而,我见过的一些在线示例使用了这个:

return Json(new PhoneSerializable(phone));

此响应主要有null个属性和DenyGet标头,这意味着它无法解析或其他内容。 Json(object)方法的文档声明它为对象使用相同的javascript序列化程序,但它无法将我的简单对象转换为JSON。

我错过了什么?我想使用Json(object)因为它更干净但我似乎无法让它工作。

用答案编辑:

Json()方法默认为" DenyGet"添加更多参数修复了问题,现在可以正常工作:

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

1 个答案:

答案 0 :(得分:2)

使用Json基类中的Controller方法只返回类型为JsonResult的新对象,使用以下重载:

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

return Json(new PhoneSerialize(phone));之后,控制器最终调用一个名为ExecuteResult(ControllerContext context)的方法,该方法在内部对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));
    }
}

这基本上意味着您将DenyGet作为默认参数传递,但您的方法是“GET”,最终会抛出InvalidOperationException。您应该明确指定“AllowGet”以避免这种情况:

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