[英]System.Text.Json JsonSerializer: Serialization and deserialization of 'System.Type' instances are not supported
[英]Serialization/Deserialization of System.Type in WebAPI Project with resource model PUT
我正在嘗試使用我的 EFCore 實體 class 上的自動映射資源 model 通過 WebAPI 修改數據。 我已經設法讓 GET、GET(by id)、DELETE 和 POST 使用這種方法正常工作。
現在我面臨的問題是我在嘗試使用此資源執行 PUT 時收到的“System.Type”錯誤消息的 Automapper 序列化和反序列化。 我設法將這個錯誤縮小到我的 ID 字段,這是 SQL 服務器中的主鍵身份字段。 在資源 model 中省略此 ID 可使 PUT 工作。
但是,我需要其他GETS 和DELETE 的ID 字段,因此不能從資源model 中省略它。
這是我的實體:
[Table("BlazorWebApiDemo")]
public partial class BlazorEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("First Name")]
[StringLength(50)]
public string FirstName { get; set; } = string.Empty;
[Column("Last Name")]
[StringLength(50)]
public string LastName { get; set; } = string.Empty;
[StringLength(50)]
public string Address { get; set; } = string.Empty;
}
這是我的 API 資源 Model:
public class BlazorEntityModel
{
public int Id { get; set; } // Commenting this out makes PUT work.
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
}
自動映射器簡介:
public class BlazorEntityProfile : Profile
{
public BlazorEntityProfile()
{
this.CreateMap<BlazorEntity, BlazorEntityModel>()
.ForMember(dest => dest.FirstName, opt => opt.NullSubstitute(""))
.ForMember(dest => dest.LastName, opt => opt.NullSubstitute(""))
.ForMember(dest => dest.Address, opt => opt.NullSubstitute(""))
//.ForMember(src => src.Id, opts => opts.Ignore())
.ReverseMap();
}
}
Controller PUT 方法:
[HttpPut("{id:int}")]
public async Task<ActionResult<BlazorEntityModel>> UpdateBlazorItem(int id, BlazorEntityModel blazorEntityModel)
{
try
{
var oldBlazorEntity = await blazorRepository.GetBlazorById(id);
if (oldBlazorEntity == null) return NotFound($"LetItem with the ID: {id} not found");
mapper.Map(blazorEntityModel, oldBlazorEntity);
if(await blazorRepository.SaveChangesAsync())
{
return mapper.Map<BlazorEntityModel>(oldBlazorEntity);
}
}
catch (Exception e)
{
return StatusCode(StatusCodes.Status500InternalServerError,
e);
}
return BadRequest(); //Error getting caught here.
}
有任何想法嗎?
代碼看起來不錯,這個問題可能出在客戶端; 即在調用/發送到backend API
時如何從Front end/Client
對其進行序列化。
仔細檢查您正在使用contentType:"application/json"
並在發送時使用JSON.stringify
方法將其轉換為 JSON 字符串。
更新 2:在您的 blazor 實體中嘗試添加key attribute
public class BlazorEntityModel
{
[Key] // add this to force it to recognize it as key
public int Id { get; set; } // Commenting this out makes PUT work.
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
}
更新 3:配置/覆蓋序列化處理
您可以嘗試在global.asax
中添加以下內容嗎
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
如果這可行,請告訴我我們可能必須轉移到 DTO 或 VM,以便我們跟蹤和循環/循環引用。
一種處理方法是使用 inheritance 的兩個類。
public class MyObject {
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
}
public class CreatedVersionOfMyObject : MyObject {
public int Id { get; set; }
}
然后您的 controller 可以輕松地使用這些實體公開多個端點
[Route("objects")]
public class MyObjectControLler : Controller
{
[Route("{id}")]
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
[ProducesResponseType(typeof(CreatedVersionOfMyObject), (int)HttpStatusCode.OK)]
public Task<IActionResult> GetByIdAsync(Guid id)
{
// Do what you have to do to retrieve the object by id
}
[Route("{id}")]
[HttpDelete]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
public Task<IActionResult> DeleteByidAsync(Guid id)
{
// Do what you have to do to delete the object by id
}
[Route("{id}")]
[HttpPut]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
[ProducesResponseType(typeof(MyObject), (int)HttpStatusCode.OK)]
public Task<IActionResult> PutAsync([FromRoute]Guid id, [FromBody]MyObject theModifiedObject)
{
// Do what you have to do to retrieve the object by id
}
[Route("")]
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
[ProducesResponseType(typeof(CreatedVersionOfMyObject), (int)HttpStatusCode.Created)]
public Task<IActionResult> PostAsync(MyObject theModifiedObject)
{
// Do what you have to do to create the object and return the version with the id
}
}
最后,關於映射,您也可以輕松處理(參見原始文檔https://docs.automapper.org/en/stable/Mapping-inheritance.html )
CreateMap<BaseEntity, BaseDto>()
.ForMember(dest => dest.SomeMember, opt => opt.MapFrom(src => src.OtherMember));
CreateMap<DerivedEntity, DerivedDto>()
.IncludeBase<BaseEntity, BaseDto>();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.