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