How to provide custom format formats for OData Api

I am developing an ASP.NET application that uses ODataApiController. The application shows users the grid, requesting data and displaying them in a table. I would like the opportunity to export to various formats, including CSV and custom XML format. Ideally, I would just take the same OData query that the grid uses, set the Accepts header, and return CSV or XML.

I created MediaTypeFormatters to do what I need, but they only work with the "regular" ApiController, not the ODataApiController. Looking at the code on github, I see that OData has its own MediaTypeFormatter scheme for handling various cases and is built in XML and JSON formats. But I can’t figure out how to connect to this to provide custom formats. I tried to inherit ODataMediaTypeFormatter, but the breakpoint set on it never hits.

I'm really interested only in output formats. How can I extend OdataApi to output various formats?

+2
source share
1 answer

You can use MediaTypeFormatter for OData queries. Just add a new class to your project that inherits MediaTypeFormatter . Then add this to your WebApiConfig file in Register:

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

If you then query your object using $format=jsonp , it will return the object as JSONP. You can also request it with a content application/javascript type to get a JSONP return.

Here is a complete example for MediaFormatter to return JSONP. You can easily change it for your needs:

 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 }) + ")"); } }); } } } 

Note. I am using Web API 2. I do not know for sure whether it also works in Web Api 1.

+2
source

All Articles