最大文字列長などを定義するために、OData V4 のメタデータで語彙ベースの注釈を設定/読み取る方法を知っている人はいますか?
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 年の記事「WCF Data Services の語彙」を見つけました。
やってみます。
OData V4 でこれを行うための簡単でより良い方法があることを願っています。
更新 1
config.AnnotationsBuilder が System.Web.Http.HttpConfiguration にないため、WCF 語彙の例は OData V4 では機能しません。
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 ボキャブラリ ファイルを作成する必要があることがわかりました。(ValidationVocabularies.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);
文字列値ではなく名前でプロパティにアクセスする方法を誰かが知っていると便利です。
私は builder.EntityType().Property(p => p.FirstName) を試しましたが、その型は IEdmProperty ではありません。
とにかく先に進みます...
ブラウザを使用して $metadata にアクセスすると、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);
しかし、それは私に次のエラーを与えます。
値を null にすることはできません。パラメータ名:要素それから私は試しました:
DbContext.TryGetAnnotation<Func<string>, string>(() => personQueryResponse.FirstName, "Org.OData.Validation.V1.StringLength", out annotation);
しかし、注釈は null です。
TryGetAnnotation を呼び出しても OData サービスが再度呼び出されないことに気付きました。
それで、クライアント側の CSDL ファイルを読む必要があると思ったので、WCF の記事を振り返りましたが、「注釈」コレクションをどこで入手したかはわかりません。
私はまだ掘り下げていますが、これは失われた原因になりつつあります。
Microsoft が OData をこのような優れたサービスとしてプッシュしたかったのは残念ですが、ドキュメントはほとんどなく、サポート グループも非常に小規模です。
未解決の OData に関する質問が 4 つあり、ヒットはほとんどありません。
誤解しないでほしいのですが、私は OData が大好きですが、これは好き嫌いの関係です。
更新 3
現在の回避策は、エンティティのように見える部分クラスを作成してから、データ注釈を含むインターフェイスを作成することです。
エンティティ フレームワークによって生成されたクラスにデータ アノテーションを追加する