0

私はMVC3を初めて使用し、学習ツールとしてブログアプリケーションを作成しようとしています。

ブログ投稿用のデータベースオブジェクトを作成し、読み取り/書き込みアクションを備えたコントローラーを使用してコントローラーを生成し、エンティティフレームワークを使用してビューを生成してエンティティを制御しました。

編集コマンドに問題があります。ブログ投稿には約6つのプロパティがありますが、投稿のタイトルとコンテンツを変更するための編集のみを許可したいと思います。私のコードは次のとおりです。

public ActionResult Edit(int id)
    {
        blog_Post blog_post = db.blog_Post.Find(id);
        return View(blog_post);
    }

    //
    // POST: /Post/Edit/5

    [HttpPost]
    public ActionResult Edit(blog_Post blog_post)
    {
        if (ModelState.IsValid)
        {
            db.Entry(blog_post).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(blog_post);
    }

@model BlogVersion1._0.blog_Post

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
    <legend>blog_Post</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Title)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Title)
        @Html.ValidationMessageFor(model => model.Title)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.PostContent)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.PostContent)
        @Html.ValidationMessageFor(model => model.PostContent)
    </div>

    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
}

<div>
@Html.ActionLink("Back to List", "Index")
</div>

発生する問題は、パブリックActionResult Edit(blog_Post blog_post)メソッドにあります。Edit(int id)メソッドで、ブレークポイントを設定しました。blog_postがビューに適切に渡されていることがわかります(入力されているすべてのプロパティを含む)。

ただし、[HttpPost]メソッドに返されるblog_postには、UserId、DateCreatedなどのプロパティがありません。必要な外部キーがないため、db.SaveChanges呼び出しで例外が明らかにスローされます。

正しく更新するために、すべてのプロパティが2番目の編集メソッドに返されるようにするにはどうすればよいですか?

4

4 に答える 4

7

POSTを実行するときに、フォームからこれらの要素の値を送信していないためです。これを修正する1つの方法は、Hidden変数を使用してフォーム内に保持することです。

@using(Html.BeginForm())
{
  @Html.EditorFor(model => model.Title)
  @Html.HiddenFor(model => model.UserId)
  <input type="submit" />
}

クリーンな解決策は、「ビューでドメインモデルを使用しないで、ビューに必要なプロパティを持つViewModelを使用することです。この場合、明らかにCreatedDateは、ビューが提供するものではなく、コードが提供するものである必要があります。オブジェクトに入力されます。

したがって、このためのViewModelを作成します

public class BlogPostViewModel
{
  public int ID { set;get;}
  public string Title { set;get;}
  public string Description { set;get;}  
}

ビューからコントローラーおよびその逆にデータを転送するためにこれを使用します

public ActionResult Edit(int id)
{
  var domainObject=repo.GetPost(id);
  var viewModel=new BlogPostViewModel();
  viewModel.ID=domainObject.ID;
  viewModel.Title=domainObject.Title;
 //map other REQUIRED properties also
  return View(viewModel);
}

あなたの見解はこれに強くタイプされます

@model BlogPostViewModel
@using(Html.BeginForm())
{
  @Html.EditorFor(model => model.Title)
  @Html.HiddenFor(model => model.Description)
  <input type="submit" />
}

POSTアクションで、ドメインオブジェクトにマップして戻し、保存します

[HttpPost]
public ActionResult Edit(BlogPostViewModel model)
{
 if(ModelState.IsValid)
 {
   var domainObject=new blog_Post();
   domainObject.Title=model.Title;

   domainObject.ModifiedDate=DateTime.Now;
   //set other properties also

   repo.Update(domainObject);
   return RedirecToAction("Success");
 }
 return View(model);
}

プロパティを1つずつ手動でマッピングする代わりに、1行のコードでこれを行うAutoMapperライブラリの使用を検討できます。

于 2012-07-03T22:41:12.027 に答える
3

他のすべての編集不可能なプロパティに非表示フィールドを追加するだけです。

@Html.HiddenFor(model => model.Id)

これらのフィールドはPOSTに含まれるため、モデルバインダーはそれらをblog_postインスタンスに正しく配置します。

一方、実際にはビューモデルを使用する必要があります。これは、ビューのモデルとなる単純なPOCOクラスです。エンティティモデルを直接使用することはお勧めしません。

これに関する情報は次のとおりです
。ASP.NETMVCViewModelパターン
http://stephenwalther.com/archive/2009/04/13/asp-net-mvc-tip-50-ndash-create-view-models.aspx

于 2012-07-03T22:32:00.010 に答える
1

モデルバインダーは、HTTPリクエストでPOSTされたプロパティのみを設定します。ビューには、タイトルと投稿コンテンツのみが含まれます。

欠落しているプロパティごとに非表示フィールドを含める必要があります。または、IDプロパティだけを使用して、残りのデータベースを検索します。

于 2012-07-03T22:32:46.177 に答える
1

あなたの場合、プロパティごとに「EditorFor」を呼び出すのではなく、HtmlHelper拡張メソッド「EditorForModel」を使用する方がよいと思います。各プロパティでEditorForを使用して生活を複雑にしています(gred84が言っているように、コンテキスト内のHTTPリクエストに表示されていないプロパティを投稿しません)。

blog_Postモデルクラスでは、編集したくない各プロパティに属性[HiddenInput(DisplayValue = false)]でフラグを立てる必要があります。

次に、ビュー内のすべてのコードの代わりに、単純に(簡略化-検証の要約なしで)持つことができます

@using (Html.BeginForm())
{        
   @Html.EditorForModel()
   <input type="submit" value="Save" />   
} 
于 2012-07-03T22:40:22.177 に答える