1

I am trying to create a RESTful web service that returns a list of products using ASP.NET MVC4 Web API. Here is my controller class

public class ProductController : ApiController
{
    public IEnumerable<Product> GetProducts()
    {
        WebCatalogContext dbcontext = DatabaseConfig.Instance.Context;
        List<Product> plist = dbcontext.Products.ToList();
        return plist;
    }
}

When I run my service and call the following URL from my browser :/api/Product, I get System.Runtime.Serialization.SerializationException. I looked into my plist object and there is no problem with it.

Here is my data model:

[DataContract(Name = "p")]
[Serializable]    
public class Product
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [DataMember(Name = "id")]
    public int Id { get; set; } 

    [Required, MaxLength(50)]
    [DataMember(Name = "ti")]
    public string Title { get; set; }

    [Required]
    [DataMember(Name = "de")]
    public string Description { get; set; }

    [Required]
    [DataMember(Name = "ph")]
    public string PhotoURL { get; set; }

    [DataMember(Name = "ca")]        
    public virtual ProductCategory Category { get; set; }
}


[DataContract(Name="pc")]
[Serializable]
public class ProductCategory
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [DataMember(Name="id")]
    public int Id { get; set; }

    [DataMember(Name="nm")]
    public string Name { get; set; }
}

When I remove the reference to ProductCategory from my Product class, all things work just fine. But, when I include it I get the following exception.

Type 'System.Data.Entity.DynamicProxies.Product_664E9A0AA1F165A26C342B508BFFF1279FD3FE059285225BDA19F407A29A9CAD' with data contract name 'Product_664E9A0AA1F165A26C342B508BFFF1279FD3FE059285225BDA19F407A29A9CAD:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

Any idea about what I am missing?

Regards

2 Answers 2

1

Entity Framework has wrapped your POCO with an EF Proxy POCO so it can perform lazy loading - this uses the Virtual attribute to create a 'lazy-loadable' navigation property. I expect that is where the serialization error comes from.

You could make a new class and map the POCO to that - then pass the DTO style class from the controller. I've never returned an EF object directly from the API (I always map to some something else) so I don't know another option.

EF POCO to DTO (data transfer object) is relatively painless if you use a tool like http://valueinjecter.codeplex.com/ or http://automapper.org/

Sign up to request clarification or add additional context in comments.

Comments

1

To support Lazy Loading for navigation properties which is declared as virtual, EF will generate the proxies for any models which have navigation properties which leads to this kind of exception.

For very simple application, you can use model from EF as DTOs (if having no navigation properties), but for complex application, you should do separate and differ between DTOs and domain models. It should not be mapping 1:1 between DTO and domain model.

Therefore, in your case, you create more DTO model for Web API layer, it will be fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.