使用JSON.NET格式化程序对普通控制器进行格式化

5
当从控制器 (MVC 4 RC) 返回 Json 时,我希望修改 Json 使用驼峰式命名属性。为此,我尝试设置 GlobalConfiguration.Formatters.JsonFormatter(不确定是否正确...没有代码在我面前),但这似乎不影响 Controller.Json 方法输出的 Json。
经过查看,似乎这种方法只影响 Web API 控制器等。这是真的吗?另外,是否可以修改 Controller.Json() 方法来实现这一点?
3个回答

7

像@rouen建议的那样,创建自己的JsonDotNetResult。

这是我在我的项目中使用的一个:

public class JsonNetResult : ActionResult
{
    public Encoding ContentEncoding { get; set; }
    public string ContentType { get; set; }
    public object Data { get; set; }
    public int StatusCode { get; set; }

    public JsonSerializerSettings SerializerSettings { get; set; }

    public JsonNetResult()
    {
        SerializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var response = context.HttpContext.Response;

        response.StatusCode = StatusCode;
        response.ContentType = string.IsNullOrEmpty(ContentType) ? "application/json" : ContentType;

        if ((StatusCode >= 400) && (StatusCode <= 599))
            response.TrySkipIisCustomErrors = true;

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        if (Data == null)
            return;

        var formatting = Formatting.None;

#if DEBUG
        formatting = Formatting.Indented;
#endif

        var writer = new JsonTextWriter(response.Output) { Formatting = formatting };

        var serializer = JsonSerializer.Create(SerializerSettings);
        serializer.Serialize(writer, Data);

        writer.Flush();
    }
}

我有自己的 baseController,从中继承以提供 JsonDotNet(object viewModel)类型的方法。
例如:
protected JsonNetResult JsonNet(object data = null, int statusCode = (int)HttpStatusCode.OK, string contentType = null)
{
    return new JsonNetResult
               {
                   Data = data,
                   StatusCode = statusCode,
                   ContentType = contentType
               };
}

protected JsonNetResult JsonNetForbidden()
{
    return JsonNet(statusCode: (int)HttpStatusCode.Forbidden);
}

protected JsonNetResult JsonNetNotFound()
{
    return JsonNet(statusCode: (int)HttpStatusCode.NotFound);
}

protected JsonNetResult JsonNetNoContent()
{
    return JsonNet(statusCode: (int)HttpStatusCode.NoContent);
}

protected JsonNetResult JsonNetCreated(object data)
{
    return JsonNet(data, (int)HttpStatusCode.Created);
}

protected JsonNetResult JsonNetReload()
{
    return JsonNet(new { reload = true });
}

protected JsonNetResult JsonNetRedirect(string url = null, string contentType = null)
{
    return JsonNet(new { redirectUrl = url }, contentType: contentType);
}

protected JsonNetResult JsonNetClientError(ErrorDictionary errors)
{
    return JsonNet(new { Errors = errors }, (int)HttpStatusCode.BadRequest);
}

protected JsonNetResult JsonNetUnauthorized()
{
    return JsonNet(null, (int)HttpStatusCode.Unauthorized);
}

protected JsonNetResult JsonNetFlashMessage(string message)
{
    return JsonNet(new { flashMessage = message });
}

嗨,Charlino。抱歉回复晚了。我喜欢你提出的想法以及它如何适用于MVC框架。我会尝试一下,希望在周末之内看看它的效果如何。 - MotoSV

2
据我所知,无法更改默认JavaScriptSerializer的行为。
个人而言,在所有json操作中,我都使用自己的JsonDotNetResult(以及在我的BaseController上的快捷方式方法)。不仅可以以多种方式更改其设置,而且使用JSON.NET的性能要好得多 - 在这里查看:http://james.newtonking.com/archive/2008/10/27/json-net-3-5-beta-1-big-performance-improvements-compact-framework-support-and-more.aspx 此外,还有许多小的好处,例如自动解决循环依赖关系(在大型项目中总是遇到)等。
花费5分钟时间创建自己的JsonDotNetResult,一定会物超所值。

+1 这正是我所做的。当我在调试时,我也发现它很方便缩进。 - Charlino

0
根据 asp.net MVC 3 的源代码(我手头没有第四版的源代码,但是很不可能有变动),您无法这样做。 Controller.Json 使用 new JsonResult,而 JsonResult.ExecuteResult 直接使用 new JavaScriptSerializer
一段时间以前,我们正在寻找某种影响此行为的方法,但没有找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接