【问题标题】:How should you build an OData URI?您应该如何构建 OData URI?
【发布时间】:2019-04-24 10:08:17
【问题描述】:

我正在寻找构建 URI,例如 https://example.com/data/customers?$top=100

是否有用于创建 OData URI 的 UriBuilder(即可以适当地处理 $ 等字符)?

完整信息

我有这样的代码(简化示例):

public Uri CreateMyApiUri(string rootUri, string apiPath, string entity, int pageSize)
{
    var builder = new UriBuilder(rootUri);
    builder.Path = ConcatPathParts(builder.Path, apiPath, entity); //basically string.Join("/", args), plus code to remove superfluous slashes
    var parameters = HttpUtility.ParseQueryString(builder.Query);
    if (pageSize > 0) parameters["$top"] = pageSize.ToString();
    builder.Query = parameters.ToString();
    return builder.Uri; 
}
//called like this
var uri = CreateMyApiUri("https://example.com", "data", "customers", 100);

但是,OData 特殊字符 $ 被编码为在 URI 中使用为 %24

我在 GitHub 上找到了OData.Net,这似乎是一个对此类事情很有帮助的库,但它不是标准库的一部分,而且对于我的简单需求来说看起来相当重量级,所以我希望在承诺之前找到更简单的东西沿着 OData.Net 路径前进...

当然,我可以通过简单的var uri = string.Join("/", new [] {rootUri, apiPath, entity, $"?$top={pageSize}"}); 来避免这种情况...但我想确保我正在利用 .net 库的字符转义功能/而不是为框架已经给我的东西创建解决方案.

注意:我知道您可以从 OData 服务生成类,但我不想使用这种方法,因为如果 API 发生更改,我需要重新生成客户端代码(例如,将新字段添加到目标实体)。相反,我想使用更“纯”的 HTTP 方法。

【问题讨论】:

  • OData 发布其架构。如果 API 发生变化,架构也会发生变化。这不亚于任何其他方法的“纯 HTTP”。事实上,GraphQL 和 Open API 试图恢复这种可发现的模式
  • @PanagiotisKanavos “非纯 HTTP” 我的意思是你有一个 C# 客户端类,例如 docs.microsoft.com/en-us/aspnet/web-api/overview/… 中的 ProductClient。我正在编写获取数据并将其转换为 XML 的中间件,然后可以通过 XLST 对其进行转换,然后再被其他系统使用。通过避免生成 C#,我不必重新部署程序集;我可以仅使用受影响服务的配置(XSLT / URI)来更新中间件。不过可能有更好的方法/我对想法持开放态度。
  • 这不是纯粹的问题,而是使用 XSLT 或 JSON 路径无法解决的版本控制问题 - 您需要知道架构才能编写正确的转换。 ODATA client 允许您编写 LINQ 查询,仅检索您想要的字段并将它们映射到您想要的任何 client 实体,甚至使用匿名类型。 XSLT 映射和 LINQ 查询之间没有真正的区别,除了易用性、编译时检查等

标签: c# odata query-string querystringparameter uribuilder


【解决方案1】:

我找到了解决方案;我不需要特别的ODataUriBuilder;而是在我使用 query.ToString() 时出现了一个错误,如下所述:https://stackoverflow.com/a/26789977/361842

将该修复应用于上述代码可以解决问题:

public Uri CreateMyApiUri(string rootUri, string apiPath, string entity, int pageSize)
{
    var builder = new UriBuilder(rootUri);
    builder.Path = ConcatPathParts(builder.Path, apiPath, entity); //basically string.Join("/", args), plus code to remove superfluous slashes
    var parameters = HttpUtility.ParseQueryString(builder.Query);
    if (pageSize > 0) parameters["$top"] = pageSize.ToString();

    //the fix:
    builder.Query = Uri.EscapeUriString(HttpUtility.UrlDecode(parameters.ToString()));
    //instead of:
    //builder.Query = parameters.ToString();

    return builder.Uri; 
}
//called like this
var uri = CreateMyApiUri("https://example.com", "data", "customers", 100);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多