MVC 不一定具有网络表单意义上的“事件”(尽管您可以使用它们),但通常不建议这样做。 MVC 对应于从服务器发送/接收数据的 HTTP 模型。当您想与服务器交互时,您需要控制器类上的其他操作方法。
您的控制器可以通过多种方式接受来自客户端的输入,但其中最基本的是通过为您的操作方法指定参数,MVC 将尝试绑定到请求数据(表单、查询字符串等)。这是一个示例控制器:
//Controller class
public class ReportController : Controller {
public ActionResult Index() {
ActionResult result = null;
ReportSelectionViewModel viewModel = this.BuildViewModel();
result = View("Index", viewModel);
return result;
} // end action Index
[HttpPost()]
public ActionResult ChangeReport(ChangeReportRequest changeRequest) {
ActionResult result = null;
ReportSelectionViewModel viewModel = this.BuildViewModel();
Session["ReportOptions"] = changeRequest;
viewModel.Messages.Add("Selection was changed.");
viewModel.ReportRequest = changeRequest;
result = View("Index", viewModel);
return result;
} // end action ChangeReport
//Method that encapsulates the logic needed to build a view model for actions on this controller
protected ReportSelectionViewModel BuildViewModel() {
ReportSelectionViewModel viewModel = null;
viewModel = new ReportSelectionViewModel();
viewModel.AvailableThresholds.AddRange(new int[] { 1, 2, 3, 4 });
//Set the value to whatever the user previously selected if available
if (Session["ReportOptions"] != null) {
viewModel.ReportRequest.ThresholdSelect = ((ChangeReportRequest)Session["ReportOptions"]).ThresholdSelect;
} // end if
return viewModel;
} // end function BuildViewModel
} // end class ReportController
在上面的控制器中,默认的Index() 操作不接受任何参数,因为它不需要任何第一次访问。 ChangeReport() 操作接受 ChangeReportRequest 类型的参数,称为模型。这告诉 MVC 这个动作是 EXPECTING 来自客户端的一个值(或一系列值)并导致 MVC 深入挖掘以找出客户端提供哪些值来满足控制器的参数参数并返回一个完全填充的模型对象。
这是模型类的样子:
//Model class that gets built by the DefaultModelBinder
public class ChangeReportRequest {
private int _reportId;
private int _thresholdSelect;
public ChangeReportRequest() {
_reportId = 1; // Meaningful default value here
_thresholdSelect = 0;
} // end constructor
public int ReportId {
get {
return _reportId;
} set {
_reportId = value;
}
} // end property ReportId
public int ThresholdSelect {
get {
return _thresholdSelect;
} set {
_thresholdSelect = value;
}
} // end property ThresholdSelect
} // end class ChangeReportRequest
拥有一个专门用于显示目的的不同类型的模型(ViewModel)也是一个好主意(这与用于保存事务数据的普通模型不同)。 ViewModel 在视图中添加编译时支持,可以在视图中显示这些内容。一个示例ViewModel 如下所示:
//Strongly typed view model class passed to the view to add intellisense support in the view and avoid the ViewBag.
using System.Collections.Generic;
public class ReportSelectionViewModel {
private List<int> _availableThresholds;
private List<string> _messages;
private ChangeReportRequest _reportRequest;
public ReportSelectionViewModel() {
_availableThresholds = new List<int>();
_messages = new List<string>();
_reportRequest = new ChangeReportRequest();
} // end constructor
public List<int> AvailableThresholds {
get {
return _availableThresholds;
}
} // end property AvailableThresholds
public List<string> Messages {
get {
return _messages;
}
} // end property Messages
public ChangeReportRequest ReportRequest {
get {
return _reportRequest;
} set {
if (value != null) {
_reportRequest = value;
} // end if
}
} // end property ReportRequest
} // end class ReportSelectionViewModel
MVC 具有内置模型绑定,它将尝试将表单字段映射到控制器操作方法上的输入值。通过将控制器方法参数命名为与选择列表相同的名称(除了 ID 之外,您还必须为选择列表命名),您可以简单地在选择列表周围创建一个表单包装器:
下面是与上述代码一起使用的视图:
@model ReportSelectionViewModel
<h2>Index</h2>
<div class="message-wrapper">
<ul class="messages">
@foreach(string message in Model.Messages) {
<li>@message</li>
}
</ul>
</div>
<form method="post" action="@Url.Action("ChangeReport")">
<select id="ThresholdSelect" name="ThresholdSelect">
@foreach(int item in Model.AvailableThresholds) {
<option value="@item" @(Model.ReportRequest.ThresholdSelect == item ? "selected" : "")>@item</option>
}
</select>
<!--Later this can be made into a text box or drop down or whatever, as long as the name matches the model-->
<input type="hidden" name="ReportId" value="@Model.ReportRequest.ReportId" />
<input id="submit" type="submit" name="submit" value="Select" />
</form>
默认的 MVC ModelBinder 是智能的。它通过ModelMetaDataProvider 使用反射来迭代方法中的参数,并尝试从HTTP 请求中根据名称匹配的字段(这就是为什么命名表单字段很重要的原因)。它也可以做比 int 或 string 更复杂的事情。
这里有一些资源: