我有点困惑如何在我的WebAPI控制器中使用DTO。我正在使用数据库第一个实体框架概念。生成了以下实体数据模型:
//Generated class by EDM:
public partial class Address
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Address()
{
this.Member = new HashSet<Member>();
}
public int Id { get; set; }
public string Street { get; set; }
public Nullable<short> Street_Number { get; set; }
public Nullable<decimal> Zip { get; set; }
public string City { get; set; }
public string Country { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Member> Member { get; set; }
}
使用数据注释我需要定义AddressDTO
,因为每当我需要修改EDM时,数据模型将再次生成并且数据注释将丢失。
接下来,我定义了AddressDTO
:
public class AddressDTO
{
public int Id { get; set; }
[Required]
[StringLength(100,ErrorMessage="The max. length of the street name is 100 characters.")]
public string Street { get; set; }
public Nullable<short> Street_Number { get; set; }
[Required]
public Nullable<decimal> Zip { get; set; }
[Required]
[RegularExpression(@"[a-z,A-Z]",ErrorMessage="Only characters are allowed.")]
public string City { get; set; }
[Required]
public string Country { get; set; }
}
控制器看起来像下面的代码:
[RoutePrefix("api/address")]
public class AddressController : ApiController
{
private PersonEntities db = new PersonEntities();
// GET: api/Address
[HttpGet]
[ResponseType(typeof(AddressDTO))]
public async Task<IHttpActionResult> GetAll()
{
var addressList = await db.Address.ToListAsync();
return Ok(addressList);
}
}
当我启动RestAPI以在浏览器中显示结果时,我总是得到以下json结果:
[
{
"Member": [ ],
"Id": 1,
"Street": "Example Street",
"Street_Number": 1,
"Zip": 12345.0,
"City": "New York",
"Country": "USA"
},...
]
但我需要以下预期结果:
[
{
"Street": "Example Street",
"Street_Number": 1,
"Zip": 12345.0,
"City": "New York",
"Country": "USA"
},...
]
有谁知道如何解决这个问题?
答案 0 :(得分:6)
您的新修改只是意味着您的Id
模型中不需要Member
和AddressDTO
属性。当你返回List<AddressDTO>
时,哟应该将结果整形为List<Address>
。
因此,只需从AddressDTO
中移除未使用的属性,然后选择新的AddressDTO
并设置属性来调整结果:
var result = db.Address.Select(x=> new AddressDTO()
{
Street = x.Id,
Street_Number = x.Street_Number,
City = x.City,
Country = x.Country
}).ToListAsync();
如果你想缩短linq,你可以将这样的构造函数添加到AddressDTO
:
public AddressDTO(Address x)
{
Street = x.Id;
Street_Number = x.Street_Number;
City = x.City;
Country = x.Country;
}
然后在控制器中:
var result = db.Address.Select(x=> new AddressDTO(x)).ToListAsync();
同样在一个大型项目中,您可以依赖一些对象映射器,如答案中提到的自动映射器。
答案 1 :(得分:2)
使用像Automapper这样的库来满足您的需求。
然后你只需要将以下行修改为例如:
var addressList = await Mapper.Map<IList<AddressDto>>(db.Address.ToListAsync());
这会将您的地址列表转换为AddressDto列表,您可以在其中控制转换的内容,以便不将会员传递给您的视图。如果字段名称相同,Automapper将自动知道要转换的内容。