dateonly字段未从表格中填充.net6 ef6剃刀页没有mvc

发布于 2025-02-10 19:10:13 字数 3325 浏览 0 评论 0原文

由于某种原因,我在表单的日期类型输入中输入的日期未进入数据库。取而代之的是,在我研究和尝试的所有不同方法之后,毫无用处,默认日期为01/01/01,我理解是defualt min值是吗?在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>

For some reason the dates that I enter in the date-type inputs of the form are not getting into the database. Instead, after all the different methods I researched and tried, to no avail, the dates default to 01/01/01, which I understand to be the defualt min value yes? And in the postgres database, the date fields show "-infinity". I can use pgadmin query tool to update the dates successfully, but when I try to create or edit a record from the form, the above occurs.

When I get to the ModelState.IsValid line in the debugger, it is showing the data I entered correctly in the other fields, but the date fields are showing 01/01/01.

I have been through the docs and other forum posts but none of the fixes I attempted worked.
Any help would be greatly appreciated.

Here is the model

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

    }

... the post

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

... and the form

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

倒带 2025-02-17 19:10:13

感谢迈克(Mike)解决了问题,这就是我所做的。

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

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

但是我得到了这个错误:

“不能用bink = local to postgresql类型编写dateTime'timestamp
随着时区',仅支持UTC“

所以我应用了以下修复此线程的修复:

。net6 and dateTime问题。不能用bint = utc编写dateTime to postgresql类型'timestamp'没有时区域'

这就是我所做的。

我创建了一个“扩展” “我的项目中的文件夹,其中我创建了一个“ 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; }
    }
}

我通过使用语句等添加适当的添加适当的错误来纠正所有错误

。然后,我立即在public 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>

。帮助!

Thanks Mike that did the trick, here's what I did.

I applied your first solution,

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

but I got this error:

"Cannot write DateTime with Kind=Local to PostgreSQL type 'timestamp
with time zone', only UTC is supported"

So I applied the following fix from this thread:

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

Here's what I did.

I created an "Extensions" folder in my project and within that I created a "UtcDateAnnotation.cs" file and pasted the following.

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

I corrected all the errors by adding the appropriate using statements etc.

Then I added the following in my DbContext file right after the public DbSet statement

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

That did the trick, but it still showed the time as well, I just wanted to display the date.

I tried the below but it didn't work.

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

Instead I added this to the view:

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

That did the trick. Thanks again for the help!

第几種人 2025-02-17 19:10:13

您正在使用新的dateonly类型。 ASP.NET核心模型活页夹目前不支持与dateonly https://github.com/dotnet/aspnetcore/issues/34591 )。直到.NET 7,您可以使用DateTime类型和数据注释来控制渲染的输入类型( https://www.learnrazorpages.com/razor-pages/forms/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");
}

You are using the new DateOnly type. The ASP.NET Core model binder does not support binding to DateOnly at the moment (https://github.com/dotnet/aspnetcore/issues/34591). Until .NET 7, you can use a DateTime type and data annotations to control the input type that gets rendered (https://www.learnrazorpages.com/razor-pages/forms/dates-and-times):

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

Alternatively, you can extract the value from Request.Form yourself and assign it to the relevant property:

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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文