有没有人知道如何在OData V4的metatdata中设置/读取基于词汇的注释来定义最大字符串长度等内容?
有一篇文章Client Annotation Support,但它没有显示任何示例代码,我也不是100%确定他们甚至在谈论数据注释。
它的代码如下:
var person = dsc.People.ByKey("russellwhyte").GetValue();
// Try to get an annotation for a property
dsc.TryGetAnnotation<Func<ObservableCollection<string>>, string>(() => person.Emails, fullQualifiedTermName, qualifier, out annotation);
但它没有解释“fullQualifiedTermName”或“qualifier”的用途 我正在添加“odata.inculde-annotations = *”但这似乎没有帮助。
我也尝试了以下内容。
dsc.TryGetAnnotation<Func<string>, string>(() => person.FirstName, "System.ComponentModel.DataAnnotations", out annotation);
但是只返回null。
我在2012年发现了一篇文章Vocabularies in WCF Data Services,其中讨论了对验证元数据的支持 我打算试一试 我希望在OData V4中有一个简单/更好的方法。
更新1
WCF词汇表示例在OData V4中不起作用,因为System.Web.Http.HttpConfiguration中缺少config.AnnotationsBuilder。
OData V4支持此处定义的词汇表http://www.odata.org/vocabularies/,甚至提供我需要的内容“元数据注释可以定义特定属性的有效值范围”但似乎没有任何样本代码SAP https://blogs.sap.com/2013/10/07/vocabulary-based-annotations/使用它。
更新2
看完TripPinService之后我注意到他们在预算上有一些注释,如下所示。
<Property Name="Budget" Type="Edm.Single" Nullable="false">
<Annotation Term="Org.OData.Measures.V1.ISOCurrency" String="USD"/>
<Annotation Term="Org.OData.Measures.V1.Scale" Int="2"/>
</Property>
幸运的是,该项目的源代码是ODataSamples TripPin
查看服务后,我发现我首先必须创建自己的xml词汇表文件。 (ValidationVocabularyies.xml)
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Org.OData.Validation.V1" Alias="Validation">
<Term Name="StringLength" Type="Edm.String" AppliesTo="Property">
<Annotation Term="Core.Description" String="Set max length of string." />
</Term>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
在WebApiConfig文件中,我必须访问xml文件并将词汇表注释添加到元数据中。
我很幸运,因为TripPin的源代码有一个很好的助手类。 (我将其修改为如下所示)
public static class DataValidationHelpers
{
public static readonly IEdmModel Instance;
public static readonly IEdmTerm StringLengthTerm;
internal const string StringLength = "Org.OData.Validation.V1.StringLength";
static DataValidationHelpers()
{
using (var stream = System.IO.File.OpenRead(System.Web.HttpContext.Current.Server.MapPath("~/bin") + @"\App_Start\ValidationVocabularies.xml"))
{
IEnumerable<EdmError> errors;
System.Xml.XmlReader reader = System.Xml.XmlReader.Create(stream);
CsdlReader.TryParse(reader, out Instance, out errors);
}
StringLengthTerm = Instance.FindDeclaredTerm(StringLength);
}
public static void SetStringLengthAnnotation(this EdmModel model, IEdmProperty property, int length)
{
if (model == null) throw new ArgumentNullException("model");
if (property == null) throw new ArgumentNullException("property");
var target = property;
var term = StringLengthTerm;
var expression = new EdmIntegerConstant(length);
var annotation = new EdmVocabularyAnnotation(target, term, "StringLength", expression);
annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
model.AddVocabularyAnnotation(annotation);
}
}
然后我从GetEdmModel()方法中调用它,如下所示:
var target = ((EdmEntityType)edmModel.FindDeclaredType("Test.Models.Person")).FindProperty("FirstName");
((EdmModel)edmModel).SetStringLengthAnnotation(target, 50);
如果有人知道如何通过Name而不是某些字符串值知道该属性,那将是很好的
我确实尝试过builder.EntityType()。Property(p =&gt; p.FirstName)但该类型不是IEdmProperty。
无论如何继续前进...
所以现在使用我的浏览器来获取$元数据我可以清楚地看到FirstName上的字符串长度属性。
<Property Name="FirstName" Type="Edm.String">
<Annotation Term="Org.OData.Validation.V1.StringLength" Qualifier="StringLength" Int="50"/>
</Property>
这很好,但现在是下一个问题。如何从客户端获取它?
一开始我试过了。
DbContext.TryGetAnnotation<string>(personQueryResponse.FirstName, "Org.OData.Validation.V1.StringLength", out annotation);
但是这给了我以下错误。
值不能为空。参数名称:element 然后我试了一下:
DbContext.TryGetAnnotation<Func<string>, string>(() => personQueryResponse.FirstName, "Org.OData.Validation.V1.StringLength", out annotation);
但注释为空 我注意到调用TryGetAnnotation不会再次调用OData服务 所以我认为我必须阅读客户端CSDL文件,然后我回头看看WCF文章,但他们没有告诉你他们在哪里获得了“annotations”集合。
我还在挖掘,但这已成为一个失败的原因
很遗憾微软希望将OData推向如此优质的服务,但几乎没有文档和非常小的支持小组。
我有4个开放的OData问题和很少的点击率
不要误会我的意思,我喜欢OData,但这是一种爱/恨的关系。
更新3
我目前的解决方法是创建一个看起来像我的实体的分部类,然后创建一个包含数据注释的接口
Add data annotations to a class generated by entity framework