我正在尝试使用ASP.Net OData v4(例如ODataController)来允许访问密钥是字符串的位置。 95%的例子都使用整数作为键,我发现的几篇帖子讨论了使用字符串作为键的步骤对我来说并不适用。
在所有情况下,我都尝试使用以下网址访问我的资源:
/ API / ContactTypes('机构&#39)
乐观地说,我开始只是将键的类型从int更改为key:
public SingleResult<ContactType> Get([FromODataUri] string key)
但我收到了404回复。将URL更改为整数,/ api / ContactTypes(1)确实&#34;工作&#34;因为它路由到正确的方法,并且键是字符串类型,但显然,这对我没有帮助。这是本文中描述的场景: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/基本上说你必须使用显式路由来装饰Get方法:
[ODataRoute("({key})")]
public SingleResult<ContactType> Get([FromODataUri] string key)
如果我单独这样做,我会得到&#34;路径模板&#39;({key})&#39;关于行动&#39;获取&#39;在控制器&#39; ContactTypes&#39;不是有效的OData路径模板。请求URL中遇到空段。请确保指定了有效的请求网址。&#34;
这篇文章中的评论(https://damienbod.com/2014/06/16/web-api-and-odata-v4-crud-and-actions-part-3/)表明我需要用ODataRoutePrefix来装饰Controller:
[ODataRoutePrefix("ContactTypes")]
public class ContactTypesController : ODataController
这似乎违反直觉,因为我没有任何ASP.Net应该让人困惑。我的控制器名称已经遵循惯例,我没有可能让它混淆的Web API控制器。
无论如何,似乎&#34;修复&#34;错误消失的问题,但后来我回到了第一个方向(例如,只能在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()
);
}
答案 0 :(得分:6)
1.如果在EdmModel
中,字符串属性是键,则不需要ODataRoute,例如:
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
ConventionModelBuilder将使用名为“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作为键,但你想使用string作为另一个键,那么你应该尝试这个功能:http://odata.github.io/WebApi/#04-17-Alternate-Key,你可以这样调用:
localhost\api\Products(StringKey='test')