【问题标题】:DateOnly field not being populated from form .NET6 EF6 Razor Pages No MVC没有从表单 .NET6 EF6 Razor Pages No MVC 填充 DateOnly 字段
【发布时间】:2022-11-10 03:39:16
【问题描述】:

由于某种原因,我在表单的日期类型输入中输入的日期没有进入数据库。相反,在我研究和尝试了所有不同的方法之后,无济于事,日期默认为 01/01/01,我理解这是默认的最小值,是吗?在 postgres 数据库中,日期字段显示“-infinity”。我可以使用 pgadmin 查询工具成功更新日期,但是当我尝试从表单创建或编辑记录时,会发生上述情况。

当我到达调试器中的 ModelState.IsValid 行时,它显示了我在其他字段中正确输入的数据,但日期字段显示的是 01/01/01。

我浏览过文档和其他论坛帖子,但我尝试的修复都没有奏效。 任何帮助将不胜感激。

这是模型

 public class ToDo
    {
        [Key]
        public int Id { get; set; }

        public DateOnly CreateDate { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Description { get; set; }

        public DateOnly DueDate { get; set; }

        public bool Complete { get; set; }

    }

...帖子

public async Task<IActionResult> OnPost()

{

    if (!ModelState.IsValid)
    {
        var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));
    }

    if (ModelState.IsValid)
    {
        await _db.Todo.AddAsync(Todo);
        await _db.SaveChangesAsync();
        TempData["success"] = "ToDo created successfully.";
        return RedirectToPage("Index");
    }
    return Page();
}

...和形式

<form method="post">
    <input hidden asp-for="Todo.Id" />
    <div class="p-3 mt-4">
        <div class="row pb-2">
            <h2 class="text-primary pl-3">Create ToDo</h2>
            <hr />
        </div>
        <div asp-validation-summary="All"></div>
        <div class="mb-3">
            <label asp-for="@Model.Todo.CreateDate"></label>
            <input asp-for="@Model.Todo.CreateDate" class="form-control"  type="date"/>
            <span asp-validation-for="Todo.CreateDate" class="text-danger"></span>
        </div>
        <div class="mb-3">
            <label asp-for="@Model.Todo.Name"></label>
            <input asp-for="@Model.Todo.Name" class="form-control" />
            <span asp-validation-for="Todo.Name" class="text-danger"></span>
        </div>
        <div class="mb-3">
            <label asp-for="@Model.Todo.Description"></label>
            <input asp-for="@Model.Todo.Description" class="form-control" />
            <span asp-validation-for="Todo.Description" class="text-danger"></span>
        </div>
        <div class="mb-3">
            <label asp-for="@Model.Todo.DueDate"></label>
            <input asp-for="@Model.Todo.DueDate" class="form-control"  type="date"/>
            <span asp-validation-for="Todo.DueDate" class="text-danger"></span>
        </div>
        <div class="form-check m-4">
            <input asp-for="@Model.Todo.Complete" class="form-check-input" type="checkbox"/>
            <label class="form-check-label ms-3" asp-for="@Model.Todo.Complete">
            Complete
            </label>
        </div>
        <button type="submit" class="btn btn-outline-primary rounded-pill" style="width:150px;">Update</button>
        <a asp-page="Index" class="btn btn-outline-secondary rounded-pill text-white" style="width:150px;">Back To List</a>
    </div>
</form>

【问题讨论】:

    标签: entity-framework-6 razor-pages


    【解决方案1】:

    感谢迈克成功了,这就是我所做的。

    我应用了你的第一个解决方案,

    [DataType(DataType.Date)]
    public DateTime CreateDate { get; set;}
    

    但我收到了这个错误:

    “无法将 Kind=Local 的 DateTime 写入 PostgreSQL 类型 'timestamp 带时区',仅支持 UTC"

    所以我从这个线程应用了以下修复:

    .NET6 and DateTime problem. Cannot write DateTime with Kind=UTC to PostgreSQL type 'timestamp without time zone'

    这就是我所做的。

    我在我的项目中创建了一个“Extensions”文件夹,并在其中创建了一个“UtcDateAnnotation.cs”文件并粘贴了以下内容。

    namespace ToDoRazorNoMvcPostgres.Extensions
    {
        public static class UtcDateAnnotation
        {
            private const string IsUtcAnnotation = "IsUtc";
            private static readonly ValueConverter<DateTime, DateTime> UtcConverter = new ValueConverter<DateTime, DateTime>(convertTo => DateTime.SpecifyKind(convertTo, DateTimeKind.Utc), convertFrom => convertFrom);
        
            public static PropertyBuilder<TProperty> IsUtc<TProperty>(this PropertyBuilder<TProperty> builder, bool isUtc = true) => builder.HasAnnotation(IsUtcAnnotation, isUtc);
        
            public static bool IsUtc(this IMutableProperty property)
            {
                if (property != null && property.PropertyInfo != null)
                {
                    var attribute = property.PropertyInfo.GetCustomAttribute<IsUtcAttribute>();
                    if (attribute is not null && attribute.IsUtc)
                    {
                        return true;
                    }
        
                    return ((bool?)property.FindAnnotation(IsUtcAnnotation)?.Value) ?? true;
                }
                return true;
            }
        
            /// <summary>
            /// Make sure this is called after configuring all your entities.
            /// </summary>
            public static void ApplyUtcDateTimeConverter(this ModelBuilder builder)
            {
                foreach (var entityType in builder.Model.GetEntityTypes())
                {
                    foreach (var property in entityType.GetProperties())
                    {
                        if (!property.IsUtc())
                        {
                            continue;
                        }
        
                        if (property.ClrType == typeof(DateTime) ||
                            property.ClrType == typeof(DateTime?))
                        {
                            property.SetValueConverter(UtcConverter);
                        }
                    }
                }
            }
        }
        public class IsUtcAttribute : Attribute
        {
            public IsUtcAttribute(bool isUtc = true) => this.IsUtc = isUtc;
    
            public bool IsUtc { get; }
        }
    }
    

    我通过添加适当的 using 语句等更正了所有错误。

    然后我在公共 DbSet 语句之后在我的 DbContext 文件中添加了以下内容

    protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.ApplyUtcDateTimeConverter();//Put before seed data and after model creation
        }
    

    这成功了,但它仍然显示时间,我只是想显示日期。

    我尝试了以下方法,但没有奏效。

    [DataType(DataType.Date)]`
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime CreateDate { get; set; }
    

    相反,我将其添加到视图中:

    <td>@Convert.ToString(string.Format("{0:MM/dd/yyyy}", obj.CreateDate))</td>
    

    那成功了。再次感谢您的帮助!

    【讨论】:

      【解决方案2】:

      您正在使用新的 DateOnly 类型。 ASP.NET Core 模型绑定器目前不支持绑定到 DateOnly (https://github.com/dotnet/aspnetcore/issues/34591)。在 .NET 7 之前,您可以使用 DateTime 类型和数据注释来控制呈现的输入类型 (https://www.learnrazorpages.com/razor-pages/forms/dates-and-times):

      [DataType(DataType.Date)]
      public DateTime CreateDate { get; set; }
      

      或者,您可以自己从Request.Form 中提取值并将其分配给相关属性:

      if(DateTime.TryParse(Request.Form["Todo.CreateDate"].ToString(), out var created))
      {
          Todo.CreateDate = DateOnly.FromDateTime(created);
      }
      else
      {
          ModelState.AddModelError("Todo.CreateDate", "A created date must be a date");
      }
      

      【讨论】:

        猜你喜欢
        • 2021-07-23
        • 2021-08-09
        • 1970-01-01
        • 1970-01-01
        • 2021-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-11
        相关资源
        最近更新 更多