57

asp.net mvc 4で日時の形式を強制するにはどうすればよいですか?表示モードでは希望どおりに表示されますが、モデルの編集では表示されません。私はdisplayforとeditorforを使用しており、applyformatineditmode=trueをdataformatstring="{0:dd / MM /yyyy}"で使用しています。

  • 私の文化とuicultureによるweb.config(両方)のグローバリゼーション。
  • application_start()でカルチャとuicultureを変更する
  • 日時用のカスタムmodelbinder

強制する方法がわからないので、日付をデフォルトではなくdd / MM/yyyyとして入力する必要があります。

詳細:私のビューモデルはこのようなものです

    [DisplayName("date of birth")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime? Birth { get; set; }

私は使用しています@Html.DisplayFor(m=>m.Birth)が、これは期待どおりに機能し(フォーマットが表示されます)、使用する日付を入力します@Html.EditorFor(m=>m.Birth)が、13/12/2000のようなものを入力しようとすると、有効な日付ではないというエラーで失敗します(12 / 13/2000と2000/12/13は期待どおりに機能していますが、dd / MM/yyyyが必要です。

カスタムmodelbinderはapplication_start()b/cで呼び出されます。他の場所はわかりません。

を使用して、私にdd / MM/yyyyを与える他の文化を<globalization/>試しました。culture="ro-RO", uiCulture="ro"また、application_start()でスレッドごとに設定しようとしました(これを行う方法については、ここに多くの例があります)


この質問を読むすべての人のために:私がクライアントの検証を持っていない限り、DarinDimitrovの答えはうまくいくようです。別のアプローチは、クライアント側の検証を含むカスタム検証を使用することです。アプリケーション全体を再作成する前に、これを見つけてよかったです。

4

3 に答える 3

103

ああ、今それは明らかです。値のバインドに問題があるようです。ビューに表示することではありません。実際、これはデフォルトのモデル バインダーの欠点です。[DisplayFormat]モデルの属性を考慮したカスタムを作成して使用できます。このようなカスタム モデル バインダーをここに示しました: https://stackoverflow.com/a/7836093/29407


どうやらいくつかの問題がまだ残っているようです。ASP.NET MVC 3 と 4 RC の両方で完全に正常に動作する完全なセットアップを次に示します。

モデル:

public class MyViewModel
{
    [DisplayName("date of birth")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime? Birth { get; set; }
}

コントローラ:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            Birth = DateTime.Now
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

意見:

@model MyViewModel

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.Birth)
    @Html.EditorFor(x => x.Birth)
    @Html.ValidationMessageFor(x => x.Birth)
    <button type="submit">OK</button>
}

でのカスタム モデル バインダーの登録Application_Start:

ModelBinders.Binders.Add(typeof(DateTime?), new MyDateTimeModelBinder());

そして、カスタム モデル バインダー自体:

public class MyDateTimeModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var displayFormat = bindingContext.ModelMetadata.DisplayFormatString;
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (!string.IsNullOrEmpty(displayFormat) && value != null)
        {
            DateTime date;
            displayFormat = displayFormat.Replace("{0:", string.Empty).Replace("}", string.Empty);
            // use the format specified in the DisplayFormat attribute to parse the date
            if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
            {
                return date;
            }
            else
            {
                bindingContext.ModelState.AddModelError(
                    bindingContext.ModelName,
                    string.Format("{0} is an invalid date format", value.AttemptedValue)
                );
            }
        }

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

これで、web.config (<globalization>要素) または現在のスレッド カルチャで設定したカルチャに関係なく、カスタム モデル バインダーは、DisplayFormatnull 許容日付を解析するときに属性の日付形式を使用します。

于 2012-06-30T09:20:55.317 に答える
0

Darin に感謝します。私にとって、create メソッドに投稿できるようにするには、BindModel コードを :

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    var displayFormat = bindingContext.ModelMetadata.DisplayFormatString;
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

    if (!string.IsNullOrEmpty(displayFormat) && value != null)
    {
        DateTime date;
        displayFormat = displayFormat.Replace("{0:", string.Empty).Replace("}", string.Empty);
        // use the format specified in the DisplayFormat attribute to parse the date
         if (DateTime.TryParse(value.AttemptedValue, CultureInfo.GetCultureInfo("en-GB"), DateTimeStyles.None, out date))
        {
            return date;
        }
        else
        {
            bindingContext.ModelState.AddModelError(
                bindingContext.ModelName,
                string.Format("{0} is an invalid date format", value.AttemptedValue)
            );
        }
    }

    return base.BindModel(controllerContext, bindingContext);
}

これが他の誰かを助けることを願っています...

于 2016-08-11T08:56:16.220 に答える