我的代码有问题。 我有一些基本的WEB API控制器工作正常(三个字段没有任何外键),但我有一个问题,API控制器返回模型中的对象列表,并且该类有一个外键到另一个类来自模型。 这会引发错误: 这是Api控制器:
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
这是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
当我从浏览器到此地址消费时,尝试:
......../api/maestroprovincia
我收到了一个错误:
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.
当我调试Controller时,在"l"
变量中放入一个WATCH(inspect),列表对象的类型很奇怪,而不是MaestroProvincia
类型我得到{{ 1}}。
从没有FK的模型返回对象的所有其他API控制器没有任何问题。
感谢您的帮助。
答案 0 :(得分:0)
看起来您正在使用EF模型优先或数据库优先方法。 EF返回动态代理,允许您通过使用外键来延迟加载依赖表。您无法序列化动态代理,这是API返回结果所必需的。直接返回EF实体通常不是一个好习惯。您应该使用纯data transfer objects (DTO)的POCOS。
纯粹的POCOS我指的是你自己定义的类,它们模仿实体但只返回客户端所需的数据。您不能使用EF生成的POCOS使用T4模板,因为有时它们是纯POCOS,有时它们是动态代理。将实体转换为DTO的方法是使用与实体中属性相同的名称创建一个类,并仅包括客户端使用的那些属性。我通常将DTO放在一个单独的命名空间中,以区别于实体。然后使用Automapper自动将实体映射到DTO,将DTO映射到返回的实体。 Automapper将苦差事带出了映射过程。只用一行代码创建地图:
Mapper.CreateMap<Entity.MaestroProvincia, DTO.MaestroProvincia>();
然后它只需要另一行代码来执行实际的映射:
DTO.MaestroProvincia dto = Mapper.Map<Entity.MaestroProvincia, DTO.MaestroProvincia>(maestroProvincia);
答案 1 :(得分:0)
这些是由Entityy Framework创建的代理,以方便延迟加载。但它将拥有您的域模型所具有的所有功能。您应该做的是从这些类中读取数据并将ViewModel(POCO类)返回给公共世界。将您的域名模型返回到公共世界是不一个好主意。人们可以从中弄清楚你的桌子是怎么样的。
创建ViewModels( POCO类 ),以便将数据返回到外部世界。只有返回所需的财产。您不需要在viewmodel中拥有域模型的所有属性。稍后从您的数据访问中获取数据,读取项目,将其映射到viewmodel的实例并返回该项目。
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
假设Mastero
是POCO类,则是您的viewmodel。
public class Mastero
{
public string Name { set;get;}
public string Description { set;get;}
}