4

所以我有一个模型Subscription,它继承自 Azure 的TableEntity类,用于 WebApi Get 方法,如下所示:

[HttpGet]
public IEnumerable<Subscription> Subscribers()

在这种方法中,我Select对我的订阅者表进行查询以查找所有订阅者,但我只想返回一些列(属性),如下所示:

var query = new TableQuery<Subscription>().Select(new string[] {
    "PartitionKey", 
    "RowKey", 
    "Description", 
    "Verified"
    });

该模型的定义如下:

public class Subscription : TableEntity
{
    [Required]
    [RegularExpression(@"[\w]+",
     ErrorMessage = @"Only alphanumeric characters and underscore (_) are allowed.")]
    [Display(Name = "Application Name")]
    public string ApplicationName
    {
        get
        {
            return this.PartitionKey;
        }
        set
        {
            this.PartitionKey = value;
        }
    }

    [Required]
    [RegularExpression(@"[\w]+",
     ErrorMessage = @"Only alphanumeric characters and underscore (_) are allowed.")]
    [Display(Name = "Log Name")]
    public string LogName
    {
        get
        {
            return this.RowKey;
        }
        set
        {
            this.RowKey = value;
        }
    }

    [Required]
    [EmailAddressAttribute]
    [Display(Name = "Email Address")]
    public string EmailAddress { get; set; }

    public string Description { get; set; }

    public string SubscriberGUID { get; set; }

    public bool? Verified { get; set; }
}

以下是 API 查询的 XML 响应:

<ArrayOfSubscription>
    <Subscription>
        <ETag>W/"datetime'2013-03-18T08%3A54%3A32.483Z'"</ETag>
        <PartitionKey>AppName1</PartitionKey><RowKey>Log1</RowKey>
        <Timestamp>
            <d3p1:DateTime>2013-03-18T08:54:32.483Z</d3p1:DateTime>
            <d3p1:OffsetMinutes>0</d3p1:OffsetMinutes>
        </Timestamp>
        <ApplicationName>AppName1</ApplicationName>
        <Description>Desc</Description>
        <EmailAddress i:nil="true"/>
        <LogName>Log1</LogName>
        <SubscriberGUID i:nil="true"/>
        <Verified>false</Verified>
    </Subscription>
</ArrayOfSubscription>

正如你所看到的,模型不仅有一些额外的属性,比如SubscriberGUID我不想在响应中被序列化(因为它们不在选择查询中,所以它们无论如何都是空的),而且 TableEntity 本身也有这样的字段as PartitionKey, RowKey, Etag, 并且Timestamp也被序列化了。

如何继续使用 Azure 表,但避免在响应中序列化这些我不希望用户看到的不需要的字段。

4

4 回答 4

7

不同意使用特定 DTO 的答案,但 Microsoft.WindowsAzure.Storage 程序集现在提供了一个属性,IgnorePropertyAttribute您可以使用该属性来装饰您的公共属性以避免序列化。

我实际上还没有尝试过,但是有一个方法可以在返回之前检查一些事情(TableEntity即不要跳过):ShouldSkipProperty()false

  • 属性名称是“PartitionKey”、“RowKey”、“Timestamp”还是“ETag”之一 -> 跳过
  • getter 和 setter 中的任何一个都是非公开的 -> 跳过
  • 是静态的 -> 跳过
  • 属性是否具有属性 IgnorePropertyAttribute -> 跳过

看起来它会做的伎俩。

于 2014-01-12T05:56:34.530 回答
2

我建议使用 DTO(数据传输对象)来解决此类问题。DTO 可能意味着更多代码(更多类),但从长远来看会使您受益。您可以更好地控制电线上的内容。从安全的角度来看,它们也更好,而不是使用某些序列化程序特定的属性来控制在线上的内容。

有关更多信息,请参阅asp.net Web API 教程。

于 2013-03-19T02:35:05.320 回答
1

恕我直言,使用 DTO 是可行的方法,但要澄清一下,因为从帖子中不太明显的是在哪里实施 DTO。我希望我可以将它用作查询的一部分,但我不能。相反,我必须这样做:

query.SelectColumns = new List<string> { "QuoteId", "RateId", "Date" };
var results = await MyCloudTable.ExecuteQuerySegmentedAsync(query, null);
return results.Select(d => new MyDto { QuoteId = d.QuoteId, RateId = d.RateId, Date = d.Date }).ToList();

您必须从 TableQuery 返回 TableEntity 派生对象,但由于所有属性均为空(通过显式选择所需的列),因此在线上没有其他数据。然后,您可以投影到您的 DTO 中,这样您就可以准确地返回您需要的对象。

于 2015-01-04T18:24:56.850 回答
1

您不需要从 TableEntity 类继承。您可以使用 TableEntity.Flatten 方法从您的 Subscription 类创建一个 DynamicTableEntity 并写入表存储。当您从天蓝色表存储中读取 DynamicTableEntity 时,您可以使用 TableEntity.ConvertBack 方法重构您的订阅对象。这些静态帮助方法在 Azure 表存储 SDK 版本 >= 8.0.0 中可用

TableEntity.Flatten:https ://msdn.microsoft.com/en-us/library/azure/mt775434.aspx TableEntity.ConvertBack:https ://msdn.microsoft.com/en-us/library/azure/mt775432.aspx

消除您在 DTO 和业务数据模型之间进一步编写转换器类的需要

于 2017-03-13T22:51:45.660 回答