2015-01-13 4 views
4

Я использую последнюю версию WebApi и OData, и все настроено на правильную работу. Единственная проблема, когда я пытаюсь использовать $ select.

Он бросает ошибку сильфона

Object of type 'System.Linq.EnumerableQuery`1[System.Web.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[WebApplication1.Controllers.Person]]' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[WebApplication1.Controllers.Person]'. 

Я посмотрел на документации и их предложение заключается в использовании [Queryable] на верхней части методы Получить в контроллере или в WebApiConfig использовать config.EnableQuerySupport и ни один из них доступны опции. Я в настоящее время использую [EnableQuery]

EDIT

OdataController:

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Linq; 
using System.Net; 
using System.Net.Http; 
using System.Web.Http; 
using System.Web.OData; 
using System.Xml.Serialization; 

namespace WebApplication1.Controllers 
{ 
    public class PeopleController : ODataController 
    { 
     // GET api/values 
     [EnableQuery] 
     public IQueryable<Person> Get() 
     { 
      return new Person[] { new Person() 
      { 
       Id = 1, 
       FirstName = "Testing", 
       LastName = "2" 
      }, new Person() 
      { 
       Id = 2, 
       FirstName = "TestTest", 
       LastName = "3" 
      } }.AsQueryable(); 
     } 

     // GET api/values/5 
     public Person Get(int id) 
     { 
      return new Person() 
      { 
       Id = 3, 
       FirstName = "Test", 
       LastName = "1" 
      }; 
     } 

     // POST api/values 
     public void Post([FromBody]Person value) 
     { 
     } 

     // PUT api/values/5 
     public void Put(int id, [FromBody]Person value) 
     { 
     } 

     // DELETE api/values/5 
     public void Delete(int id) 
     { 
     } 
    } 

    public class Person 
    { 
     [Key] 
     public int Id { get; set; } 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
    } 
} 

WebApiConfig

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web.Http; 
using System.Web.OData; 
using System.Web.OData.Builder; 
using System.Web.OData.Extensions; 
using System.Web.OData.Formatter; 
using WebApplication1.Controllers; 

namespace WebApplication1 
{ 
    public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API configuration and services 

      // Web API routes 
      config.MapHttpAttributeRoutes(); 

      var odataFormatters = ODataMediaTypeFormatters.Create(); 
      config.Formatters.InsertRange(0, odataFormatters); 

      ODataModelBuilder builder = new ODataConventionModelBuilder(); 
      builder.EntitySet<Person>("People"); 
      config.AddODataQueryFilter(); 
      config.MapODataServiceRoute(
      routeName: "ODataRoute", 
      routePrefix: "api", 
      model: builder.GetEdmModel()); 

     } 
    } 
} 

UPDATE 2

, похоже, только выдает ошибку, получая данные в формате xml. Json, похоже, работает

+0

Пожалуйста, покажите контроллер OData и код действия. – JotaBe

+1

Формат Atom устарел из Web API OData V4. –

+0

Спасибо за обновление Shems. У меня была такая же проблема, и я могу использовать $ format = JSON в моем случае, который разрешил это для меня. –

ответ

0

Это известное ограничение класса XmlMediaTypeFormatter из пакета System.Net.Formatting Nuget. Реализация форматирования JSON поддерживает команды $ select и $ expand, но они недоступны, когда согласование содержимого определяет, что XML должен быть возвращен.

Вы должны изучить конечные точки OData (в отличие от конечных точек WebAPI), если вам нужно вернуть ответы в формате XML. Более подробную информацию о том, как это можно сделать, можно найти здесь:

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

0

Найдено решение. Это не идеально, но он работает!

Возможно, это будет полезно для кого-то, потому что я потратил на это несколько часов исследований и попыток.

Шаг # 1 создать пользовательские XML форматировщик:

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

      } 
     }); 
    } 
} 

Шаг # 2 зарегистрировать его в автозапуск?:

 var formatters = ODataMediaTypeFormatters.Create(); 
     var jsonFormatter = config.Formatters.JsonFormatter; 
     var customXmlFormatter = new CustomXmlFormatter(jsonFormatter); 

     customXmlFormatter.AddQueryStringMapping("$format", "cxml", "application/xml"); 
     config.Formatters.Add(customXmlFormatter); 

использовать его как http://url..../actionName $ формате = CXML & $ выбрать = ObjectName , ObjectId

Смежные вопросы