2

I have a problem with my code. I have some basics WEB API Controller that works ok (three fields without any foreign keys), but i have a problem with a API Controller that returns a list of objects from the model, and that class has a Foreign key to another class from the model. This throws an error: Here is the Api Controller:

Public Class MaestroProvinciaController
    Inherits System.Web.Http.ApiController

    Private db As New UnificadorEntities

    ' GET api/MaestroProvincia
    Function GetMaestroProvincias() As IEnumerable(Of MaestroProvincia)
        Dim l As IEnumerable(Of MaestroProvincia)
        l = db.MaestroProvincia.AsEnumerable()
        Return l
    End Function
End Class

And here is the Model of MaestroProvincia

Partial Public Class MaestroProvincia
  Public Property Codigo As Integer
  Public Property Descripcion As String
  Public Overridable Property Usuario As ICollection(Of Usuario) = New HashSet(Of Usuario)

End Class

When i consume , to try, from the browser to this address: ......../api/maestroprovincia

I got an error: Error del servidor El sistema encontró un error mientras extraía ......../api/maestroprovincia . Es posible que el servidor no esté disponible por mantenimiento o no esté bien configurado. A continuación se detallan algunas sugerencias: Volver a cargar esta página web después. Error HTTP 500 (Internal Server Error): Se encontró una situación inesperada mientras el servidor intentaba cumplir con la solicitud.

When I debug the Controller, put a WATCH (inspect) in the "l" variable, and the type of the objects of the list it is very strange, instead of MaestroProvincia type I get system.data.entity.DynamicProxies.MaestroProvincia_D7543654378543.

All the other API Controllers that returns objects from models without FK does not have any problem.

I would appreciate your help.

tereško
  • 58,060
  • 25
  • 98
  • 150
user1800750
  • 21
  • 1
  • 3

2 Answers2

0

It looks like you are using EF with either a model-first or database-first approach. EF is returning dynamic proxies that allow you to lazy load dependent table by using the foreign keys. You cannot serialize dynamic proxies, which will be required for your API to return the results. It is generally not a good practice to return your EF entities directly. You should use data transfer objects (DTO) that are pure POCOS instead.

By pure POCOS I mean classes you have defined yourself that mimic the Entities but only return the data required by the client. You cannot use the POCOS generated by EF using the T4 template as sometimes they are pure POCOS and sometimes they are dynamic proxies. The way you convert your Entities to DTO's is to create a class using the same names for the properties in your Entity and only including those properties used by the client. I usually put the DTO's in a separate namespace to distinguish them from the Entities. Then use Automapper to automatically map the Entities to DTO's and DTO's to Entities coming back. Automapper takes the drudgery out of the mapping process. You create the map with just a single line of code:

Mapper.CreateMap<Entity.MaestroProvincia, DTO.MaestroProvincia>();

And then it just takes another line of code to perform the actual mapping:

DTO.MaestroProvincia dto = Mapper.Map<Entity.MaestroProvincia, DTO.MaestroProvincia>(maestroProvincia);
Community
  • 1
  • 1
Kevin Junghans
  • 17,475
  • 4
  • 45
  • 62
  • How can i do that? I think that the EF with the db.MaestroProvincia.AsEnumerable already returns a list of POCO entities. – user1800750 Nov 06 '12 at 12:20
  • Thank you very much, one last question, when should i execute then Mapper.createmap? just before the Mapper.Map or i can do it one time in another place in the code? – user1800750 Nov 06 '12 at 20:23
  • I define them at the top of the Web API Controller so they are created when the controller is constructed. – Kevin Junghans Nov 07 '12 at 13:26
0

Those are the proxies created by Entityy Framework to facilitate lazy loading. But it will have all the propeties your domain model had. What you should do is read the data from those classes and return your ViewModels (POCO classes) to the public world. It is not a good idea to return your domain model as it is to the public world. People can figure out how your table looks like from that.

Create ViewModels (POCO classes) for returning data to the outside world. Have only propertes which are necessary to return. you do not need to have all the properties of your domain model in your viewmodel all then time. Get the Data from your data access later, read items, map it to the instance of your viewmodel and return that.

List<Mastero> masteroList=new List<Mastero>();
var domainItems=db.MaestroProvincia.AsEnumerable();
foreach(var item in domainItems)
{
  var vm=new Mastero();
  vm.Name=item.Name;
  vm.Description=item.Description;
  masteroList.Items.Add(vm);
}  
 //Now return masteroList to the public

Assuming Mastero is a POCO class, your viewmodel.

public class Mastero
{
  public string Name { set;get;}
  public string Description { set;get;}
}
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thankyou, I understood, but i then have have to repeat the entire domain with another POCO class then?. – user1800750 Nov 06 '12 at 12:23
  • @user1800750 : Not the entire domain models. Only what you want to return to public. It is not a good idea to tie the domain models to front end, – Shyju Nov 06 '12 at 12:58