2013-06-06 2 views
2

Мне удалось создать несколько сервисов Web Api OData только для чтения, следуя инструкциям здесь: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api. Поэтому я использую построитель ODataConventionModel для создания модели из набора объектов (кстати, из ORM Telerik). Все это работает нормально, и я могу с радостью вызывать запросы, просматривать метаданные и т. Д. На службе.Как использовать ключ сгенерированный базой данных в Web Api OData

Теперь я попытался обратить внимание на другие операции CRUD - сначала создайте и наткнулись на проблему! А именно, метод Post срабатывает правильно (CreateEntity), но параметр сущности равен null - делая проверку против ModelState.IsValid, он показывает, что проблема - это значение null ID (ключа). Это неудивительно, потому что база данных использует идентификатор базы данных для столбца ID, и поэтому идентификатор будет создан, когда объект будет сохранен в контексте базы данных.

Поэтому я пробовал всевозможные способы разметки столбца идентификатора в качестве базы данных, но ничего не нашел. Как ни странно, я не могу найти ни одного сообщения о том, что кто-то просит об этом - конечно, я не могу быть единственным!

Я заметил, что при взгляде на конструктор EF (например, здесь: http://forums.asp.net/t/1848984.aspx/1) существует средство воздействия на построитель модели с свойством .HasDatabaseGeneratedOption, но аналогичного варианта в System.Web.Http нет. Эквивалент OData.

Таким образом, вопросы, следовательно, являются:

  1. Есть ли средство изменения модели строителя (или что-то еще), так что контроллер будет принимать объект и десериализацию объекта даже с нулевым значением ключа?
  2. Если да, то как я могу это сделать?
  3. Если нет, то какие-либо предложения относительно других вариантов?

Я понимаю, что могу потенциально просто заполнить объект с помощью (в данном случае) целочисленного значения из клиентского запроса, но это кажется а) семантически неправильным и b) не обязательно будет всегда возможным в результате инструментария клиента, который может быть использован.

Вся помощь с благодарностью получена!

Большое спасибо,

J.

ответ

1

Вам нужно создать ViewModel для вставки, которая не содержит параметр ID. Используйте Automapper для сопоставления свойств входящей модели вставки в ваши объекты данных.

Проблема, с которой вы сталкиваетесь, заключается в том, что идентификатор является обязательным атрибутом в вашей модели данных, потому что это ваш ПК, за исключением вставки, где он не должен указываться.

+0

Спасибо за ваши мысли Эрик - это по-прежнему кажется обходным решением, а не решением для меня. Хотя я признаю, что это сработает, оно эффективно заставляет создавать другие методы, а не разрешать проблему с моделями OData, которые автоматически создаются ModelBuilder. Если я не понял ваш ответ, конечно .... – Jamie

+0

Не совсем обходной путь. Это вставка ViewModel и очень распространенная практика в мире MVC. Контроллер принимает значение InsertEntity и возвращает полное Entity или только идентификатор. Он заканчивается очень RESTful. –

0

В моем случае ключ, сгенерированный базой данных, является Guid.

Как рабочий обход, в моем клиентском коде TypeScript я отправляю (через http POST) объект с пустым гидом как это: Примечание: ErrorId является ключевым столбцом.

let elmahEntry: ELMAH_Error = { 
     Application: 'PTUnconvCost', 
     Host: this.serviceConfig.url, 
     Message: message, 
     User: that.userService.currentUserEmail, 
     AllXml: `<info><![CDATA[\r\n\r\n${JSON.stringify(info || {})}\r\n\r\n]]></info>`, 
     Sequence: 1, 
     Source: source, 
     StatusCode: 0, 
     TimeUtc: new Date(Date.now()), 
     Type: '', 
     ErrorId: '00000000-0000-0000-0000-000000000000' 
    }; 

Затем в мой контроллер WebAPI OData, я проверяю, если ключ является пустой справ, и если да, то я заменить его новым Guid, как это:

// POST: odata/ELMAH_Error 
    public IHttpActionResult Post(ELMAH_Error eLMAH_Error) 
    { 
     if (eLMAH_Error.ErrorId == Guid.Empty) 
     { 
      eLMAH_Error.ErrorId = Guid.NewGuid(); 
     } 

     if (!ModelState.IsValid) 
     { 
      return BadRequest(ModelState); 
     } 

     db.ELMAH_Error.Add(eLMAH_Error); 

     try 
     { 
      db.SaveChanges(); 
     } 
     catch (DbUpdateException) 
     { 
      if (ELMAH_ErrorExists(eLMAH_Error.ErrorId)) 
      { 
       return Conflict(); 
      } 
      else 
      { 
       throw; 
      } 
     } 

     return Created(eLMAH_Error); 
    } 
Смежные вопросы