4

クライアントにデータを送信するときに、 DataContractJsonSerializerを使用してモデル データの JsonResult を作成します。私のモデルはデータ テーブルに表示されるデータを表しており、JSON のみでモデルのプロパティの名前を変更して、データ テーブルの各行の詳細なプロパティ名が送信されないようにしたいと考えていました。今、データ テーブルのセル値を JSON 経由でサーバーのコントローラー アクション メソッドに送信しようとしています。送り返されるフィールドの名前はまだ短い名前であり、モデル バインディングはそれを好まないようです。モデル バインディングを機能させ、JSON を介して代替プロパティ名を送信する機能を保持するにはどうすればよいですか?

モデル:

[DataContract()]
public class UsageListModel {

    [DataMember(Name = "results")]
    public IEnumerable<UsageModel> Usages { get; set; }
}

[DataContract()]
public class UsageModel {

    [DataMember(Name = "job")]
    public string JobId { get; set; }

    [DataMember(Name = "dt")]
    public DateTime UsageDate { get; set; }

    [DataMember(Name = "qty")]
    public int Quantity { get; set; }

    [DataMember(Name = "uom")]
    public string UnitOfMeasure { get; set; }

    [DataMember(Name = "nts")]
    public string Notes { get; set; }
}
4

3 に答える 3

2

それほどエレガントではありませんが、私は通常、これらのショートネームプロパティを持ち、実際のモデルとの間で相互に変換できる中間クラス(ViewModelと呼びます)を作成するだけでこれを行います。忙しい作業のように見えますが、ViewModelはこのスティントを超えて役立つ場合があります。たとえば、必要に応じてクライアント側の情報を簡単にキャッシュしたり、テストでクライアントとの間でやり取りされる内容を正確にシリアル化/逆シリアル化したりできます。

于 2012-05-11T16:54:01.567 に答える
0

この他の質問を閲覧しているときに、この質問に対する潜在的な回答をランダムに見つけました。

今まで気づかなかったのですが、どうやらメソッドのパラメータに属性を追加できるようです。簡単な例を見てみましょう:

public ActionResult SomeMethod(string val) {
    return View(val);
}

この URL -- /MyController/SomeMethod?val=mytestval -- を呼び出すと、モデルに "mytestval" が返されますよね? だから今、あなたはこれを書くことができます:

public ActionResult SomeMethod([Bind(Prefix="alias")] string val) {
    return View(val);
}

これで、この URL は同じ結果を生成します: /MyController/SomeMethod?alias=mytestval.

とにかく、それであなたの質問に答えられるかどうかはまだわかりませんが、とても興味深いと思いました。

于 2012-06-04T06:10:58.820 に答える
0

MVC がカスタム属性 (または .NET データ コントラクト属性でさえも) を使用してバインドするための簡単な方法を提供していないことを、私はまだ信じていません。そうではないことを考えると...あなたの最善の策は、独自のIModelBinderを実装することです。リフレクションを使用してプロパティのDataMember名を取得し、バインディング コンテキストでそれらの値を探します。

モデル バインディングに関する優れたリファレンスは次のとおりです: http://msdn.microsoft.com/en-us/magazine/hh781022.aspx

カスタムバインダーを維持するための優れた一般的なアプローチ: http://lostechies.com/jimmybogard/2009/03/18/a-better-model-binder/

編集

定義済みの型を扱うジェネリック モデル バインダー。これをアプリケーションに追加するには、global.asax に次の行を追加します。

ModelBinders.Binders.Add(typeof(UsageModel), new CustomModelBinder<UsageModel>());

そしてバインダー:

public class CustomModelBinder<T> : IModelBinder
{
    public override bool IsMatch(Type t)
    {
        return t == typeof(T);
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Type t = typeof(T);
        var entity = (bindingContext.Model ?? Activator.CreateInstance(t));

        // Cycle through the properties and assign values.
        foreach (PropertyInfo p in t.GetProperties())
        {
            string sourceKey;

            // this is what you'd do if you wanted to bind to the property name
            // string sourceKey = p.Name;

            // TODO bind sourceKey to the name in attribute DataMember

            Type propertyType = p.PropertyType;

            // now try to get the value from the context ...
            ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(sourceKey);
            if (valueResult != null)
            {
                bindingContext.ModelState.SetModelValue(sourceKey, valueResult);
                p.SetValue(entity, valueResult.ConvertTo(propertyType), null);
            }
        }
        return entity;
    }
}
于 2012-05-03T07:16:58.660 に答える