如何使用Microsoft.AspNet.OData版本6设置启用备用密钥

时间:2017-01-30 05:12:41

标签: asp.net-web-api odata

Microsoft.AspNet.OData V5.9.1及更低版本中,您可以通过调用WebApiConfig.cs中的EnableAlternateKeys()来启用备用密钥,如下所示:

config.EnableAlternateKeys(true);

此选项已与其他内容一起删除:

config.EnableCaseInsensitive(true);

如何在 Microsoft.AspNet.OData V6 +中启用EnableAlternateKeys选项?

2 个答案:

答案 0 :(得分:3)

在OData WebAPI 6中已经发生了变化。自从引入了v6依赖注入(参见docs)。这意味着更改了配置服务的旧方法。从现在开始,您应该在MapODataServiceRoute方法

中注册所有必要的服务和路线
public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    config.Count().Filter().OrderBy().Expand().Select().MaxTop(null);

    setErrorDetailPolicy();
    var model = BuildEdmModel();

    // Web API routes
    config.MapODataServiceRoute("routeName", "routePrefix", builder =>
        builder.AddDefaultODataServices()
        .AddService<IEdmModel>(ServiceLifetime.Singleton, s => model)
        .AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp => ODataRoutingConventions.CreateDefaultWithAttributeRouting("routeContact", config))
        .AddService<ODataUriResolver>(ServiceLifetime.Singleton, s => new AlternateKeysODataUriResolver(model))
    );
}

这里重要的一行是最后一行:

.AddService<ODataUriResolver>(ServiceLifetime.Singleton, s => new AlternateKeysODataUriResolver(model))

启用此功能后,我发现我的模型在识别AddAlternateKeyAnnotation扩展方法时遇到问题。这是通过将实例强制转换为EdmModel(而不是使用IEdmModel来解决的)。我的ModelBuilder类看起来像这样:

    internal static IEdmModel GetModel()
    {
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        builder.Namespace = "MyNamespace";

        var personsSet = builder.EntitySet<PersonDTO>("Persons");
        builder.EntityType<PersonDTO>().HasKey(k => k.Id);

        var model = builder.GetEdmModel();

        // model is built, add alternateKey annotation as necessary
        // first, find entity type
        IEdmEntityType t = model.FindDeclaredEntitySet("Persons").EntityType();

        // now find the properties we want to use as alternateKey
        var firstNameProp = t.FindProperty("FirstName");
        var lastNameProp = t.FindProperty("LastName");

        // and finally add the annotation
        ((EdmModel)model).AddAlternateKeyAnnotation(t, new Dictionary<string, IEdmProperty> {
            {
                "FirstName", firstNameProp
            },
            {
                "LastName", lastNameProp
            }
        });

        return model;
    }

请注意,仍有一些便利方法。来自文档:

  

你可能还会发现我们仍然保留了之前的重载   MapODataServiceRoute采用批处理程序,路径处理程序,HTTP   消息处理程序等。它们基本上包装了第一个重载   这需要一个configureAction。我们保留它们的原因是我们   希望为用户提供创建OData服务的便利   他们熟悉的API的轴承。

如果您想知道第一行的作用:

config.Count().Filter().OrderBy().Expand().Select().MaxTop(null);

这是因为默认情况下在OData v6中禁用所有查询选项(再次参见docs)。您应该在每个控制器/操作上启用它们,或者像我一样启用它们,并全局启用它们(这就是上面的行)。

答案 1 :(得分:0)

jonathan.meesschaert答案中缺少的内容是您在OData控制器中的操作的签名。

在我的情况下,我具有以下备用密钥:

((EdmModel)edmModel).AddAlternateKeyAnnotation(
entityType,
new Dictionary<string, IEdmProperty>() {
    { "Text", edmProperty }
});

和关联的控制器动作是:

public MenuItem Get([FromODataUri]string keyText)

请注意,您无需使用[HttpGet][ODataRoute("Menus(Text={Text})")]即可使其正常运行。但是,关键部分是我必须在参数名称后附加 key 。没有它,它就不能在OData v7.1.0上运行