如何正确地将 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 形式的对象的主要内容,如果未能解决你的问题,请参考以下文章