12

これは非常に奇妙な動作です。何が起こっているのかを理解するために、いくつかのデモ コードをセットアップしました。

基本的に、2 つのアクションと 1 つのビューがあります。最初のアクションは空のモデルをビューに送信し、セクション アクションはモデルを受け取り、その内容を変更して同じビューに送り返します。

ビューでは、モデルには更新された値が含まれているように見えますが、 Html.TextBoxFor(x => x.PropertyNameHere) を実行すると、変更されていない値を含むテキストボックスがレンダリングされます。

笑...トイレのユーモアを前もってお詫びしますが、1日が退屈になりすぎないようにします。;)

ここで何が起こっているのか誰にも分かりませんか?TextBoxFor の出力で古い値が value 属性に入れられるのはなぜですか?

複製するコードは次のとおりです。

/Views/Demo/Index.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<TestWeb.DemoModel>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Demo</title>
</head>
<body>
    <div>
      <%using (Html.BeginForm("DemoSubmit", "Admin", FormMethod.Post)) { %>
        Foo: <%=Html.TextBoxFor(x => x.Foo)%> <%:Model.Foo %><br />
        Bar: <%=Html.TextBoxFor(x => x.Bar) %> <%:Model.Bar %><br />
        PoopSmith: <%=Html.TextBoxFor(x => x.PoopSmith) %> <%:Model.PoopSmith %><br />
        <button type="submit">Submit</button>
      <%} %>
    </div>
</body>
</html>

DemoModel.cs

namespace TestWeb {
    public class DemoModel {
        public string Foo { get; set; }
        public int Bar { get; set; }
        public string PoopSmith { get; set; }
    }
}

DemoController.cs

public class AdminController : Controller {

        public ActionResult Index() {
            var m = new DemoModel();
            return View(m);
        }

        public ActionResult DemoSubmit(DemoModel demo) {
            demo.Foo += "!!!";
            demo.Bar++;
            demo.PoopSmith += " has pooped.";
            return View("Index", demo);
        }
}

そして、ここに奇妙な出力があります:

奇妙な

4

5 に答える 5

14

デフォルトの Html ヘルパーは、投稿されたデータを再表示しようとします。最初に投稿されたデータの値を使用し、投稿されたデータが利用できない場合は、モデルからデータを取得します。

これは明らかに望んでいるものではありませんが、最も一般的な使用方法です: get リクエストを受け取った後、フォームフィールドにいくつかのデータを表示します。Update アクションに投稿します。エラーがある場合は、入力した値を使用してフォームを再表示する必要があります。

私は何人かの人々がこれを回避しているのを見てきました (私は ModelState に書いていると思います) が、私の選択は常にデフォルトのヘルパーが役に立たない場合は使用しないことでした. これは特に非表示フィールドに当てはまります。非表示フィールドに値を設定するとほとんどの人が混乱しますが、実際に使用される値は投稿からのものです。少なくとも、SOでそれについて1日おきに質問があります:-)

「ほとんどの人」を忘れて、「全員」に置き換えます。

ASP.NET MVC: 非表示のフィールド値が HtmlHelper.Hidden を使用してレンダリングされない

http://blog.johnwest.com/post/ASPNET-MVC-Hidden-Form-Field-Bug.aspx

http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx?utm_medium=Twitter&utm_source=共有

更新 ああ、今日から別のものを見つけました(あなたは一人ではありません):

テキストボックスの値を更新する方法

于 2010-05-27T22:11:58.780 に答える
6

Do ModelState.Clear(); in your controller to prevent this happening. Check MSDN for that.

于 2010-09-03T06:24:11.893 に答える
3

絶対に必要でない限り、ModelState.Clear() または ModelState.Remove() は避けます。通常、この動作が見られる場合は、a) Post-Redirect-Get パターンに従っておらず、従うべきである、または b) それが適切でない場合は、HtmlHelper の TextBox メソッドを使用しないことを検討する必要があるためです。 PRG パターンに従う際の検証などに役立つように設計されています。

例外はあると思いますが (たとえば、ウィザード スタイルの UI はこのような結果になる可能性があります)、私はそれをデフォルトのアプローチと考えています。

于 2011-03-30T20:12:24.287 に答える
1

解決策は、コントローラーで新しい値が割り当てられる前に、ModelState.Remove("[モードのプロパティ名]") を使用することです。または、ビュー ページで、特定のモデル プロパティの Html.TextBoxFor() を Html.TextBox() に変更します。

于 2011-03-31T13:33:52.503 に答える
0

VS 2010 でも同じ問題が発生し、1 日中壁にぶつかっていました。一晩中考えた後、その理由が分かった気がします。理由は持続性です。ブラウザに入力された値のみを記憶します。しかし、これは拘束力のある原則に違反していると思います。モデル パラメーターをビューに渡すことが許可されている場合、ビューは、モデルの現在の状態で渡したものをすべて取得して、そのパラメーターをバインドする必要があります。

于 2011-03-31T13:27:16.967 に答える