【问题标题】:ASP.NET Model binding based on attribute基于属性的 ASP.NET 模型绑定
【发布时间】:2017-09-23 03:22:09
【问题描述】:

在 asp.net mvc 应用程序中,我创建了自定义模型绑定器和 IModelBinderProvider 以在货币以千位格式发布到服务器时处理货币,例如 $123,456.00

只有当模型的属性应用了某些属性时,我才想调用自定义模型绑定器。下面是我的代码

public interface IScrubberAttribute
{
    object Scrub(string modelValue, out bool success);
}

public class CurrencyScrubberAttribute : Attribute, IScrubberAttribute
{    
    public object Scrub(string modelValue, out bool success)
    {
       // do something
    }
}

public class ScrubbingModelBinder : DefaultModelBinder
{
    IScrubberAttribute _attribute;

    public ScrubbingModelBinder(Type type, IScrubberAttribute attribute)
    {
        _attribute = attribute as IScrubberAttribute;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // do something
    }
}

public class ScrubbingModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(Type modelType)
    {
        if (modelType == typeof(decimal) || modelType == typeof(decimal?))
        {

            //??? ISSUE: the line below always returns null.
            var attribute = modelType.GetCustomAttributes(typeof(CurrencyScrubberAttribute), false).FirstOrDefault();
            if (attribute != null)
            {
                return new ScrubbingModelBinder(modelType, attribute as IScrubberAttribute);
            }
        }

        return null;
    }
}

我的模型

public class MyModel
{
    [CurrencyScrubber]       
    public decimal? MyValue { get; set; }
}

我在应用程序启动时注册了ScrubbingModelBinderProvider,所以它会被调用。

问题
ScrubbingModelBinderProvider 中,我试图查找该属性是否应用了[CurrencyScrubber] 属性;如果是则只调用ScrubbingModelBinder
但是modelType.GetCustomAttributes() 方法无法找到或返回CurrancyScrubber 属性。当我在调试模式下快速观看时,modelType.GetCustomAttributes() 方法返回 3 个属性,但没有一个属性属于 CurrancyScrubber

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-4 asp.net-mvc-5 model-binding


    【解决方案1】:

    我在原始问题中发布的IModelBinderProvider 方法用于 asp.net 核心应用程序,它适用于 asp.net 核心。我试图在经典的 asp.net 中使用相同的方法。但是在经典的 asp.net 中,您无法获得自定义属性。相关的 SO 帖子 herehere

    所以为了解决这个问题,我覆盖了System.Web.Mvc.DefaultModelBinderBindProperty 方法,我可以在其中获取自定义属性

    public class ScrubbingModelBinder : DefaultModelBinder
    {    
        public ScrubbingModelBinder()
        {           
        }       
    
        protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
        {
            var propBindAttr = propertyDescriptor.Attributes.OfType<CurrencyScrubberAttribute>().FirstOrDefault();
            if (propBindAttr != null &&
                (propertyDescriptor.PropertyType == typeof(decimal) || propertyDescriptor.PropertyType == typeof(decimal?)))
            {
                var value = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
                if (value != null && value.AttemptedValue != null)
                {
                    var success = true;
                    var result = propBindAttr.Scrub(value.AttemptedValue, out success);
                    if (success)
                    {
                        propertyDescriptor.SetValue(bindingContext.Model, result);
                        return;
                    }
                }
            }
    
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }
    }
    

    然后在Application_Start()方法中注册为DefaultBinder。无需使用IModelBinderProvider

     ModelBinders.Binders.DefaultBinder = new ScrubbingModelBinder();
    

    所以现在默认绑定器将像以前一样用于所有属性,除了具有[CurrencyScrubber] 属性的那个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多