ASP.NET MVC3 JSON 模型与嵌套类的绑定

发布于 2024-11-18 15:50:28 字数 1137 浏览 5 评论 0原文

在MVC3中,如果模型有嵌套对象,是否可以自动将javascript对象绑定到模型?我的模型如下所示:

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

当我将以下 JSON 发布到我的控制器时,除“坐标”之外的所有内容都会成功绑定:

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

这就是我的控制器操作的样子:

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

我是否在这里遗漏了某些内容,或者新的自动绑定功能是否仅支持原始对象?

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?

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

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

发布评论

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

评论(2

善良天后 2024-11-25 15:50:28

是的,您可以使用 ASP.NET MVC3 绑定复杂的 json 对象。

Phil Haack 写了关于它 最近
您的 Geo 类有问题。
不要使用可为 null 的属性:

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

这是我用来测试它的 javascript 代码:

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

更新

我尝试使用模型绑定程序进行一些实验,并且得出了这个似乎有效的解决方案正确地使用可空类型。

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

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

并且我已经为所有类型的推文注册了它:

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

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

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

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);
    }
春夜浅 2024-11-25 15:50:28

我遇到了同样的问题,但就我而言,这与数据从客户端传输的方式有关。确保 AJAX 请求使用正确的标头和格式。例如:

    dataType: 'json',
    contentType: 'application/json; charset=UTF-8',
    data: JSON.stringify({
        MemberId : '123',
        UserName: '456',
        Parameters: [
            { Value : 'testing' },
            { Value : 'test2' }
        ]
    }),

I experienced the same issue, however in my case this was related to how the data was being transmitted from client side. Make sure the AJAX request is using the proper headers and formatting. For example:

    dataType: 'json',
    contentType: 'application/json; charset=UTF-8',
    data: JSON.stringify({
        MemberId : '123',
        UserName: '456',
        Parameters: [
            { Value : 'testing' },
            { Value : 'test2' }
        ]
    }),
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文