与ASP.NET MVC联系页3

问题描述:

我有一个联系页面,而这个页面应由显示窗体或成功消息或失败消息,所以基本上是这样的:与ASP.NET MVC联系页3

@model MyApp.Models.ContactData 

@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

<div> 

...Some static content... 


If page was opened the first time 
    -> Render a form here 
Else If form was posted and data successfully processed 
    -> Render a success message here 
Else If form was posted but error occurred during processing 
    -> Render a failure message here 

...Some static content... 


</div> 

我不不知道用MVC 3实现这一点的最好方法是什么?我是否创建了三个完全独立的视图(这是我想避免的,因为静态内容对于所有三个视图都是相同的)?或者,我可以创建三个部分视图,然后根据一个额外的标志来决定我可以放入模型类中的部分视图来渲染吗?或者我可以从控制器动态注入局部视图到视图中?

控制器我到目前为止是这样的:

public class ContactController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 

    [HttpPost] 
    public ActionResult Index(ContactData contactData) 
    { 
     if (ModelState.IsValid) 
     { 
      ContactService service = new ContactService(); 
      bool result = service.Process(contactData); 

      return ?; // What do I return now? It must somehow depend on result. 
     } 
     else 
      return View(contactData)); 
    } 

} 

我也有类似的页面和行为与ASP.NET WebForms和解决方案在那里把标记的三可变块为asp:Panel控制和然后从代码隐藏开启或关闭这些面板的标志。我想我需要另一种方法与ASP.NET MVC达到相同的目标。

什么是最好的方法?

感谢您提前提出建议!

你可以试试这个方法:

[HttpPost] 
    public ActionResult Index(Contact contactData) 
    { 
     if (ModelState.IsValid) 
     { 
      ContactService service = new ContactService(); 
      if (service.Process(contactData)) 
      { 
       TempData["Success"] = "Your success message."; 
       return RedirectToAction("Index"); 
      } 
      else 
      { 
       TempData["Error"] = "Your fail message.";     
      } 
     } 
     return View(contact); 
    } 
+0

您的解决方案似乎比p.campbell的解决方案有优势(请参阅我对他的回答的评论)。 TempData与ViewBag形成鲜明对比需要多长时间?它似乎在'RedirectToAction'中存在,而ViewBag显然不是这种情况。 – Slauma 2011-05-08 11:43:04

+0

TempData存在于这些场景中。数据仅适用于一个请求。但是,如果您需要多个后续请求的数据(比如某个向导),则可以通过调用Keep()方法来“延长”此数据。查看MSDN上的更多详细信息:http://goo.gl/rEQ03 – frennky 2011-05-08 12:24:55

+0

这看起来确实很像完美的方式。在此期间,我了解到这种模式甚至有一个名称:“Post/Redirect/Get(PRG)模式”,并且TempData用于支持这种模式。再次感谢! – Slauma 2011-05-09 14:33:50

也许使用ViewBag来帮助实现所有这些。当然这是一个动态的,所以你可以添加&检查任何你想/需要/期望的道具。

[HttpPost] 
public ActionResult Index(ContactData contactData) 
{ 
    if (ModelState.IsValid) 
    { 
     ContactService service = new ContactService(); 
     bool result = service.Process(contactData); 
     ViewBag.ContactSuccess = true; 
    } 
    else 
    { 
     ViewBag.ModelStateErr= "some err"; 
    } 

    return View(contactData)); 
} 

然后在您的视图:

if (ViewBag.ContactSuccess !=null && ((bool)ViewBag.ContactSuccess)) 
{ 
     //thanks for posting! 
} 
else 
{ 
    if (ViewBag.ModelStateErr !=null) 
    { 
     //show that we have an err 
    } 
    else 
    { 
     //we have no err nor a 'true' contact success yet 
     //write out the form 
    } 
} 
+2

我不喜欢这个解决方案。它可以工作,但是它会在提交后渲染一个来自输入数据的from。 – frennky 2011-05-08 00:48:44

+0

这会导致视图标记中存在一个很大的丑陋块。不理想的优化和维护。 – 2011-05-08 01:00:45

+0

@frennky:为什么这会呈现提交后的表单?在帖子发布之后,你永远不会到达第二个else标记,你呢? – Slauma 2011-05-08 10:56:35

看起来,你可以发出在客户端Ajax调用,并基于JSON结果,可以呈现在客户端不同的内容。

我建议编码了三个不同的看法

  • index.cshtml
  • contactSuccess.cshtml
  • contactFail.cshtml

然后在你的控制中LER,你也有类似的代码之前

public class ContactController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 

    [HttpPost] 
    public ActionResult Index(ContactData contactData) 
    { 
     if (ModelState.IsValid) 
     { 
      ContactService service = new ContactService(); 
      bool result = service.Process(contactData); 

      return View("contactSuccess.cshtml"); 
     } 
     else 
      return View("contactFail.cshtml", contactData); 
    } 

} 

这样,每个视图有一个独立的,你没有一个大的直列IF块在您的标记中间。

或者(这是我怎么会做),你可以有index.cshtml包含三个谐音......

  • _ContactForm.cshtml
  • _ContactSuccess.cshtml
  • _ContactFail 。cshtml

然后您可以将部分视图加载到索引视图中,甚至可以使用AJAX动态地将它们交换出去。

+0

“...你可以将部分视图加载到索引视图中......”:这听起来像是一个很好的解决方案,但我不知道该怎么做。如果我正确理解你,你的代码片段提供了三种完全不同的视图,这是不理想的,因为所有三个视图都有公共部分的标记,我需要复制它们。是否可以动态注入不同的局部视图而不使用Ajax? – Slauma 2011-05-08 10:48:07