C# 绑定属性没有“排除”,是否有解决方法?

C# 绑定属性没有“排除”,是否有解决方法?,c#,asp.net-core-mvc,C#,Asp.net Core Mvc,在ASP.Net核心MVC中,Bind属性似乎不再具有Exclude属性。假设我的模型中有20个属性,例如,我只想从模型中为编辑功能排除一个字段,那么为了排除单个字段而键入19个属性的名称将非常不方便 问题的关键是要找出微软是否为此添加了任何其他属性,或者在我看来有什么隐藏的东西可以做到这一点 与类似,您必须实现IPropertyFilterProvider接口 大概是这样的: [AttributeUsage(AttributeTargets.Class | AttributeTarge

在ASP.Net核心MVC中,
Bind
属性似乎不再具有
Exclude
属性。假设我的模型中有20个属性,例如,我只想从模型中为编辑功能排除一个字段,那么为了排除单个字段而键入19个属性的名称将非常不方便

问题的关键是要找出微软是否为此添加了任何其他属性,或者在我看来有什么隐藏的东西可以做到这一点

与类似,您必须实现
IPropertyFilterProvider
接口

大概是这样的:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
    public class ExcludeBindAttribute : Attribute, IModelNameProvider, IPropertyFilterProvider
    {
        private static readonly Func<ModelMetadata, bool> _default = (m) => true;

        private Func<ModelMetadata, bool> _propertyFilter;

        public string[] Exclude { get; }

        public string Prefix { get; set; }

        public ExcludeBindAttribute(params string[] exclude)
        {
            var items = new List<string>();
            foreach (var item in exclude)
            {
                items.AddRange(SplitString(item));
            }

            Exclude = items.ToArray();
        }

        public string Name
        {
            get { return Prefix; }
        }

        public Func<ModelMetadata, bool> PropertyFilter
        {
            get
            {
                if (Exclude != null && Exclude.Length > 0)
                {
                    if (_propertyFilter == null)
                    {
                        _propertyFilter = (m) => !Exclude.Contains(m.PropertyName, StringComparer.Ordinal);
                    }

                    return _propertyFilter;
                }
                else
                {
                    return _default;
                }
            }
        }

        private static IEnumerable<string> SplitString(string original)
        {
            if (string.IsNullOrEmpty(original))
            {
                return Array.Empty<string>();
            }

            var split = original.Split(',').Select(piece => piece.Trim()).Where(piece => !string.IsNullOrEmpty(piece));

            return split;
        }
    }
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter,AllowMultiple=false,Inherited=true)]
公共类ExcludeBindAttribute:Attribute、IModelNameProvider、IPropertyFilterProvider
{
私有静态只读函数默认值=(m)=>true;
私人功能过滤器;
公共字符串[]排除{get;}
公共字符串前缀{get;set;}
public ExcludeBindAttribute(参数字符串[]exclude)
{
var items=新列表();
foreach(排除中的var项)
{
items.AddRange(拆分字符串(item));
}
Exclude=items.ToArray();
}
公共字符串名
{
获取{返回前缀;}
}
公共功能属性过滤器
{
得到
{
if(Exclude!=null&&Exclude.Length>0)
{
if(_propertyFilter==null)
{
_propertyFilter=(m)=>!Exclude.Contains(m.PropertyName,StringComparer.Ordinal);
}
返回属性过滤器;
}
其他的
{
返回默认值;
}
}
}
私有静态IEnumerable SplitString(原始字符串)
{
if(string.IsNullOrEmpty(原始))
{
返回Array.Empty();
}
var split=original.split(',')。选择(piece=>piece.Trim())。其中(piece=>!string.IsNullOrEmpty(piece));
收益分割;
}
}

我不太确定要将该字段排除在何处。如果您有一个操作方法,该方法获取包含20个属性的viewmodel类类型的参数,并且希望从模型绑定中排除其中一个属性,则可以在该属性上使用[BindNever]注释(请查看)


因此,您的操作方法会得到一个带有注释属性的viewmodel,该属性始终为null-用户无法传递该属性的值,因为它不会被处理为模型绑定。

Good fix@rocky。一个问题是,前缀属性用于什么?我看不出任何界面都需要它,只是想确定在删除它之前它没有被模型绑定器或其他东西使用。不确定我为什么包含它…可能是从其他地方复制的。无论如何,其中一个接口只需要
Name
属性,因此删除它应该是安全的。如果您进行测试,很快就会发现;)@当所有(或大部分)模型属性名称都以某个前缀开头时(如“udg_..”),bcngr前缀很有用,这可能发生在同时作为视图模型的基于实体框架的实体上(当应用程序被迫与某些旧数据库表对齐时)通过使用前缀属性,不需要键入所有以“udg_”开头的属性名称(如下示例),而是枚举明确的属性名称(“Id,Password”,vs“udg_Id,udg_Password”)。因此@rocky必须更改为
Exclude.Contains(string.Concat(Prefix,m.PropertyName),…)
好的,一个很常见的例子可能是在创建和编辑视图中使用视图模型类以避免重复,在这种情况下,可能需要排除键属性(Id)我不是说这是一个典型的例子,而是一个例子。好的观点!在这种情况下,我将创建两个视图模型类:一个包含除ID之外的所有属性的创建视图模型类,然后通过继承(如果你赞成的话,也可以用构图,尽管在这种情况下,我会坚持继承)具有单个附加属性ID的编辑视图模型。在操作方法中使用一个或另一个视图模型。这样做的好处是,您不会轻易忘记“排除”,因为您必须对两个视图模型类中的一个作出明确的决定。这使整件事不那么容易出错。