阻止Azure TableEntity属性在MVC 4 WebAPI中序列化

时间:2013-03-19 00:05:18

标签: c# serialization asp.net-mvc-4 asp.net-web-api azure-table-storage

所以我有一个模型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,我不希望在响应中序列化(并且因为它们不在select查询中,所以它们无论如何都是null ),但TableEntity本身包含PartitionKeyRowKeyEtagTimestamp等字段,这些字段也被序列化。

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

4 个答案:

答案 0 :(得分:6)

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

我还没有真正尝试过但是TableEntity上有一个名为ShouldSkipProperty()的方法在返回false之前会检查很多事情(即不要跳过):< / p>

  • 属性名称是“PartitionKey”,“RowKey”,“Timestamp”还是“ETag” - &gt;跳过
  • getter和setter是非公开的 - &gt;跳过
  • 是静态的 - &gt;跳过
  • 该属性是否具有属性IgnorePropertyAttribute - &gt;跳过

看起来它会起作用。

答案 1 :(得分:2)

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

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

答案 2 :(得分: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派生对象,但由于所有属性都为null(从显式选择所需的列),因此线上没有其他数据。然后,您可以投影到DTO,这样就可以准确地返回所需的对象。

答案 3 :(得分:1)

您不需要继承TableEntity类。您可以使用TableEntity.Flatten方法从Subscription类创建DynamicTableEntity并写入表存储。当您从azure表存储中读取DynamicTableEntity时,可以使用TableEntity.ConvertBack方法重新构建订阅对象。 Azure Table Storage SDK版本&gt; = 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和业务数据模型之间进一步编写转换器类

相关问题