绑定时格式化日期(ASP.NET MVC)

时间:2020-03-06 14:43:25  来源:igfitidea点击:

在我的ASP.net MVC应用程序中,我有一个如下所示的视图:

...
<label>Due Date</label>
<%=Html.TextBox("due")%>
...

我正在使用" ModelBinder"将帖子绑定到我的模型(到期属性为" DateTime"类型)。问题是当我在文本框中输入" 01/01/2009"时,该帖子无法验证(由于其他数据输入错误)。活页夹用日期和时间" 01/01/2009 00:00:00"重新填充。

有什么方法可以告诉活页夹正确格式化日期(即" ToShortDateString()")吗?

解决方案

为了在视图背后的代码中获得对模型的强类型访问,我们可以执行以下操作:

public partial class SomethingView : ViewPage<T>
{
}

其中T是要从Action传入的ViewData类型。

然后在控制器中,我们将执行以下操作:

public ActionResult Something(){
    T myObject = new T();
    T.Property = DateTime.Today();

    Return View("Something", myObject);
}

之后,我们在视图中拥有不错的强类型化模型数据,因此我们可以执行以下操作:

<label>My Property</label>
<%=Html.TextBox(ViewData.Model.Property.ToShortDateString())%>

我个人认为应该通过强类型化页面和一些定义的模型类来做到最好或者最简单,但是如果我们希望它成为活页夹中的东西,我可以这样进行:

public class SomeTypeBinder : IModelBinder
{
    public object GetValue(ControllerContext controllerContext, string modelName,
                              Type modelType, ModelStateDictionary modelState)
    {
        SomeType temp = new SomeType();
        //assign values normally
        //If an error then add formatted date to ViewState
        controllerContext.Controller.ViewData.Add("FormattedDate",
                              temp.Date.ToShortDateString());
    }
}

然后在创建文本框时在视图中使用它,即:

<%= Html.TextBox("FormattedDate") %>

希望能有所帮助。

你为什么不使用

<% =Html.TextBox("due", Model.due.ToShortDateString()) %>

我自己寻找答案时发现了这个问题。上面的解决方案对我不起作用,因为我的DateTime可为空。这是我通过支持可为null的DateTime对象解决此问题的方法。

<%= Html.TextBox(String.Format("{0:d}", Model.Property)) %>

我发现最好的方法是重置ModelValue

ModelState.SetModelValue("due", new ValueProviderResult(
       due.ToShortDateString(), 
       due.ToShortDateString(), 
       null));

首先,添加此扩展名以获取属性路径:

public static class ExpressionParseHelper
{
    public static string GetPropertyPath<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
    {                       
         Match match = Regex.Match(property.ToString(), @"^[^\.]+\.([^\(\)]+)$");
         return match.Groups[1].Value;
    }
}

比为HtmlHelper添加此扩展名:

public static MvcHtmlString DateBoxFor<TEntity>(
                this HtmlHelper helper,
                TEntity model,
                Expression<Func<TEntity, DateTime?>> property,
                object htmlAttributes)
            {
                DateTime? date = property.Compile().Invoke(model);
                var value = date.HasValue ? date.Value.ToShortDateString() : string.Empty;
                var name = ExpressionParseHelper.GetPropertyPath(property);

                return helper.TextBox(name, value, htmlAttributes);
            }

另外,我们应该添加以下jQuery代码:

$(function() {
    $("input.datebox").datepicker();
});

datepicker是一个jQuery插件。

现在我们可以使用它:

<%= Html.DateBoxFor(Model, (x => x.Entity.SomeDate), new { @class = "datebox" }) %>

ASP.NET MVC2和DateTime格式

这是一个肮脏的hack,但它似乎可以工作。

<%= Html.TextBoxFor(model => model.SomeDate,
    new Dictionary<string, object> { { "Value", Model.SomeDate.ToShortDateString() } })%>

我们将获得模型绑定,并能够使用格式化的字符串覆盖文本字段的HTML" value"属性。

我刚刚遇到了这个非常简单而优雅的解决方案,可在MVC 2中使用:

http://geekswithblogs.net/michelotti/archive/2010/02/05/mvc-2-editor-template-with-datetime.aspx

基本上,如果我们使用的是MVC 2.0,请在视图中使用以下内容。

<%=Html.LabelFor(m => m.due) %>
 <%=Html.EditorFor(m => m.due)%>

然后在/ Views / Shared / EditorTemplates中创建一个名为DateTime.ascx的局部视图

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%=Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty), new { @class = "datePicker" }) %>

调用EditorFor <>时,它将找到一个匹配的Editor模板。

用DataType属性装饰模型中的属性,并指定其属性为Date而不是DateTime:

public class Model {
  [DataType(DataType.Date)]
  public DateTime? Due { get; set; }
}

我们也必须在视图中使用EditorFor而不是TextBoxFor

@Html.EditorFor(m => m.Due)