C#Odata v4开放式原始值

C#Odata v4开放式原始值,c#,asp.net-web-api,odata,C#,Asp.net Web Api,Odata,我有一个包含动态属性的简单打开类型: public class Person { [Key] public string Uid { get; set; } public IDictionary<string, object> DynamicProperties { get; set; } } 我可以通过~/Person('uid')/foo这样的URL来单独请求这些属性,这要归功于它们的键和此方法: public IHttpActionResul

我有一个包含动态属性的简单打开类型:

public class Person {
    [Key]
    public string Uid { get; set; }     
    public IDictionary<string, object> DynamicProperties { get; set; }
}
我可以通过~/Person('uid')/foo这样的URL来单独请求这些属性,这要归功于它们的键和此方法:

public IHttpActionResult GetDynamicProperty([FromODataUri] string key, [FromODataUri] string dynamicProperty) {
    Person person;
    // ...
    // (string) for the example
    return this.Ok((string)person.DynamicProperties[dynamicProperty]);
}
结果是:

{
    "@odata.context": "http://myServer/$metadata#Person('uid')/foo",
    "value": "foo_value"
}
但我不知道如何使用像~/Person('uid')/foo/$value这样的URL获取这些属性的原始值

如果我尝试一下,结果是:

{
    "error": {
        "code": "",
        "message": "No HTTP resource was found that matches the request URI 'http://myServer/Person('uid')/foo/$value'.",
        "innererror": {
            "message": "No routing convention was found to select an action for the OData path with template '~/entityset/key/dynamicproperty/$value'.",
            "type": "",
            "stacktrace": ""
        }
    }
}
我应该如何路由以访问这些原始值?或者有没有一种方法或其他东西可以处理它

--在用户回答后编辑

谢谢你的例子,它很有魅力。我已经跟踪了你的样本的第1点和第2点。对于第3点,如果它可以帮助某人,这是一个经典Web API的注册方法的改编版本:

public static void Register(HttpConfiguration config) {
    // Custom routing for dynamic attributes raw values
    var routings = ODataRoutingConventions.CreateDefault();
    routings.Insert(0, new DynamicRawValueRoutingConvention());
    // Our model
    ODataModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Person>("Person");
    // ...
    // Old way
    //config.MapODataServiceRoute(
    //    routeName: "myDefaultRouteName",
    //    routePrefix: null,
    //    model: builder.GetEdmModel()
    //);
    // New way with Sam's samples
    config.MapODataServiceRoute(
        "myDefaultRouteName",
        null,
        configureAction =>
        configureAction.AddService(ServiceLifetime.Singleton, sp => builder.GetEdmModel()).AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp => routings)
    );
    var formatters = ODataMediaTypeFormatters.Create();
    foreach (var oDataMediaTypeFormatter in formatters) {
        oDataMediaTypeFormatter.MediaTypeMappings.Insert(0, new ODataDynamicValueMediaTypeMapping());
    }
    config.Formatters.InsertRange(0, formatters);
}
公共静态无效寄存器(HttpConfiguration配置){
//动态属性原始值的自定义路由
var routings=ODataRoutingConventions.CreateDefault();
插入(0,新的DynamicRawValueRoutingConvention());
//我们的模型
ODataModelBuilder=新ODataConventionModelBuilder();
建造商实体集(“人”);
// ...
//老路
//config.MapODataServiceRoute(
//routeName:“myDefaultRouteName”,
//routePrefix:null,
//模型:builder.GetEdmModel()
//);
//山姆样品的新方法
config.MapODataServiceRoute(
“myDefaultRouteName”,
无效的
配置操作=>
configureAction.AddService(ServiceLifetime.Singleton,sp=>builder.GetEdmModel()).AddService(ServiceLifetime.Singleton,sp=>routings)
);
var formatters=ODataMediaTypeFormatters.Create();
foreach(格式化程序中的变量oDataMediaTypeFormatter){
oDataMediaTypeFormatter.MediaTypeMappings.Insert(0,新的ODataDynamicValueMediaTypeMapping());
}
config.Formatters.InsertRange(0,格式化程序);
}
@Max Xapi

OData没有内置逻辑来支持动态属性的
$value

但是,您可以自己解决问题来完成它

这很简单,只需几个步骤:

  • 创建自己的路由约定
  • 创建动态属性值映射
  • 在配置中插入路由约定和动态属性值映射
  • 我创建了一个可以参考的示例,请参见提交。请让我知道任何进一步的问题,并希望它可以帮助

    问候,

    -山姆

    @Max Xapi

    OData没有内置逻辑来支持动态属性的
    $value

    但是,您可以自己解决问题来完成它

    这很简单,只需几个步骤:

  • 创建自己的路由约定
  • 创建动态属性值映射
  • 在配置中插入路由约定和动态属性值映射
  • 我创建了一个可以参考的示例,请参见提交。请让我知道任何进一步的问题,并希望它可以帮助

    问候,


    -Sam

    是否将
    ~/Person('uid')?$select=foo
    足够?不幸的是,否,因为除非在技术上尚不可行(我无法回答这个问题),否则客户端希望使用非动态属性的“经典”语法是否将
    ~/Person('uid')?$select=foo
    足够?不幸的是否,因为除非在技术上还不可能(我不能回答这个问题),客户机希望使用“经典”语法来处理非动态属性
    public static void Register(HttpConfiguration config) {
        // Custom routing for dynamic attributes raw values
        var routings = ODataRoutingConventions.CreateDefault();
        routings.Insert(0, new DynamicRawValueRoutingConvention());
        // Our model
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Person>("Person");
        // ...
        // Old way
        //config.MapODataServiceRoute(
        //    routeName: "myDefaultRouteName",
        //    routePrefix: null,
        //    model: builder.GetEdmModel()
        //);
        // New way with Sam's samples
        config.MapODataServiceRoute(
            "myDefaultRouteName",
            null,
            configureAction =>
            configureAction.AddService(ServiceLifetime.Singleton, sp => builder.GetEdmModel()).AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp => routings)
        );
        var formatters = ODataMediaTypeFormatters.Create();
        foreach (var oDataMediaTypeFormatter in formatters) {
            oDataMediaTypeFormatter.MediaTypeMappings.Insert(0, new ODataDynamicValueMediaTypeMapping());
        }
        config.Formatters.InsertRange(0, formatters);
    }