如何正确地将 asp.net 核心模型状态错误反序列化为 xamarin 形式的对象
Posted
技术标签:
【中文标题】如何正确地将 asp.net 核心模型状态错误反序列化为 xamarin 形式的对象【英文标题】:How to properly deserialize asp.net core Model State errors to object in xamarin forms 【发布时间】:2020-09-21 02:06:51 【问题描述】:我在尝试将 asp.net 核心模型状态错误反序列化为对象时遇到了一个愚蠢的问题。我的代码是这样的
后端注册方法
[HttpPost("register-user")]
[ValidateModel]
public async Task<IActionResult> Index(RegisterDto registerDto)
try
Data.Models.User user = mapper.Map<RegisterDto, Data.Models.User>(registerDto);
user.LockoutEnd = DateTimeOffset.Now;
user.Warehouse = configuration["Config:Warehouse"];
user.SiteId = Convert.ToInt32(configuration["Config:SiteId"]);
IdentityResult result = await userManager.CreateAsync(user, registerDto.Password);
if (result.Succeeded)
AddLogInformation(logger, "User created a new account with password.");
string token = await userManager.GenerateEmailConfirmationTokenAsync(user);
token = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(token));
string confirmationUrl = Url.Action("Index", "EmailConfirmation",
new userId = user.Id, code = token, Request.Scheme);
emailSender.SendEmailAsync(registerDto.Email, "Confirm your email",
GetEmailConfirmationTemplate(registerDto.FirstName, registerDto.LastName,
confirmationUrl));
ApplicationRole retailPersonRole =
await roleManager.FindByNameAsync(RoleHelper.GetRetailUserRoleName());
if (retailPersonRole != null) await userManager.AddToRoleAsync(user, retailPersonRole.Name);
if (userManager.Options.SignIn.RequireConfirmedAccount)
AddLogInformation(logger, "Sent email confirmation email to user");
return Ok(SuccessResult(null));
//If confirm account is set to false
await signInManager.SignInAsync(user, false);
return Ok(SuccessResult(null));
// If we got this far, something failed, redisplay form
return Ok(FailedMessage(logger, "Cannot register user at this time. Please try again later."));
catch (Exception e)
return ServerErrorJsonResult(logger, "Error while trying to register user. Error message is: " + e.Message);
我在动作过滤器中捕获模型状态错误并返回如下响应。
public class ValidateModelAttribute : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext context)
var modelState = context.ModelState;
if (!modelState.IsValid)
context.Result = new BadRequestObjectResult(new JsonResult(new modelError = true, Errors = modelState));
现在在前端 (xamarin) 中,我有一个模型来反序列化错误,以便我可以向用户显示正确的错误。
我在前端的寄存器模型是这样的
public class RegisterDto: BaseDto
public string FirstName get; set;
public string MiddleName get; set;
public string LastName get; set;
public string PhoneNumber get; set;
public string Email get; set;
public string Password get; set;
public string ConfirmPassword get; set;
public AddressDto BillingAddress get; set;
public RegisterDto Errors get; set;
我的地址 Dto 是这样的
public class AddressDto
public string Address1 get; set;
public string Address2 get; set;
public string City get; set;
public string PostCode get; set;
public string State get; set;
我正在像这样在 xamarin 中创建发布请求。
public async Task<TResult> PostAsync<TResult>(string uri, TResult data, string token = "", string header = "")
try
HttpClient httpClient = CreateHttpClient(token);
if (!string.IsNullOrEmpty(header))
AddHeaderParameter(httpClient, header);
var content = new StringContent(JsonConvert.SerializeObject(data));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await httpClient.PostAsync(uri, content);
await HandleResponse(response);
string serialized = await response.Content.ReadAsStringAsync();
TResult result = await Task.Run(() =>
JsonConvert.DeserializeObject<TResult>(serialized, serializerSettings));
return result;
catch (Exception e)
return default;
最后,在视图模型中,我正在这样做
--
userToBeRegistered is an instance of RegisterDto
await something.PostAsync(UrlHelper.RegisterUrl, userToBeRegistered);
序列化后的字符串输出是这样的
"errors":
"Email":[
"Email is required"
],
"LastName":[
"Last name is required"
],
"Password":[
"Password is required"
],
"FirstName":[
"First name is required"
],
"PhoneNumber":[
"Phone number is required"
],
"BillingAddress.City":[
"Suburb is required"
],
"BillingAddress.State":[
"State is required"
],
"BillingAddress.Address1":[
"Street address is required"
],
"BillingAddress.PostCode":[
"Postcode is required"
]
,
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"|3c2d7d70-49a6eceecbeedab8."
我的问题是如何将其反序列化为错误对象。如果我继续运行上述代码,则会收到此错误。
"Unexpected character encountered while parsing value: [. Path 'errors.Email', line 1, position 20."
谁能帮我解决这个问题?
【问题讨论】:
你能用 JSON 格式发布你收到的电子邮件 ID,我猜它的格式或字符错误。将电子邮件中的名称更改为xyz
@Blu 我不认为这是问题所在。我的问题是映射模型
【参考方案1】:
试试下面的方法。
创建ErrorInfor类:
class ErrorInfor
public MyError errors get; set;
public string type get; set;
public string title get; set;
public int status get; set;
public string traceId get; set;
public class MyError
public List<string> FirstName get; set;
public List<string> LastName get; set;
public List<string> PhoneNumber get; set;
public List<string> Email get; set;
public List<string> Password get; set;
[JsonProperty("BillingAddress.City")]
public List<string> Citiy get; set;
[JsonProperty("BillingAddress.State")]
public List<string> State get; set;
[JsonProperty("BillingAddress.Address1")]
public List<string> Address1 get; set;
[JsonProperty("BillingAddress.PostCode")]
public List<string> PostCode get; set;
然后你可以从你上面的 json 字符串中获取数据。
ErrorInfor errorInfor = JsonConvert.DeserializeObject<ErrorInfo>(json);
【讨论】:
以上是关于如何正确地将 asp.net 核心模型状态错误反序列化为 xamarin 形式的对象的主要内容,如果未能解决你的问题,请参考以下文章
如何正确地将 OData 与 ASP.net Core 集成
如何反序列化 422 无法处理的实体错误模型并将错误绑定到 asp.net core razor pages 模型状态
如何有条件地将多个模型映射到 ASP.NET Core Identity 中的一个表(AspNetUsers)?