breezejs:覆盖displayname

breezejs:覆盖displayname,breeze,Breeze,我正在定制验证消息。使用messageTemplates属性工作正常。但是,它使用%displayName%来呈现属性的名称,而我找不到如何重写此值?有什么办法吗 这还没有很好的文档记录,但是您可以简单地在任何dataProperty上设置'displayName'属性,这将覆盖自动生成的显示名称,并将用于此属性的所有验证消息。所以 var custType = myEntityManager.metadataStore.getEntityType("Customer"); var dp =

我正在定制验证消息。使用messageTemplates属性工作正常。但是,它使用%displayName%来呈现属性的名称,而我找不到如何重写此值?有什么办法吗

这还没有很好的文档记录,但是您可以简单地在任何dataProperty上设置'displayName'属性,这将覆盖自动生成的显示名称,并将用于此属性的所有验证消息。所以

 var custType = myEntityManager.metadataStore.getEntityType("Customer");
 var dp = custType.getProperty("companyName");
 dp.displayName = "My custom display name";

另外,请参阅本页底部的“自定义消息模板”:

我也想这样做,但我想使用EF模型中的[DisplayName]属性。在我找到一种我认为可以分享的方法后,我找不到任何人有这样做的例子

首先,我扩展了从BreezeController返回的元数据:

[HttpGet]
public string Metadata()
{
    // Extend metadata with extra attributes
    JObject metadata = JObject.Parse(contextProvider.Metadata());
    string nameSpace = metadata["schema"]["namespace"].ToString();
    foreach (var entityType in metadata["schema"]["entityType"])
    {
        string typeName = entityType["name"].ToString();
        Type t = Type.GetType(nameSpace + "." + typeName);
        foreach (var prop in t.GetProperties())
        {
            foreach (var attr in prop.CustomAttributes)
            {
                string name = attr.GetType().Name;
                foreach (var p in entityType["property"])
                {
                    if (prop.Name == p["name"].ToString()) {
                        if (attr.AttributeType.Name == "DisplayNameAttribute") {
                            DisplayNameAttribute a = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
                            p["displayName"] = a.DisplayName;
                            break;
                        }
                    }
                }
            }
        }
    }

    return metadata.ToString();
}
然后,我在元数据加载之后添加了一点javascript,以便从Breeze希望找到的扩展元数据中插入显示名称

manager.fetchMetadata().then(function (md) {
    angular.forEach(md.schema.entityType, function (et) {
        var etype = manager.metadataStore.getEntityType(et.name);
        angular.forEach(et.property, function (p) {
            var prop = etype.getProperty(p.name);
            prop.displayName = p.displayName;
        });
    });

    console.log("starting app");
    angular.bootstrap($("#app"), ["app"]);
});
我用的是角度的,所以如果你不是,你可以忽略角度的东西,可能会得到这个想法。这似乎很有效。将其扩展到其他模型属性以及RegularExpression验证属性应该非常容易。下一步我可能会做这个

仅供参考,这些代码中的一些没有经过优化,可能会被重构、修饰,但我只是让它工作起来,并认为我会与大家分享。如果有人有更好的建议,请告诉我。希望将来Breeze能够以更受支持的方式扩展元数据。这看起来确实有点像黑客。

看看


这可以通过将现有的“name”值重命名为nameOnServer(以满足getDataProperty调用)并将DisplayNameAttribute值插入为“name”来改进吗?

在jpcoder请求建议之后,下面是我略微改进的服务器部分:

JObject metadata = JObject.Parse(contextProvider.Metadata());
string nameSpace = metadata["schema"]["namespace"].ToString();
foreach (var entityType in metadata["schema"]["entityType"])
{
    string typeName = entityType["name"].ToString();
    Type t = Type.GetType(nameSpace + "." + typeName);

    IEnumerable<JToken> metaProps = null;
    if (entityType["property"].Type == JTokenType.Object)
        metaProps = new[] { entityType["property"] };
    else
        metaProps = entityType["property"].AsEnumerable();

    var props = from p in metaProps
                let pname = p["name"].ToString()
                let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
                where prop != null
                from attr in prop.CustomAttributes
                where attr.AttributeType.Name == "DisplayNameAttribute"
                select new
                {
                    Prop = p,
                    DisplayName = ((DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute))).DisplayName
                };
    foreach (var p in props)
        p.Prop["displayName"] = p.DisplayName;
}
JObject metadata=JObject.Parse(contextProvider.metadata());
字符串名称空间=元数据[“架构”][“名称空间”]。ToString();
foreach(元数据[“架构”][“entityType”]中的变量entityType)
{
字符串typeName=entityType[“name”].ToString();
Type t=Type.GetType(名称空间+“+”类型名称);
IEnumerable metaProps=null;
if(entityType[“property”].Type==JTokenType.Object)
metaProps=new[]{entityType[“属性”]};
其他的
metaProps=entityType[“属性”].AsEnumerable();
var props=来自metaProps中的p
让pname=p[“name”].ToString()
让prop=t.GetProperties().SingleOrDefault(prop=>prop.Name==pname)
其中prop!=null
从prop.CustomAttributes中的attr
其中attr.AttributeType.Name==“DisplayNameAttribute”
选择新的
{
Prop=p,
DisplayName=((DisplayNameAttribute)属性.GetCustomAttribute(prop,typeof(DisplayNameAttribute))).DisplayName
};
foreach(道具中的var p)
p、 Prop[“displayName”]=p.displayName;
}

对服务器代码的必要更改是,如果您的模型类位于不同的程序集中,则不能使用

Type t = Type.GetType(nameSpace + "." + typeName);
您需要每个类型的名称空间(在元数据中),并且(我认为)使用BuildManager在不同的程序集中定位适当的类型。cSpaceOSpaceMapping的映射可能会更优雅,但我没有时间研究不同的json格式选项

JObject metadata = JObject.Parse(UnitOfWork.Metadata());
string EFNameSpace = metadata["schema"]["namespace"].ToString();
string typeNameSpaces = metadata["schema"]["cSpaceOSpaceMapping"].ToString();
typeNameSpaces = "{" + typeNameSpaces.Replace("],[", "]|[").Replace("[", "").Replace("]", "").Replace(",", ":").Replace("|", ",") + "}";
        JObject jTypeNameSpaces = JObject.Parse(typeNameSpaces);

        foreach (var entityType in metadata["schema"]["entityType"])
        {
            string typeName = entityType["name"].ToString();
            string defaultTypeNameSpace = EFNameSpace + "." + typeName;
            string entityTypeNameSpace = jTypeNameSpaces[defaultTypeNameSpace].ToString();
            Type t = BuildManager.GetType(entityTypeNameSpace, false);

            IEnumerable<JToken> metaProps = null;
            if (entityType["property"].Type == JTokenType.Object)
                metaProps = new[] { entityType["property"] };
            else
                metaProps = entityType["property"].AsEnumerable();

            var props = from p in metaProps
                        let pname = p["name"].ToString()
                        let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
                        where prop != null
                        from attr in prop.CustomAttributes
                        where attr.AttributeType.Name == "DisplayNameAttribute"
                        select new
                        {
                            Prop = p,
                            DisplayName = ((DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute))).DisplayName
                        };
            foreach (var p in props)
            {
                p.Prop["displayName"] = p.DisplayName;
            }
        }
JObject-metadata=JObject.Parse(UnitOfWork.metadata());
字符串EFNameSpace=metadata[“schema”][“namespace”].ToString();
string typenamespace=元数据[“schema”][“cSpaceOSpaceMapping”]。ToString();
typeNameSpaces=“{”+typeNameSpaces.Replace(“],[”,“]|[”)。Replace(“[”,”)。Replace(“,”)。Replace(“,”:”)。Replace(“;”,“,”)+”);
JObject jTypeNameSpaces=JObject.Parse(类型名称空间);
foreach(元数据[“架构”][“entityType”]中的变量entityType)
{
字符串typeName=entityType[“name”].ToString();
字符串defaultTypeNameSpace=EFNameSpace+“+typeName;
字符串entityTypeNameSpace=jTypeNameSpaces[defaultTypeNameSpace].ToString();
类型t=BuildManager.GetType(entityTypeNameSpace,false);
IEnumerable metaProps=null;
if(entityType[“property”].Type==JTokenType.Object)
metaProps=new[]{entityType[“属性”]};
其他的
metaProps=entityType[“属性”].AsEnumerable();
var props=来自metaProps中的p
让pname=p[“name”].ToString()
让prop=t.GetProperties().SingleOrDefault(prop=>prop.Name==pname)
其中prop!=null
从prop.CustomAttributes中的attr
其中attr.AttributeType.Name==“DisplayNameAttribute”
选择新的
{
Prop=p,
DisplayName=((DisplayNameAttribute)属性.GetCustomAttribute(prop,typeof(DisplayNameAttribute))).DisplayName
};
foreach(道具中的var p)
{
p、 Prop[“displayName”]=p.displayName;
}
}
JObject metadata=JObject.Parse(this.\u context.metadata());
字符串EFNameSpace=metadata[“schema”][“namespace”].ToString();
string typenamespace=元数据[“schema”][“cSpaceOSpaceMapping”]。ToString();
typeNameSpaces=“{”+typeNameSpaces.Replace(“],[”,“]|[”)。Replace(“[”,”)。Replace(“,”)。Replace(“,”:”)。Replace(“;”,“,”)+”);
JObject jTypeNameSpaces=JObject.Parse(类型名称空间);
foreach(元数据[“架构”][“entityType”]中的变量entityType)
{
字符串typeName=entityType[“name”].ToString();
字符串defaultTypeNameSpa
        JObject metadata = JObject.Parse(this._context.Metadata());
        string EFNameSpace = metadata["schema"]["namespace"].ToString();
        string typeNameSpaces = metadata["schema"]["cSpaceOSpaceMapping"].ToString();
        typeNameSpaces = "{" + typeNameSpaces.Replace("],[", "]|[").Replace("[", "").Replace("]", "").Replace(",", ":").Replace("|", ",") + "}";
        JObject jTypeNameSpaces = JObject.Parse(typeNameSpaces);

        foreach (var entityType in metadata["schema"]["entityType"])
        {
            string typeName = entityType["name"].ToString();
            string defaultTypeNameSpace = EFNameSpace + "." + typeName;
            string entityTypeNameSpace = jTypeNameSpaces[defaultTypeNameSpace].ToString();
            Type t = BuildManager.GetType(entityTypeNameSpace, false);

            IEnumerable<JToken> metaProps = null;
            if (entityType["property"].Type == JTokenType.Object)
                metaProps = new[] { entityType["property"] };
            else
                metaProps = entityType["property"].AsEnumerable();

            var props = from p in metaProps
                        let pname = p["name"].ToString()
                        let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
                        where prop != null
                        from attr in prop.CustomAttributes
                        where attr.AttributeType.Name == "DisplayAttribute"
                        select new
                        {
                            Prop = p,
                            DisplayName = ((DisplayAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayAttribute))).Name
                        };
            foreach (var p in props)
            {
                p.Prop["displayName"] = p.DisplayName;
            }
        }

        return metadata.ToString();
    manager.metadataStore.getEntityTypes().forEach(function (storeEntityType) {
        if (!(storeEntityType instanceof breeze.EntityType)) {
            throw new Error("loadExtendedMetadata found '" + storeEntityType
                + "' StructuralType that is not an EntityType (e.g. a ComplexType)");
        }

        var extEntityType = extendedMetadata.entitiesExtended.find((extendedEntityType) => {
            return extendedEntityType.shortName + ":#" + extendedEntityType.nameSpace === storeEntityType.name;
        });


        (storeEntityType as breeze.EntityType).getProperties().forEach((storeProperty) => {
            //Both NavigationProperty & DataProperty have displayName & nameOnServer properties
            var storeDataProperty = <breeze.DataProperty>storeProperty;

            var extProperty;
            if (extEntityType) {
                extProperty = extEntityType.propertiesExtented.find((extendedProperty) => {
                    return extendedProperty.name === storeDataProperty.nameOnServer;
                });
            }

            //Smart default: nameOnServer "PascalCaseFieldName" or "camelCaseFieldName" converted to "Upper Case Field Name"
            storeDataProperty.displayName = (extProperty && extProperty.displayName)
                || storeDataProperty.nameOnServer.replace(/^./, function (str) {
                    // first ensure the first character is uppercase
                    return str.toUpperCase();
                    // insert a space before all caps, remove first character (added space)
                }).replace(/([A-Z])/g, " $1").substring(1);
        });
    });