[attributeusage(attributetargets.property | attributetargets.field | attributetargets.parameter)]
    public class minfieldattribute : basecompareattribute
    {
        public string minvaluefield { get; set; }
        private string mindisplayname { get; set; }

        public minfieldattribute(type operandtype, string minvaluefield,string mindisplayname) : base(operandtype, minvaluefield, () => localizationextensions.t("rundong.infrastructure.minfieldattribute.errormsg", "{0}不能小于{1}"))
        {
            minvaluefield = minvaluefield;
            mindisplayname = mindisplayname;
        }

        protected override validationresult isvalid(object value, validationcontext validationcontext)
        {
            var minpropertyinfo = validationcontext.objecttype.getproperty(minvaluefield);
            if (minpropertyinfo == null)
            {
                return new validationresult(string.format(cultureinfo.currentculture, localizationextensions.t("rundong.infrastructure.minfieldattribute.notexist", "{0}不存在"), minvaluefield));
            }

            var minpropertyvalue = minpropertyinfo.getvalue(validationcontext.objectinstance, null);
            var comparevalue = (icomparable) value;
            if (value!=null&& comparevalue.compareto(minpropertyvalue)<0)
            {
                if (mindisplayname == null)
                {
                    mindisplayname = modelmetadataproviders.current.getmetadataforproperty(
                        () => validationcontext.objectinstance, validationcontext.objecttype, minvaluefield).getdisplayname();
                }
                return new validationresult(formaterrormessage(validationcontext.displayname));
            }
            return null;
        }


        public override string formaterrormessage(string name)
        {
            return string.format(errormessagestring, name, mindisplayname??minvaluefield);
        }

    }

  

public class minfieldvalidationmetadata<tvaluetype> : modelvalidationmetadata where tvaluetype : struct
    {
        public string minvaluefield { get; set; }
        protected override modelvalidator createvalidatorcore(extendedmodelmetadata modelmetadata,
            controllercontext context)
        {
            var type = typeof(tvaluetype?).getunderlyingtype();
            var minmodelmetadata=  modelmetadata.properties.firstordefault(a => a.propertyname == minvaluefield);
            var mindisplayname = minmodelmetadata!=null ? minmodelmetadata.getdisplayname() : modelmetadataproviders.current.getmetadataforproperty(() => null, modelmetadata.containertype, minvaluefield).getdisplayname();
            var attribute = new minfieldattribute(type, minvaluefield, mindisplayname);
            return new basecompareattributeadapter(modelmetadata, context, attribute){minvaluefield = minvaluefield };
        }
    }

  通过重写isvalid方向添加自定义验证,minvaluefield为需要比较的字段名,mindisplayname是显示的名字。basecompareattribute记录的构造函数第三个参数为重写formaterrormessage函数,以及提供比较值的类型转换

 

具体是参考微软两个字段比较是否相同https://github.com/aspnet/aspnetwebstack/blob/master/src/system.web.mvc/compareattribute.cs