我有一個很奇怪的問題。我正在創建一個ASP.Net Core前端網站和一個ASP.Net Core後端API。後端API使用Entity Framework Core來實現持久性。試圖從一個領域類映射到視圖模型類跳過屬性
我用一個視圖模型類,從網站的數據發佈到API,然後我用AutoMapper從視圖模型類的實體類映射到它傳遞給基於EF庫。這適用於此項目中與其他數據庫表有關的另外兩個視圖模型/實體類關係。
不過,我加入了一個新的數據庫表和相關視圖模型/實體類集合是給我這個奇怪的問題。
通過這種特定的實體/視圖模型關係,Automapper失敗並且沒有錯誤。它只是跳過實體類中未定義的任何屬性,並在數據類型之後帶有問號(使屬性可爲空)。
我創建了一個方法的屬性,一個一個手動映射,從視圖模型類的實體類,我看到了同樣的問題,所以我認爲這是沒有具體的AutoMapper問題。
這是我的實體類;
using System;
using System.Collections.Generic;
namespace API.Models
{
public partial class UserFeaturesEvs
{
public int UserId { get; set; }
public bool Active { get; set; }
public string LoginNickname { get; set; }
public string CarrierLoginName { get; set; }
public string CarrierLoginPassword { get; set; }
public int CarrierId { get; set; }
public int? CarrierLoginId { get; set; }
public string PermitNumber { get; set; }
public string PermitType { get; set; }
public string PermitName { get; set; }
public int? McdPrimaryId { get; set; }
public string Crid { get; set; }
public string CapsId { get; set; }
public bool? IsGovernment { get; set; }
public string CityStateOfPo { get; set; }
public string PoOfAccountZip { get; set; }
public string MasterMid { get; set; }
public string ChildMid { get; set; }
public string IndiciaText { get; set; }
public string LoginId { get; set; }
public string PostageType { get; set; }
public int? SiteId { get; set; }
}
}
這裏是我的視圖模型類;
using System.ComponentModel.DataAnnotations;
namespace API.ViewModels.EVS
{
public class UserFeaturesEvsViewModel
{
public bool Active { get; set; }
[Display(Name = "User ID")]
public int UserId { get; set; }
[Display(Name = "Carrier ID")]
[Required]
public int CarrierId { get; set; }
[Display(Name = "Site ID")]
public int SiteId { get; set; }
[Display(Name = "Nick Name")]
public string LoginNickname { get; set; }
[Display(Name = "Login Name")]
[Required]
public string CarrierLoginName { get; set; }
[Display(Name = "Password")]
[Required]
public string CarrierLoginPassword { get; set; }
[Display(Name = "Carrier Login ID")]
public int CarrierLoginId { get; set; }
[Display(Name = "MCD Primary ID")]
public int McdPrimaryId { get; set; }
[Display(Name = "Permit Number")]
public string PermitNumber { get; set; }
[Display(Name = "Permit Type")]
public string PermitType { get; set; }
[Required]
[Display(Name = "Permit Name")]
public string PermitName { get; set; }
[Display(Name = "CRID")]
public string Crid { get; set; }
[Display(Name = "CAPS ID")]
public string EvsCapsId { get; set; }
[Display(Name = "Government Permit")]
public bool EvsGovernmentPermit { get; set; }
[Display(Name = "PO of Account - City/State")]
public string EvsCityStateOfPo { get; set; }
[Display(Name = "PO of Account - Zipcode")]
public string EvsPoOfAccountZip { get; set; }
[Display(Name = "Master MID")
public string EvsMasterMid { get; set; }
[Display(Name = "Child ID")]
public string EvsChildMid { get; set; }
[Display(Name = "Indicia Text")]
public string EvsIndiciaText { get; set; }
[Display(Name = "Login ID")]
public string EvsLoginId { get; set; }
[Display(Name = "Postage Type")]
public string PostageType { get; set; }
}
}
這是我在API控制器類創建的測試方法,以手動地從視圖模型類映射到實體類現在
private UserFeaturesEvs MapUserFeaturesEvsViewModelToUserFeaturesEvs(UserFeaturesEvsViewModel a_model)
{
try
{
UserFeaturesEvs model = new UserFeaturesEvs();
if (a_model != null)
{
model.SiteId = a_model.SiteId;
model.Active = a_model.Active;
model.UserId = a_model.UserId;
model.CarrierId = a_model.CarrierId;
model.LoginNickname = a_model.LoginNickname;
model.CarrierLoginName = a_model.CarrierLoginName;
model.CarrierLoginPassword = a_model.CarrierLoginPassword;
model.CarrierLoginId = a_model.CarrierLoginId;
model.McdPrimaryId = a_model.McdPrimaryId;
model.PermitNumber = a_model.PermitNumber;
model.PermitType = a_model.PermitType;
model.PermitName = a_model.PermitName;
model.Crid = a_model.Crid;
model.CapsId = a_model.EvsCapsId;
model.IsGovernment = a_model.EvsGovernmentPermit;
model.CityStateOfPo = a_model.EvsCityStateOfPo;
model.PoOfAccountZip = a_model.EvsPoOfAccountZip;
model.MasterMid = a_model.EvsMasterMid;
model.ChildMid = a_model.EvsChildMid;
model.IndiciaText = a_model.EvsIndiciaText;
model.LoginId = a_model.EvsLoginId;
model.PostageType = a_model.PostageType;
}
return model;
}
catch (Exception ex)
{
m_logger.LogError(1, ex, "An exception occurred in the MapUserFeaturesEvsViewModelToUserFeaturesEvs method while trying to map the UserFeaturesEvsViewModel [{VM}] to the UserFeaturesEvs Model.", a_model);
return null;
}
,我可以看到出現的問題,因爲我單一步驟在Visual Studio 2015中,通過使用F11的MapUserFeaturesEvsViewModelToUserFeaturesEvs方法。一旦我越過if(a_model!= null)行,調試僅停止在SiteId,CarrierLoginId,McdPrimaryId和EvsGovernmentPermit的行上,跳過所有其他行。並且返回的UserFeaturesEvs對象只在這4個字段中有數據。我確認傳入該方法的UserFeaturesEvsViewModel對象在所有屬性中都有數據。
正在成功地分配數據UserFeatruesEvs類屬性只是具有由所指爲空的數據類型的人?在數據類型之後,如下面的UserFeaturesEvs類的屬性摘錄所示;
public int? CarrierLoginId { get; set; }
public int? McdPrimaryId { get; set; }
public bool? IsGovernment { get; set; }
public int? SiteId { get; set; }
實體類,UserFeaturesEvs從現有的數據庫表使用所生成..
dotnet ef dbcontext scaffold ...
...命令。
上面的命令行命令,還增加了以下到的DbContext類的代碼...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserFeaturesEvs>(entity =>
{
entity.HasKey(e => e.UserId)
.HasName("PK_UserFeatures_EVS");
entity.ToTable("UserFeatures_EVS");
entity.Property(e => e.UserId)
.HasColumnName("UserID")
.ValueGeneratedNever();
entity.Property(e => e.CapsId)
.HasColumnName("CapsID")
.HasColumnType("varchar(50)");
entity.Property(e => e.CarrierId).HasColumnName("CarrierID");
entity.Property(e => e.CarrierLoginId).HasColumnName("CarrierLoginID");
entity.Property(e => e.CarrierLoginName)
.IsRequired()
.HasColumnType("varchar(50)");
entity.Property(e => e.CarrierLoginPassword)
.IsRequired()
.HasColumnType("varchar(50)");
entity.Property(e => e.ChildMid)
.HasColumnName("ChildMID")
.HasColumnType("varchar(50)");
entity.Property(e => e.CityStateOfPo)
.HasColumnName("CityStateOfPO")
.HasColumnType("varchar(50)");
entity.Property(e => e.Crid)
.HasColumnName("CRID")
.HasColumnType("varchar(50)");
entity.Property(e => e.IndiciaText).HasColumnType("varchar(50)");
entity.Property(e => e.LoginId).HasColumnType("varchar(50)");
entity.Property(e => e.LoginNickname).HasColumnType("varchar(50)");
entity.Property(e => e.MasterMid)
.HasColumnName("MasterMID")
.HasColumnType("varchar(50)");
entity.Property(e => e.McdPrimaryId).HasColumnName("MCDPrimaryID");
entity.Property(e => e.PermitName).HasColumnType("varchar(50)");
entity.Property(e => e.PermitNumber).HasColumnType("varchar(50)");
entity.Property(e => e.PermitType).HasColumnType("varchar(50)");
entity.Property(e => e.PoOfAccountZip)
.HasColumnName("PoOfAccountZip")
.HasColumnType("varchar(50)");
entity.Property(e => e.PostageType).HasColumnType("varchar(50)");
entity.Property(e => e.SiteId).HasColumnName("SiteID");
});
}
public virtual DbSet<UserFeaturesEvs> UserFeaturesEvs { get; set; }
.
.
.
我什麼都看不到,是造成這個問題,就像我前面說的,我已經使用這個與其他兩個數據庫表相同的實體類/視圖模型類技術沒有問題。
我在上面討論的所有代碼都在ASP.Net Core API項目中。
我試過刪除?從UserFeaturesEvs類屬性中的數據類型聲明中,當我這樣做時,調試器跳過了所有的屬性賦值,並從映射方法返回所有的空數據。
編輯:進一步的分析表明,問題是與UserFeaturesEvsViewModel。我可以靜態地將值分配給MapUserFeaturesEvsViewModelToUserFeaturesEvs方法中的UserFeaturesEvs對象實例,它不會跳過沒有的屬性分配?在他們的數據類型聲明之後。由於這是一個API,UserFeatruesEvsViewModel來自API控制器中的Create方法。
[HttpPost("")]
public IActionResult Create([FromBody]UserFeaturesEvsViewModel a_vm)
{
try
{
//Test assignment of vm to local variables
int SiteId = a_vm.SiteId; // This gets skipped
bool Active = a_vm.Active; // This gets skipped
int UserId = a_vm.UserId; // This gets skipped
int CarrierId = a_vm.CarrierId; // This gets skipped
string LoginNickname = a_vm.LoginNickname; // This gets skipped
if (ModelState.IsValid)
{
UserFeaturesEvs model = MapUserFeaturesEvsViewModelToUserFeaturesEvs(a_vm);
//UserFeaturesEvs model = Mapper.Map<UserFeaturesEvs>(a_vm);
.
.
.
這是我張貼的應用/ JSON從谷歌Chrome郵差應用
{
"active": true,
"userId": 1,
"carrierId": 1,
"siteId": 1,
"loginNickname": "testNickname",
"carrierLoginName": "testLoginName",
"carrierLoginPassword": "testLoginPassword",
"carrierLoginId": 0,
"mcdPrimaryId": 0,
"permitNumber": "123456",
"permitType": "",
"permitName": "UserID1-123456",
"crid": "11",
"evsCapsId": "112233",
"evsGovernmentPermit": false,
"evsCityStateOfPo": "Somewhere, NY",
"evsPoOfAccountZip": "90210",
"evsMasterMid": "654321",
"evsChildMid": "654322",
"evsIndiciaText": "Test",
"evsLoginId": "",
"postageType": "P"
}
當我在調試器中查看a_vm,我看到了API控制器的JSON的樣本我發佈的數據,它似乎在UserVeaturesEvsViewModel類的結構中。但是,當我嘗試在Create方法的開始處簡單地將a_vm變量的屬性分配給局部變量時,如上所示,這些分配也僅由調試器跳過(即使我在賦值上放置了斷點),就像MapUserFeaturesEvsViewModelToUserFeaturesEvs方法中發生的一樣。
在其他沒有此問題的API控制器中,我將a_vm對象傳遞到我的實體框架存儲庫中。例如,這個相同的API的另一個控制器中的代碼工作得很好。
[HttpPost("")]
public IActionResult Create([FromBody]MerSettingsViewModel a_vm)
{
try
{
if (ModelState.IsValid)
{
MailEventsRetrieverSettings settings = Mapper.Map<MailEventsRetrieverSettings>(a_vm);
Task<MailEventsRetrieverSettings> task = m_cdiMppsRepository.AddMailEventsRetrieverSettingsAsync(settings);
MailEventsRetrieverSettings response = task.Result;
if (response != null)
{
return Ok(response);
}
}
return BadRequest(ModelState);
}
catch (Exception ex)
{
m_logger.LogError(1, ex, "Could not create new MailEventsRetrieverSettings record for the following object [{@VM}] to the database", a_vm);
return Json(new { Message = ex.Message });
}
}
所以,這個問題似乎是從對象自動從HttpPost的身體在創建方法反序列化的方式來。儘管在調試器中,我看到了a_vm中的值,並且它似乎結構正確,但如果未將類屬性或局部變量定義爲,我不能直接將這些屬性的值分配給另一個類屬性或局部變量空。
任何想法?
所以它只適用於可爲空屬性? – CodingYoshi
他們刪除您的整個bin文件夾並執行重建並重試。 – CodingYoshi
爲什麼你的模型類是部分的?你能展示這堂課的其他部分嗎? –