2016-08-17 5 views
0

Я пытаюсь использовать ASP.Net OData v4 (например, ODataController), чтобы разрешить доступ, где ключ является строкой. 95% примеров используют целое число в качестве ключа и пару сообщений, которые я нашел, которые обсуждают шаги по использованию строки, поскольку ключ не работает для меня.ASP.Net OData со строковыми ключами

Во всех случаях я пытаюсь получить доступ к своему ресурсу со следующим URL:

/апи/ContactTypes («Агентство»)

оптимистически, я начал с только изменяя тип ключа от int к ключу:

public SingleResult<ContactType> Get([FromODataUri] string key) 

Но я получаю ответ 404. Изменение URL-адреса на целое число/api/ContactTypes (1) «работает» тем, что оно направляется к правильному методу и что ключ является строковым типом, но, очевидно, это мне не помогает. Это сценарий, описанный в этом сообщении: How to get ASP.Net Web API and OData to bind a string value as a key?, за исключением того, что это сообщение подразумевает, что доступ к URL-адресу должен быть таким, каким я должен работать (а также для OData v3).

После дальнейших поисков, я нашел эту статью: https://blogs.msdn.microsoft.com/davidhardin/2014/12/17/web-api-odata-v4-lessons-learned/ которая в основном говорит, что вы должны украсить Получ с явной маршрутизации:

[ODataRoute("({key})")] 
public SingleResult<ContactType> Get([FromODataUri] string key) 

Если бы я сделать это в одиночку, хотя, я получаю «Путь template '({key})' в действии 'Get' в контроллере 'ContactTypes' не является допустимым шаблоном пути OData. Пустой сегмент встречается в URL-адресе запроса. Убедитесь, что указан правильный URL-адрес запроса. "

Комментарии в этом посте (https://damienbod.com/2014/06/16/web-api-and-odata-v4-crud-and-actions-part-3/) предполагают, что мне нужно, чтобы украсить контроллер с ODataRoutePrefix:

[ODataRoutePrefix("ContactTypes")] 
public class ContactTypesController : ODataController 

Это кажется нелогичным, так как я не имею ничего ASP.Net должно вводить в заблуждение. Мое имя контроллера уже соответствует соглашению, и у меня нет контроллеров веб-API, которые могут смутить его.

Несмотря на это, кажется, что «исправлена» проблема в том, что ошибка уходит, но затем я вернусь на квадрат (например, только целые значения могут быть переданы в URL-адресе).

Что мне не хватает?

Полный код контроллера:

[Authorize] 
[ODataRoutePrefix("ContactTypes")] 
public class ContactTypesController : ODataController 
{ 
    PolicyContext _Db; 

    public ContactTypesController(PolicyContext db) 
    { 
     if (db == null) 
      throw new ArgumentNullException("db"); 

     this._Db = db; 
    } 

    public ContactTypesController() : this(new PolicyContext()) 
    { 

    } 

    protected override void Dispose(bool disposing) 
    { 
     _Db.Dispose(); 

     base.Dispose(disposing); 
    } 

    [EnableQuery] 
    [ODataRoute()] 
    public IQueryable<ContactType> Get(ODataQueryOptions options) 
    { 
     return _Db.ContactType; 
    } 

    [EnableQuery] 
    [ODataRoute("({key})")] 
    public SingleResult<ContactType> Get([FromODataUri] string key) 
    { 
     IQueryable<ContactType> result = _Db.ContactType.Where(p => p.ContactTypeKey == key); 

     return SingleResult.Create(result); 
    } 

Полный WebApiConfig:

public static void Register(HttpConfiguration config) 
{ 
     // Web API configuration and services 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     builder.EntitySet<ContactType>("ContactTypes"); 

     config.MapODataServiceRoute(
      routeName: "ODataRoute", 
      routePrefix: "api", 
      model: builder.GetEdmModel() 
     ); 
    } 

ответ

1

1.Если в вашем EdmModel свойство строка является ключом, то ни ODataRoute не нужно, например:

public class Product 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
    public double Price { get; set; } 
} 

КонвенцияModelBuilder будет использовать свойство с именем «Id» в качестве ключа, или вы должны указать у это ключ, как:

public class Product 
{ 
    [Key] 
    public string StringKey { get; set; } 
    public string Name { get; set; } 
    public double Price { get; set; } 
} 

Тогда вызов как localhost\api\Products('test') должен просто пойти

public SingleResult<Product> GetProduct([FromODataUri]string key) 

2.Если у вас уже есть ключ int, но вы хотите использовать строку в качестве другого ключа, попробуйте эту функцию: http://odata.github.io/WebApi/#04-17-Alternate-Key, и вы можете позвонить по телефону: localhost\api\Products(StringKey='test')

+0

Да, хорошо, так оно и было. На самом деле у меня было свойство CallTypeId, а также свойство ContactTypeKey (в нашей базе данных оба уникальны). Фактический первичный ключ в таблице - ContactTypeId по соображениям производительности. Мне пришлось добавить атрибут Key к свойству ContactTypeKey, чтобы распознать OData, который должен использоваться в качестве ключа для его цели, но это путало Entity Framework, поэтому в итоге также добавлен следующий код для переопределения аннотации данных ключа для его назначение: modelBuilder.Entity () .HasKey (p => p.ContactTypeID) –

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