Web Api with OData v4 throwing exception on $select

后端 未结 2 745
猫巷女王i
猫巷女王i 2021-01-06 09:45

I\'m using the latest version of WebApi and OData and everything is set up to work right. The only problem is when I try to use $select .

It throws the error bellow

相关标签:
2条回答
  • 2021-01-06 10:46

    This is a known limitation of the XmlMediaTypeFormatter class from the System.Net.Formatting Nuget package. The implementation of the JSON formatter does support the $select and $expand commands but these are not available when content negotiation determines that XML should be returned.

    You should look into implementing OData endpoints (as opposed to WebAPI endpoints) should you need to return XML formatted responses. More information on how this can be done can be found here:

    http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options

    0 讨论(0)
  • 2021-01-06 10:47

    Found a solution. It isn't perfect but it does work!

    Maybe it will be useful for someone because I've spent on it few hours of research and trying.

    Step #1 create custom xml formatter:

    public class CustomXmlFormatter : MediaTypeFormatter
    {
        private JsonMediaTypeFormatter jFormatter = null;
        public CustomXmlFormatter(JsonMediaTypeFormatter jFormatter)
        {
            SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml"));
            this.jFormatter = jFormatter;
        }
    
        public override bool CanReadType(Type type)
        {
            return false;
        }
    
        public override bool CanWriteType(Type type)
        {
            return true;
        }
        public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
        {
            return Task.Factory.StartNew(() =>
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    var tsk = jFormatter.WriteToStreamAsync(type, value, ms, content, transportContext);
                    tsk.Wait();
                    ms.Flush();
                    ms.Seek(0, SeekOrigin.Begin);
    
                    var xDoc = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(ms, new XmlDictionaryReaderQuotas()));
    
                    using (XmlWriter xw = XmlWriter.Create(writeStream))
                    {
                        xDoc.WriteTo(xw);
                    }
    
                }
            });
        }
    }
    

    Step #2 register it in startup section:

            var formatters = ODataMediaTypeFormatters.Create();
            var jsonFormatter = config.Formatters.JsonFormatter;
            var customXmlFormatter = new CustomXmlFormatter(jsonFormatter);
    
            customXmlFormatter.AddQueryStringMapping("$format", "cxml", "application/xml");
            config.Formatters.Add(customXmlFormatter);
    

    use it as http://url..../actionName?$format=cxml&$select=ObjectName,ObjectId

    0 讨论(0)
提交回复
热议问题