2013-08-18 9 views
26

ViewModel全体をコントローラに返信して「検証と保存」機能に戻す方法がわかりません。ここでMVC 4 ViewModelがコントローラに返送されない

は私のコントローラである:ここでは

[HttpPost] 
public ActionResult Send(BitcoinTransactionViewModel transaction) 
{ 
} 

は、フォームが表示されている:

<li class="check"> 
    <h3>Transaction Id</h3> 
    <p>@Html.DisplayFor(m => m.Transaction.TransactionId)</p> 
</li> 
<li class="money"> 
    <h3>Deposited Amount</h3> 
    <p>@Model.Transaction.Amount.ToString() BTC</p> 
</li> 
<li class="time"> 
    <h3>Time</h3> 
    <p>@Model.Transaction.Time.ToString()</p> 
</li> 


@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { transaction = Model })) 
{ 

@Html.HiddenFor(m => m.Token); 
@Html.HiddenFor(m => m.Transaction.TransactionId); 

    @Html.TextBoxFor(m => m.WalletAddress, new { placeholder = "Wallet Address", maxlength = "34" }) 
    <input type="submit" value="Send" />  

    @Html.ValidationMessage("walletAddress", new { @class = "validation" }) 
} 

私は提出をクリックすると、conrollerは、walletAddressフィールドの正しい値が含まれていますが、transaction.Transaction.Timetransaction.Transaction.Location,transaction.Transaction.TransactionIdは空です。

モデル全体をコントローラに戻す方法はありますか?

編集:私は、コントローラにwalletAddressを受信して​​もいけない

。すべてがゼロになる! 私はこの行だけを削除します:@Html.HiddenFor(m => m.Transaction.TransactionId); コントローラ上でトークンプロパティを取得しますが、コントローラに追加するとコントローラのtransactionオブジェクトのすべてのプロパティがNULLになります。ここで

はBitcoinTransactionViewModelです:

public class BitcoinTransactionViewModel 
    { 
     public string Token { get; set; } 
     public string WalletAddress { get; set; } 
     public BitcoinTransaction Transaction { get; set; } 
    } 

public class BitcoinTransaction 
    { 
     public int Id { get; set; } 
     public BitcoinTransactionStatusTypes Status { get; set; } 
     public int TransactionId { get; set; } 
     public decimal Amount { get; set; } 
     public DateTime Time { get; set; } 
     public string Location { get; set; } 
    } 

任意のアイデア?

編集:私はそれを考え出し、その下のマークの答えで...

答えて

32

OK、私は何か他のものに取り組んできました。同じ問題を何度も繰り返してきました。 私はそれを動作させる方法を考え出したこの時間だけ!ここで

は興味があるかもしれない人のための答えです:

はどうやら、命名規則があります。注意してください。

これは動作しません:

// Controller 
[HttpPost] 
public ActionResult Send(BitcoinTransactionViewModel transaction) 
{ 
} 

// View 
@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { transaction = Model })) 
{ 

@Html.HiddenFor(m => m.Token); 
@Html.HiddenFor(m => m.Transaction.TransactionId); 
. 
. 

これは動作します:つまり

// Controller 
[HttpPost] 
public ActionResult Send(BitcoinTransactionViewModel **RedeemTransaction**) 
{ 
} 

// View 
@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { **RedeemTransaction** = Model })) 
{ 

@Html.HiddenFor(m => m.Token); 
@Html.HiddenFor(m => m.Transaction.TransactionId); 
. 
. 

- 命名規則のエラーを! Model.Transactionプロパティとフォームフィールド+コントローラパラメータのtransactionの間に名前のあいまいさがありました。信じられない。

同じ問題が発生している場合は、コントローラのパラメータ名が一意であることを確認してください。MyTestParameterなどに名前を変更してみてください...

さらに、フォームの値をコントローラに送信する場合は、それらを隠しフィールドとして含める必要があります。

+1

私はこの答えが好きですが、それは意味がありますが、残念なことに私にとってはうまくいきませんでした。私は何をしようとしてもサブオブジェクトをコントローラに戻すことはできません。そのようなイライラしたこと。 –

+0

私も同じ問題がありました。私はFileViewModelという名前のViewModelを持っていて、私のアクションパラメータは "file"という名前でした。私はそれを "_file"に変更してくれました。 –

+0

ライフセーバー、ありがとう。 – Chris

11

これはMVC固有ではありません。 HTMLフォームは、フォーム内のフォーム要素に含まれる値のみをポストします。あなたの例は、フォーム内でもフォーム要素内にもありません(隠れた入力など)。 MVCはView Stateに依存しないので、これを行う必要があります。隠しフィールドに内部のフォームを入れて:

@Html.HiddenFor(x => x.Transaction.Time) 
// etc... 

は、ユーザーがこれらの値を更新していない場合は...あなたのアクションメソッドがそれらを必要としない...しかし自問してみてください?

+2

答えをありがとう。私は別の問題が今:最初のレベル(x => x.Token)のプロパティの非表示フィールドを作成するときに動作しますが、内部オブジェクト(X => x.Transaction.InnerField) doesntの仕事!コントローラ内のトランザクションオブジェクトのすべてのプロパティが突然nullです!なぜこれが起こるか考えていますか? –

+1

検証に失敗した場合、検証エラーで同じフォームをレンダリングし、データベースからオブジェクトを選択しないでください(ただし、私はすでに使用しているものを使用します) –

+0

新しいエラーに答えるために更新されたコードを表示する必要があります.. –

9

モデルバインディングは、投稿されたフォーム値を使用して、コントローラアクションでビューモデルを水和させます。上記の変数のフォームコントロールが表示されないので、何もポストバックされません。あなたはこれに喜んでいるかどうか分かりますか?

@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post, new { transaction = Model })) 
{ 
    @Html.TextBoxFor(m => m.WalletAddress, new { placeholder = "Wallet Address", maxlength = "34" }) 
    @Html.Hidden("Time", Model.Transaction.Time) 
    @Html.Hidden("Location", Model.Transaction.Location) 
    @Html.Hidden("TransactionId", Model.Transaction.TransactionId) 
    <input type="submit" value="Send" />  

    @Html.ValidationMessage("walletAddress", new { @class = "validation" }) 
} 
+0

内部プロパティのために隠しフィールドをレンダリングすると、受信側コントローラのすべてのプロパティが突然ゼロになります! –

+0

更新されました。 –

+0

これは構築できません。トランザクションは配列ではありません。これは単なるオブジェクトです。更新された質問をご覧ください。 –

22

フォームが送信するSendメソッドのシグネチャには、モデルバインダを混乱させるようなトランザクションという名前のパラメータがあります。それは便利な何もしていないことから、あなたのBeginForm呼び出しからhtmlAttributesパラメータを削除、また

[HttpPost] 
public ActionResult Send(BitcoinTransactionViewModel model) 
{ 
} 

:モデルのプロパティの名前と一致しないものにするために、パラメータの名前を変更します。クライアントから戻ってくるすべてのデータが改ざんされている可能性が

@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post)) 

ので、あなただけのトランザクションの一意のIDをポストバックし、さらに実行するために、あなたのデータソースから、それに関する追加情報を取得する必要があります。それはなり処理。また、データを投稿したユーザーが指定されたトランザクションIDにアクセスできることをここで確認したい場合もあります。これは、それも改ざんされている可能性があるからです。モデル

BitcoinTransactionViewModel 

がビューまたは含まれておりませんことを確認して、フォーム

@using (Html.BeginForm("Send", "DepositDetails", FormMethod.Post)) 

と内部

+1

私の質問は、オブジェクトの一意のIDだけでなく、オブジェクト全体を投稿する方法です。これは、私のデータベースに対してselectを実行したり、サーバ側でデータキャッシュを管理したりしたくないからです。 –

+0

オブジェクト全体を投稿するには、他人が選択したものを実行し、各プロパティの隠し入力を作成する必要があります。 Sendメソッドのパラメータの名前を変更すると、モデル全体がnullであるという問題が解決されます。 –

+0

これは大文字と小文字の区別がありません。 – Stonedecroze

0

入れて、すべてのフィールドが作りますか?

0

あなたは2つのモデルを組み合わせることはできますか? 1つのビューで1つのモデルを使用する方法は次のとおりです。 1.ビューテンプレートの表示テンプレートを使用して、モデル全体を渡すだけでなく、データを暗号化したままにします。 2.メインビューを次のように設定します。

@model IEnumerable<LecExamRes.Models.SelectionModel.GroupModel> 
<div id="container"> 
<div class="selectLabel">Select a Location:</div><br /> 
@foreach (var item in Model) 
{   
    @Html.DisplayFor(model=>item) 
} 
</div> 

3. DisplayTemplatesフォルダを共有フォルダに作成します。 DisplayForは、使用しているモデルの名前を付けられた表示テンプレートを探しますので、渡したいモデルの名前を付けてビューを作成します。私はGroupModelを呼び出します。表示テンプレートは、列挙のオブジェクトインスタンスと考えてください。 Groupmodelこのように、単にボタンにグループを割り当てるだけです。

@model LecExamRes.Models.SelectionModel.GroupModel 
@using LecExamRes.Helpers 
@using (Html.BeginForm("Index", "Home", null, FormMethod.Post)) 
{ 
<div class="mlink"> 
    @Html.AntiForgeryToken() 
    @Html.EncryptedHiddenFor(model => model.GroupKey) 
    @Html.EncryptedHiddenFor(model => model.GroupName) 
    <p> 
     <input type="submit" name="gbtn" class="groovybutton" value=" @Model.GroupKey   "> 
    </p> 
</div> 
}  

4.コントローラは次のとおりです。 * は& POST *

public ActionResult Index() 
    { 
     // Create a new Patron object upon user's first visit to the page. 
     _patron = new Patron((WindowsIdentity)User.Identity); 
     Session["patron"] = _patron;    
     var lstGroups = new List<SelectionModel.GroupModel>(); 
     var rMgr = new DataStoreManager.ResourceManager(); 
     // GetResourceGroups will return an empty list if no resource groups where found. 
     var resGroups = rMgr.GetResourceGroups(); 
     // Add the available resource groups to list. 
     foreach (var resource in resGroups) 
     { 
      var group = new SelectionModel.GroupModel(); 
      rMgr.GetResourcesByGroup(resource.Key); 
      group.GroupName = resource.Value; 
      group.GroupKey = resource.Key; 
      lstGroups.Add(group); 
     } 
     return View(lstGroups); 
    } 

    [ValidateAntiForgeryToken] 
    [HttpPost] 
    public ActionResult Index(SelectionModel.GroupModel item) 
    { 
     if (!ModelState.IsValid) 
      return View(); 

     if (item.GroupKey != null && item.GroupName != null) 
     {    
      var rModel = new SelectionModel.ReserveModel 
      { 
       LocationKey = item.GroupKey, 
       Location = item.GroupName 
      }; 

      Session["rModel"] = rModel; 
     }   
//So now my date model will have Group info in session ready to use 
     return RedirectToAction("Date", "Home"); 
    } 

5.をGET今、私は別のモデルとビューの多くを持っているならば、私は通常のビューに関連したモデルと、その後からデータをつかむセッションOBJを使用各モデルは最終的に私は提出するデータを持っているので。

1

フォームコレクションを試して値を取得してください。私はこれがうまくいくと思います。

public ActionResult Send(FormCollection frm) 
{ 
    var time = frm['Transaction.Time']; 
} 
3

は、データが掲載されるとアクション名は、データが掲載されているから、アクションの名前と同じでなければなりませんFOREACH

<table> 
    @for (var i = 0; i < Model.itemlist.Count; i++) 
    { 
     <tr> 
      <td> 
       @Html.HiddenFor(x => x.itemlist[i].Id) 
       @Html.HiddenFor(x => x.itemlist[i].Name) 
       @Html.DisplayFor(x => x.itemlist[i].Name) 
      </td> 
     </tr> 
    } 
</table> 
0

でfolowing文でループしないようにしてください。唯一の違いは、データが掲載されている2番目のアクションに[HttpPost]があり、PostingメソッドがGetリクエストのみを提供することです。

関連する問題