40

最简单的例子,我得到一个集合并尝试通过 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;

但这违背了我想做的很多事情的目的。有没有更好的办法?

4

10 回答 10

26

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

    [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。希望能帮助到你

于 2014-04-29T18:33:58.077 回答
25

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

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
于 2015-02-15T09:13:53.587 回答
13

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

在 WebApi 中没有延迟加载很好,因为您没有持久连接,并且无论如何您都运行了 .ToList() 。

于 2013-08-21T14:28:37.433 回答
8

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

    // GET: ALL Employee
    public IEnumerable<DimEmployee> Get()
    {
        using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities())
        {
            entities.Configuration.ProxyCreationEnabled = false;
            return entities.DimEmployees.ToList();
        }
    }
于 2016-10-21T03:32:47.463 回答
7

在Global.asax.csApplication_Start的函数中添加以下代码:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
    .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
    .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

这指示 API 将每个响应序列化为 JSON 并删除 XML 响应。

于 2017-06-05T05:28:39.247 回答
3

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

于 2016-08-12T20:16:03.560 回答
1

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

public UserVM() { }

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

缺少第一个构造函数。

于 2020-12-06T11:48:41.420 回答
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.

于 2021-03-17T14:02:02.287 回答
0

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

于 2020-04-26T00:12:22.833 回答
0

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

  1. 控制面板。2.打开或关闭Windows功能
  2. 选择互联网信息服务
  3. 检查所有万维网组件最好检查 IIS 中的所有组件。
  4. 安装组件。
  5. 在命令提示符下转到 (IIS) 类型 inetmgr。
  6. 在 Virtual 目录中选择已发布的代码。
  7. 转换为应用程序
  8. 浏览它的应用程序。
于 2020-06-16T15:51:07.630 回答