2013-04-22 7 views
9

Aktualnie pracuję nad usługą odata mvc4 web api, w której chcę zwrócić listę użytkowników, którzy mają listę języków. Kiedy chcę uzyskać Użytkownicy pojawia się następujący błąd:Odata Nie znaleziono fabryki NawigacjiLinkowej

Błąd:

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

Mój Użytkownik wygląda następująco:

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

i mojego UsersController dla OData wygląd tak:

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

Dzwonię pod następujący adres URL, który konfiguruję w routingu: http://127.0.0.1:81/odata/Users to działa, jeśli komentuję właściwość nawigacji w moim modelu użytkownika.

Co robię źle? Próbowałem już umieścić [Serializable, KnownType (typeof (Language))] na mojej klasie użytkownika, ale z jakiegoś powodu nie mogę używać KnownType. Jak mogę sprawić, aby moje OData działały z tą właściwością nawigacji?

Odpowiedz

32

Brakuje elementu dla języka. Właściwość navigation wskazuje na jednostkę i musi być powiązana z zestawem encji. W kodzie modelu konstruktora dodaj tę linię, aby rozwiązać problem.

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

Co to jest, aby utworzyć encję "języki". Konstruktor modelu konwencji powiązuje właściwość nawigacji z ustawionym obiektem, jeśli taki istnieje. Tak więc właściwość nawigacji Languages na obiekcie typu User będzie związana z jednostką ustawioną jako languages.

+0

dziękuję, że faktycznie wykonała zadanie i nie dała już błędu! Nie zwraca jednak języków w wyniku odata, czy wiesz, dlaczego tak jest? Czytałem o kwerendy rozszerzenia, ale nie wydaje się działać. – Fergers

+1

OData domyślnie nie rozwija relacji. Są one reprezentowane zamiast jako łącza. Aby uzyskać podobne języki podczas odpytywania dla użytkowników, musisz użyć uri 'http: // localhost/odata/Users? $ Expand = Languages'. Zapoznaj się z dokumentacją pod adresem http://www.odata.org/documentation/odata-v3-documentation/url-conventions/#513_Expand_System_Query_Option –

+0

Co zrobić, jeśli nie chcemy zaoferować podmiotu ustawionego na języki, aby uprościć nasze API, to istnieje przykład przy użyciu HasNavigationPropertyLink? – Michael