挂钩 OData 的 $metadata 响应并将其从 XML 转换为 JSON

Posted

技术标签:

【中文标题】挂钩 OData 的 $metadata 响应并将其从 XML 转换为 JSON【英文标题】:Hook OData's $metadata response and convert it from XML to JSON 【发布时间】:2017-05-02 09:33:03 【问题描述】:

Get OData $metadata in JSON format 的回答指出 OData 默认无法将元数据返回为 JSON。

但是是否有可能捕获或挂钩它对$metadata URL 的响应,然后在将其发送到客户端之前将其动态转换为 JSON?

我想像这样的伪代码:

[HttpGet]
[ODataRoute("$metadata")]
public string GetMetadataAsJson()

    string xml = GetOdataMetadataAsXML();
    string json = ConvertToJson(xml);
    return json;

不过,我不知道如何正确实现它,尤其是我不确定如何将标准 OData 响应作为字符串获取,以及如何挂钩 $metadata URL。

【问题讨论】:

一种选择是编写一个 HttpModule。挂钩预期的 URL,从 app/json 到 app/xml 的传入更改请求类型,用 XDoc.Load->JSon.ConvertObject->Output 流替换响应流。 @MarvinSmit 我什至无法连接$metadata 端点,[ODataRoute("$metadata")] 对此不起作用。问题是 $metadata 更像是一个可以应用于许多不同 URL 的参数,我必须将它们全部挂钩。 更复杂的选择是: 为负责 $metadata 生成的 ODataMediaTypeFormatter 编写一个装饰器。然后使用一些反射来让 OData 路由允许 app/json 进行 $metadata 请求(默认情况下它会导致路由失败)。然后在装饰器上重载“WriteToStreamAsyncProxy”以执行与上述相同的技巧(写入 XML,将 XML 转换为 JSON,输出 JSON)。最后用修饰版本替换 OData 启动中的格式化程序。 我不明白这种东西有什么用? CSDL xml 和 json 之间没有可能的等价性(例如,那个 json 会是什么样的?你会如何处理 XML 命名空间?)。无论如何,没有标准客户端能够理解它,所以,为什么不创建另一个特定的路由,例如 /$jsonmetadata 或其他什么,并在自定义客户端中使用该路由? 这仍然困扰着我 ;) 你不应该尝试拦截标准的conventional $metadata 路由,这会破坏 OData 客户端工具,但是没有什么能阻止您创建自己的未绑定操作来实现保存。 【参考方案1】:

Newtonsoft 支持 Json 部分结账https://www.newtonsoft.com/json/help/html/ConvertXmlToJson.htm

所以 Json 部分的实际解决方案将非常简单,只要你有你的 XML

[HttpGet]
[ODataRoute("$metadata")]
public string GetMetadataAsJson()

    string xml = GetOdataMetadataAsXML();
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);
    string json = JsonConvert.SerializeXmlNode(doc);
    return json;

此外,您可能应该首先检查是否例如例如,使用此代码设置格式查询

[HttpGet]
[ODataRoute("$metadata")]
public string GetMetadataAsJson([FromQuery(Name="Format")]string format)

    string metaResult = GetOdataMetadataAsXML();
    if(format.Equals("json",StringComparison.OrdinalIgnoreCase))
    
        XmlDocument metaDoc = new XmlDocument();
        doc.LoadXml(metaResult);
        metaResult = JsonConvert.SerializeXmlNode(doc);
    
    return metaResult;

【讨论】:

以上是关于挂钩 OData 的 $metadata 响应并将其从 XML 转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章

我们可以使用OData客户端为syncfusion网格创建我们的请求但是使用正常响应(Reqular WebAPI)

.Net Core 1.1 上的 OData v4 缺少 /$metadata

ASP.NET.Core允许在设置RequireAuthenticatedUser()时匿名访问OData $ metadata

为 JSON 构建 C# 对象 [重复]

从 OData 响应将默认值绑定到 Combox

如何在 kendo.data.Datasource 上获得单一结果