Подтвердить что ты не робот

В 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();
}
4b9b3361

Ответ 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();
        }