如何正确地将 asp.net 核心模型状态错误反序列化为 xamarin 形式的对象

How to properly deserialize asp.net core Model State errors to object in xamarin forms

我在尝试将 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 中创建 post 请求。

 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."

谁能帮我解决这个问题?

试试下面的方法。

创建 ErrorInfor class:

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);