2012-06-11 2 views
0

Я использую ASP.NET MVC2 и jQuery для загрузки и сохранения объектов. Я использую серилизацию/десериализацию объектов knockout.js, чтобы безопасно поддерживать структуру данных объекта при загрузке/сохранении данных.jQuery JSON сохранить объект в ASP.NET MVC2

Когда я возвращаю свой объект в его точную структуру обратно на сервер, используя следующий метод JavaScript, на стороне сервера в ASP.NET, мой объект GraduationClass получает экземпляр, но у него нет данных.

Я проверил данные сообщения в firebug, и все данные правильно отправляются обратно на сервер в запросе в правильной структуре, однако внутренний конвейер ASP.NET MVC не выполняет десериализацию данных обратно в Объект GraduationClass. Я пробовал это как с настройкой contentType, так и без него.

Мне интересно, что я делаю неправильно.

// javascript save method 
function save(graduationClass) { 
    $.ajax({ 
     url: "/SiteManagement/saveGraduationClass", 
     type: "POST", 
     // data: ko.mapping.toJSON(graduationClass), // (solution 1) 
     data: graduationClass, // (solution 2) 
     contentType: "application/json; charset=utf-8", 
     dataType: "json",    
     success: function(data) {    
    });  
} 

// both solutions result in a blank object construction on the server side 

// ASP.NET MVC2 AJAX method 
[HttpPost]    
public ActionResult saveGraduationClass(GraduationClass graduationClass) { 
    // graduationClass here has all default data rather than the data sent in the post 
    return Json(new { resultText = "success" }, JsonRequestBehavior.AllowGet); 
} 
+0

я фактически изменил запись в гораздо проще $ .post ("/ SiteManagement/saveGraduationClass", {graduationClass: graduationClass}, функция (данные) {// код здесь идет}); - и все равно получить тот же результат. –

ответ

1

Я считаю, что есть две возможные проблемы.

Во-первых, я уверен, что когда вы укажете, что вы отправляете JSON в запросе Ajax, jQuery будет сериализовать объекты Javascript, переданные в параметре данных. Вы определенно создаете объект jQuery с свойством json со значением строки (я считаю, что я не знаком с нокаутом). Значение, передаваемое MVC, будет выглядеть так:

{ 
    json : 'string of graduationClass data ' 
} 

Что представляет собой двойную сериализацию.

Вторая проблема заключается в том, что предыдущий JSON не соответствует вашему параметру метода saveGraduationClassgraduationClass.

Я думаю, что любой из этих решений должно работать:

data: ko.toJSON(graduationClass), // knockout.js utility method 

или

data: graduationClass, // let jQuery serialize the object. 

Update

Если у меня есть этот класс:

public class Person 
{ 
    public string Name { get; set; } 
} 

и у меня есть этот JSON:

{ 
    Name : 'Jon Doe' 
} 

тогда будет заселить этот метод:

public ActionResult SomeMethod(Person person) 

Однако следующий JSON не будет работать:

{ 
    json : '{ Name : "Jon Doe" }' 
} 

Он также не совпадают :

{ 
    json : 
    { 
    Name : 'Jon Doe' 
    } 
} 

макет JSON должен точно соответствовать макету класса, пытающегося быть заполненным.

+0

Я думаю, что это определенно в правильном направлении. Не имея выпускного класса, поскольку названный параметр казался ошибкой. Метод toJSON от Knockout.js выходит из дополнительных данных сопоставления, которые он помещает туда, поэтому мне нужно выяснить, смогу ли я его удалить. Будет ли сериализация в ASP.NET MVC работать, если объект не является точным совпадением? Или он будет игнорировать непризнанные поля? –

+0

Логика довольно проста, она должна соответствовать. –

+0

С ko.mapping.toJSON (graduationClass) у меня теперь точное соответствие по строкам ... Однако, хотя объект GraduationClass получает экземпляр, он по-прежнему имеет только значения данных по умолчанию. Я только что подтвердил, что json является ТОЧНЫМ совпадением загрузки и сохранения. –

1

Привет Я думаю, что эта проблема может быть по умолчанию JsonValueProvider на, но вы можете написать собственный менеджер:

public sealed class JsonDotNetValueProviderFactory : ValueProviderFactory 
    {   

     private static void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, object value) 
     { 
      IDictionary<string, object> d = value as IDictionary<string, object>; 
      if (d != null) 
      { 
       foreach (KeyValuePair<string, object> entry in d) 
       { 
        AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value); 
       } 
       return; 
      } 

      IList l = value as IList; 
      if (l != null) 
      { 
       for (int i = 0; i < l.Count; i++) 
       { 
        AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]); 
       } 
       return; 
      } 

      // primitive 
      backingStore[prefix] = value; 
     } 

     private static object GetDeserializedObject(ControllerContext controllerContext) 
     { 
      if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) 
      { 
       // not JSON request 
       return null; 
      } 

      StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream); 
      string bodyText = reader.ReadToEnd(); 
      if (String.IsNullOrEmpty(bodyText)) 
      { 
       // no JSON data 
       return null; 
      } 

      object jsonData = new JavaScriptSerializer().DeserializeObject(bodyText); 
      return jsonData; 
     } 

     public override IValueProvider GetValueProvider(ControllerContext controllerContext) 
     { 
      if (controllerContext == null) 
      { 
       throw new ArgumentNullException("controllerContext"); 
      } 

      object jsonData = GetDeserializedObject(controllerContext); 
      if (jsonData == null) 
      { 
       return null; 
      } 

      Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); 
      AddToBackingStore(backingStore, String.Empty, jsonData); 
      return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture); 
     } 

     private static string MakeArrayKey(string prefix, int index) 
     { 
      return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]"; 
     } 

     private static string MakePropertyKey(string prefix, string propertyName) 
     { 
      return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName; 
     } 


    } 

Затем добавить это в Application_Start в Global.asax:

ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault()); 
ValueProviderFactories.Factories.Add(new JsonDotNetValueProviderFactory()); 

В этом примере используется Json.NET

Также лучше использовать плагин ko.mapping ko.mapping, поскольку ваш выпускной класс может быть наблюдаемый объект:

var jsonModel = ko.mapping.toJSON(graduationClass); 

        $.ajax({ 
         url: '/SiteManagement/saveGraduationClass', 
         type: 'POST', 
         dataType: 'json', 
         data: jsonModel, 
         contentType: 'application/json; charset=utf-8', 
         success: function (data) { 
          // get the result and do some magic with it        
         } 
        }); 
+0

ko.mapping.toJSON (graduationClass) - это полезно. Однако по какой-то причине, пока объект не приходит в нуль (хорошо), он просто пропускает данные. –

+1

@AdamLevitt Вы пытались заменить поставщика стоимости? –

+0

Попытка этого теперь ... хотя кажется, что это ужасно большое обруч, чтобы проскочить. –

Смежные вопросы