2013-04-22 47 views
9

我目前正在開發一個mvc4 web api odata服務,在那裏我想返回一個用戶列表,其中用戶有一個語言列表。當我想我得到以下錯誤的用戶:Odata沒有找到NavigationLink工廠

錯誤:

<m:innererror> 
<m:message> 
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'. 
</m:message> 
<m:type>System.InvalidOperationException</m:type> 
<m:stacktrace/> 
<m:internalexception> 
<m:message> 
No NavigationLink factory was found for the navigation property 'Languages' from entity type 'MvcWebRole1.Models.User' on entity set 'Users'. Try calling HasNavigationPropertyLink on the EntitySetConfiguration. 
Parameter name: navigationProperty 
</m:message> 
<m:type>System.ArgumentException</m:type> 
<m:stacktrace> 
at System.Web.Http.OData.Builder.EntitySetLinkBuilderAnnotation.BuildNavigationLink(EntityInstanceContext instanceContext, IEdmNavigationProperty navigationProperty, ODataMetadataLevel metadataLevel) 
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteNavigationLinks(EntityInstanceContext context, ODataWriter writer, ODataSerializerContext writeContext) 
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, IEnumerable`1 propertyBag, ODataWriter writer, ODataSerializerContext writeContext) 
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObjectInline(Object graph, ODataWriter writer, ODataSerializerContext writeContext) 
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(Object graph, ODataWriter writer, ODataSerializerContext writeContext) 
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, ODataWriter writer, ODataSerializerContext writeContext) 
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) 
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.<>c__DisplayClassa.<WriteToStreamAsync>b__9() 
at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token) 
</m:stacktrace> 
</m:internalexception> 
</m:innererror> 

我的用戶是這樣的:

public class User 
{ 
    [Key] 
    public int UserId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string UserName { get; set; } 

    public string Password { get; set; } 
    public virtual ICollection<Language> Languages { get; set; } 

    public User() 
    { 
     Languages = new List<Language>(); 
    } 
} 

和我的OData的長相UsersController像這樣:

public class UsersController : EntitySetController<User, int> 
{ 
    WorldChatContext db = new WorldChatContext(); 

    public override IQueryable<User> Get() 
    { 
     return db.Users.AsQueryable(); 
    } 

    protected override User GetEntityByKey(int key) 
    { 
     return db.Users.FirstOrDefault(p => p.UserId == key); 
    } 

    public override HttpResponseMessage Post(User entity) 
    { 
     db.Users.Add(entity); 
     db.SaveChanges(); 
     return base.Post(entity); 
    } 
} 

我打電話給我在我的路由設置下面的網址:http://127.0.0.1:81/odata/Users它工作,如果我評論我的用戶模型中的導航屬性。

我在做什麼錯了?我已經嘗試將[Serializable,KnownType(typeof(Language))]放在我的用戶類的頂部,但出於某種原因,我無法使用KnownType。我怎樣才能使我的OData與這個導航屬性一起工作?

回答

32

您錯過了爲語言設置的實體。導航屬性指向實體並且必須綁定到實體集。在模型構建器代碼中,添加以下行來解決問題。

builder.EntitySet<Language>("languages"); 

這是做什麼是創建實體集「語言」。約定模型構建器將導航屬性綁定到實體集(如果有)。因此,實體類型User上的導航屬性Languages將綁定到實體集languages

+0

謝謝,實際上做了這份工作,它沒有給出錯誤了!它不會返回odata結果中的語言,但是,你知道爲什麼嗎?我一直在閱讀有關擴展查詢,但它似乎並沒有工作。 – Fergers 2013-04-23 09:46:23

+1

默認情況下,OData不會擴展關係。它們代表的是鏈接。要在查詢用戶的同時獲取相關語言,則需要使用uri'http:// localhost/odata/Users?$ expand = Languages'。請查看http://www.odata.org/documentation/odata-v3-documentation/url-conventions/#513_Expand_System_Query_Option – 2013-04-23 17:02:23

+0

上的文檔如果我們不想爲語言提供一個實體集來簡化我們的API,那該怎麼辦?有一個使用HasNavigationPropertyLink的例子嗎? – Michael 2013-11-13 20:34:30

相關問題