2

我有一个通用的 DateTime 编辑器模板,它应该使用所需的格式(“dd/MM/yyyy”)格式化我的所有 DateTime 属性:

@Html.TextBox(string.Empty, Model.ToString("dd/MM/yyyy"), new { @class = "datepicker" })

但由于某种原因,该格式不适用于我的孩子行为。


如果我在MainPage .cshtml中执行 @Html.EditorFor(x => x.MyDate)我会得到预期结果:“23/04/2012”

如果我在ChildAction .cshtml中执行 @Html.EditorFor(x => x.MyDate)我会得到以下意外结果:“2012-04-24”


我可以确认正在使用编辑器模板,因为如果我像这样更改它(注意开头的 WTF 字符串):

WTF @Html.TextBox(string.Empty, Model.ToString("dd/MM/yyyy"), new { @class = "datepicker" })

然后,如果我在 ChildAction.cshtml 中执行 @Html.EditorFor(x => x.MyDate)

我得到:“WTF 2012-04-24”

有任何想法吗?

更新

为了在 MVC 示例应用程序中重现此错误,我发现还需要另外两件事:

public class DateTimeModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        DateTime date;

        if (DateTime.TryParseExact(value.AttemptedValue, "dd/MM/yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeLocal, out date))
        {
            return date;
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

我假设每个人都知道如何连接它。同样在 MainPage.cshtml 中,您必须将模型作为第二个参数传递给 RenderAction

@{Html.RenderAction("Child", Model);}

当传递模型作为第二个参数时,MVC 使用模型绑定器来调用子操作(为什么?)。但是,日期的格式是 MM/dd/yyyy,所以它不适用于我的模型活页夹,它假设我所有的日期都是 dd/MM/yyyy 格式。这就是为什么这不起作用。

但是我该如何解决呢?日期与我的默认格式 dd/MM/yyyy 不匹配的唯一地方是呈现子操作时。

4

1 回答 1

1

问题

如果可能,MVC 使用模型状态值,但父操作与子操作的模型状态中的值不同:

  • 在父操作中,模型状态包含提交给操作的日期字符串(valueproviderresult 中的 RawValue)或默认值。

  • 当父操作将信息传递给子操作(渲染操作
    )时,它会传递模型状态中的dateTime
    (valueproviderresult 中的 RawValue )。

所以在父动作中,如果没有提交值,则正确使用 Textbox(...) 中提供的值。如果客户端以相同的格式提交了一个有效值,它似乎也可以,因为它采用模型状态的字符串,该字符串与显示模板中生成的字符串相同。

但在子操作中,它使用包含日期时间而不是提交的字符串的模型状态,然后 MVC 使用不变文化将该日期时间转换为字符串,因此它将显示 MM/dd/yyyy(我是 3 年后,所以值可能有由于您拥有 yyyy-MM-dd,因此在框架中进行了更改)

解决方案

您需要将模型状态中的值替换为您想要的值,或者将其删除以获取受影响的值。

public static void Fix(ModelStateDictionary dic, string key)
{
    ModelState modelState = dic[key];

    if (!modelState.Errors.Any() && modelState.Value.RawValue != null 
      && (modelState.Value.RawValue is DateTime || modelState.Value.RawValue is DateTime?))
    {
        var sValue = ((DateTime)modelState.Value.RawValue).ToString("dd/MM/yyyy");
        var value = new ValueProviderResult(sValue, sValue, CultureInfo.InvariantCulture);
        dic.SetModelValue(key, value);

        //or

        //dic.Remove(key);
    }
}

然后在您的子操作中调用该方法:

Fix(ModelState, nameof(viewModel.DateMax));
于 2015-12-02T21:10:33.990 回答