8

私は ASP.NET MVC 3 RTM を使用しており、次のようなビュー モデルがあります。

public class TaskModel
{
  // Lot's of normal properties like int, string, datetime etc.
  public TimeOfDay TimeOfDay { get; set; }
}

プロパティは私が持っているカスタム構造体で、TimeOfDay非常に単純なので、ここには含めません。この構造体をバインドするカスタム モデル バインダーを作成しました。モデル バインダーは非常に単純です。

public class TimeOfDayModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        try
        {
            // Let the TimeOfDay struct take care of the conversion from string.
            return new TimeOfDay(result.AttemptedValue, result.Culture);
        }
        catch (ArgumentException)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Value is invalid. Examples of valid values: 6:30, 16:00");
            return bindingContext.Model; // Also tried: return null, return value.AttemptedValue
        }
    }
}

私のカスタム モデル バインダーは正常に動作しますが、問題は、ユーザーが指定した値を変換または解析できなかった場合です。これが発生した場合 (TimeOfDay コンストラクターが をスローした場合ArgumentException)、ビューに正しく表示されるモデル エラーを追加しますが、変換できなかったユーザーが入力した値は失われます。ユーザーが値を入力したテキストボックスは空で、HTML ソースでは value 属性が空の文字列 "" に設定されています。

編集:何か間違ったことをしているのが私のエディターテンプレートではないかと思っているので、ここに含めます:

@model Nullable<TimeOfDay>
@if (Model.HasValue)
{
    @Html.TextBox(string.Empty, Model.Value.ToString());
}
else
{
    @Html.TextBox(string.Empty);
}

ユーザーが値を修正できるように、バインド エラーが発生したときに値が失われないようにするにはどうすればよいですか?

4

1 に答える 1

17

あはは!私はついに答えを見つけました!このブログ投稿で答えが得られました。私が見逃していたのはModelState.SetModelValue()、モデル バインダーで呼び出すことです。したがって、コードは次のようになります。

public class TimeOfDayModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        try
        {
            // Let the TimeOfDay struct take care of the conversion from string.
            return new TimeOfDay(result.AttemptedValue, result.Culture);
        }
        catch (ArgumentException)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Value is invalid. Examples of valid values: 6:30, 16:00");
            // This line is what makes the difference:
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, result);
            return bindingContext.Model;
        }
    }
}

これにより、私が経験した何時間ものフラストレーションから誰かが救われることを願っています.

于 2011-04-04T09:12:33.587 に答える