带字符串键的ASP.Net OData

Pau*_*aag 3 asp.net odata

我正在尝试使用ASP.Net OData v4(例如ODataController)来允许访问密钥是字符串的位置.95%的例子使用整数作为键,我发现的几个帖子讨论了使用字符串作为键的步骤对我不起作用.

在所有情况下,我都尝试使用以下URL访问我的资源:

/ API/ContactTypes( '局')

乐观地说,我开始只是将键的类型从int更改为key:

public SingleResult<ContactType> Get([FromODataUri] string key)
Run Code Online (Sandbox Code Playgroud)

但是我得到了404响应.将URL更改为整数,/ api/ContactTypes(1)确实"工作",因为它路由到正确的方法,并且键是字符串类型,但显然,这对我没有帮助.这是本文中描述的场景:如何让ASP.Net Web API和OData将字符串值绑定为键?除了该帖子意味着以我应该的方式访问URL(也适用于OData v3).

经过进一步搜索,我发现了这篇文章:https://blogs.msdn.microsoft.com/davidhardin/2014/12/17/web-api-odata-v4-lessons-learned/这基本上说你必须装饰获取具有显式路由的方法:

[ODataRoute("({key})")]
public SingleResult<ContactType> Get([FromODataUri] string key)
Run Code Online (Sandbox Code Playgroud)

但是,如果我单独执行此操作,则在控制器"ContactTypes"中的"Get"操作中获取"路径模板"({key})'不是有效的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
Run Code Online (Sandbox Code Playgroud)

这似乎反直觉,因为我没有任何东西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);
    }
Run Code Online (Sandbox Code Playgroud)

完整的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()
        );
    }
Run Code Online (Sandbox Code Playgroud)

Fan*_*ang 6

1.如果你的EdmModel,字符串属性是键,那么不需要ODataRoute,例如:

public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

ConventionModelBuilder将使用名为"Id"的属性作为键,或者您应该指定它是一个键,如:

public class Product
{
    [Key]
    public string StringKey { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

那个电话就像localhost\api\Products('test')应该去

public SingleResult<Product> GetProduct([FromODataUri]string key)
Run Code Online (Sandbox Code Playgroud)

2.如果你已经有一个int作为键,但你想使用string作为另一个键,那么你应该尝试这个功能:http://odata.github.io/WebApi/#04-17-Alternate-Key,和你可以这样打电话: localhost\api\Products(StringKey='test')