技术开发 频道

微软MVC框架功力深厚:Web开发化繁为简

 View Model

  Controller函数Customer Inquiry 调用应用服务层,返回一个表示customer data的Customer View Model。MVC Model指的是一系列表示后端数据的类,而MVC View通常需要收集不同的后端数据,此时就有了View Model类的概念,方便View 获取所有Model信息。从这个角度将,View Model是一个front-end类,连接前端的UI与后端数据通信。

/// <summary>
/// Customer View Model
/// </summary>
public class CustomerViewModel : ViewInformation
{

public List<Customer> Customers;
public Customer Customer;
public int TotalCustomers { get; set; }

public CustomerViewModel()
{
Customer
= new Customer();
Customers
= new List<Customer>();
ReturnMessage
= new List<String>();
ValidationErrors
= new Hashtable();
TotalCustomers
= 0;
}

}

/// <summary>
/// Order View Model
/// </summary>
public class OrderViewModel : ViewInformation
{

public Orders Order;
public OrderDetails OrderDetail;
public List<Orders> Orders;
public List<OrdersCustomer> OrderCustomer;
public List<OrderDetailsProducts> OrderDetailsProducts;
public OrderDetailsProducts OrderLineItem;
public List<OrderDetails> OrderDetails;
public List<Shippers> Shippers;
public Customer Customer;
public int TotalOrders { get; set; }

public OrderViewModel()
{
Customer
= new Customer();
Order
= new Orders();
OrderDetail
= new OrderDetails();
Orders
= new List<Orders>();
OrderDetails
= new List<OrderDetails>();
OrderCustomer
= new List<OrdersCustomer>();
Shippers
= new List<Shippers>();
OrderDetailsProducts
= new List<OrderDetailsProducts>();
OrderLineItem
= new OrderDetailsProducts();
ReturnMessage
= new List<String>();
ValidationErrors
= new Hashtable();
TotalOrders
= 0;

}

}

  SQL-Server的数据分页

  从后端SQL的角度,要从数据路SQL-Server返回一页数据,可使用ROW_NUMBER OVER语法,配合Record的开始与结束游标。相比于因应用程序调用而返回大量的Recordset,SQL的效率要高许多。

SELECT * FROM (
SELECT (ROW_NUMBER() OVER (ORDER BY CompanyName ASC)) as record_number,
CustomerID, CompanyName, ContactName, ContactTitle, City, Region
FROM Customers ) Rows where record_number between
16 and 30

 

  强大的JSON与Partial View

  JSON (JavaScript Object Notation)是一个轻量级的数据交互格式。如上所述,Customer Inquiry Conroller函数调用应用服务层,以View Model的形式获取数据。

  Conroller函数返回给客户端页面的是一个JSON对象。此JSON对象既包含如上所述的View Model,也包含Partial View对应的Data Grid控件经过渲染产生的HTML。MVC的真正威力之处在于,能渲染Partial View的局部HTML片段。

  Partial View渲染小帮手

  ASP.NET MVC框架包含各种不同的Helper函数,可轻松实现在视图中渲染HTML,例如创建按钮,文本框,超链接,表单。Helper函数的使用方式有两种,一是扩展已有的MVC Helper方法,二是也可以根据业务需要,自己定制。

  这里,我们创建一个RenderPartialView Helper函数,调用Partial View并将调用结果以字符串的形式输出。之后,该字符串会被封装成一个JSON对象,供AJAX调用。该Helper函数调用Razor View Engine,在服务器端运行Partial View。当我们需要将HTML返回给AJAX调用时,这一点显得尤为适用。

public static string RenderPartialView(this Controller controller,
string viewName, object model)
{

if (string.IsNullOrEmpty(viewName))
return
null;

controller.ViewData.Model
= model;

using (var sw
= new StringWriter())
{

ViewEngineResult viewResult
=
ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);

var viewContext
= new ViewContext(controller.ControllerContext,
viewResult.View, controller.ViewData, controller.TempData, sw);

viewResult.View.Render(viewContext, sw);

return sw.GetStringBuilder().ToString();

}

}

  Partial View “Customer Inquiry Grid”

  View与Partial View内部均含有服务器/客户端代码。两者在外观上与使用感觉上,都有经典ASP功能的味道。下面的Customer Inquiry Grid Partial View仅包含服务器端代码,目的是渲染一个用户自定义的Data Grid。

@model NorthwindViewModel.CustomerViewModel
@using NorthwindWebApplication.Helpers;

@{

NorthwindDataGrid pagedDataGrid
= new NorthwindDataGrid("CustomerInquirGrid");

pagedDataGrid.Title
= "Customers";
pagedDataGrid.TotalPages
= Model.TotalPages;
pagedDataGrid.TotalRecords
= Model.TotalCustomers;
pagedDataGrid.CurrentPageNumber
= Model.CurrentPageNumber;
pagedDataGrid.SortDirection
= Model.SortDirection;
pagedDataGrid.SortExpression
= Model.SortExpression;
pagedDataGrid.RowSelectionFunction
= "CustomerSelected";
pagedDataGrid.AjaxFunction
= "CustomerInquiry";

pagedDataGrid.AddColumn(
"CustomerID", "Customer ID", "20%", "left");
pagedDataGrid.AddColumn(
"CompanyName", "Company Name", "40%", "left");
pagedDataGrid.AddColumn(
"ContactName", "Contact Name", "20%", "left");
pagedDataGrid.AddColumn(
"City", "City", "20%", "left");

foreach (var item in Model.Customers)
{
pagedDataGrid.AddRow();
pagedDataGrid.PopulateRow(
"CustomerID", item.CustomerID , true);
pagedDataGrid.PopulateRow(
"CompanyName", item.CompanyName, false);
pagedDataGrid.PopulateRow(
"ContactName", item.ContactName, false);
pagedDataGrid.PopulateRow(
"City", item.City, false);
pagedDataGrid.InsertRow();
}

}

@Html.RenderNorthwindDataGrid(pagedDataGrid)

  RenderNorthwindDataGrid 函数调用一个MVC HtmlHelper对象,返回一个MvcHtmlString。Data Grid的渲染就变得与其它HTML控件一样。

public static MvcHtmlString RenderNorthwindDataGrid(this HtmlHelper html,
NorthwindWebControls.NorthwindDataGrid dataGrid)
{
string control = dataGrid.CreateControl();
return MvcHtmlString.Create(control);
}

  下面Partial View的名称为MessageBox ,包含Razor View Engine语法的客户端/服务器端代码。这个MessageBox 会贯穿整个示例Web App,为客户端渲染状态与错误信息。

@model NorthwindViewModel.ViewInformation
@{

ViewInformation viewInformation
= new NorthwindViewModel.ViewInformation();

viewInformation.ReturnMessage
= Model.ReturnMessage;
viewInformation.ReturnStatus
= Model.ReturnStatus;

if (viewInformation.ReturnMessage.Count() > 0)
{
<div style="padding: 10px 10px 10px 0px; width:90%">
@
if (viewInformation.ReturnStatus == true)
{
<div style="background-color: Scrollbar;
border: solid 1px black; color: black; padding: 15px 15px 15px 15px">

@foreach (var message in viewInformation.ReturnMessage)
{
<text>@Html.Raw(message)</text>
<br />
}
</div>
}
else
{
// ====== an error has occurred - Display the message box in red ======

<div style="background-color: #f4eded; border:
solid 1px #d19090; color: #762933; padding: 15px 15px 15px 15px">

@foreach (var message in viewInformation.ReturnMessage)
{
<text>@Html.Raw(message)</text>
<br />
}
</div>
}
</div>
}
}

  渲染Customer Inquiry DataGrid

  CustomerInquiry Controller函数调用返回一个JSON对象,客户端JavaScript函数CustomerInquiryComplete函数调用并解析该JSON对象,得到返回状态值,使用JQuery将返回的Data Grid更新DIV标签。

  如果服务器发生错误,页面会渲染前面提到的Partial View —— Message Box。这个过程实际上是一个AJAX调用,利用MVC的灵活控制性,渲染局部页面内容。

function CustomerInquiryComplete(result)
{
if (result.ReturnStatus == true)
{
$(
"#CustomerResults").html(result.CustomerInquiryView);
$(
"#MessageBox").html("");
}
else
{
$(
"#MessageBox").html(result.MessageBoxView);
}

}

  选择一个Customer

  当选择一个下订单的客户(Customer ID域位于Customer Inquiry grid)时,调用JavaScript函数theCustomerSelected,将customer ID传到表单对象,然后使用POST方法提交至服务器。之所以采用POST而非GET方法,是处于安全考虑。

<script language="javascript" type="text/javascript">
function CustomerSelected(customerID) {
$(
"#OrderEntry #CustomerID").val(customerID);
$(
"#OrderEntry").submit();
}
</script>

<form id="OrderEntry" method="post" action="/Orders/OrderEntry">
<input id="CustomerID" name="CustomerID" type="hidden" />
</form>

       Order Entry Header View 

       选定customer后,OrderEntryHeader View被渲染,让用户填入订单的物流信息。OrderEntryHeader View的功能由Knockout控制。

 

0
相关文章