В ASP.NET MVC десериализуйте JSON до или в режиме действия контроллера
Я работаю над сайтом, который отправит объект JSON (используя метод JQuery Post) на сервер.
{
"ID" : 1,
"FullName" : {
"FirstName" : "John",
"LastName" : "Smith"
}
}
В то же время я написал классы на стороне сервера для этой структуры данных.
public class User
{
public int ID { get; set; }
public Name FullName { get; set;}
}
public class Name
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Когда я запускаю веб-сайт со следующим кодом в классе контроллера, свойство FullName не десериализуется. Что я делаю не так?
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Submit(User user)
{
// At this point, user.FullName is NULL.
return View();
}
Ответы
Ответ 1
Я решил проблему, выполнив фильтр действий; приведенный ниже пример кода. Из исследования я узнал, что существует другое решение, модельное связующее, как описано выше. Но я не знаю, какие плюсы и минусы делают в любом подходе.
Спасибо Steve Gentile сообщение в блоге для этого решения.
public class JsonFilter : ActionFilterAttribute
{
public string Parameter { get; set; }
public Type JsonDataType { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
{
string inputContent;
using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
{
inputContent = sr.ReadToEnd();
}
var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
filterContext.ActionParameters[Parameter] = result;
}
}
}
[AcceptVerbs(HttpVerbs.Post)]
[JsonFilter(Parameter="user", JsonDataType=typeof(User))]
public ActionResult Submit(User user)
{
// user object is deserialized properly prior to execution of Submit() function
return View();
}
Ответ 2
1.Создать настраиваемое связующее устройство
public class UserModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
User model;
if(controllerContext.RequestContext.HttpContext.Request.AcceptTypes.Contains("application/json"))
{
var serializer = new JavaScriptSerializer();
var form = controllerContext.RequestContext.HttpContext.Request.Form.ToString();
model = serializer.Deserialize<User>(HttpUtility.UrlDecode(form));
}
else
{
model = (User)ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext);
}
return model;
}
}
2. Связующее устройство модели 2.add в событии application_start
ModelBinders.Binders[typeof(User)] = new UserModelBinder();
3.use jQuery $.get/$. post в виде клиентского кода JavaScript.
<% using(Html.BeginForm("JsonData","Home",new{},FormMethod.Post, new{id="jsonform"})) { %>
<% = Html.TextArea("jsonarea","",new {id="jsonarea"}) %><br />
<input type="button" id="getjson" value="Get Json" />
<input type="button" id="postjson" value="Post Json" />
<% } %>
<script type="text/javascript">
$(function() {
$('#getjson').click(function() {
$.get($('#jsonform').attr('action'), function(data) {
$('#jsonarea').val(data);
});
});
$('#postjson').click(function() {
$.post($('#jsonform').attr('action'), $('#jsonarea').val(), function(data) {
alert("posted!");
},"json");
});
});
</script>
Ответ 3
Вы можете попробовать Json.NET. Документация довольно хороша, и она должна иметь возможность делать то, что вам нужно. Вы также захотите захватить JsonNetResult, поскольку он возвращает ActionResult, который может использоваться в приложении ASP.NET MVC. Он довольно прост в использовании.
Json.NET также хорошо работает с сериализацией Date. Подробнее о том, что можно найти здесь.
Надеюсь, что это поможет.
Ответ 4
Попробуйте это;
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Submit(FormCollection collection)
{
User submittedUser = JsonConvert.DeserializeObject<User>(collection["user"]);
return View();
}
Ответ 5
После некоторых исследований я нашел решение Takepara лучшим вариантом для замены десериализатора MVC JSON по умолчанию на Newtonsoft Json.NET. Он также может быть обобщен для всех типов в сборке следующим образом:
using Newtonsoft.Json;
namespace MySite.Web
{
public class MyModelBinder : IModelBinder
{
// make a new Json serializer
protected static JsonSerializer jsonSerializer = null;
static MyModelBinder()
{
JsonSerializerSettings settings = new JsonSerializerSettings();
// Set custom serialization settings.
settings.DateTimeZoneHandling= DateTimeZoneHandling.Utc;
jsonSerializer = JsonSerializer.Create(settings);
}
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
object model;
if (bindingContext.ModelType.Assembly == "MyDtoAssembly")
{
var s = controllerContext.RequestContext.HttpContext.Request.InputStream;
s.Seek(0, SeekOrigin.Begin);
using (var sw = new StreamReader(s))
{
model = jsonSerializer.Deserialize(sw, bindingContext.ModelType);
}
}
else
{
model = ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext);
}
return model;
}
}
}
Затем в Global.asax.cs
, Application_Start()
:
var asmDto = typeof(SomeDto).Assembly;
foreach (var t in asmDto.GetTypes())
{
ModelBinders.Binders[t] = new MyModelBinder();
}