4

MVC3 のアクションの引数として使用している POCO があります。このようなもの:

私のタイプ

public class SearchData
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
}

私の行動

public ActionResult Index(SearchData query)
{
    // I'd like to be able to do this
    if (query == null)
    {
        // do something
    }
}

現在、すべてのプロパティを としてqueryのインスタンスとして渡されます。上記のコードにある null チェックを実行できるように、 for を取得することをお勧めします。SearchDatanullnullquery

のプロパティのいずれかを取得しているかどうかを確認するために、いつでもModelBinder.Any()さまざまなキーを調べたり、単に調べたりすることができますが、リフレクションを使用して のプロパティをループする必要はありません。また、クエリが唯一のパラメーターである場合にのみチェックを使用できます。パラメータを追加するとすぐに、その機能が壊れます。ModelBinderqueryqueryModelBinder.Any()

MVC3 の現在のモデル バインディング機能では、アクションの POCO 引数に対して null を返す動作を取得できますか?

4

6 に答える 6

6

これを行うには、カスタムのモデルバインダーを実装する必要があります。そのまま延長できますDefaultModelBinder

public override object BindModel(
    ControllerContext controllerContext, 
    ModelBindingContext bindingContext)
{
    object model = base.BindModel(controllerContext, bindingCOntext);
    if (/* test for empty properties, or some other state */)
    {
        return null;
    }

    return model;
}

具体的な実装

これは、すべてのプロパティが null の場合にモデルに対して null を返すバインダーの実際の実装です。

/// <summary>
/// Model binder that will return null if all of the properties on a bound model come back as null
/// It inherits from DefaultModelBinder because it uses the default model binding functionality.
/// This implementation also needs to specifically have IModelBinder on it too, otherwise it wont get picked up as a Binder
/// </summary>
public class SearchDataModelBinder : DefaultModelBinder, IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // use the default model binding functionality to build a model, we'll look at each property below
        object model = base.BindModel(controllerContext, bindingContext);

        // loop through every property for the model in the metadata
        foreach (ModelMetadata property in bindingContext.PropertyMetadata.Values)
        {
            // get the value of this property on the model
            var value = bindingContext.ModelType.GetProperty(property.PropertyName).GetValue(model, null);

            // if any property is not null, then we will want the model that the default model binder created
            if (value != null)
                return model;
        }

        // if we're here then there were either no properties or the properties were all null
        return null;
    }
}

これを global.asax のバインダーとして追加する

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    ModelBinders.Binders.Add(typeof(SearchData), new SearchDataModelBinder());
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    MvcHandler.DisableMvcResponseHeader = true;
}
于 2012-07-13T17:54:47.223 に答える
1

パラメータの属性としてカスタム モデル バインダーを実装します。

注: モデルのすべてのプロパティは null 可能である必要があります

  1. 上記のModelBinderClassは次のとおりです

    public class NullModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
             // use the default model binding functionality to build a model, we'll look at each property below
             object model = base.BindModel(controllerContext, bindingContext);
    
             // loop through every property for the model in the metadata
             foreach (ModelMetadata property in bindingContext.PropertyMetadata.Values)
             {
                 // get the value of this property on the model
                 var value = bindingContext.ModelType.GetProperty(property.PropertyName).GetValue(model, null);
    
                 // if any property is not null, then we will want the model that the default model binder created
                 if (value != null) return model;
             }
    
             // if we're here then there were either no properties or the properties were all null
             return null;
         }
    }
    
  2. 属性を作成する

    public class NullModelAttribute : CustomModelBinderAttribute
    {
        public override IModelBinder GetBinder()
        {
            return new NullModelBinder();
        }
    }
    
  3. コントローラーメソッドで属性を使用する

    public ActionResult Index([NullModel] SearchData query)
    {
        // I'd like to be able to do this
        if (query == null)
        {
            // do something
        }
    }
    
于 2016-01-19T05:46:37.187 に答える
1

ルートで試してください

new { controller = "Articles", action = "Index", query = UrlParameter.Optional }
于 2012-07-13T17:55:31.183 に答える
0

あなたの特定の質問に対する答えはわかりませんが、回避策を考えることができます。SearchDataクラスにメソッドを追加しないのはなぜですか?

public bool IsEmpty(){
  return Property1 == null 
      && Property2 == null 
      && Property3 == null;
}

もちろん、これを実行しようとしているタイプが複数ある場合は、面倒になるかもしれません。

于 2012-07-13T17:54:55.397 に答える