【问题标题】:.net core unable to pass binding phase with nested object.net 核心无法通过嵌套对象的绑定阶段
【发布时间】:2020-04-11 03:19:50
【问题描述】:

我是 .Net Core(和 Blazor)的新手,我刚刚按照教程配置了一个使用最新版本的 .net core (3.1.xxx) 的项目并检查了 Microsoft Docs。

我的项目中有几个实体,我可以使用 API 保存由简单属性(原始类型)组成的实体。但是当我尝试对具有其他实体作为属性(因此嵌套对象)的实体进行相同操作时,我遇到了一个问题。

我得到的错误根本没有帮助,它抱怨从 Char 到 String 的转换,正如您在下面的堆栈跟踪中看到的那样:

失败:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] 执行请求时发生未处理的异常。 System.InvalidCastException:无法将“System.Char”类型的对象转换为“System.String”类型。 在 System.ComponentModel.DataAnnotations.StringLengthAttribute.IsValid(对象值) 在 System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(对象值,ValidationContext 验证上下文) 在 System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(对象值,ValidationContext 验证上下文) 在 Microsoft.AspNetCore.Mvc.DataAnnotations.DataAnnotationsModelValidator.Validate(ModelValidationContext 验证上下文) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.ValidateNode() 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitSimpleType() 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata 元数据,字符串键,对象模型) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy 策略) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata 元数据,字符串键,对象模型) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy 策略) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata 元数据,字符串键,对象模型)

这只发生在嵌套实体中。这是我应该编写自定义模型绑定类的情况吗?

我的代码是这样的:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace src.Data.Entities
{
    [Table("Screening")]
    public class Screening
    {
        public Screening()
        {
            this.Beneficiary = new Beneficiary();
        }
        public int ScreeningId { get; set; }
        public DateTime ScreeningDate { get; set; } = DateTime.Now;
        public virtual Beneficiary Beneficiary { get; set; }
        public int BeneficiaryId { get; set; }
        public virtual SimpleEntity ActionTaken { get; set; }
        public int ActionTakenId { get; set; }

        public virtual SimpleEntity ReasonForVisit { get; set; }
        public int ReasonForVisitId { get; set; }

    }
}

控制器类

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using src.Data;
using src.Data.Entities;
using src.Data.DTO;
using src.Helpers;
using System.Linq;

namespace src.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class ScreeningController : ControllerBase
    {
        private readonly ApplicationDbContext context;

        public ScreeningController(ApplicationDbContext context)
        {
            this.context = context;
        }

        [HttpGet]
        public async Task<ActionResult<List<Screening>>> Get([FromQuery] PaginationDTO pagination)
        {
            var queryable = context.Screenings.AsQueryable().OrderBy(x => x.ScreeningDate);
            await HttpContext.InsertPaginationParameterInResponse(queryable, pagination.RecordsPerPage);
            return await queryable.Paginate(pagination).ToListAsync();
        }

        [HttpGet("{id}", Name = "GetScreening")]
        public async Task<ActionResult<Screening>> Get(int id)
        {
            return await context.Screenings.FirstOrDefaultAsync(x => x.ScreeningId == id);
        }

        [HttpPost]
        public async Task<ActionResult> Post(Screening screening)
        {
            context.Add(screening);
            await context.SaveChangesAsync();
            return new CreatedAtRouteResult("GetScreening", new { id = screening.ScreeningId }, screening);
        }

        [HttpPut]
        public async Task<ActionResult> Put(Screening screening)
        {
            context.Entry(screening).State = EntityState.Modified;
            await context.SaveChangesAsync();
            return NoContent();
        }

        [HttpDelete("{id}")]
        public async Task<ActionResult> Delete(int id)
        {
            var screening = new Screening { ScreeningId = id };
            context.Remove(screening);
            await context.SaveChangesAsync();
            return NoContent();
        }
    }
}

观看次数

筛选表单组件


    @inject HttpClient http

    <RadzenCard>
        <EditForm Model="@Screening" OnValidSubmit="@OnValidSubmit">
            <DataAnnotationsValidator/>
            <div class="from-field">
                <label>Screening date:</label>
                <div>
                    <RadzenDatePicker @bind-Value="Screening.ScreeningDate"/>
                </div>
            </div>
            <div class="from-field">
                <label>Client name:</label>
                <div>
                    <RadzenTextBox Style="margin-bottom: 20px" @bind-Value="@Screening.Beneficiary.FirstName"/>
                </div>
            </div>
            <div class="from-field">
                <label>Client surname:</label>
                <div>
                    <RadzenTextBox Style="margin-bottom: 20px" @bind-Value="@Screening.Beneficiary.Surname"/>
                </div>
            </div>
            <div class="from-field">
                <label>Reason for visit:</label>
                <div>
                    <RadzenDropDown 
                        AllowClear="true" 
                        TValue="int" 
                        FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" 
                        AllowFiltering="true" 
                        Data="@ReasonForVistList" 
                        TextProperty="Description" 
                        ValueProperty="SimpleEntityID" 
                        Style="margin-bottom: 20px"  />
                </div>
            </div>
            <div class="from-field">
                <label>Action taken:</label>
                <div>
                    <RadzenDropDown 
                        AllowClear="true" 
                        TValue="int" 
                        FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" 
                        AllowFiltering="true" 
                        Data="@ActionTakenList" 
                        TextProperty="Description" 
                        ValueProperty="SimpleEntityID" 
                        Style="margin-bottom: 20px"  />
                </div>
            </div>
            <hr/>
            <button type="submit" class="btn btn-success">
                Create
            </button>
        </EditForm>
    </RadzenCard>

    @code {
        [Parameter] public  Screening Screening{get;set;}
        [Parameter] public  string ButtonText{get;set;} = "Save";
        [Parameter] public  EventCallback OnValidSubmit{get;set;}
        IEnumerable<SimpleEntity> ReasonForVistList;
        IEnumerable<SimpleEntity> ActionTakenList;

        protected override async Task OnInitializedAsync() 
        {
            var reasonForVisitType = "reason-for-visit";
            var actionTaken = "screening-action-taken";
            ReasonForVistList =  await http.GetJsonAsync<SimpleEntity[]>($"api/simpleentity/type/?type={reasonForVisitType}");
            ActionTakenList = await http.GetJsonAsync<SimpleEntity[]>($"api/simpleentity/type/?type={actionTaken}");
        }
    }


创建视图


    @page "/screening/create"
    @inject HttpClient http
    @inject NavigationManager uriHelper

    <h3>New Screening Process</h3>

    <ScreeningForm ButtonText="Create" Screening="@screening" OnValidSubmit="@Save"/>

    @code{
        Screening screening = new Screening();

        async Task Save()
        {
            await http.PostJsonAsync("api/screening", screening);
            uriHelper.NavigateTo("screening");
        }
    }

【问题讨论】:

  • 从您提供的代码中不清楚,但某处 char 正在转换为 string。很可能您在应该使用双引号的地方使用了单引号。一般来说,在代码中寻找明确处理 char 类型或使用单引号表示“字符串”的地方。
  • @ChrisPratt 感谢您的及时评论。但我没有在我的应用程序的任何地方处理char,这就是为什么我对这个错误如此惊讶。我添加了视图代码,如果这有助于理解问题,请告诉我
  • 您的异常说,您正在尝试将字符串分配给 char。所以,我会检查你的输入数据到数据库中期待 CHAR 的列
  • 感谢大家帮助我。不幸的是,由于我的声誉,我可以发布答案,但我解决了我的问题。不确定我是否可以在 cmets 上分享这里

标签: c# asp.net-mvc asp.net-core blazor


【解决方案1】:

请检查从您的表单发布到操作并因此发布到数据库的数据。

失败: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] 执行请求时发生未处理的异常。 System.InvalidCastException:无法转换类型的对象 'System.Char' 输入 'System.String'。在 System.ComponentModel.DataAnnotations.StringLengthAttribute.IsValid(对象 值)在

【讨论】:

    猜你喜欢
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 2014-06-16
    • 2014-05-08
    相关资源
    最近更新 更多