2013-09-25 24 views
9

Điều này đang giết chết tôi. Không có bài viết nào ở đây cũng không có trên web.Lỗi ODAP WebAPI Kiểu ObjectContent không thể sắp xếp từng phần nội dung phản hồi cho kiểu nội dung 'appliation/json ...'

Để bắt đầu, tôi đang làm việc trên ASP.Net WebForms (Không phải MVC) sử dụng .Net 4.5. Tôi đã tìm thấy một số great article giúp bạn thêm nguồn cấp dữ liệu OData vào trang WebForms của bạn. Nó hoạt động như một nhà vô địch. Tôi đã có thể tạo một ứng dụng Web EMPTY và làm cho nó hoạt động. Tuy nhiên, tôi nhận thấy rằng nó không sử dụng mới nhất (và được cho là dễ dàng hơn) EntitySetController mà tôi đã tạo thông qua this article. Cả hai đều làm việc riêng biệt. Sau đó tôi xoa bóp bài viết gốc để xem nó có thể xử lý các EntitySetController và nó có thể. Đã sử dụng Fiddler như được đề xuất để kiểm tra OData và lọc của nó. Ồ ngày tuyệt vời.

Bước tiếp theo của tôi là thêm vào ứng dụng ASP.Net 4.5 WebForms hiện có của tôi. Có nó làm việc một chút. Tất cả mọi thứ biên dịch và tôi có thể thực hiện cuộc gọi đến locallhost:55777/kid và nó trả Products như mong đợi:

<workspace> 
    <atom:title type="text">Default</atom:title> 
    <collection href="Products"> 
    <atom:title type="text">Products</atom:title> 
    </collection> 
</workspace> 

sau đó tôi thử Get hoặc GetEntityByKey phương pháp và họ chạy và trả lại những gì họ cần. Tuy nhiên, tôi nhận được thông báo lỗi sau:

{ 
    "odata.error":{ 
    "code":"","message":{ 
     "lang":"en-US","value":"An error has occurred." 
    }, 
    "innererror":{ 
     "message":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata=minimalmetadata; streaming=true; charset=utf-8'.", 
     "type":"System.InvalidOperationException", 
     "stacktrace":"", 
     "internalexception":{ 
     "message":"No IdLink factory was found. Try calling HasIdLink on the EntitySetConfiguration for 'Products'.", 
     "type":"System.InvalidOperationException", 
     "stacktrace":" at System.Web.Http.OData.Builder.EntitySetLinkBuilderAnnotation.BuildIdLink(EntityInstanceContext instanceContext, ODataMetadataLevel metadataLevel)\r\n 
         at System.Web.Http.OData.Builder.EntitySetLinkBuilderAnnotation.BuildEntitySelfLinks(EntityInstanceContext instanceContext, ODataMetadataLevel metadataLevel)\r\n 
         at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)\r\n 
         at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)\r\n 
         at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n 
         at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)\r\n 
         at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n 
         at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n 
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n 
         at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 
         at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__10.MoveNext()" 
     } 
    } 
    } 
} 

Controller là:

using System.Collections.Generic; 
using System.Linq; 
using System.Web.Http.OData; 

namespace BOR.InternalWebsite.Controllers { 

    public class ProductsController : EntitySetController<Product, int> { 

     static List<Product> products = new List<Product>() { 
      new Product() { ID = 1, Name = "Hat", Price = 15, Category = "Apparel" }, 
      new Product() { ID = 2, Name = "Socks", Price = 5, Category = "Apparel" }, 
      new Product() { ID = 3, Name = "Scarf", Price = 12, Category = "Apparel" }, 
      new Product() { ID = 4, Name = "Yo-yo", Price = 4.95M, Category = "Toys" }, 
      new Product() { ID = 5, Name = "Puzzle", Price = 8, Category = "Toys" }, 
     }; 

     public override IQueryable<Product> Get() { 
      return products.AsQueryable(); 
     } 

     protected override Product GetEntityByKey(int key) { 
      return products.FirstOrDefault(p => p.ID == key); 
     } 

    } 
} 

Các WebApiConfig là:

using Microsoft.Data.Edm; 
using System.Web.Http; 
using System.Web.Http.OData.Builder; 

namespace BOR.InternalWebsite { 

    public static class WebApiConfig { 

     public static void Register(HttpConfiguration config) { 
      config.EnableQuerySupport(); 

      ODataModelBuilder modelBuilder = new ODataModelBuilder(); 
      var products = modelBuilder.EntitySet<Product>("Products"); 

      IEdmModel model = modelBuilder.GetEdmModel(); 
      config.Routes.MapODataRoute("ODataRoute", "kid", model); 
     } 

    } 
} 

Các Global.asax.cs tập tin của Application_Start không có gì nhưng sau:

WebApiConfig.Register(GlobalConfiguration.Configuration); 

Chỉ để cho bạn thấy những gói tôi có trong dự án, đây là tập tin Packages.config của tôi. Tôi biết rằng các mục Microsoft.AspNet.WebApi.* được phát hành trước. Tôi đã có chúng trong bản phát hành ổn định hiện tại và không có gì là khác nhau vì vậy tôi nghĩ rằng tôi sẽ cố gắng để xem nếu phát hành trước sẽ sửa chữa nó.

<?xml version="1.0" encoding="utf-8"?> 
<packages> 
    <package id="DynamicDataTemplatesCS" version="1.0.1" targetFramework="net45" /> 
    <package id="elmah" version="1.2.2" targetFramework="net45" /> 
    <package id="elmah.corelibrary" version="1.2.2" targetFramework="net45" /> 
    <package id="EntityFramework" version="5.0.0" targetFramework="net45" /> 
    <package id="jQuery" version="2.0.3" targetFramework="net45" /> 
    <package id="jquery.mobile" version="1.3.2" targetFramework="net45" /> 
    <package id="jQuery.UI.Combined" version="1.10.3" targetFramework="net45" /> 
    <package id="knockoutjs" version="2.3.0" targetFramework="net45" /> 
    <package id="Microsoft.AspNet.WebApi" version="5.0.0-rc1" targetFramework="net45" /> 
    <package id="Microsoft.AspNet.WebApi.Client" version="5.0.0-rc1" targetFramework="net45" /> 
    <package id="Microsoft.AspNet.WebApi.Core" version="5.0.0-rc1" targetFramework="net45" /> 
    <package id="Microsoft.AspNet.WebApi.OData" version="5.0.0-rc1" targetFramework="net45" /> 
    <package id="Microsoft.AspNet.WebApi.WebHost" version="5.0.0-rc1" targetFramework="net45" /> 
    <package id="Microsoft.Bcl" version="1.1.3" targetFramework="net45" /> 
    <package id="Microsoft.Bcl.Build" version="1.0.10" targetFramework="net45" /> 
    <package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net45" /> 
    <package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net45" /> 
    <package id="Microsoft.Net.Http" version="2.2.15" targetFramework="net45" /> 
    <package id="Newtonsoft.Json" version="5.0.6" targetFramework="net45" /> 
    <package id="System.Spatial" version="5.6.0" targetFramework="net45" /> 
    <package id="Twitter.Bootstrap" version="3.0.0" targetFramework="net45" /> 
</packages> 

Vì tôi có thể làm việc này độc lập, tôi thấy có điều gì đó đang cản trở. Bất kỳ trợ giúp hữu ích nào cũng sẽ được đánh giá cao! TIA!

EDIT == SOLUTION

Nhờ @RaghuRam điều duy nhất mà cần thay đổi là phương pháp ký của WebApiConfig. Phiên bản cập nhật và do đó hoạt động như sau:

config.EnableQuerySupport(); 

ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
var products = modelBuilder.EntitySet<Product>("Products"); 

IEdmModel model = modelBuilder.GetEdmModel(); 
config.Routes.MapODataRoute("ODataRoute", "kid", model); 

Tuyệt vời!

Trả lời

10

Thay vì ODataModelBuilder, sử dụng ODataConventionModelBuilder như thế này,

var modelBuilder = new ODataConventionModelBuilder(); 
var products = modelBuilder.EntitySet<Product>("Products"); 

IEdmModel model = modelBuilder.GetEdmModel(); 

là một lớp mức rất thấp dự định sẽ được sử dụng khi bạn muốn cấu hình toàn bộ mô hình một cách rõ ràng. Bạn cần phải nói cho nó mỗi và mọi thuộc tính, mỗi và mọi thuộc tính điều hướng và sau đó là các liên kết tự (id, chỉnh sửa và đọc) và các liên kết điều hướng.

ODataConventionModelBuilder mặt khác, có một số quy ước để suy ra những điều này một cách tự động. Bạn chỉ cần định cấu hình điều gì đó một cách rõ ràng với số ODataConventionModelBuilder nếu bạn đi chệch khỏi các quy ước.

Nếu bạn vẫn muốn sử dụng lớp ODataModelBuilder, bạn nên viết mã như thế này,

ODataModelBuilder modelBuilder = new ODataModelBuilder(); 
var products = modelBuilder.EntitySet<Product>("Products"); 
var product = products.EntityType; 

product.HasKey(p => p.ID); 
product.Property(p => p.Name); 
product.Property(p => p.Price); 
product.Property(p => p.Category); 

products.HasIdLink((ctxt) => ctxt.Url.ODataLink(new EntitySetPathSegment("Products"), new KeyValuePathSegment(ctxt.EntityInstance.ID))); 

IEdmModel model = modelBuilder.GetEdmModel(); 

Mọi thứ trở nên phức tạp hơn khi bạn có đặc tính điều hướng và entitysets liên quan, vv

+0

vui lòng cập nhật câu trả lời của bạn, bạn đang sử dụng cái cũ trong ví dụ đầu tiên –

Các vấn đề liên quan