如何为 OData 提供自定义媒体类型格式 Api
How to provide custom mediatype formats for OData Api
我正在开发一个使用 ODataApiController 的 ASP.NET 应用程序。该应用程序通过查询数据并在 table 中显示给用户一个网格。我希望能够导出为多种不同的格式,包括 CSV 和自定义 XML 格式。理想情况下,我会采用网格使用的相同 OData 查询,设置接受 header,然后取回 CSV 或 XML.
我已经创建了 MediaTypeFormatters 来做我需要的,但它们只适用于 "regular" ApiController,而不是 ODataApiController。查看 github 中的代码,我发现 OData 有自己的 MediaTypeFormatter 方案来处理各种情况,并内置 XML 和 JSON 格式化程序。但我看不出如何连接到它来提供自定义格式。我尝试继承 ODataMediaTypeFormatter,但在其上设置的断点从未命中。
我只对这里的输出格式感兴趣。如何扩展 OdataApi 以输出不同的格式?
您也可以对 OData 查询使用 MediaTypeFormatter
。只需向继承 MediaTypeFormatter
的项目添加一个新的 class。然后将其添加到您的 WebApiConfig 文件中 Register:
config.Formatters.Add(new JSONPFormatter(new QueryStringMapping("$format","jsonp","application/javascript")));
如果您随后使用 $format=jsonp
查询您的实体,它将 return 作为 JSONP 的实体。您还可以使用内容类型 application/javascript
请求它以获得 JSONP return.
这是 JSONP return 的 MediaFormatter 的完整示例。您可以根据需要轻松更改它:
using MyProject.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.ServiceModel.Syndication;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using Newtonsoft.Json;
namespace SMSIdent.Modules.Formatter
{
/// <summary>
/// Adds a $format=jsop to all odata query
/// </summary>
public class JSONPFormatter : MediaTypeFormatter
{
private readonly string jsMIME = "application/javascript";
public JSONPFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue(jsMIME));
}
public JSONPFormatter(MediaTypeMapping mediaTypeMapping) : this()
{
MediaTypeMappings.Add(mediaTypeMapping);
}
//THis checks if you can POST or PUT to this media-formater
public override bool CanReadType(Type type)
{
return false;
}
//this checks if you can GET this media. You can exclude or include your Resources by checking for their types
public override bool CanWriteType(Type type)
{
return true;
}
//This actually takes the data and writes it to the response
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
{
//you can cast your entity
//MyType entity=(MyType) value;
var callback=HttpContext.Current.Request.Params["callback"];
return Task.Factory.StartNew(() =>
{
using (StreamWriter sw = new StreamWriter(writeStream))
{
if (string.IsNullOrEmpty(callback))
{
callback = "values";
}
sw.Write(callback + "(" + JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}) + ")");
}
});
}
}
}
注意:我正在使用 Web API 2. 我不知道它是否也适用于 Web Api 1.
我正在开发一个使用 ODataApiController 的 ASP.NET 应用程序。该应用程序通过查询数据并在 table 中显示给用户一个网格。我希望能够导出为多种不同的格式,包括 CSV 和自定义 XML 格式。理想情况下,我会采用网格使用的相同 OData 查询,设置接受 header,然后取回 CSV 或 XML.
我已经创建了 MediaTypeFormatters 来做我需要的,但它们只适用于 "regular" ApiController,而不是 ODataApiController。查看 github 中的代码,我发现 OData 有自己的 MediaTypeFormatter 方案来处理各种情况,并内置 XML 和 JSON 格式化程序。但我看不出如何连接到它来提供自定义格式。我尝试继承 ODataMediaTypeFormatter,但在其上设置的断点从未命中。
我只对这里的输出格式感兴趣。如何扩展 OdataApi 以输出不同的格式?
您也可以对 OData 查询使用 MediaTypeFormatter
。只需向继承 MediaTypeFormatter
的项目添加一个新的 class。然后将其添加到您的 WebApiConfig 文件中 Register:
config.Formatters.Add(new JSONPFormatter(new QueryStringMapping("$format","jsonp","application/javascript")));
如果您随后使用 $format=jsonp
查询您的实体,它将 return 作为 JSONP 的实体。您还可以使用内容类型 application/javascript
请求它以获得 JSONP return.
这是 JSONP return 的 MediaFormatter 的完整示例。您可以根据需要轻松更改它:
using MyProject.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.ServiceModel.Syndication;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using Newtonsoft.Json;
namespace SMSIdent.Modules.Formatter
{
/// <summary>
/// Adds a $format=jsop to all odata query
/// </summary>
public class JSONPFormatter : MediaTypeFormatter
{
private readonly string jsMIME = "application/javascript";
public JSONPFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue(jsMIME));
}
public JSONPFormatter(MediaTypeMapping mediaTypeMapping) : this()
{
MediaTypeMappings.Add(mediaTypeMapping);
}
//THis checks if you can POST or PUT to this media-formater
public override bool CanReadType(Type type)
{
return false;
}
//this checks if you can GET this media. You can exclude or include your Resources by checking for their types
public override bool CanWriteType(Type type)
{
return true;
}
//This actually takes the data and writes it to the response
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
{
//you can cast your entity
//MyType entity=(MyType) value;
var callback=HttpContext.Current.Request.Params["callback"];
return Task.Factory.StartNew(() =>
{
using (StreamWriter sw = new StreamWriter(writeStream))
{
if (string.IsNullOrEmpty(callback))
{
callback = "values";
}
sw.Write(callback + "(" + JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}) + ")");
}
});
}
}
}
注意:我正在使用 Web API 2. 我不知道它是否也适用于 Web Api 1.