Aru*_*run 5 .net odata asp.net-web-api asp.net-core
我已经在https://github.com/OData/ODataSamples/tree/master/WebApi/v4/DynamicEdmModelCreation看到了动态 Odata 路由和模型生成的示例。
我需要同样的点网核心,但由于 Asp.net 和 Asp.net 核心在类/路由等方面有所不同。我无法将此代码转换为点网核心。
有人可以提供一些指导吗?
我的 Startup.cs 配置方法有这个 -
IEdmModel model = this.GetEdmModel(app.ApplicationServices);
IList<IODataRoutingConvention> routingConventions = new List<IODataRoutingConvention>();
routingConventions.Insert(0, new MatchAllRoutingConvention());
app.UseMvc(routeBuilder => routeBuilder.MapODataServiceRoute("odata", "odata", model, new CustomPathHandler(), routingConventions));
Run Code Online (Sandbox Code Playgroud)
CustomPathHandler.cs -
public class CustomPathHandler : DefaultODataPathHandler
{
public override ODataPath Parse(string serviceRoot, string odataPath, IServiceProvider requestContainer)
{
var path = base.Parse(serviceRoot, odataPath, requestContainer);
return path;
}
public override string Link(ODataPath path)
{
return base.Link(path);
}
}
Run Code Online (Sandbox Code Playgroud)
ODataEndpointController.cs -
public class ODataEndpointController : ODataController
{
[EnableQuery]
[ODataRoute]
public EdmEntityObjectCollection Get()
{
// Get entity set's EDM type: A collection type.
ODataPath path = Request.ODataFeature().Path;
IEdmCollectionType collectionType = (IEdmCollectionType)path.EdmType;
IEdmEntityTypeReference entityType = collectionType.ElementType.AsEntity();
// Create an untyped collection with the EDM collection type.
EdmEntityObjectCollection collection =
new EdmEntityObjectCollection(new EdmCollectionTypeReference(collectionType));
// Add untyped objects to collection.
DataSourceProvider.Get(entityType, collection);
return collection;
}
Run Code Online (Sandbox Code Playgroud)
MatchAllRoutingConvention.cs
public class MatchAllRoutingConvention : IODataRoutingConvention
{
public IEnumerable<ControllerActionDescriptor> SelectAction(RouteContext routeContext)
{
ControllerActionDescriptor test = new ControllerActionDescriptor();
test.ControllerName = "ODataEndpoint";
return new List<ControllerActionDescriptor> { test }.AsEnumerable();
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么吗?当我尝试点击http://localhost:port/odata/Products 时,我得到一些source is null错误
编辑(1 月 15 日):
如下修改 MatchAllRoutingConvention 会根据需要重定向路由,但任何 $metadata 请求(抛出异常)也是如此。并且 $filter 查询也不起作用。因此,任何指示/提示都会有所帮助-
public class MatchAllRoutingConvention : IODataRoutingConvention
{
public IEnumerable<ControllerActionDescriptor> SelectAction(RouteContext routeContext)
{
ControllerActionDescriptor odataControllerDescriptor = new ControllerActionDescriptor
{
ControllerName = "ODataEndpoint",
ActionName = "Get",
Parameters = new List<ParameterDescriptor>(),
FilterDescriptors = new List<FilterDescriptor>(),
BoundProperties = new List<ParameterDescriptor>(),
MethodInfo = typeof(ODataEndpointController).GetMethod("Get"),
ControllerTypeInfo = typeof(ODataEndpointController).GetTypeInfo()
};
return new List<ControllerActionDescriptor> { odataControllerDescriptor };
}
}
Run Code Online (Sandbox Code Playgroud)
由于我还没有看到任何回复,因此将其发布为答案,希望这会对某人有所帮助。我修改了 MatchAllRoutingConvention 类如下 -
public class MatchAllRoutingConvention : IODataRoutingConvention
{
public IEnumerable<ControllerActionDescriptor> SelectAction(RouteContext routeContext)
{
if (routeContext.RouteData.Values["odataPath"] == null ||
routeContext.RouteData.Values["odataPath"].ToString() == "$metadata")
return new MetadataRoutingConvention().SelectAction(routeContext);
IActionDescriptorCollectionProvider actionCollectionProvider =
routeContext.HttpContext.RequestServices.GetRequiredService<IActionDescriptorCollectionProvider>();
IEnumerable<ControllerActionDescriptor> actionDescriptors = actionCollectionProvider
.ActionDescriptors.Items.OfType<ControllerActionDescriptor>()
.Where(c => c.ControllerName == "ODataEndpoint");
return actionDescriptors;
}
}
Run Code Online (Sandbox Code Playgroud)
这可以正确服务元数据请求以及简单的实体请求。然而,这不会响应 $filter、$select 等。据我了解,ODataQueryOptions 类用于应用 OData 过滤等,但它们不适用于非 CLR 类。所以不确定这个问题是否有解决方案。
[编辑] 所以我设法解决了这个过滤问题。有一个库LinqToQueryString可以应用于 IQueryable,显然不是 EdmEntityObjectCollection(这并不容易)。
我首先将数据加载到字典中,他们的网站上有一个示例可以做到这一点。首先在该字典上应用 OData 查询选项字符串,然后将筛选结果加载到我的实体中,然后加载到 EdmEntityObjectCollection 中
var list = new List<IEdmEntityObject>();
var dataList = new List<Dictionary<string, object>>();
// Load data in Dictionary
foreach (var item in data)
{
var dataItem = new Dictionary<string, object>();
// Load data
dataList.Add(dataItem);
}
var filteredDataList = dataList.AsQueryable().LinqToQuerystring(oDataQuery);
// Now add filtered/sorted etc data in EdmEntityObject
foreach (var item in filteredDataList)
{
var entity = new EdmEntityObject(entityType);
foreach (var key in item.Keys)
entity.TrySetPropertyValue(key, item[key].ToString());
list.Add(entity);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3398 次 |
| 最近记录: |