2013-09-25 9 views
9

これは私を殺しています。ここの記事やウェブで助けられたことはありません。WebAPI ODataエラーコンテンツタイプ 'appliation/json ...'のレスポンスボディをObjectContentタイプのシリアル化に失敗しました。

まず、.Net 4.5を使用してASP.Net WebForms(MVCではなく)を作成しています。 WebFormsサイトにODataフィードを追加するのに役立つgreat articleが見つかりました。それはチャンピオンのように働いた。私はEMPTY Webアプリケーションを作成して動作させることができました。しかし、this articleで作成した最新の(そしておそらくもっと簡単な)EntitySetControllerを使用していないことに気付きました。両方とも別々に働いた。私は元の記事をマッサージしてEntitySetControllerを扱うことができるかどうかを調べました。 ODataとそのフィルタリングをテストするために、Fiddlerを使用してください。ああ、幸せな一日。

私の次のステップは、それを既存のASP.Net 4.5 WebFormsアプリケーションに追加することでした。それはいくらか働いています。すべてがコンパイルされ、私はlocallhost:55777/kidに電話をかけることができますし、それが期待通りProducts返します。私は、その後GetまたはGetEntityByKey方法を試してみて、彼らが実行するとどのような彼らが必要恩返し

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

。しかし、私は、次のエラーメッセージが表示されます。

{ 
    "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()" 
     } 
    } 
    } 
} 

コントローラは次のとおりです。

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

    } 
} 

WebApiConfigは次のとおりです。

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

    } 
} 

Global.asax.csファイルのApplication_Startは以下しかありません。

WebApiConfig.Register(GlobalConfiguration.Configuration); 

私がプロジェクトに持っているパッケージを表示するには、ここに私のPackages.configファイルがあります。私はMicrosoft.AspNet.WebApi.*アイテムがプレリリース版であることを知っています。私は現在の安定したリリースでそれらを持っていたので、私はプレリリースがそれを修正するかどうかを試してみるだろうと思ったので、何も違っていた。

<?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> 

私はこれをスタンドアロンで動作させることができるので、途中で何かが起こっていると思います。有用な助けをいただければ幸いです。 TIA!

EDIT == SOLUTION

変更に必要な唯一のものを@RaghuRamのおかげでWebApiConfigの登録方法でした。更新されたバージョンは次のとおりです。

config.EnableQuerySupport(); 

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

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

恐ろしいです!代わりにODataModelBuilderの

答えて

10

、このようODataConventionModelBuilder使用し、

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

IEdmModel model = modelBuilder.GetEdmModel(); 

は、明示的にモデル全体を構成するときに使用されることを意図し、非常に低レベルのクラスです。それぞれのプロパティ、それぞれ、すべてのナビゲーションプロパティ、そして自己リンク(ID、編集、読み込み)、およびナビゲーションリンクにそれを伝える必要があります。一方、

ODataConventionModelBuilder、自動的にこれらの事を推測するために、いくつかの規則があります。あなたが慣習から逸脱する場合にのみ、ODataConventionModelBuilderで明示的に何かを設定する必要があります。あなたは、ナビゲーションプロパティおよびその他の関連entitysetsを持っていたら

それでもODataModelBuilderクラスを使用したい場合には、このようなコードを記述する必要があり、

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

物事が複雑になります

+0

あなたの答えを更新してください、あなたは最初の例で古いものを使用しています –

関連する問題