4

次のモデルを考えると、

public class A
{
    public string Name { get; set; }
}

public class B
{
    public string Address { get; set; }
    public A InstanceOfA { get; set; }
}

意見、

<%= Html.TextBox("A.Name") %>

およびコントローラー

UpdateModel<B>(b, collection.ToValueProvider());

私の b インスタンスには、Name に空の文字列を持つ A のプロパティが含まれます。

名前に値が入力されていない場合、UpdateModel に A プロパティを null に設定させる方法はありますか?

明確にするために、これは単純なケースです。私の現実世界のシナリオには、この類の何百ものプロパティを持つデータ モデルが含まれています。これらのデータ モデルの定義は、私の手に負えません。したがって、一般的なケースの解決策が必要です。つまり、値が入力されていない場合はプロパティを作成しないでください。

さらなる明確化: これは編集シナリオでも機能する必要があります。つまり、A.Name が "foo" に設定された b のインスタンスは、A.Name を "" に設定するように編集されます。A を null にする必要があります。

4

5 に答える 5

5

私はこの動作を発見しました (チェック制約のおかげで偶然に)、それは間違いだと思います。nullの代わりに空の文字列をデータベースに誤って保存している開発者がどれだけいるのだろうか? :-)

とにかく、これをもう少し調べて、より良い解決策があるかどうかを確認します。

アップデート:

ここに解決策があります:

using System.ComponentModel;
using System.Web.Mvc;

namespace CustomerWebsite.Mvc
{
  public sealed class EmptyStringToNullModelBinder : DefaultModelBinder
  {
    protected override void SetProperty(ControllerContext controllerContext,
      ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
      if ((value != null)
          && (value.GetType() == typeof(string)
              && ((string)value).Length == 0))
      {
        value = null;
      }

      base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    }
  }
}

そして Application_Start にこれを入れます:

ModelBinders.Binders.DefaultBinder = new EmptyStringToNullModelBinder();
于 2009-03-12T20:41:46.820 に答える
3

これはちょっと関連していて、何とかこのページにたどり着いた人の助けになると思いました。私は ASP.NET MVC 3 を使用しています。このバージョンでは、空のテキスト ボックスがサーバーに投稿されると、モデルに null としてバインドされます。

null 文字列を空の文字列に変更する反対のモデル バインダーを作成する必要がありました。

Andrew Peters による上記のコードを取り上げ (ありがとうございます!)、次のように変更しました。

注意事項:

  1. すでに述べたように、このモデル バインダーは反対のことを行います。
  2. 値の型をチェックする代わりに、propertyDescriptor を介してチェックしています。値を説明することが目的であるため、より良いと思います。私の場合、null の値を調べることができないため、これは不可欠です。記述子を通じて、必要なものをすべて見つけることができます。

コードは次のとおりです。

public sealed class CustomModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext,
        ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
        if (value == null && propertyDescriptor.PropertyType == typeof(string))
            value = string.Empty;

        base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    }
}

これが誰かに役立つことを願っています。

于 2011-11-25T02:25:54.230 に答える
2

UpdateModelは、このプロパティがFormCollectionにある場合に、プロパティを初期化します。UpdateModelが一部のプロパティを空の値に設定しないようにするために、値が空のFormCollectionからすべてのアイテムを削除できます。これを行うには、NameValueCollectionタイプに拡張メソッドを追加できます。

于 2009-02-18T05:08:47.740 に答える
2

ASP.NET MVC 2 Preview 1 は、モデル バインディングを行うときにこれを行うようです。

すなわち。自動的に ?Foo=&Bar=cat に変換します

model.Foo = null;
model.Bar = "cat":

私は実際にはヌルよりも空の文字列を取得することを好むので、最終的なデザインかどうかはまだわかりませんが、変更があるようです.

于 2009-08-11T23:37:44.113 に答える
0

回答ありがとうございます。すべての文字列プロパティが変更されないように、また文字列以外のプロパティも変更できるように、少し変更しました。に感謝しDefaultValueAttributeます。

public class DefaultValueModelBinder: DefaultModelBinder
{
  protected override void SetProperty( ControllerContext controllerContext,
                                       ModelBindingContext bindingContext,
                                       PropertyDescriptor propertyDescriptor, 
                                       object value )
  {
    if( value == null )
    {
      var defaultValue = (DefaultValueAttribute)propertyDescriptor.Attributes[ typeof(DefaultValueAttribute) ];
      if( defaultValue != null )
        value = defaultValue.Value;
    }

    base.SetProperty( controllerContext, bindingContext, propertyDescriptor, value );
  }
}
于 2013-01-29T15:05:31.147 に答える