7

是否有 .Net 属性会告诉 Breeze 完全忽略某个属性?

我知道使属性受到保护是一种将其隐藏在 Breeze 中并防止其序列化的方法,但是如果我希望它保留public呢?

4

2 回答 2

15

设计一种简单、可维护的方法让 EF 生成的元数据对客户端说一件事,而对 EF 本身说另一件事是很棘手的。

但是,如果您愿意拥有两个DbContext ,则可以这样做:用于服务器端模型操作的“真实” DbContext和另一个严格用于客户端元数据生成的DbContext 。

元数据的 DbContext

这并不像听起来那么困难。我在 DocCode 中尝试过这样的事情。我创建了一个NorthwindMetadataContext继承自NorthwindContext. 它隐藏了废弃的CustomerID_OLD属性。

这是整个 DbContext:

公共类 NorthwindMetadataContext : NorthwindContext
{
    受保护的覆盖无效 OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Customer>().Ignore(t => t.CustomerID_OLD);
    }
}

你没看错!我只是添加了一条 EF Fluent API 指令来CustomerID_OLD隐藏NorthwindMetadataContext.

它仍然在Customertype 上,并且仍然为 base 所知NorthwindContext。这意味着CustomerID_OLD当您使用 查询时,查询将返回该属性,NorthwindContext但在您使用 查询时不会返回该属性NorthwindMetadataContext

当然,您只使用NorthwindMetadataContext来为 Breeze 客户端生成元数据。您的所有服务器逻辑继续使用“真实”的基础NorthwindContext

NorthwindRepository我通过更改实现Metadata属性的方式来确保会发生这种情况:

公共字符串元数据
{
    得到
    {
        var metaContextProvider = new EFContextProvider<NorthwindMetadataContext>();
        返回 metaContextProvider.Metadata();
    }
}

所有其他成员对“真实” DbContextNorthwindRepository使用EFContextProvider

私有只读 EFContextProvider<NorthwindContext>
    _contextProvider = new EFContextProvider<NorthwindContext>();

这就像一个魅力。据客户所知,该CustomerID_OLD物业不存在。

尽量让隐藏的数据远离网络

尽管您已对 Breeze 客户端隐藏了该属性,但该属性仍保留在服务器端实体类型上,并且因为我们使用“真实”DbContext 进行查询和保存操作,您可以在CustomerID_OLD查询中看到该属性通过线路传输结果有效载荷。

为了防止这种情况发生,您可以将 JSON.NET 序列化程序[JsonIgnore]属性添加到Customer.CustomerID_OLD模型中的属性(如果您不想使用 JSON.NET 序列化属性污染模型,则可以使用其他 JSON.NET 配置选项)。

再次运行,CustomerID_OLD不再序列化。该CustomerID_OLD属性现在对客户端完全不可见,但仍然可以在服务器上的模型中访问。

谨防

隐藏在元数据中的属性对 Breeze 客户端是隐藏的……但对世界是隐藏的。因为您希望该属性在 SERVER-SIDE TYPE 上可用,所以即使您在序列化完整类型时隐藏了该数据,邪恶的客户端(不是 Breeze 客户端)仍然可以通过投影获取该数据。

以下查询 URL 返回投影数据,其中包含CustomerID_OLD查询整个Customer对象时不可见的数据。

http://localhost:47595/breeze/Northwind/Customers?$filter=startswith(CompanyName,'C') eq true&$select=CustomerID_OLD,CompanyName

这是一些结果:

    {
        "$id": "1",
        "$type": "_IB_em9q7XTURqKf5bmIrAQD0bJ6f_po[[System.String, mscorlib],[System.String, mscorlib]], _IB_em9q7XTURqKf5bmIrAQD0bJ6f_po_IdeaBlade",
        "CustomerID_OLD": "CACTU",
        "CompanyName": "Cactus Comidas para llevar"
    },

也许更严重的是,POST 可以更新到“SaveChanges”请求的有效负载中的隐藏属性。

与敏感数据一样,您必须检查每个保存请求,以确保允许用户保存OriginalValues集合中标识的每个更改的属性值。

如果您有安全方面的顾虑,我觉得将DTO用于携带不得暴露给未经授权的客户端的数据的类型会更安全。我不喜欢每种类型的 DTO。这是矫枉过正,可能会破坏生产力。但对于具有重要保密要求的实体类型,我确实喜欢它们。

示例代码

我还没有决定是否将这个示例保留在已发布的 DocCode 中或将其存储在我的私人保留中。这是一个很酷的技巧。

我担心的是人们会认为这种技术是一种隐藏机密数据的安全方法,而事实并非如此。隐藏您宁愿隐藏的数据很好。但如果它必须远离电线,你最好使用 DTO。

让我知道我所描述的内容是否足够清楚,您可以在没有具体示例的情况下继续进行。

于 2013-05-01T07:33:21.493 回答
6

如果您使用 Json.Net 序列化程序(Breeze.WebApi 默认),您可以使用 JsonIgnoreAttribute,在此处描述

于 2013-04-30T05:31:09.927 回答