【问题标题】:How to provide custom mediatype formats for OData Api如何为 OData Api 提供自定义媒体类型格式
【发布时间】:2015-04-02 05:08:18
【问题描述】:

我正在开发一个使用 ODataApiController 的 ASP.NET 应用程序。该应用程序通过查询数据并将其显示在表格中向用户显示网格。我希望能够导出为多种不同格式,包括 CSV 和自定义 XML 格式。理想情况下,我会采用与网格相同的 OData 查询,设置 Accepts 标头,然后取回 CSV 或 XML。

我创建了 MediaTypeFormatters 来做我需要的事情,但它们只适用于“常规”ApiController,而不是 ODataApiController。查看 github 中的代码,我看到 OData 有自己的 MediaTypeFormatter 方案来处理各种情况,并内置了 XML 和 JSON 格式化程序。但我看不出如何使用它来提供自定义格式。我尝试过继承 ODataMediaTypeFormatter,但在其上设置的断点从未命中。

我只对这里的输出格式感兴趣。如何扩展 OdataApi 以输出不同的格式?

【问题讨论】:

    标签: asp.net-web-api odata


    【解决方案1】:

    您也可以在 OData 查询中使用 MediaTypeFormatter。只需向您的项目添加一个继承 MediaTypeFormatter 的新类。然后将其添加到注册时的 WebApiConfig 文件中:

    config.Formatters.Add(new JSONPFormatter(new QueryStringMapping("$format","jsonp","application/javascript")));
    

    如果您随后使用$format=jsonp 查询您的实体,它将以 JSONP 形式返回该实体。您也可以使用 contenttype application/javascript 请求它以获得 JSONP 返回。

    这是用于 JSONP 返回的 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。

    【讨论】:

      猜你喜欢
      • 2014-11-16
      • 1970-01-01
      • 2014-03-12
      • 2012-05-23
      • 1970-01-01
      • 2019-12-25
      • 2015-12-23
      • 1970-01-01
      • 2015-08-22
      相关资源
      最近更新 更多