Какова правильная модель для связывания этого сложного вложенного JSON - PullRequest
1 голос
/ 07 декабря 2011

Я целый день пытался построить модель в asp.net mvc3 для обработки этого поста json. Я просмотрел большую часть сообщения stackoverflow'а, но все еще не смог его построить. Данные JSON как показано ниже

{"form":[{
          "ora1":{"start":"08:00:00","end":"08:50:00"},
          "ora2":{"start":"09:00:00","end":"09:50:00"},
          "ora3":{"start":"10:00:00","end":"10:50:00"},            
          "...":{"start":"12:10:00","end":"13:00:00"},
          "oran":{"start":"12:10:00","end":"13:00:00"}
         }]}

или даже

 {"form":
    {"Monday":
          {
             "ora1":{"start":"08:00:00","end":"08:50:00"},
             "ora2":{"start":"09:00:00","end":"09:50:00"},
             "ora3":{"start":"10:00:00","end":"10:50:00"},
             "....":{"start":"11:10:00","end":"12:00:00"},
             "oran":{"start":"12:10:00","end":"13:00:00"}
            }
     },
     {"Tuesday":
          {
             "ora1":{"start":"08:00:00","end":"08:50:00"},
             "ora2":{"start":"09:00:00","end":"09:50:00"},
             "ora3":{"start":"10:00:00","end":"10:50:00"},
             "....":{"start":"11:10:00","end":"12:00:00"},
             "oran":{"start":"12:10:00","end":"13:00:00"}
            }
     }
}

Любая помощь будет оценена. Спасибо dynamicus

Ответы [ 2 ]

2 голосов
/ 08 декабря 2011

Мне было любопытно посмотреть, смогу ли я получить механизм связывания пользовательских моделей для вашего сценария.Ниже приведен очень грубый пример, который работает с вашими входящими данными.Обратите внимание, что он нуждается в значительном улучшении, но связывание успешно:

С учетом следующих моделей просмотра:

public class OraFormData
{
    public IDictionary<string, Duration> form { get; set; }
}

public class Duration
{
    public string Start { get; set; }
    public string End { get; set; }
}

Использование этой привязки пользовательской модели:

public class OraFormDataModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        const string FORMKEY = "form[0][{0}][{1}]";
        const string PREFIX = "form[0][";

        try
        {
            var form = controllerContext.HttpContext.Request.Form;

            var vm = new OraFormData();

            var oraKeys = (from mainKey in form.AllKeys
                           where mainKey.StartsWith(PREFIX)
                           let trimmedKey = mainKey.Replace(PREFIX, String.Empty)
                           select trimmedKey.Substring(0, trimmedKey.IndexOf(']'))).Distinct().ToList();

            vm.form = new Dictionary<string, Duration>(oraKeys.Count);
            foreach (var oraKey in oraKeys)
            {
                vm.form.Add(oraKey, new Duration
                                        {
                                            Start = form[string.Format(FORMKEY, oraKey, "start")],
                                            End = form[string.Format(FORMKEY, oraKey, "end")]
                                        });
            }

            return vm;
        }
        catch
        {
            return null;
        }
    }
}

действие связывается при использовании строки из вашего первого примера:

[HttpPost]
public ActionResult TestPost([ModelBinder(typeof(OraFormDataModelBinder))]OraFormData form)
{
    // added modelbinder here just for example, could move to global.asax
    return Json(...);
}
1 голос
/ 07 декабря 2011

Согласно ответам в этой публикации , привязка к объекту Dictionary, как вы обрисовали, изначально не поддерживается. Однако один из ответов на тот же вопрос, очевидно, создал пользовательский ModelBinder для достижения желаемого результата.

Если вы имеете больший контроль над входящими данными JSON, вы можете сделать что-то вроде этого:

public class OraViewModel
{
    public IList<LineItem> LineItems { get; set; }
}

public class LineItem
{
    public string Name { get; set; }
    public Duration Duration { get; set; }
}

public class Duration
{
    public string Start { get; set; }
    public string End { get; set; }
}

Тогда, с вашей точки зрения, вы должны написать так:

$('#buttonId').click(function () {

    var data = { LineItems: [{ Name: "name 0", Duration: { Start: "start 0", End: "end 0"} }, { Name: "name 1", Duration: { Start: "start 1", End: "end 1"} }, { Name: "name 2", Duration: { Start: "start 2", End: "end 2"} }, { Name: "name 3", Duration: { Start: "start 3", End: "end 3"} }, { Name: "name 4", Duration: { Start: "start 4", End: "end 4"}}] };

    $.ajax({
        url: "/home/testpost2",
        data: JSON.stringify(data),  //*** using JSON2.js to stringify the js object
        type: "POST",
        contentType: 'application/json',   // *** note the content type is set to json
        dataType: 'json',
    });
});

Это позволило следующему действию контроллера правильно связать входящие данные с моим объектом:

[HttpPost]
public ActionResult TestPost2(OraViewModel data)
{
    return Json("whatever you want the return to be");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...