如何正确地将 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 集成

如何在 ASP.NET MVC 中获取模型状态错误的集合?

如何反序列化 422 无法处理的实体错误模型并将错误绑定到 asp.net core razor pages 模型状态

如何有条件地将多个模型映射到 ASP.NET Core Identity 中的一个表(AspNetUsers)?

如何在 ASP Net Core Web API 上正确地将列表转换为 IQueryable

ASP.NET Core 模型绑定错误消息本地化