3

複数のモデルタプルをコントローラーにポストするためのMVCカスタムモデルバインダーの作成について支援が必要です。カスタムモデルバインダーを使用したことはありません。この問題に対する他の回答を検討しましたが、モデルのタプルを処理したり、望ましい解決策を提供したりすることに近づいていないようです。どんなアイデアでも大歓迎です。- ありがとう

意見

@model Tuple<Contact, Communications, Addresses>
@using (Html.BeginForm()) {
  <div id="contact">
    <div class="editor-label">
         @Html.LabelFor(m => m.Item1.FirstName)
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(m => m.Item1.FirstName)
    </div>
    <div class="editor-label">
        @Html.LabelFor(m => m.Item1.LastName)
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(m => m.Item1.LastName)
    </div>
    <div>
        <input type="submit" value="Create" />
    </div>
  </div>
  <div id="communication">
    <div class="editor-label">
        @Html.LabelFor(m => m.Item2.TelephoneValue)
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(m => m.Item2.TelephoneValue)
    </div>
  </div> 
  <div id="address">
    <div class="editor-label">
        @Html.LabelFor(m => m.Item3.Address1)
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(m => m.Item3.Address1
    </div>
    <div class="editor-label">
        @Html.LabelFor(m => m.Item3.City)
    </div>
    <div class="editor-field"> 
        @Html.TextBoxFor(m => m.Item3.City)
    </div>
    <div class="editor-label">
        @Html.LabelFor(m => m.Item3.StateProvince)
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(m => m.Item3.StateProvince)
    </div>
    <div class="editor-label">
        @Html.LabelFor(m => m.Item3.PostalCode) 
    </div>
    <div class="editor-field"> 
        @Html.TextBoxFor(m => m.Item3.PostalCode, new { id = "zip", style = "width:90px;" })
    </div>
  </div> 
}

コントローラー

[HttpPost]
public ActionResult CreateContact(Tuple<Contact, Communications, Addresses> tuple) {
      //…. Do tuple processing to transfer values to add values to App Service here.
}
4

3 に答える 3

1

「連絡先、通信、アドレス」モデルを新しいモデル内に保持して、ビューにバインドしてみませんか。

取り扱いがとても簡単になります。

于 2013-07-23T13:16:39.663 に答える
0

このアプローチのこの実装の結果に興味があるかもしれない人のために、私はそれが非常にうまく機能し、柔軟性のすべての期待を上回ったことを報告したいと思います。元々は、3つのモデルオブジェクトタプルを解決するために使用されていましたが、その後4つのモデルオブジェクトタプルに正常に拡張されました。このアプローチには8アイテムの制限があることに注意してください。ただし、タプルをさらにカスケードする方法があります。アイテム、それが実用的でさえあるかどうかわからない。役立つ可能性のあるコードスニペットを次に示します。

//Custom Model Binder
public class TupleModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext,
              ModelBindingContext bindingContext, Type modelType)
   {
      if (modelType == typeof(Tuple<ContactModel, CommunicationModel, AddressModel>))
            return new Tuple<ContactModel, CommunicationModel, AddressModel>(new ContactModel(), new CommunicationModel(), new AddressModel());
      if (modelType == typeof(Tuple<ContactModel, CommunicationModel, AddressModel, CustomerModel>))
            return new Tuple<ContactModel, CommunicationModel, AddressModel, CustomerModel>(new ContactModel(), new CommunicationModel(), new AddressModel(), new CustomerModel());

         return base.CreateModel(controllerContext, bindingContext, modelType);
      }
 }

 // In Global.asax Application_Start()
     ModelBinders.Binders.DefaultBinder = new TupleModelBinder();
于 2013-08-20T13:23:01.380 に答える
0

タプルごとにカスタムバインダーにバインディングラインを追加する必要がある場合、タプルをモデルとして使用することの容易さは大幅に低下します。

これは、すべてのタプルで機能するカスタムモデルバインダーです。登録されている型バインダーが引き続き機能するように、再帰的に呼び出します。これで、タプルモデルを1か所で変更するだけで済みます。これは理想的です。

public class CustomModelBinder : DefaultModelBinder
{
    private static Type _tupleInterfaceType = Type.GetType("System.ITuple", true, false);

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        if (modelType.FindInterfaces((a, b) => a == (Type)b, _tupleInterfaceType).Length == 1)
        {
            object[] args = new object[modelType.GenericTypeArguments.Length];
            for (int i = 0; i < args.Length; i++)
            {
                if (modelType.GenericTypeArguments[i].IsValueType) args[i] = Activator.CreateInstance(modelType.GenericTypeArguments[i]);
                else args[i] = CreateModel(controllerContext, bindingContext, modelType.GenericTypeArguments[i]);
            }
            return Activator.CreateInstance(modelType, args);
        }
        return base.CreateModel(controllerContext, bindingContext, modelType);
    }
}

注:System.ITupleインターフェースタイプは保護されたインターフェースであるため、文字列から作成する必要があります。

これで時間を節約できることを願っています。8)

于 2015-12-21T20:34:51.100 に答える