2011-08-11 21 views
1

私のブログアプリケーションの投稿にユーザーがコメントできるようにフォームを追加しようとしています。これまでは、投稿の詳細ビューにフォームを追加しました。コメントを投稿してデータベースに正しく追加できます。しかし、ユーザーに検証エラーを表示する際に問題があります。コメントフォームは部分的なビュー内に含まれ、投稿の詳細ビュー内でHtml.RenderActionを使用してレンダリングされます。私は進歩的な拡張の観点からこれにアプローチしたいので、AJAXをこのために使用したくないということを強調したいと思います。ASP.NET MVC3:親ビューの子ビューからの妥当性検査エラーの表示

は、ここで関連する投稿アクションです:私はここのビューを返すいくつかの方法を試してみた

[HttpPost, Authorize] 
public ActionResult AddComment(CommentViewModel newComment) 
{ 
    if (ModelState.IsValid) 
    { 
     Comment comment = new Comment(_userRepository.GetByUsername(User.Identity.Name)); 
     Mapper.Map(newComment, comment); 

     _commentRepository.Add(comment); 

     _postsRepository.CommentAdded(comment.Article); 

     return RedirectToAction("Index", new { id = newComment.PostID }); 
    } 

    // What do I do here? 
} 

が、私の問題は、私は、親アクションで起こっているいくつかのコントローラのパラメータの検証によってさらに複雑になる。

// 
// GET: /Posts/5/this-is-a-slug 

public ActionResult Index(int id, string slug) 
{ 
    PostViewModel viewModel = new PostViewModel(); 
    var model = _postsRepository.GetByID(id); 

    if (model != null) 
    { 
     if (slug == null || slug.CompareTo(model.Slug) != 0) 
     { 
      return RedirectToActionPermanent("Index", new { id, slug = model.Slug }); 
     } 
     else 
     { 
      _postsRepository.PostVisited(model); 

      Mapper.Map(model, viewModel); 

      viewModel.AuthorName = _userRepository.GetById(model.AuthorID); 
     } 
    } 

    return View(viewModel); 
} 

このアクションは、基本的にSOのURLの仕組みを模倣します。投稿IDが指定されている場合、投稿が作成されたときに作成されたスラッグとともに、投稿がデータベースから取得されます。 URLのスラッグがデータベースのスラッグと一致しない場合、スラッグを含むようにリダイレクトされます。これがうまく機能していますが、それは私がフォローしている私の親のviewmodelを、移入しようとしている問題を抱えている意味は:

public class PostViewModel 
{ 
    public int PostID { get; set; } 
    public string Title { get; set; } 
    public string Body { get; set; } 
    public string Slug { get; set; } 
    public DateTime DatePublished { get; set; } 
    public int NumberOfComments { get; set; } 
    public int AuthorID { get; set; } 
    public string AuthorName { get; set; } 

    public List<CommentViewModel> Comments { get; set; } 
    public CommentViewModel NewComment { get; set; } 
} 

私は仕事と期待していたが、それはデータを持っている場合、テストを確認するために、PostViewModel.NewCommentを移入することですモデルエラーを表示するために使用します。残念ながら、私はそれを達成する方法について迷っています。 This questionは私のアプローチを形作るのを助けましたが、私の問題にはあまり答えませんでした。

誰かが私に正しい方向に優しいプッシュを与えることができますか?私のアプローチが不合理に思えるなら、私はなぜ、そして潜在的な修正が何であるかを知りたい。

事前に感謝します。

答えて

2

ここで私の答えを記入してください。これにつまづいている人にとっては、ModelStateのエラーを格納してから、該当するコントローラのアクションにModelStateを再投入するのに、TempDataを使用するという答えがありました。

まず、コントローラー内でTempDataのデータを参照するために使用されるキーを宣言しました。両方のアクションがそれに依存しているので、私はこれをCommentViewModelタイプに基づいて決めました。この最初のアクションで

public class PostsController : Controller 
{ 
    private static readonly string commentFormModelStateKey = typeof(CommentViewModel).FullName; 
    // Rest of class. 
} 

、コードがTempDataがキーに割り当てられたデータを含むかどうかを確認。そうであれば、ModelStateにコピーされます。 ModelStateがデータベースにコメントを追加する前に有効であるかどう

// GET: /posts/comment 
[ChildActionOnly] 
public PartialViewResult Comment(PostViewModel viewModel) 
{ 
    viewModel.NewComment = new CommentViewModel(viewModel.PostID, viewModel.Slug); 

    if (TempData.ContainsKey(commentFormModelStateKey)) 
    { 
     ModelStateDictionary commentModelState = TempData[commentFormModelStateKey] as ModelStateDictionary; 
     foreach (KeyValuePair<string, ModelState> valuePair in commentModelState) 
      ModelState.Add(valuePair.Key, valuePair.Value); 
    } 

    return PartialView(viewModel.NewComment); 
} 

このアクションは、決定します。 ModelStateが有効でない場合は、TempDataにコピーされ、最初の処理で使用できるようになります。

// POST: /posts/comment 
[HttpPost, Authorize] 
public ActionResult Comment(CommentViewModel newComment) 
{ 
    if (!ModelState.IsValid) 
    { 
     TempData.Add(commentFormModelStateKey, ModelState); 
     return Redirect(Url.ShowPost(newComment.PostID, newComment.Slug)); 
    } 

    // Code to add a comment goes here. 
} 
関連する問題