Я изучаю, как использовать OData в ASP.Core.
Я создал BooksController
, подкласс из ODataController
, в рамках которого я определил два действия: Get()
и Get(int id)
.
/odata/books
разрешает первое действие, но /odata/books(1)
не находит второе действие.
Как только модели определены, он может найти следующий контроллер:
[ODataRoutePrefix("Books")]
public class BooksController : ODataController
{
private BookStoreContext _db;
public BooksController(BookStoreContext context)
{
_db = context;
}
[ODataRoute]
[EnableQuery]
public IActionResult Get()
{
return Ok(_db.Books);
}
[EnableQuery]
[ODataRoute("({key})")]
public IActionResult Get([FromODataUri] int key)
{
return Ok(_db.Books.FirstOrDefault(c => c.Id == key.ToGuid()));
}
}
На сайте действуют правила конвенции по умолчанию для всех маршрутов (см. Ниже).
Но я думаю, что это не в игре, поскольку BooksController
украшен [ODataRoutePrefix("Books")]
и действиями с [ODataRoute]
(и [EnableQuery]
) - которые, я думаю, будучи маршрутизацией на основе атрибутов, имеют приоритет (является ли это правильное предположение?).
Мои модели dto регистрируются с использованием Reflection ...), но ключевая часть - это когда Startup вызывает UseMvc(...)
и определяет маршруты, которые заканчиваются вызовом здесь:
private void CreateODataRoutes(IRouteBuilder routeBuilder)
{
// register the convention routes for MVC first...
routeBuilder.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
...
// then do the OData stuff...
routeBuilder.Count().Expand().Filter()
.MaxTop(100).OrderBy().Select();
// Use method further down the page
// to create a Build Model by reflection, using
// all OData Model definitions (ie, classes that implement
// IAllModulesOdataModelBuilderConfiguration)
var oDataConventionModelBuilder = BuildODataModelUsingReflectionAcrossAllAssemblies();
// Use the modelBuilder as the basis of defining routes:
RegisterRoutesToODataController(routeBuilder, oDataConventionModelBuilder);
}
Где BuildODataModelUsingReflectionAcrossAllAssemblies
использует отражение, чтобы найти отдельные определения модели, каждое из которых довольно просто, только определяя их идентификатор (полагаясь на соглашение для остальных).
Обратите внимание, что я не определяю действия, как это было принято условно (см. Ниже).
public class BookODataModelBuilderConfigurationBase<T> : IAllModulesOdataModelBuilderConfiguration
where T : class, IHasGuidId, new()
{
public virtual void Apply(ODataModelBuilder builder ...)
{
var _controllerName = this.GetControllerNameByConvention(typeof(Book));
var entity = builder.EntitySet<T>(this._controllerName).EntityType;
entity.HasKey(x => x.Id);
//Note...no Actions defined, as planning to rely on default conventions (routing by Verb to method starting with Get...)
}
}
Когда модель создана, она регистрируется следующим образом;
private void RegisterRoutesToODataController(IRouteBuilder routeBuilder,
ODataConventionModelBuilder oDataConventionModelBuilder)
{
string routePrefix = $"{App.Modules.Core.Shared.Constants.ModuleSpecific.Module.AssemblyNamePrefix}.";
// Build the Edm model used to parse commands:
var edmModel = oDataConventionModelBuilder.GetEdmModel();
// Register the Odata paths
routeBuilder.MapODataServiceRoute(
routeName: $"{routePrefix}odataDefault",
routePrefix: "odata",
edmModel,
pathHandler:new DefaultODataPathHandler(),
// By convention? So that Get verb goes to Get action, etc.
routingConventions: ODataRoutingConventions.CreateDefault()
);
}
Когда путь равен /odata/book(1)
, возвращается HTTP ERROR 404
, страница не существует.
Спасибо!
Другие вещи, которые я пробовал, включают:
- закомментировал конфигурацию SwaggerAPI
- Удалено
[FromODataUri]
на ключевом параметре (это необходимо?)
- Добавлено / удалено
[ODataRoute("({key})")]
- Зарегистрированный контроллер как
BooksController
во множественном числе / единственное число
- Изменил название действия на
GetBook
и снова на Get
- Добавлено / удалено
ODataRoutePrefix
- регистрация маршрутов OData перед регистрацией маршрутов соглашения по умолчанию (думаю, что так должно быть всегда, верно?).
- ... все это начинает больше походить на отчаяние, чем на кодирование :-( ...
- Все еще смотрю. Спасибо за любые рекомендации.