Entity framework Asp.Net Web API错误:“ObjectContent`1”类型未能序列化内容类型“application/xml”的响应正文;字符集=utf-8'
最简单的例子是,我得到一个集合并尝试通过Web API输出它:Entity framework Asp.Net Web API错误:“ObjectContent`1”类型未能序列化内容类型“application/xml”的响应正文;字符集=utf-8',entity-framework,entity-framework-4,asp.net-web-api,Entity Framework,Entity Framework 4,Asp.net Web Api,最简单的例子是,我得到一个集合并尝试通过Web API输出它: // GET api/items public IEnumerable<Item> Get() { return MyContext.Items.ToList(); } 但这违背了我所做的很多事情的目的。有更好的方法吗?如果您有导航属性,请将其设置为非虚拟。映射仍然有效,但它会阻止创建无法序列化的动态代理实体。] 在WebApi中,没有延迟加载是可以的,因为您没有持久连接,并且您运行了.ToList。我建议仅在
// GET api/items
public IEnumerable<Item> Get()
{
return MyContext.Items.ToList();
}
但这违背了我所做的很多事情的目的。有更好的方法吗?如果您有导航属性,请将其设置为非虚拟。映射仍然有效,但它会阻止创建无法序列化的动态代理实体。]
在WebApi中,没有延迟加载是可以的,因为您没有持久连接,并且您运行了.ToList。我建议仅在不需要或给您带来麻烦的地方禁用代理创建。您不必全局禁用它,您只需通过代码禁用当前数据库上下文即可
[HttpGet]
[WithDbContextApi]
public HttpResponseMessage Get(int take = 10, int skip = 0)
{
CurrentDbContext.Configuration.ProxyCreationEnabled = false;
var lista = CurrentDbContext.PaymentTypes
.OrderByDescending(x => x.Id)
.Skip(skip)
.Take(take)
.ToList();
var count = CurrentDbContext.PaymentTypes.Count();
return Request.CreateResponse(HttpStatusCode.OK, new { PaymentTypes = lista, TotalCount = count });
}
在这里,我只在这个方法中禁用了ProxyCreation,因为对于每个请求,都会创建一个新的DBContext,因此我只在这种情况下禁用了ProxyCreation。
希望它能帮助你如果你有导航属性,你不想让它们成为非虚拟的,你应该使用JSON.NET并将App_中的配置改为使用JSON而不是XML! 从NuGet安装JSON.NET后,在Register方法中的WebApiConfig.cs中插入此代码
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
在我的例子中,返回的对象中有一个属性,其类型没有无参数/默认构造函数。通过向该类型添加零参数构造函数,可以成功序列化对象。我只是根据需要禁用了代理类:
// GET: ALL Employee
public IEnumerable<DimEmployee> Get()
{
using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities())
{
entities.Configuration.ProxyCreationEnabled = false;
return entities.DimEmployees.ToList();
}
}
这帮助了我:
在Global.asax.cs的Application_Start函数中添加以下代码
禁用代理创建后,使用“即时加载包含”加载代理对象。在从WebApi操作方法返回的my Project EntityCollection中。 Configuration.ProxyCreationEnabled=false不适用。我已经尝试了下面的方法,它对我来说很好 控制面板 2.打开或关闭Windows功能 选择互联网信息服务 检查所有万维网组件最好检查IIS中的所有组件。 安装部件。 在命令提示符下转到IIS类型inetmgr。 在虚拟目录中选择已发布的代码。 转换为应用程序 在应用程序中浏览它。
我也有同样的问题,我的DTO缺少一个无参数构造函数
public UserVM() { }
public UserVM(User U)
{
LoginId = U.LoginId;
GroupName = U.GroupName;
}
缺少第一个构造函数。我收到了此错误消息,结果发现问题在于我不小心将类设置为对两个属性使用相同的序列化属性名:
public class ResultDto
{
//...
[JsonProperty(PropertyName="DataCheckedBy")]
public string ActualAssociations { get; set; }
[JsonProperty(PropertyName="DataCheckedBy")]
public string ExpectedAssociations { get; set; }
//...
}
如果您遇到此错误,并且没有直接通过API发送实体,请将无法序列化的类复制到LINQPad,并在其上调用JsonConvert.SerializeObject,它应该会给您提供比此垃圾更好的错误消息。当我尝试此操作时,它给了我以下错误消息:“UserQuery+ResultDto”上已经存在名为“DataCheckedBy”的成员。使用JsonPropertyAttribute指定另一个名称。关闭代理如何阻止序列化对象?这是一个代理对象,而不是全局关闭代理的实际位置,这意味着您无法使用延迟加载的导航属性。我同意如果您需要导航属性,那么这不是一个合适的解决方案。我自己仍然在寻找这个问题的答案。我也有同样的问题,让导航属性非虚拟化可以解决这个问题,但我很想知道这种技术是否有缺点?谢谢@Robert将它们标记为vitual将允许在内部重写该类。EF将重写以允许延迟加载,例如,它将仅在请求内部列表或属性时获取它们。在MVC或其他有断开连接的架构的情况下,它实际上没有什么区别,因为您需要立即获得所有数据。假设默认情况下JSON.NET与VS15上的新webapi项目一起添加,请也添加解释。这是一个很好且准确的答案。这将指示api将每个响应序列化为json并删除XML响应+1还要加上解释。
public UserVM() { }
public UserVM(User U)
{
LoginId = U.LoginId;
GroupName = U.GroupName;
}
public class ResultDto
{
//...
[JsonProperty(PropertyName="DataCheckedBy")]
public string ActualAssociations { get; set; }
[JsonProperty(PropertyName="DataCheckedBy")]
public string ExpectedAssociations { get; set; }
//...
}