ASP.NET MVC3 JSON Привязка модели с вложенным классом - PullRequest
14 голосов
/ 03 июля 2011

В 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
    }

Я что-то здесь упускаю или новая функция автоматической привязки поддерживает только примитивные объекты?

Ответы [ 2 ]

19 голосов
/ 04 июля 2011

Да, вы можете связывать сложные объекты json с ASP.NET MVC3.

Фил Хаак написал об этом недавно .
У вас проблема с вашим классом Geo здесь.
Не используйте обнуляемые свойства:

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);
    }
0 голосов
/ 03 октября 2013

У меня возникла та же проблема, однако в моем случае это было связано с тем, как данные передавались со стороны клиента. Убедитесь, что в запросе AJAX используются правильные заголовки и форматирование. Например:

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