星期一, 8月 12, 2013

Json.NET 取代 JsonResult

最近在處理 AJAX 上遇到一個問題,當我後端 Action 傳資料到前端讓 Javascript 處理時,會遇到 Json 字串無法轉成 Javascript 物件,花了一些時間 Debug,原來是「Datetime」型別在 ASP.NET MVC 的內建 Json 處理方式跟 Javascript 的定義不同,所以當下就換了 Json.NET 來處理,問題就消失了

來問題重現一下
 
要序列化的型別

public class User
{
    public string Name { get { return "Bibby"; } }
    public int Age { get { return 22; } }
    public DateTime Birthday { get { return new DateTime(2001, 01, 01); } }
}

內建的序列化

{"Name":"Bibby","Age":22,"Birthday":"\/Date(978278400000)\/"}

Json.NET 序列化

{"Name":"Bibby","Age":22,"Birthday":"2001-01-01T00:00:00"}

兇手就是 Datetime 型別,因為也不太想去查內建的 JsonResult 是怎麼處理的,於是乾脆在 BaseController 把預設的 ASP.NET MVC 的內建 JsonResult 複寫(override)掉,下面就是 Code 的部份

public abstract class BaseController : Controller
{ 
    //override jsonresult
    protected override JsonResult Json(object data, string contentType
            , System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonDotNetJsonResult()
        {
            Data = data,
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            JsonRequestBehavior = behavior
        };
    }

    public class JsonDotNetJsonResult : JsonResult
    {
        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if ((this.JsonRequestBehavior == System.Web.Mvc.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)
            {
                response.Write(JsonConvert.SerializeObject(this.Data));
            }
        }
    }
}

有問題再討論吧!

Reference
http://www.servicestack.net/docs/text-serializers/override-mvc-jsonresult
http://stackoverflow.com/questions/726334/asp-net-mvc-jsonresult-date-format
http://www.dotblogs.com.tw/wadehuang36/archive/2012/02/05/jsonplusresult.aspx