Asp.net web api ASP.NET WebApi2 OData使用斜杠处理查询/

Asp.net web api ASP.NET WebApi2 OData使用斜杠处理查询/,asp.net-web-api,asp.net-web-api2,odata,asp.net-web-api-routing,Asp.net Web Api,Asp.net Web Api2,Odata,Asp.net Web Api Routing,我制作了一个带有约定模型路由的“标准”WebAPI2OData项目。以下OData查询正在运行: /odata/Users /odata/Users(123) /odata/$metadata /odata/Users?$select=Username 所以,在我尝试这一点之前,一切似乎都很好,我认为这也是一个法律问题: /odata/Users(123)/Username Slash/in查询会破坏一切,它根本不会影响控制器类和OData身份验证流。在Microsoft ASP.NET ODa

我制作了一个带有约定模型路由的“标准”WebAPI2OData项目。以下OData查询正在运行:

/odata/Users

/odata/Users(123)

/odata/$metadata

/odata/Users?$select=Username

所以,在我尝试这一点之前,一切似乎都很好,我认为这也是一个法律问题:

/odata/Users(123)/Username


Slash/in查询会破坏一切,它根本不会影响控制器类和OData身份验证流。在Microsoft ASP.NET OData实现中是否应该支持这一点?或者,只有当我为每个属性(如Username)定义具有正确路由的显式方法时,才支持这种方法吗?有什么建议可以解决这个问题吗?我尝试过显式{*rest}路由等。

AFAIK,内置路由约定不包括用于属性访问的路由约定。您需要为每个属性访问添加许多操作

但是,基于此资源,添加自定义路由约定来处理属性访问路径模板并不困难:
~/entityset/key/property

这里有一个自定义路由约定,它是根据我上面共享的链接改编的

使用的程序集:Microsoft.AspNet.OData 7.4.1-该方法与您可能使用的任何其他OData Web API库相同

用于说明的类

公共类产品
{
[关键]
公共int Id{get;set;}
公共字符串名称{get;set;}
}
添加属性访问的路由约定

//使用
使用Microsoft.AspNet.OData.Routing;
使用Microsoft.AspNet.OData.Routing.Conventions;
使用制度;
使用System.Linq;
使用System.Web.Http.Controller;
// ...
公共类CustomPropertyRoutingConvention:NavigationSourceRoutingConvention
{
私有常量字符串ActionName=“GetProperty”;
公共重写字符串SelectAction(ODataPath ODataPath、HttpControllerContext controllerContext、ILookup actionMap)
{
如果(odataPath==null | | controllerContext==null | | actionMap==null)
{
返回null;
}
如果(odataPath.PathTemplate==“~/entityset/key/property”||
odataPath.PathTemplate==“~/entityset/key/cast/property”||
odataPath.PathTemplate==“~/singleton/property”||
odataPath.PathTemplate==“~/singleton/cast/property”)
{
var segment=odataPath.Segments.OfType().LastOrDefault();
如果(段!=null)
{
字符串actionName=FindMatchingAction(actionMap,actionName);
if(actionName!=null)
{
if(odataPath.PathTemplate.StartsWith(“~/entityset/key”,StringComparison.Ordinal))
{
var keySegment=odataPath.Segments.OfType().FirstOrDefault();
if(keySegment==null | |!keySegment.Keys.Any())
抛出新的InvalidOperationException(“此链接不包含密钥”);
controllerContext.RoutedData.Values[ODataRouteConstants.Key]=keySegment.Keys.First().Value;
}
controllerContext.RouteData.Values[“propertyName”]=segment.Property.Name;
返回actionName;
}
}
}
返回null;
}
公共静态字符串FindMatchingAction(ILookup actionMap,参数字符串[]targetActionNames)
{
foreach(targetActionName中的字符串targetActionName)
{
if(actionMap.Contains(targetActionName))
{
返回targetActionName;
}
}
返回null;
}
}
在控制器中添加单个方法以处理任何属性的请求

公共类产品控制器:ODataController
{
// ...
[HttpGet]
公共IHttpActionResult GetProperty(int键,字符串propertyName)
{
var product=_db.Products.FirstOrDefault(d=>d.Id.Equals(key));
如果(产品==null)
{
返回NotFound();
}
PropertyInfo=typeof(Product).GetProperty(propertyName);
对象值=信息获取值(产品);
返回Ok(value,value.GetType());
}
私有IHttpActionResult Ok(对象内容,类型)
{
var resultType=typeof(OkNegotiatedContentResult)。MakeGenericType(type);
将Activator.CreateInstance(resultType,content,this)作为IHttpActionResult返回;
}
// ...
}
在WebApiConfig.cs中(或配置服务的等效位置)

var modelBuilder=new ODataConventionModelBuilder();
modelBuilder.EntitySet(“产品”);
var routingConventions=ODataRoutingConventions.CreateDefaultWithAttributeRouting(“odata”,配置);
routingConventions.Insert(0,新的CustomPropertyRoutingConvention());
MapODataServiceRoute(“odata”、“odata”、modelBuilder.GetedModel()、新的DefaultODataPathHandler()、路由约定);
configuration.Count().Filter().OrderBy().Expand().Select().MaxTop(null);
configuration.ensureIninitialized();
请求名称属性:
/Products(1)/Name

请求Id属性:
/Products(1)/Id