2016-08-17 40 views
0

我正在尝试使用ASP.Net OData v4(例如ODataController)来允许访问键是字符串的位置。 95%的示例使用整数作为关键字,我发现的几篇文章讨论使用字符串作为关键字的步骤对我来说并不合适。ASP.Net使用字符串键的OData

在任何情况下,我想用下面的URL来访问我的资源:

/API/ContactTypes(“局”)

乐观,我开始从只是改变了密钥的类型int to key:

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/这基本上是说你有一个显式路由来装点Get方法:

[ODataRoute("({key})")] 
public SingleResult<ContactType> Get([FromODataUri] string key) 

如果我这样做,独自一人,不过,我得到“的路径模板'({key})'在控制器'GetType'中的操作'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应该是混乱。我的控制器名称已经遵循惯例,并且我没有Web 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() 
     ); 
    } 

回答

1

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作为键,但你想使用字符串作为另一个键,那么你应该尝试这个功能:http://odata.github.io/WebApi/#04-17-Alternate-Key,你可以打电话,如: localhost\api\Products(StringKey='test')

+0

是的,好吧,就这样。我实际上有一个名为ContactTypeId的属性,还有一个名为ContactTypeKey的属性(在我们的数据库中,它们都是唯一的)。出于性能原因,表格上的实际主键是ContactTypeId。我不得不将Key属性添加到ContactTypeKey属性中,以使OData识别应该用作其用途的关键点,但这会混淆实体框架,因此最终还要添加以下代码以覆盖其关键数据注释用途:modelBuilder.Entity ().HasKey(p => p.ContactTypeID) –