I am currently working on a mvc4 web api odata service where I want to return a List of Users where Users have a list of Languages. When I want to get the Users I get the following error:
Error:
<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>
My User looks like this:
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>();
}
}
and my UsersController for OData looks like this:
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);
}
}
I am calling the following url which i setup in my routing: http://127.0.0.1:81/odata/Users
it works if I comment navigation property in my User model.
What am i doing wrong? I already tryed to put [Serializable, KnownType(typeof(Language))] on top of my user class but for some reason i cant use KnownType. How can i make my OData work with this navigation property?
You are missing the entity set for Language. A navigation property points to an entity and has to be bound to an entity set. In your model builder code, add this line to fix the issue.
builder.EntitySet<Language>("languages");
What this does is to create the entity set 'languages'. The convention model builder binds a navigation property to an entity set if there is one. So, the navigation property Languages
on the entity type User
will be bound to the entity set languages
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With