Ajaxを使用してクライアントで.NETメタデータを取得する

ASP.NET MVC環境でプログラムを作成するすべての人は、.NET全般、特にMVCでメタデータがどの程度広く使用されているかをよく知っています。 MVCでは、属性はマークアップの生成とクライアントから受信したデータの検証の両方で使用されます。

従来のサイトプログラミングモデルを使用すると、これは非常に効果的です。 しかし、ajaxを使用して作業し、クライアントでHTMLマークアップを動的に生成するとどうなりますか? クライアントにモデルメタデータ(以降、MDMと呼びます)を使用しますか? 私-はい!



直接的な方法は、データとMDMの両方を含めてjsonを形成することです。 コントローラーには次のようにいつでも書き込むことができます。

public ActionResult GetData() { return Json(new { data = new {  }, meta = new {  } }); }
      
      





これは単純ですが、ブラウザでモデルを操作する場合は便利ではなく、見た目も見苦しくなります。

MDMは、サーバーやブラウザーと同じ方法、つまりhttpヘッダーで送信する必要があると思いました。 以下を試してみましょう。

  1. メタオブジェクトを形成しましょう。
  2. JSON文字列にシリアル化します。
  3. 文字列をbase64にエンコードまたは変換します(httpヘッダーがASCIIで渡されるため、これが必要です)。
  4. 「meta-data」という名前のhttpヘッダーを作成しましょう。


次に、このアイデアを実装する簡単なコードを書きました。

まず、モデルを定義し、プロパティに属性を設定します。

 public class Data { [ReadOnly(true)] [DisplayName("")] public int Id { get; set; } [DisplayName("")] public string Name { get; set; } }
      
      







データとMDMをクライアントに返す簡単なアクションメソッドを記述します。

 public ActionResult GetData() { var data = new Data { Id = 1, Name = "Test" }; var meta = ModelMetadataProviders.Current.GetMetadataForType(() => data, typeof(Data)); var metaForJS = meta.Properties.ToDictionary( p => p.PropertyName, p => new { displayName = p.GetDisplayName(), readOnly = p.IsReadOnly }); var jsonMeta = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(metaForJS); // Uri.EscapeDataString -    .     base64. Response.Headers.Add("data-meta", Uri.EscapeDataString(jsonMeta)); return Json(data, JsonRequestBehavior.AllowGet); }
      
      





ブラウザのアドレスバーにlocalhostと入力してみましょう:67578 / Hab / GetDataとhttpヘッダーを見てください。

 HTTP/1.1 200 OK Cache-Control: private Content-Type: application/json; charset=utf-8 Server: Microsoft-IIS/8.0 X-AspNetMvc-Version: 4.0 data-meta:5B%7B%22displayName%22%3A%22%D0%9D%D0%B0%D0%B7%D0%B2%D0%B0%D0%BD %D0%B8%D0%B5%22%2C%22readOnly%22%3Afalse%7D%2C%7B%22displayName%22%3A%22%D0%9D %D0%B0%D0%B7%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%22%2C%22readOnly%22%3Atrue%7D%5D X-AspNet-Version: 4.0.30319 ...
      
      





すべてが正常に機能することを確認し、コードのクライアント側に進みます。



 function createField(name, value, meta) { //      return $('<div/>').append( $("<label/>").attr('for', name).text(meta[name].displayName), $("<input type='text'/>").attr("name", name).attr("readonly", meta[name].readOnly).val(value) ); } $(function () { $.getJSON("/Hab/GetData") .done(function (data, s, xhr) { // ,    js  meta var meta = $.parseJSON(decodeURIComponent(xhr.getResponseHeader("data-meta"))); //       for (var p in data) $('body').append(createField(p, data[p], meta)); }) .error(function(d,s){alert(s);}); });
      
      





その結果、サーバー上のモデルのメタデータを考慮に入れた2つの入力フィールドを取得します。



このアプローチは、 バックボーンクライアントで使用すると特にエレガントに見えます。 parseメソッドをオーバーライドすることにより、MDMを取得できます。

 var model= Backbone.Model.extend({ .... parse: function(data, xhr){ this.meta = $.parseJSON(decodeURIComponent(xhr.getResponseHeader("data-meta"))); return data; }, ...... });
      
      





model.metaでMDMをjsオブジェクトとして受け取ったので、ビューでMDMを使用してモデルをレンダリングできます

 var view = Backbone.View.extend({ render: functoin(){ var m = this.model.toJSON(); this.$el.html(this.template(_.extend(m, { meta: this.model}))); } });
      
      





tempalteに次のようなものを使用します。

 <script > ... <label><%-meta.name.displayName%></label> <input type='text' value="<%name%>" <%-meta.readOnly ?"readonly":"" %> />" ... </script>
      
      





結論として、説明したアプローチを簡単に適用して、クライアントでモデルを検証できることを付け加えます。



All Articles