これを行うには、カスタムのモデルバインダーを実装する必要があります。そのまま延長できます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;
}