与嵌套类ASP.NET MVC3 JSON模式结合 [英] ASP.NET MVC3 JSON Model-binding with nested class

查看:125
本文介绍了与嵌套类ASP.NET MVC3 JSON模式结合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在MVC3,是有可能,如果模型嵌套对象的JavaScript对象自动绑定到款?我的模型是这样的:

 公共类分享Tweet
 {
    公开资料Tweet()
    {
         坐标=新的地缘();
    }
    公共字符串ID {搞定;组; }
    公共字符串用户{搞定;组; }
    公众的DateTime创建{搞定;组; }
    公共字符串文本{搞定;组; }
    公共地理坐标{搞定;组; }}公共类地理{    公共地理位置(){}    公共地理(双?纬度,双?LNG)
    {
        this.Latitude =纬度;
        this.Longitude = LNG;
    }    公共双?纬度{搞定;组; }
    公共双?经度{搞定;组; }    公共BOOL的HasValue
    {
        得到
        {
            回报(纬度= NULL ||经度!= NULL!);
        }
    }
}

当我发布以下JSON到我的控制器一切,除了坐标成功绑定:

<$p$p><$c$c>{\"Text\":\"test\",\"Id\":\"testid\",\"User\":\"testuser\",\"Created\":\"\",\"Coordinates\":{\"Latitude\":57.69679752892457,\"Longitude\":11.982091465576104}}

这是我的控制器操作如下:

  [HttpPost]
    公共JsonResult锐推(唧啾)
    {
        //做一些东西
    }

我失去了一些东西在这里还是新的自动绑定功能只支持原始的对象?


解决方案

是的,你可以绑定ASP.NET MVC3复杂的JSON对象。

菲尔哈克写了一篇关于它的recently.

你在这里得到了与你的地理类的问题。结果
不要使用可空属性:

 公共类地理
{    公共地理位置(){}    公共地理(双纬度,双LNG)
    {
        this.Latitude =纬度;
        this.Longitude = LNG;
    }    公共双纬度{搞定;组; }
    公共双经度{搞定;组; }    公共BOOL的HasValue
    {
        得到
        {
            回报(纬度= NULL ||经度!= NULL!);
        }
    }
}

这是JavaScript code我已经使用来测试它:

  VAR jsonData = {文:测试,ID:testid,用户:testuser的,创建:,坐标 :{纵横:57.69679752892457,经度:11.982091465576104}};
VAR鸣叫= JSON.stringify(jsonData);
$阿贾克斯({
    输入:POST,
    网址:家庭/索引,
    数据:鸣叫,
    成功:函数(){
        警报(OK);
    },
    数据类型:JSON,
    的contentType:应用/ JSON的;字符集= UTF-8
});

更新

我试着做一些实验与模型粘结剂和我来到了这个解决方案,这似乎与空类型正常工作。

我创建了一个自定义的模型绑定:

 使用系统;
使用System.Web.Mvc;
使用System.IO;
使用System.Web.Script.Serialization;公共类TweetModelBinder:IModelBinder
{
    公共对象BindModel(ControllerContext controllerContext,ModelBindingContext的BindingContext)
    {
        VAR的contentType = controllerContext.HttpContext.Request.ContentType;
        如果(!contentType.StartsWith(应用/ JSON,StringComparison.OrdinalIgnoreCase))
            回报(NULL);        串bodyText的;        使用(VAR流= controllerContext.HttpContext.Request.InputStream)
        {
            stream.Seek(0,SeekOrigin.Begin);
            使用(VAR读者=新的StreamReader(流))
                bodyText的= reader.ReadToEnd();
        }        如果(string.IsNullOrEmpty(bodyText的))回报(NULL);        。VAR鸣叫=新的JavaScriptSerializer()反序列化&LT; Models.Tweet&GT;(bodyText的);        返回(鸣叫);
    }
}

和我已经把它注册为各类鸣叫:

 保护无效的Application_Start()
    {
        AreaRegistration.RegisterAllAreas();        ModelBinders.Binders.Add(typeof运算(Models.Tweet),新TweetModelBinder());        RegisterGlobalFilters(GlobalFilters.Filters);
        的RegisterRoutes(RouteTable.Routes);
    }

In MVC3, is it possible to automatically bind javascript objects to models if the model has nested objects? My model looks like this:

 public class Tweet
 {
    public Tweet()
    {
         Coordinates = new Geo();
    }
    public string Id { get; set; }
    public string User { get; set; }
    public DateTime Created { get; set; }
    public string Text { get; set; }
    public Geo Coordinates { get; set; } 

}

public class Geo {

    public Geo(){}

    public Geo(double? lat, double? lng)
    {
        this.Latitude = lat;
        this.Longitude = lng;
    }

    public double? Latitude { get; set; }
    public double? Longitude { get; set; }

    public bool HasValue
    {
        get
        {
            return (Latitude != null || Longitude != null);
        }
    }
}

When I post the following JSON to my controller everything except "Coordinates" binds successfully:

{"Text":"test","Id":"testid","User":"testuser","Created":"","Coordinates":{"Latitude":57.69679752892457,"Longitude":11.982091465576104}}

This is what my controller action looks like:

    [HttpPost]
    public JsonResult ReTweet(Tweet tweet)
    {
        //do some stuff
    }

Am I missing something here or does the new auto-binding feature only support primitive objects?

解决方案

Yes, you can bind complex json objects with ASP.NET MVC3.

Phil Haack wrote about it recently.
You've got a problem with your Geo class here.
Don't use nullable properties:

public class Geo
{

    public Geo() { }

    public Geo(double lat, double lng)
    {
        this.Latitude = lat;
        this.Longitude = lng;
    }

    public double Latitude { get; set; }
    public double Longitude { get; set; }

    public bool HasValue
    {
        get
        {
            return (Latitude != null || Longitude != null);
        }
    }
}

This is the javascript code I've use to test it:

var jsonData = { "Text": "test", "Id": "testid", "User": "testuser", "Created": "", "Coordinates": { "Latitude": 57.69679752892457, "Longitude": 11.982091465576104} };
var tweet = JSON.stringify(jsonData);
$.ajax({
    type: 'POST',
    url: 'Home/Index',
    data: tweet,
    success: function () {
        alert("Ok");
    },
    dataType: 'json',
    contentType: 'application/json; charset=utf-8'
});

UPDATE

I've tried to do some experiments with model binders and I came out with this solutions which seems to work properly with nullable types.

I've created a custom model binder:

using System;
using System.Web.Mvc;
using System.IO;
using System.Web.Script.Serialization;

public class TweetModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var contentType = controllerContext.HttpContext.Request.ContentType;
        if (!contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            return (null);

        string bodyText;

        using (var stream = controllerContext.HttpContext.Request.InputStream)
        {
            stream.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(stream))
                bodyText = reader.ReadToEnd();
        }

        if (string.IsNullOrEmpty(bodyText)) return (null);

        var tweet = new JavaScriptSerializer().Deserialize<Models.Tweet>(bodyText);

        return (tweet);
    }
}

and I've registered it for all types tweet:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        ModelBinders.Binders.Add(typeof(Models.Tweet), new TweetModelBinder());

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

这篇关于与嵌套类ASP.NET MVC3 JSON模式结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆