2

我正在创建我的第一个 ASP.NET MVC4 Web API。我有一个数据库,其中已经在 Azure 上创建和托管了 20 个左右的实体,并使用 Entity Framework 将数据库反向工程为 POCO 类。

他们最终看起来像这样:

public class Activity
{
    public Activity()
    {
        this.ActivityCategories = new List<ActivityCategory>();
        this.ActivityImages = new List<ActivityImage>();
        this.PerformedActivities = new List<PerformedActivity>();
        this.UserActivities = new List<UserActivity>();
    }

    public int ActivityID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<int> Thumbnail { get; set; }
    public virtual Image Image { get; set; }
    public virtual ICollection<ActivityCategory> ActivityCategories { get; set; }
    public virtual ICollection<ActivityImage> ActivityImages { get; set; }
    public virtual ICollection<PerformedActivity> PerformedActivities { get; set; }
    public virtual ICollection<UserActivity> UserActivities { get; set; }
}

然后,我创建了一个 ApiController 扩展类,其操作如下:

    public IEnumerable<Activity> All()
    {
        return db.Activities.ToArray();
    }

而且,正如预期的那样,它返回了一个很长的 JSON 回复。JSON 回复包括 Activity 类中定义的所有内容。但是,如果我不想包含所有内容怎么办?例如,我不想返回 UserActivities、PerformedActivities 等内容。

基本上我希望我的 JSON 看起来像:

[
    {
        "id":"32",
        "name":"this activity name",
        "description":"blah blah",
        "thumbnail":"http://mydomain.com/images/32/thumbnail.png",
        "images": [
            {
                "name":"this image",
                "url":"http://mydomain.com/images/32/1.png",
            },
            {
                "name":"cool image",
                "url":"http://mydomain.com/images/32/2.png",
            },
        ],
    },
    ...
]

(忽略我的 JSON 中的任何格式错误,只是非常快地输入了示例)

请注意,我也不一定要使用相同的属性名称。有没有一种有效的方法可以将我的数据转换成我想要的格式?

我的第一个想法是将每个活动复制到一个仅包含我想要的属性的结构数组中。有没有更优雅的解决方案?

4

2 回答 2

4

在这种情况下,DTO 对象会拯救您,DTO 将为您的消费者提供足够的数据,因此请定义需要通过 Web API 传输数据的 DTO。在某些情况下,您可以使用 EF 中的模型,但是:

  1. 通常,EF 会在后台生成动态代理以支持延迟加载和跟踪更改。您可能遇到的问题是序列化问题,因为 Web API 将序列化代理,而不是您的 POCO 对象。

  2. 向消费者传输太多不必要的数据会使 HTTP 请求变得繁重并泄露数据泄漏。

  3. 违反关注点分离,当 EF Model 是领域实体时,它们不作为数据传输对象承担责任。

在您的示例中,您可以定义ActivityDto并消除您提到的不必要的属性:

public class ActivityDto
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<int> Thumbnail { get; set; }
    public virtual Image Image { get; set; }
}

public IEnumerable<Activity> All()
{
    return db.Activities.Select(a => new ActivityDto(){
        Name = a.Name,
        Description = a.Description,
        Thumbnail = a.Thumbnail
        // More properties if you need

    }).ToArray();
}

如果您想寻找自动将 DTO 映射到 EF 模型的工具,AutoMapper就在这里。

于 2012-09-19T07:25:37.240 回答
1

在 MVC 中,将数据库实体用作模型并不是真正的最佳实践,相反,我会创建一个 POCO(甚至更复杂的对象)作为您的 ViewModel,然后您可以返回它只包含您的视图所需的数据(或者在这种情况下是 API 用户)。如果您只想操作返回的数据,我不知道该怎么做,但我知道 WebAPI 使用 newtonsoft 的 JSON.NET 库来输出 JSON,因此您将研究操作它的方法。

于 2012-09-18T17:18:42.757 回答