在 MVC 3 应用程序中,如何执行 DateTimes 和 TimeSpans 的简单 AJAX/JSON 往返?

发布于 2024-10-31 09:53:53 字数 2560 浏览 0 评论 0 原文

给定一个简单的往返场景,如何将 JSON 数据返回到浏览器,然后通过 ModelBinds 到具有 3 个属性的类型(Int32、DateTime、TimeSpan)的 JSON 接受来自浏览器的更新?

来自即时窗口客户端代码的服务器代码(控制器)

    public class Product
    {
        public int Id { get; set; }
        public DateTime Start { get; set; }
        public TimeSpan Duration { get; set; }
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public JsonResult data()
    {
        return Json(
           new Product {
               Id = 1, Start = DateTime.Now, 
               Duration = TimeSpan.FromMinutes(30)}
           , JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public void data(Product product)
    {
        //product is not bound; modelbinder fails on DateTime and TimeSpan
        Console.WriteLine("Data: " + product);
    }

错误

ModelState["Start"].Errors[0]
{System.Web.Mvc.ModelError}
    ErrorMessage: "The value '/Date(1302295231115)/' is not valid for Start."
    Exception: null

ModelState["Duration"].Errors[0]
{System.Web.Mvc.ModelError}
    ErrorMessage: "The Duration field is required."
    Exception: null

(getData 和 changeData 绑定到 2 个不同的按钮)

<script type='text/javascript'>
    var myData;
    function getData(event)
    {
        $.getJSON('/home/data', function (data)
        {
            myData=data;
            console.dir(data);                
        });
    }

    function changeData(event)
    {
        var postData = JSON.stringify(myData);

        $.ajax({
            url: '/home/data',
            type: "POST",
            data: postData,
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function () {
                console.log('success!');
            },
            error: function () {
                console.log('fail!');
            }
            });
    }

    $(document).ready(function ()
    {
        $('#get').click(getData);
        $('#post').click(changeData);
    }
</script>

<body>
    <button id="get" onclick="return(false);">get</button>
    <button id="post" onclick="return(false);">post</button>
</body>

2012 年 3 月更新

看起来像即将推出的 Microsoft WebAPI 将序列化为 ISO8601 感谢 Scott Hanselman 和 詹姆斯·牛顿-金

Given a simple round tripping scenario, how can I return JSON data to a browser and then accept updates from the browser via JSON that ModelBinds to a type w/ 3 properties: Int32, DateTime, TimeSpan?

Server Code (Controller)

    public class Product
    {
        public int Id { get; set; }
        public DateTime Start { get; set; }
        public TimeSpan Duration { get; set; }
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public JsonResult data()
    {
        return Json(
           new Product {
               Id = 1, Start = DateTime.Now, 
               Duration = TimeSpan.FromMinutes(30)}
           , JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public void data(Product product)
    {
        //product is not bound; modelbinder fails on DateTime and TimeSpan
        Console.WriteLine("Data: " + product);
    }

Errors from Immediate Window

ModelState["Start"].Errors[0]
{System.Web.Mvc.ModelError}
    ErrorMessage: "The value '/Date(1302295231115)/' is not valid for Start."
    Exception: null

ModelState["Duration"].Errors[0]
{System.Web.Mvc.ModelError}
    ErrorMessage: "The Duration field is required."
    Exception: null

Client Code (getData and changeData are bound to 2 different buttons)

<script type='text/javascript'>
    var myData;
    function getData(event)
    {
        $.getJSON('/home/data', function (data)
        {
            myData=data;
            console.dir(data);                
        });
    }

    function changeData(event)
    {
        var postData = JSON.stringify(myData);

        $.ajax({
            url: '/home/data',
            type: "POST",
            data: postData,
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function () {
                console.log('success!');
            },
            error: function () {
                console.log('fail!');
            }
            });
    }

    $(document).ready(function ()
    {
        $('#get').click(getData);
        $('#post').click(changeData);
    }
</script>

<body>
    <button id="get" onclick="return(false);">get</button>
    <button id="post" onclick="return(false);">post</button>
</body>

Update March 2012

Looks like the upcoming Microsoft WebAPI will serialize to ISO8601 thanks to Scott Hanselman and James Newton-King

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是有多爱你 2024-11-07 09:53:54

处理日期的方式存在问题。 JavaScriptSerializer 使用以下格式:处理日期: /Date(1302296382818)/ 不幸的是,在解析 GET JSON 响应时,这对 jQuery 来说没有什么意义,因此您在客户端得不到真正的日期,而是字符串。因此,您需要一个无耻的黑客才能将此字符串转换为真实的日期:

myData.Start = new Date(parseInt(data.Start.substr(6)));

这是黑客的完整故事:

模型:

public class Product
{
    public int Id { get; set; }
    public DateTime Start { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Data()
    {
        var product = new Product
        {
            Id = 1,
            Start = DateTime.Now,
        };
        return Json(product, JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public ActionResult Data(Product product)
    {
        return Json(product);
    }
}

视图:

<script type="text/javascript">
    var myData;

    function getData(event) {
        $.getJSON('/home/data', function (data) {
            myData = data;
            myData.Start = new Date(parseInt(data.Start.substr(6)));
        });
        return false;
    }

    function changeData(event)
    {
        var postData = JSON.stringify(myData);

        $.ajax({
            url: '/home/data',
            type: 'POST',
            data: postData,
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            success: function (result) {
                console.log(result);
            }
        });

        return false;
    }

    $(function () {
        $('#get').click(getData);
        $('#post').click(changeData);
    });
</script>

<button id="get">get</button>
<button id="post">post</button>

TimeSpan 案例留给读者作为练习这将需要另一个无耻的黑客,我厌倦了黑客:-)

There's an issue with the way dates are handled. The JavaScriptSerializer uses the following format when dealing with dates: /Date(1302296382818)/ which unfortunately makes little sense to jQuery when parsing the GET JSON response so you don't get a real date on the client side but string. So you need a shameless hack in order to convert this string to a real date:

myData.Start = new Date(parseInt(data.Start.substr(6)));

And here's the full story of the hack:

Model:

public class Product
{
    public int Id { get; set; }
    public DateTime Start { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Data()
    {
        var product = new Product
        {
            Id = 1,
            Start = DateTime.Now,
        };
        return Json(product, JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public ActionResult Data(Product product)
    {
        return Json(product);
    }
}

View:

<script type="text/javascript">
    var myData;

    function getData(event) {
        $.getJSON('/home/data', function (data) {
            myData = data;
            myData.Start = new Date(parseInt(data.Start.substr(6)));
        });
        return false;
    }

    function changeData(event)
    {
        var postData = JSON.stringify(myData);

        $.ajax({
            url: '/home/data',
            type: 'POST',
            data: postData,
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            success: function (result) {
                console.log(result);
            }
        });

        return false;
    }

    $(function () {
        $('#get').click(getData);
        $('#post').click(changeData);
    });
</script>

<button id="get">get</button>
<button id="post">post</button>

Leaving the TimeSpan case as an exercise to the reader as it will require another shameless hack and I am tired of hacks :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文