Asp.Net Web API错误:'ObjectContent`1'类型无法序列化内容类型'application / xml的响应主体;字符集= UTF-8'

时间:2012-12-19 18:48:20

标签: entity-framework entity-framework-4 asp.net-web-api

最简单的例子,我得到一个集合并尝试通过Web API输出:

// GET api/items
public IEnumerable<Item> Get()
{
    return MyContext.Items.ToList();
}

我收到错误:

  

类型的对象   
'System.Data.Objects.ObjectQuery`1 [Dcip.Ams.BO.EquipmentWarranty]'   无法转换为类型   
'System.Data.Entity.DbSet`1 [Dcip.Ams.BO.EquipmentWarranty]'

这是与新代理相关的常见错误,我知道我可以通过设置来修复它:

MyContext.Configuration.ProxyCreationEnabled = false;

但这违背了我想要做的很多事情的目的。还有更好的方法吗?

10 个答案:

答案 0 :(得分:25)

如果你有导航属性并且你不想让它们非虚拟,你应该使用JSON.NET并将App_Start中的配置更改为使用JSON而不是XML!
安装JSON.NET之后从NuGet中,将此代码插入Register方法

中的WebApiConfig.cs中
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

答案 1 :(得分:24)

我建议只在您不需要或导致麻烦的地方禁用代理创建。您不必全局禁用它,您只需通过代码禁用当前的数据库上下文...

    [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。 希望它有所帮助

答案 2 :(得分:12)

如果您有导航属性,则将它们设为非虚拟。映射仍然有效,但它会阻止创建无法序列化的动态代理实体。]

没有延迟加载在WebApi中没问题,因为你没有持久连接而且你还是运行了.ToList()。

答案 3 :(得分:7)

我只是根据需要禁用了代理类:

    // GET: ALL Employee
    public IEnumerable<DimEmployee> Get()
    {
        using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities())
        {
            entities.Configuration.ProxyCreationEnabled = false;
            return entities.DimEmployees.ToList();
        }
    }

答案 4 :(得分:4)

这对我有所帮助:
Global.asax.cs

Application_Start函数中添加以下代码
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
    .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
    .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

答案 5 :(得分:3)

在我的例子中,返回的对象在其中有一个属性,其类型没有无参数/默认构造函数。通过向该类型添加零参数构造函数,可以成功序列化对象。

答案 6 :(得分:1)

我收到此错误消息,结果发现问题是我不小心将类设置为对两个属性使用相同的序列化属性名称:

public class ResultDto
{
    //...
    [JsonProperty(PropertyName="DataCheckedBy")]
    public string ActualAssociations { get; set; }
    [JsonProperty(PropertyName="DataCheckedBy")]
    public string ExpectedAssociations { get; set; }
    //...
}

如果您收到此错误并且没有直接通过 API 发送实体,请将无法序列化的类复制到 LINQPad 并对其调用 JsonConvert.SerializeObject(),它应该会给您更好的错误消息比这个废话。我一尝试,它就给了我以下错误消息:A member with the name 'DataCheckedBy' already exists on 'UserQuery+ResultDto'. Use the JsonPropertyAttribute to specify another name.

答案 7 :(得分:0)

在禁用代理创建后,使用预先加载(Include())来加载代理对象。

答案 8 :(得分:0)

在我的项目中,从WebApi操作方法返回的EntityCollection。 Configuration.ProxyCreationEnabled = false不适用。我尝试了以下方法,对我来说很好用。

  1. 控制面板。 2.打开或关闭Windows功能
  2. 选择Internet信息服务
  3. 检查所有万维网组件,最好检查IIS中的所有组件。
  4. 安装组件。
  5. 转到(IIS)在命令提示符下键入inetmgr。
  6. 在“虚拟”目录中选择已发布的代码。
  7. 转换为应用程序
  8. 浏览该应用程序。

答案 9 :(得分:0)

我遇到了同样的问题,我的DTO缺少缺少参数的构造函数。

public UserVM() { }

public UserVM(User U)
    {
        LoginId = U.LoginId;
        GroupName = U.GroupName;
    }

缺少第一个构造函数。