【问题标题】:Web API OData Typeless support for $select query option对 $select 查询选项的 Web API OData 无类型支持
【发布时间】:2015-05-15 05:46:22
【问题描述】:

我正在使用 ASP.NET Web API 2 OData 中的新无类型支持。我有兴趣为 $select 查询选项提供支持。如何从 EdmEntityObject 中省略 $select 查询选项未选择的结构属性?

以下是使用无类型模型的非常简单示例的 Web API 配置示例。

public static IEdmModel BuildEdmModel()
{
    var model = new EdmModel();
    var container = new EdmEntityContainer("Model", "OData");
    var product = new EdmEntityType("Model", "Product");
    var productKey = product.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Guid);
    product.AddKeys(productKey);
    product.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
    product.AddStructuralProperty("Price", EdmPrimitiveTypeKind.Double);
    model.AddElement(product);
    model.AddElement(container);
    model.SetIsDefaultEntityContainer(container, true);
    container.AddEntitySet("Products", product);

    return model;
}

public static void Register(HttpConfiguration config)
{
    config.Routes.MapODataRoute("ODataRoute", "odata", BuildEdmModel());
}

以下是来自简单 ODataController 的部分 sn-p

public EdmEntityObjectCollection Get()
{
    var path = Request.GetODataPath();
    var edmType = path.EdmType;
    var collectionType = edmType as IEdmCollectionType;
    var entityType = collectionType.ElementType.AsEntity();
    var entitySetName = entityType.EntityDefinition().Name;
    var model = Request.GetEdmModel();
    var queryContext = new ODataQueryContext(Request.GetEdmModel(), entityType.Definition);
    var queryOptions = new ODataQueryOptions(queryContext, Request);

    return GetData(Request.GetEdmModel(), queryOptions);
}

public static EdmEntityObjectCollection GetData(IEdmModel edmModel, ODataQueryOptions queryOptions)
{
    var selectedPropertyNames = new string[0];
    // determine the selected property names
    if (queryOptions.SelectExpand != null && queryOptions.SelectExpand.SelectExpandClause != null && (!queryOptions.SelectExpand.SelectExpandClause.AllSelected || queryOptions.SelectExpand.SelectExpandClause.SelectedItems.OfType<WildcardSelectItem>().Any()))
    {
        selectedPropertyNames = queryOptions.SelectExpand.RawSelect.Split(',');
    }    

    // TODO: Now that we have the selected properties, how do I remove the structural properties from the EdmEntityObject that were not selected by the $select query option?

    var productSchemaType = edmModel.FindDeclaredType(string.Format("{0}.Product", "Model"));
    var productEntityType = productSchemaType as IEdmEntityType;
    var productEntityTypeReference = new EdmEntityTypeReference(productEntityType, true);
    var products = new EdmEntityObjectCollection(new EdmCollectionTypeReference(new EdmCollectionType(productEntityTypeReference), true));

    var productWindows = new EdmEntityObject(productEntityTypeReference);
    productWindows.TrySetPropertyValue("ID", new Guid("52D811A0-9065-4B83-A2E8-0248FBA9FBF5"));
    productWindows.TrySetPropertyValue("Name", "Microsoft Windows 8");
    productWindows.TrySetPropertyValue("Price", 179.99);

    var productOffice = new EdmEntityObject(productEntityTypeReference);
    productOffice.TrySetPropertyValue("ID", new Guid("CB39EBD0-4751-4D5F-A76C-78FCC7A9CE1A"));
    productOffice.TrySetPropertyValue("Name", "Microsoft Office 2013");
    productOffice.TrySetPropertyValue("Price", 399.99);

    products.Add(productWindows);
    products.Add(productOffice);

    return products;
}

这将输出:

{
  "odata.metadata":"http://localhost:59511/odata/$metadata#Products","value":[
    {
        "ID":"52d811a0-9065-4b83-a2e8-0248fba9fbf5","Name":"Microsoft Windows 8","Price":179.99
    },{
        "ID":"cb39ebd0-4751-4d5f-a76c-78fcc7a9ce1a","Name":"Microsoft   Office 2013","Price":399.99
    }
  ]
}

如果用户应用 $select 查询选项,例如 /odata/Products?$select=Name。这应该会产生以下输出:

{
  "odata.metadata":"http://localhost:59511/odata/$metadata#Products","value":[
    {
      "Name":"Microsoft Windows 8"
    },{
      "Name":"Microsoft Office 2013"
    }
  ]
}

任何帮助将不胜感激

【问题讨论】:

    标签: asp.net-web-api-odata


    【解决方案1】:

    以下对我有用。

    var oDataProperties = Request.ODataProperties()
    oDataProperties.SelectExpandClause = queryOptions.SelectExpand.SelectExpandClause;
    

    扩展功能在 System.web.OData.dll v5.2.0.0.

    【讨论】:

      【解决方案2】:

      这是我的代码。

      private void ApplySelectExpand(SelectExpandQueryOption selectExpand)
          {
              if (selectExpand != null)
              {
                  Request.SetSelectExpandClause(selectExpand.SelectExpandClause);
              }
          }
      

      【讨论】:

        【解决方案3】:

        如果我正确理解了您的问题,有两种方法可以解决您的问题。

        1. 对 IQueryable 结果调用 ODataQueryOptions 的 ApplyTo 方法
          return queryOptions.ApplyTo(products);

        2. 在 GetData 方法上添加属性 Queryable 并让 WebAPI 处理查询选项
          [Queryable]
          public static EdmEntityObjectCollection GetData(IEdmModel edmModel) {...}

        【讨论】:

        • 这个答案不正确,因为ApplyTo[EnableQuery] 都只适用于CLR 类型。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多