2

我有點困惑如何在我的WebAPI控制器中使用DTO。我正在使用實體框架的數據庫第一個概念。生成下面的實體數據模型:如何在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因爲每次定義,當我需要修改數據模型將再次產生的電火花和數據註釋都將丟失。

所以接下來,我定義了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" 
    },... 
] 

但是我需要以下desir編輯結果:

[ 
     { 
      "Street": "Example Street", 
      "Street_Number": 1, 
      "Zip": 12345.0, 
      "City": "New York", 
      "Country": "USA" 
     },... 
    ] 

有沒有人有想法我怎麼能解決這個問題?

+0

創建僅包含要暴露給API的屬性的包裝類 – Fabio

+0

僅因爲要使用某些數據註釋屬性就不需要創建其他模型。你可以簡單地使用[MetadataTypeAttribute](https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute(v = vs.110).aspx) –

+0

@RezaAghaei你可以舉個例子碼? – yuro

回答

4

您的新編輯僅表示您不需要AddressDTO型號中的IdMember屬性。而你應該把結果塑造成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(); 

同樣在一個大型項目中,您可以依賴一些對象映射器,如自動映射器,如答案中所述。

+0

我是否需要創建另一個部分類「地址」? – yuro

+0

如果您對答案有任何疑問,或者您覺得有用,請告知我:) –

+0

感謝您的支持!我會稍後再嘗試,並給你一個反饋:) – yuro

2

使用庫如Automapper來處理您的需求。

然後你只需要修改下面一行到這個例如:

var addressList = await Mapper.Map<IList<AddressDto>>(db.Address.ToListAsync()); 

這將您的地址列表轉換成AddressDto列表,您可以控制被轉換或不那麼不通過議員例如你的看法。如果字段名稱相同,Automapper將自動知道要轉換的內容。

相關問題