ASP.NET MVC中对数据进行排序的方“.NET研究”法

简介:   本系列是讲解如何在asp.net mvc中对数据进行展示、排序、分页等的系列文章。在上周的文章中,一步一步教会了大家如何使用ASP.NET MVC框架去的展示数据。在上周的文章中,我们先用Visual Studio创建了一个新的ASP.NET MVC应用程序,接着连接到了Northwind数据库,并展示了如何使用微软的LINQ-SQL的工具去访问数据库中的数据,接着指导如何去实现视图层去展示产品信息及如何设计控制器。

  本系列是讲解如何在asp.net mvc中对数据进行展示、排序、分页等的系列文章。在上周的文章中,一步一步教会了大家如何使用ASP.NET MVC框架去的展示数据。在上周的文章中,我们先用Visual Studio创建了一个新的ASP.NET MVC应用程序,接着连接到了Northwind数据库,并展示了如何使用微软的LINQ-SQL的工具去访问数据库中的数据,接着指导如何去实现视图层去展示产品信息及如何设计控制器。

  本文是在上一篇文章的例子基础上,展示了如何去实现数据的双向排序。如果你是已经熟悉ASP.NET WebForm开发的开发者,你应该知道,在GridView控件中可以很简单的通过点击就能实现排序。但可惜的是,在ASP.NET MVC中实现排序的功能并不是那么简单,但工作量也没有显着增多。在ASP.NET MVC中,我们能更多地控制网格和排序的界面布局和标记,以及通过何种机制来实现排序。以往使用GridView控件时,排序是通过将参数以POSTBACK的形式回传到后台,以决定用什么样的列进行排序以及是以升序或降序-排列,回传的参数作为隐藏表单域提交。在本文中,我们将使用查询字符串参数来指定排序参数,这意味着排序的顺序可以被搜索引擎搜索到,能通过电子邮件发送给同事,还能做很多GridView内置排序功能不能实现的事情。

  与上一篇文章一样,本文提供了分步的指导说明,包括一个完整的可以工作的代码例子,在文章末尾可以下载。

  步骤0:一个简要指南

  本文将介绍如何实现双向的排序,并假定读者已经阅读掌握了上一篇文章介绍的内容。

  在上一篇文章中,我们可以通过ASP.NET MVC中的URL转发功能,以下面的地址形式访问产品的首页:

  www.yoursite.com/Products/Index(可以简写成www.yoursite.com/Products)。本文中,我们将用下面的URL去访问要排序的内容:

  www.yoursite.com/Products/Sortable?sortBy=ColumnNameascending=true|false

  具体的一些例子如下:

  /Products/Sortable- 这表示按默认顺序排列产品。当没指定排序的列时,默认按产品名称的字母顺序(如升序)排列。换句话说,如果SortBy参数没有提供,按产品名称排序,如果不提供ascending参数,按递增顺序排列。

  /Products/Sortable?sortBy=UnitPrice 按单价的升序排序产品。

  /Products/Sortable?sortBy=UnitPriceascending=false – 按UnitPrice列降序排序(即从最昂贵的到价格最便宜的)。

  跟使用GridView控件一样,在点击网格中标题行中的列名时可以进行。但不同于GridView的是,我们每次点列的这些标题,是以超链接的形式实现的,并且带有参数,比

  如表格中有价格这个列,当第一次点击列名时,将以

  www.yoursite.com/Products/Sortable?sortBy=UnitPriceascending=true的形式发送链接到后端,请注意的是,在网格中显示的列名,不一定跟在URL中sortBy查询字符串参数中传递的名称是一样的。sortBy 参数提供的是在数据库中的列名,两者并不要求一定相同。

  步骤1:创建指定的视图模型

  在上一篇文章的演示中,我们使用了产品的集合作为其实体模型(以NorthwindDataContext去命名)。这对简单的网格来说是可以的,但对于要排序的数据表格,需要知道一点的不仅仅是产品的集合,还要视图层方面知道哪些列的数据需要进行排序,是按升序或降序排序,如果用户要点的列已经按某一个顺序已排序的话,则此时会按原来的顺序排序(假设某列已经是按升序排列,用户点标题一次,则倒过来按降序排列,再点一次,又按升序,如此类推)。

  为此,我们添加一个新类,这些类被称为特定视图服务的模型,打开上一篇文章中已经实现的应用程序,在Models文件夹下添加一个名为ProductGridModel.cs 的文件,代码如下:

 
 
namespace Web.Models
{
public class ProductGridModel
{
// Data properties
public IEnumerable   Product Products { get ; set ; }



// Sorting-related properties
public string SortBy { get ; set上海徐汇企业网站制作n style="color: #000000;">; }
public bool SortAscending { get ; set ; }
public string SortExpression
{
get
{
return this .SortAscending ?上海企业网站制作pan> this.SortBy + " asc" : this.SortBy + " desc";
}
}
}
}

  该ProductGridModel类定义了一个产品属性,它是一个集合类的属性,用来显示产品集合,同时也有三种排序相关的属性:

  SortBy

  在数据库中用来排序的数据列名称

  SortAscending

  一个布尔值,指示是否用升序排序数据

  SortExpression

  只读属性,返回一个排序字符串,其构造为SortBy和SortAscending值的组合。

  例如,如果SortBy分为UnitePrice和SortAscending是true,SortExpression的值为

   UnitedPrice asc。

  如果SortBy设置为Discontinued 和SortAscending是false,则SortExpression返回Discontinued desc 。

  步骤2:创建Sortable 的Action方法

  在上一篇教程中,我们创建了一个名为ProductsController的控制器,其中有一个叫index的action和一个辅助属性DataContext,本文中,我们将添加一个新的action方法到控制器中,并命名为Sortable,当有来自如www.yoursite.com/Products/Sortable的请求时,则执行该排序方法。

  ASP.NET MVC中实现了自动参数绑定,来自URL或其他的参数请求,将被映射到执行的实际的action中去。例如,如果你在控制器action中定义了一个输入参数,名为sortBy,则MVC框架将搜索传入的请求的参数,看是否有任何具有相同名称的参数(在这里,一个参数可能是一个提交表单域,一个查询字符串参数或路由参数。)如果找到一个匹配,则自动把参数的值得赋给action中定义的参数。

  下面是其实际代码:

 
 
public class ProductsController : Controller

  {

  ...


// GET: /Products/Sortable?SortColumn=columnNameAscending=true|false

  
public ActionResult Sortable( string sortBy = " ProductName " , bool ascending = true )

  {

  var model
= new ProductGridModel()

  {

  SortBy
= sortBy,

  SortAscending
= ascending

  };

  model.Products
= this .DataContext.Products.OrderBy(model.SortExpression);


return View(model);

  }

  }

  请注意,action中接受两个输入参数:sortBy和ascending。任何来自URL的请求,只要符合这两个参数的名称的,其值得都会被自动匹配传入到该action中去, 也就是说,如果有人访问www.yoursite.com不指定查询字符串参数,则默认按照产品的名称进行升序排序。

  Sortable的action首先创建一个新的ProductGridModel实例,命名为model,并且对model的SortBy和SortAscending属性进行赋值,接着,Sortable action获得了产品的集合(this.DataContext.Products),并调用其中的OrderBy方法进行排序,而排序的参数表达式正好是SortExpression。最后,将model模型返回给一个强类型的视图,。

  如果您熟悉使用LINQ,你会觉得我在这里使用的OrderBy方法有点奇怪,你可能会用LINQ中的lambda表达式如下这样写,如:this.DataContext.Products.OrderBy(p =p.ProductName)。

  OrderBy方法,我使用的是不标准的LINQ,相反是微软的动态LINQ库中的方法

  (http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx),它是一个库允许使用字符串做为查询参数。本文附件中提供了一个名为Dynamic.cs的文件(它在HelperClasses文件夹中),其中包含了OrderBy扩展方法签名,大家可以去学习一下。 

  步骤3:创建视图

  鼠标右键点控制器中的Sortable action,在弹出的菜单中选择添加视图选项。从添加视图对话框中,选中Create a strongly-typed view 复选框,然后从View data class 下拉选择Web.Models.ProductGridModel,点击确定。这时会创建视图Sortable.aspx,如下图:

在ASP.NET MVC中对数据进行排序

  接下来,修改代码如下:

 
 
table class ="grid"
tr
th Product / th
th Category / th
th Qty/Unit / th
上海闵行企业网站制作an style="color: #800000;">th Price / th
th Discontinued / th
/ tr % foreach (var item in Model.Products) { %

tr
td class ="left" % : item.ProductName % / td
td class ="left" % : item.Category.CategoryName % / td
td class ="left" % : item.QuantityPerUnit % / td
td class ="right" % : String .Format( " {0:C} " , item.UnitPrice) % / td
td
% if (item.Discontinued) { %
img src ="%=Url.Content(" ~/Content/cancel.png") % " alt="Discontinued" title="Discontinued" /
% } %
/ td
/ tr

% } % / table

  上面的代码跟上一篇文章中你看到的基本没什么区别,唯一的区别,其实是在foreach语句中,在上一篇文章中,是:

在ASP.NET MVC中对数据进行排序

  foreach(var item in Model) { ... },而本文中,其模型变成了ProductGridModel实例,其产品属性包含产品的集合。因此,在foreach循环遍历Model.Products。运行后,你会发现访问页面时默认的是按产品的升序排列的:

  现在网格的列标题是文本,等下我们会将其修改为超级链接,但现在我们也可以马上在浏览器中,通过输入的方法体验下了,举例来说,如果你输入:

  www.yoursite.com/Products/Sortable?sortBy=UnitPriceascending=false- 你应该看到按 照价格从高到低排列的产品。

  在网格中添加排序链接

  此时,用户无法直观地去排序,除非他在浏览器中象上面的方法输入查询字符串,因此我们在每个网格的标题行中提供超链接指向适当的网址。乍一看,这可能会像一个简单的任务,比如产品名称列,其url应该是

  Products/Sortable?sortBy=ProductNameascending=true,而价格列,则应该是

  Products/Sortable?sortBy=UnitPriceascending=true,如此类推,归纳一下,其URL的连接方式应该象:

  Products/Sortable?sortBy=ColumnNameascending=false,同时,还应该增加一个象图标这样的指示,让用户可以清楚地看到当前排序的情况。

  要做到这一点,需要创建一个局部视图。一个局部视图看上去跟WebForms模型中的用户控件的概念差不多。总之,这是一可以重用的视图。

  在解决方案资源管理器中的Views/Shared目录下,鼠标右键点击,在弹出的菜单中选择添加视图,将其命名为SmartLink,并选中下面的两个复选框,然后选择Web.Models.ProductGridModel作为其view data class,如下图。

下载得到

  单击确定后,Visual Studio将创建一个新的局部视图(SmartLink.ascx)。其中局部视图只包含下列标记:

 
 
% @Control
Language
= " C# " Inherits = " System.Web.Mvc.ViewUserControlWeb.Models.ProductGridModel " %

  我们现在来学习如何将局部视图添加到正常的视图中去,这可以使用下列Html.RenderParial方法之一:

 
 
% Html.RenderPartial( " partialViewName " ); %
%
Html.RenderPartial( " partialViewName " , viewData); %
%
Html.RenderPartial( " partialViewName " , model); %
%
Html.RenderPartial( " partialViewName " , model, viewData); %

  可选的参数是一个ViewDataDictionary的ViewData对象。如果提供,可以通过

  ViewData["name"].去访问这些值。

  当要展示局部视图的时候,我们还需要将ProductGridModel和一些额外的信息传进来,下面的代码展示了对于产品名称一列这个表头,我们是如何通过局部视图去产生的,注意的是,我们通过ViewDataDictionary可以设置表头中显示的列的名称以及该列实际对应的是数据库中的列名:

 
 
% Html.RenderPartial( " SmartLink " , Model, new ViewDataDictionary {
{
" ColumnName " , " ProductName " }, { " DisplayName " , " Product " } }); %

  这里设置了列名是ProductName,而显示在表头中的列名是Product。同理,其他表头列也是这样的处理,就可以把Model传递到部分视图中来了。

 
 
table class ="grid"
tr
th % Html.RenderPartial( " SmartLink " , Model, new ViewDataDictionary { { " ColumnName " , " ProductName " }, { " DisplayName " , " Product " } }); % / th
th % Html.RenderPartial( " SmartLink " , Model, new ViewDataDictionary { { " ColumnName " , " Category.CategoryName " }, { " DisplayName " , " Category " } }); % / th
th % Html.RenderPartial( " SmartLink " , Model, new ViewDataDictionary { { " ColumnName " , " QuantityPerUnit " }, { " DisplayName " , " Qty/Unit " } }); % / th
th % Html.RenderPartial( " SmartLink " , Model, new ViewDataDictionary { { " ColumnName " , " UnitPrice " }, { " DisplayName " , " Price " } }); % / th
th % Html.RenderPartial( " SmartLink " , Model, new ViewDataDictionary { { " ColumnName " , " Discontinued " }, { " DisplayName " , " Discontinued " } }); % / th
/ tr

...
/ table

  现在我们可以看到,从局部视图中可以通过Model属性访问在Sortable视图中的任何值了,访问的方法是通过ViewData[name]即可。还要记得,我们之所以要在这里使用局部视图,其目的为某个特定的列生成超级链接。

  我们接下来要判断某个列是否要升序还是降序排列,下面的代码创建了isDescending变量,这个值只有当要排序的列(由Model.SortBy产生)和数据库中的列名相同(由ViewDate[ColumnName]产生)时,并且当前的排序为升序(Model.SortAscending)时,其值才为True。

 
 
var isDescending = string .CompareOrdinal(Model.SortBy,
ViewData[
" ColumnName " ].ToString()) == 0 Model.SortAscending;

  同时,我们最好通过设置CSS样式,告诉用户当前的排序方向,因此我们在 CustomStyles.css的CSS类定义了两个CSS类-sortAsc和sortDesc,增加了一个向上或向下箭头,可以用如下代码去判断:

 
 
f ( string .CompareOrdinal(Model.SortBy, ViewData[ " ColumnName " ].ToString()) == 0 )
{
if (Model.SortAscending)
htmlAttributes.Add(
" class " , " sortAsc " );
else
htmlAttributes.Add(
" class " , " sortDesc " );

  最后,完成的局部视图代码如下:

 
 
%
var isDescending
= string .CompareOrdinal(Model.SortBy, ViewData[ " ColumnName " ].ToString()) == 0 Model.SortAscending;

var routeData
= new RouteValueDictionary { { " sortBy " , ViewData[ " ColumnName " ].ToString() }, { " ascending " , ! isDescending } };

var htmlAttributes
= new Dictionary string , object ();
if ( string .CompareOrdinal(Model.SortBy, ViewData[ " ColumnName " ].ToString()) == 0 )
{
if (Model.SortAscending)
htmlAttributes.Add(
" class " , " sortAsc " );
else
htmlAttributes.Add(
" class " , " sortDesc " );
}
%% : Html.ActionLink(
ViewData[
" DisplayName " ].ToString(), // Link Text
Html.ViewContext.RouteData.Values[ " action " ].ToString(), // Action
Html.ViewContext.RouteData.Values[ " controller " ].ToString(), // Controller
routeData, // Route data 上海闵行企业网站设计与制作>
htmlAttributes // HTML attributes to apply to hyperlink
)
%

  Html.ActionLink方法会向浏览器端产生超链接的HTML。它的第一个参数为要显示的文字超链接的标题,这里通过ViewData[displayname]读取。

  第二个和第三个参数指定了action和控制器去生成链接,我们使用Html.ViewContext.RouteData.Values[action].ToString

  和Html.ViewContext.RouteData.Values[controller].ToString()来获得当前请求的action和控制器,而避免了硬编码。

  第四个输入参数指定了路由的数据,这是我们用RouteValueDictionary字典的形式,分别向sortBy和ascending参数传入值。

  最后的参数设定了生成链接的HTML的CSS样式。

  当运行程序后,默认是按产品名称升序排序的,如下图。

下载的到

  当点产品标题列旁边的小箭头时,会向控制器发出如

  Products/Sortable?sortBy=ProductNameascending=False的请求,于是产品名称按降序排序了,如下图:

下载的到

  本文的代码可以在:http://aspnet.4guysfromrolla.com/code/GridDemosMVC.zip下载得到。

目录
相关文章
|
1月前
|
机器学习/深度学习 JSON 测试技术
CNN依旧能战:nnU-Net团队新研究揭示医学图像分割的验证误区,设定先进的验证标准与基线模型
在3D医学图像分割领域,尽管出现了多种新架构和方法,但大多未能超越2018年nnU-Net基准。研究发现,许多新方法的优越性未经严格验证,揭示了验证方法的不严谨性。作者通过系统基准测试评估了CNN、Transformer和Mamba等方法,强调了配置和硬件资源的重要性,并更新了nnU-Net基线以适应不同条件。论文呼吁加强科学验证,以确保真实性能提升。通过nnU-Net的变体和新方法的比较,显示经典CNN方法在某些情况下仍优于理论上的先进方法。研究提供了新的标准化基线模型,以促进更严谨的性能评估。
62 0
|
16天前
|
前端开发
Spring-MVC的数据响应-19
Spring-MVC的数据响应-19
|
23天前
|
安全 前端开发 测试技术
安全开发-PHP应用&模版引用&Smarty渲染&MVC模型&数据联动&RCE安全&TP框架&路由访问&对象操作&内置过滤绕过&核心漏洞
安全开发-PHP应用&模版引用&Smarty渲染&MVC模型&数据联动&RCE安全&TP框架&路由访问&对象操作&内置过滤绕过&核心漏洞
|
1月前
|
Linux C# C++
【.NET Developer】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务
本文介绍了如何使用VS2019和.NET框架创建一个Blazor应用,并将其部署到Azure应用服务。首先,Blazor是一个使用C#而非JavaScript构建交互式Web UI的框架,支持共享服务器和客户端应用逻辑,以及与Docker和Azure集成。任务包括创建Blazor项目,配置Dockerfile为Linux容器,本地测试,发布到Azure Container Registry (ACR),然后在Azure App Service for Container上部署。在部署过程中,需确保Docker设置正确,开启ACR的Admin访问权限,并监控镜像拉取和容器启动日志。
|
2月前
|
数据采集 前端开发 Java
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
32 3
|
2月前
|
前端开发 Java Spring
数据之桥:深入Spring MVC中传递数据给视图的实用指南
数据之桥:深入Spring MVC中传递数据给视图的实用指南
48 3
|
2月前
|
前端开发 Java API
饼干探秘:深入Spring MVC中获取Cookie数据的技术解析
饼干探秘:深入Spring MVC中获取Cookie数据的技术解析
35 3
|
2月前
|
前端开发 Java API
头头是道:揭示Spring MVC如何获取和处理请求头数据
头头是道:揭示Spring MVC如何获取和处理请求头数据
53 1
|
2月前
|
机器学习/深度学习 算法 数据可视化
MATLAB基于深度学习U-net神经网络模型的能谱CT的基物质分解技术研究
MATLAB基于深度学习U-net神经网络模型的能谱CT的基物质分解技术研究
|
2月前
|
存储 测试技术 计算机视觉
高维数据惩罚回归方法:主成分回归PCR、岭回归、lasso、弹性网络elastic net分析基因数据
高维数据惩罚回归方法:主成分回归PCR、岭回归、lasso、弹性网络elastic net分析基因数据