ASP.NET MVC - 复杂的视图逻辑

时间:2011-10-29 14:04:51

标签: asp.net-mvc

我正在从webforms转换到MVC(我知道,已经晚了3年)而且我在大多数情况下“得到它”,但有一些我想要建议和澄清的事情:

首先,如果要动态地向视图添加输入会发生什么?例如,在用于生成发票的旧webform中,我有一个带有服务器端点击事件处理程序的按钮,该处理程序添加了额外的5个发票项目行。 webforms的有状态特性意味着服务器“安全地”处理POST事件而不改变页面的其余部分。

在MVC中我想不出如何在不使用客户端脚本(不是showstopper,但我想支持没有启用脚本的客户端)的情况下这样做。

第二个问题与发票示例有关。如果我的模型有一个List,我该如何为它生成输入?

我知道数据绑定是一种可能的解决方案,但我想放弃控制权。

最后,回到“有状态页面”的概念 - 比如我有一个有日历的Dashboard页面(我编写了自己的日历Control类,控件本身是无状态的,但是可以使用webform viewstate来存储分页信息) - 用户页面如何通过日历月?显然POST是不合适的,所以它必须与GET一起使用查询字符串参数 - 我怎么能在MVC中做到这一点? (不要说AJAX)。

谢谢!

3 个答案:

答案 0 :(得分:2)

在MVC中,您可以设计自己的行动以满足您的需求。例如,如果您希望能够在不使用客户端脚本的发票中添加5行,则可能需要对发票生成执行GET操作,并为行数采用可为空的int参数。将当前行数存储在页面的视图模型中,并在页面上生成一个链接到GET操作,该参数值的参数值设置为比当前值多5。用户单击该链接,GET视图将生成具有所请求行数的页面。

控制器

 [HttpGet]
 public ActionResult Invoice( int? rows )
 {
      rows = rows ?? 5; // probably you'd pull the default from a configuration
      ...

      viewModel.CurrentRows = rows;
      return View( viewModel );
 }

查看

 @Html.ActionLink( "Add 5 Lines", "invoice", new { rows = Model.CurrentRows + 5 }, new { @class = "add-rows" } )

您可能还会在拦截点击处理程序的页面中添加一些脚本,并通过您的操作将执行的脚本执行相同的操作,以便在一般情况下用户不必执行往返操作服务器

 <script type="text/javascript">
      $(function() {
          $('.add-rows').click( function() {
                ...add additional inputs to the invoice...
                return false; // abort the request
          });
      });
 </script>

同样适用于您的日历。一般的想法是,您在视图模型中放置了足够的信息,以生成您希望从视图中执行的所有操作。在视图中构建链接或表单(是的,您可以有多个表单!)来执行操作。使用参数与控制器/操作进行通信需要完成的操作。在极少数情况下,您需要在操作之间保留状态,例如在执行采取多个操作的向导时,您可以将信息存储在会话中或使用TempData(使用会话)。

对于像日历这样的东西,您需要当前日期和当前视图类型(月/日/年)。由此您可以构建一个将您带到下个月/日/年的动作。对于分页列表,您需要当前页面,当前排序列和方向,每页的项目数和页数。使用这些信息,你可以构建你的分页链接,回调到那些只需要为它们被调用的参数执行正确的事情的参数的动作。

最后,不要害怕AJAX,拥抱它。它并不总是合适的(例如,您无法使用它上传文件),但您的用户将会喜欢支持AJAX的界面。

答案 1 :(得分:0)

在MVC中,您可以通过各种方式存储应用程序状态。在您的控制器中,您可以直接访问Session对象,还可以将状态存储到数据库中。

答案 2 :(得分:0)

您的视图可以包含基本的控制流逻辑,因此,如果您的模型有一个列表,您可以在视图中迭代它,例如,为列表中的每个项呈现输入控件。您还可以将模型中的变量设置为视图页面上的最大行数,然后在表格中为模型指定的数字呈现行。

分页基本上是一回事。您可以创建一个部分视图(webform世界中的用户控件),将页码显示为链接,其中每个链接都调用一个操作来获取该页面结果的数据。

我不确定你的牛肉用ajax或javascript是什么