【问题标题】:ASP.Net OData with string keys带有字符串键的 ASP.Net OData
【发布时间】:2016-08-18 10:17:26
【问题描述】:

我正在尝试使用 ASP.Net OData v4(例如 ODataController)来允许访问密钥是字符串的地方。 95% 的示例使用整数作为键,而我发现讨论使用字符串作为键的步骤的几篇文章对我不起作用。

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

/api/ContactTypes('Agency')

乐观地说,我一开始只是将键的类型从 int 更改为 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)

但是,如果我单独执行此操作,我会在控制器“ContactTypes”中的“Get”操作中收到“路径模板 '({key})' 不是有效的 OData 路径模板。请求 URL 中遇到空段。请确保指定了有效的请求 URL。”

这篇文章 (https://damienbod.com/2014/06/16/web-api-and-odata-v4-crud-and-actions-part-3/) 中的 cmets 建议我需要用 ODataRoutePrefix 装饰 Controller:

[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()
        );
    }

【问题讨论】:

    标签: asp.net odata


    【解决方案1】:

    1.如果在你的EdmModel中,字符串属性为key,则不需要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')

    【讨论】:

    • 是的,好的,就是这样。实际上,我有一个名为 ContactTypeId 的属性和一个名为 ContactTypeKey 的属性(在我们的数据库中,两者都是唯一的)。出于性能原因,表上的实际主键是 ContactTypeId。我必须将 Key 属性添加到 ContactTypeKey 属性以使 OData 识别应该用作其目的的键,但这混淆了实体框架,因此最终还添加了以下代码来覆盖其 Key 数据注释目的:modelBuilder.Entity().HasKey(p => p.ContactTypeID)
    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 2014-09-10
    • 1970-01-01
    • 2013-06-06
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多