2012-03-26 2 views
2

Я пытаюсь обновить магистральную модель, на стороне сервера asp.net MVC 4. Я получаю:Backbonejs обновление модели с idAttribute установлен Id

«System.ArgumentException: элемент с тот же ключ уже добавлен "исключение.

Причина в том, что позвоночник посылает Id и идентификатор на сервер в качестве свойств, а JsonValueProvider пытается добавить это в словарь.

Вот моя модель:

var Task = Backbone.Model.extend({ 
     url: "/tasks/task", 
     idAttribute: "Id" 
}); 

Это отправить на сервер по запросу Пут:

{"Id":294912,"Task":"test","DueDate":"2012-03-24T02:00:00.000Z", "id":294912} 

Есть ли способ предотвратить позвоночник, послав свойство «ID»?

+0

Какой у вас код, «обновляющий» модель? Вы уверены, что не пытаетесь создать модель, которая уже существует? –

+0

Довольно точно. Проблема связана с JsonValueProvider – adriaanp

+0

, что произойдет, если вы установите 'idAttribute' в' 'id" 'вместо этого? Дублировать или они сливаются (я думаю, что они объединены)? – jgauffin

ответ

3

Проблема здесь в том, что соглашения в C# не то же самое, что и в JavaScript. В классах C# есть свойства, начинающиеся с заглавных букв (Pascal Case), и в JavaScript для нормальной работы в нижнем регистре (Camel Case) является нормой.

Таким образом, при сериализации моделей просмотра поведение по умолчанию для сериализатора JSON.NET заключается в сериализации объекта точно с той же капитализацией свойств. Я мог бы переименовать свойства в модели вида, чтобы быть верблюжьим футляром, но это было бы «странно», поскольку у вас есть свойства с паскалем в ваших объектах JavaScript.

Таким образом, вместо того чтобы принудительно использовать Магистральную сеть, я меняю сериализацию объектов, чтобы преобразовать свойства корпуса Pascal в свойства корпуса Camel, используя функциональность JSON.NET's Contract Resolver.

var settings = new JsonSerializerSettings(); 
settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
JsonSerializer serializer = JsonSerializer.Create(settings); 

JsonConvert.SerializeObject(object, Formatting.None, settings); 

Теперь это создает согласованность на стороне клиента с моим кодом и со всеми классными библиотеками.

0

Звучит так, как будто проблема связана с вашим серверным кодом, а не с вызовом от базовой линии. A PUT - операция редактирования на сервере, поэтому вы обновляете существующий объект. Для идентификации модели на сервере и изменения свойств, которые были изменены, требуется свойство ID.

Если ASP.NET MVC жалуется, что модель уже существует в базе данных, вы пытаетесь сделать INSERT вместо UPDATE. Нам нужно будет увидеть контроллер и код доступа к данным, чтобы увидеть, где все происходит.

ОБНОВЛЕНИЕ: Что произойдет, если вы оставите имущество idAttribute? Из документации Backbone:

A special property of models, the id is an arbitrary string (integer id or UUID). 
If you set the id in the attributes hash, it will be copied onto the model as a 
direct property. 

Атрибут id должен быть отправлен по умолчанию; похоже, вы заставляете его быть включенным во второй раз.

Под idAttribute в документации:

A model's unique identifier is stored under the id attribute. If you're directly communicating 
with a backend (CouchDB, MongoDB) that uses a different unique key, you may set a Model's 
idAttribute to transparently map from that key to id. 

модель ASP.NET MVC в связывании должны быть в состоянии справиться с id VS. Id.

ОБНОВЛЕНИЕ: Нашел хороший blog post, который описывает использование модели представления, чтобы помочь в сериализации ваших объектов C# в формате, который ожидает Магистраль. Это кажется разумным, если немного раздражающим, решением.

+0

Действие еще не выполняется и база данных. Проблема с JsonValueProvider, обновила вопрос, чтобы это отразить. – adriaanp

+0

Обновлен мой ответ. –

+0

Шаблоны представлений ASP.NET MVC сериализуются для клиента с свойством «Id», если я не устанавливаю idAttribute, тогда мои базовые модели не имеют свойства «id», поэтому я использую idAttribute. Привязка модели ASP.NET MVC не чувствительна к регистру, выглядит так, поэтому теперь мои базовые модели имеют свойство «Id» и «id», которое отправляется на сервер, когда я делаю Model.save() – adriaanp

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