Да, вы можете связывать сложные объекты 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);
}