ASP.NET MVC:排序、搜索、分页以及多对多数据库

ASP.NET MVC自动生成的手脚架很方便,但是在我们实际的工作中,那仅仅是开始而已。下面我们以一个实例来讨论ASP.NET MVC的排序、搜索和分页,最后我们完成一个简单的多对多数据库。

打开VS2015,创建一个MVC项目,取名为PersonnelTask,新建一个Model-Personnels:

public class Personnels
    {
        public int PersonnelsId { get; set; }
        [Required(ErrorMessage = "请输入名称。")]
        [StringLength(160, MinimumLength = 4)]
        [Display(Name = "名称")]
        public string Name { get; set; }
        [Required(ErrorMessage = "请输入薪水。")]
        [Display(Name = "薪水")]
        public decimal Pay { get; set; }
        [Required(ErrorMessage = "请输入入职时间。")]
        [Display(Name = "入职时间")]
        public DateTime Date { get; set; }
    }

接着,我们新建一个控制器:包含视图的MVC 5控制器,具体设计如下图:

mark

完成手脚架后,我们开始填入种子数据

1.在项目里面的Models文件夹,新建一个种子类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace PersonnelTask.Models
{
    public class DbInitializer:System.Data.Entity.DropCreateDatabaseAlways<PersonnelTaskContext>
    {
        protected override void Seed(PersonnelTaskContext context)
        {
            context.Personnels.Add(new Personnels { Name = "张三", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "李四", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "张马子", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "阳明", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "张伟", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "徐可", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "王丽", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "玛丽", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "麦克", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "潭门", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "于谦", Pay = 2000, Date = DateTime.Now });
            context.Personnels.Add(new Personnels { Name = "郭德", Pay = 2000, Date = DateTime.Now });
            base.Seed(context);
        }
    }
}

2.打开Global.asax.cs,加入下面打代码:

 protected void Application_Start()
        {
            Database.SetInitializer(new DbInitializer());
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

下面我们来演示一下排序。

数据库排序的功能是很重要的,在本例中,我希望可以通过点击“薪水”或者“入职时间”,重新按照“薪水”或者“入职时间”的升序或者降序来排列我们的数据。

思路:我们在index控制器里面增加一个参数sortOrder,用它来接收需要排序的值 public ActionResult Index(string sortOrder)

通过这些值的不同,我们的数据排序就是根据这些值进行排列的。下面是源代码:

public ActionResult Index(string sortOrder)
        {
            var ps = from s in db.Personnels select s;

            ViewBag.PaySortPam = sortOrder == "pay" ? "pay_desc" : "pay";
            ViewBag.DateSort = sortOrder == "date" ? "date_desc" : "date";
            switch (sortOrder)
            {
                case "pay_desc":
                    ps = ps.OrderByDescending(s => s.Pay);
                    break;
                case "pay":
                    ps=ps.OrderBy(s => s.Pay);
                    break;
                case "date_desc":
                    ps = ps.OrderByDescending(s => s.Date);
                    break;
                case "date":
                    ps=ps.OrderBy(s => s.Date);
                    break;
                default:
                    ps = ps.OrderByDescending(s => s.PersonnelsId);
                    break;

            }

           
            return View(ps.ToList());
        }

从上面的代码可以看出,我们总共列出了5种数据排列方式,默认排列方式、按薪水高低两种排列方式、按入职日期早晚两种排列方式。

在视图里面我们也要做一下修改:

 <tr>
        <th>
   @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
          @Html.ActionLink("薪水", "Index", new { sortOrder = ViewBag.PaySortPam })  
        </th>
        <th>
           @Html.ActionLink("入职日期", "Index", new { sortOrder = ViewBag.DateSort })
        </th>
        <th></th>
    </tr>
mark

这样就好了,完成了我们的排序功能。

下面,我们下面来做一个搜索名称的搜索框,打开视图,加入下面的代码

@using (Html.BeginForm())
{ 
  <p>
        Find By Name:
        @Html.TextBox("SearchString") <input type="submit" value="Search" />
    </p>
}
mark

看起来还不错,再到控制器里面修改代码:

 public ActionResult Index(string sortOrder,string searchString)
        {
            var ps = from s in db.Personnels select s;
            if (!string.IsNullOrEmpty(searchString)) {
                ps = ps.Where(s => s.Name.ToUpper().Contains(searchString.ToUpper()));
            }
   ...省掉重复代码
        }
mark

不错,这个功能也能用了。

分页需要到NuGet下载PagedList.Mvc 包,安装完成以后有提示

mark

在控制器中增加一句:using PagedList;

由于增加了分页包,代码修改量比较大,下面将全部代码奉上。首先修改自控制器:

 public ActionResult Index(string sortOrder, string currentFilter, string searchString, int? page)
        {
            ViewBag.CurrentSort = sortOrder;
            ViewBag.PaySortPam = sortOrder == "pay" ? "pay_desc" : "pay";
            ViewBag.DateSort = sortOrder == "date" ? "date_desc" : "date";
            if (searchString != null) { page = 1; } else { searchString = currentFilter; }
            ViewBag.CurrentFilter = searchString;

            var ps = from s in db.Personnels select s;
            if (!string.IsNullOrEmpty(searchString))
            {
                ps = ps.Where(s => s.Name.ToUpper().Contains(searchString.ToUpper()));
            }
            switch (sortOrder)
            {
                case "pay_desc":
                    ps = ps.OrderByDescending(s => s.Pay);
                    break;
                case "pay":
                    ps = ps.OrderBy(s => s.Pay);
                    break;
                case "date_desc":
                    ps = ps.OrderByDescending(s => s.Date);
                    break;
                case "date":
                    ps = ps.OrderBy(s => s.Date);
                    break;
                default:
                    ps = ps.OrderByDescending(s => s.PersonnelsId);
                    break;

            }

            int pageSize = 3;
            int pageNumber = (page ?? 1);
            return View(ps.ToPagedList(pageNumber, pageSize));
        }

视图页全部代码:

@using PagedList.Mvc;
@model PagedList.IPagedList<PersonnelTask.Models.Personnels >
<link href = "~/Content/PagedList.css" type = "text/css" rel = "stylesheet" />
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm("Index","Personnels", FormMethod.Get))
{ <p>
        Find By Name:
        @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
     <input type="submit" value="Search" />
    </p>
}
<table class="table">
    <tr>
        <th>
           名称
        </th>
        <th>
             @Html.ActionLink("薪水", "Index", new { sortOrder = ViewBag.PaySortPam, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th>
            @Html.ActionLink("入职日期", "Index", new { sortOrder = ViewBag.DateSort, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Pay)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Date)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.PersonnelsId }) |
                @Html.ActionLink("Details", "Details", new { id = item.PersonnelsId }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.PersonnelsId })
            </td>
        </tr>
    }

</table>
<br />
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount 

@Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
mark

测试通过。

好,现在已经基本实现了员工表的基本功能,现在,我们来新建一个Tasks任务表

public class Tasks
    {
        public int TasksId { get; set; }
        [Required(ErrorMessage = "请输入名称。")]
        [StringLength(160, MinimumLength = 4)]
        [Display(Name = "名称")]
        public string Name { get; set; }

        public virtual ICollection<Taskspersonnel> Taskspersonnels { get; set; }
    }

同时修改一下Personnels类:

public class Personnels
    {
        public int PersonnelsId { get; set; }
        [Required(ErrorMessage = "请输入名称。")]
        [StringLength(160, MinimumLength = 1)]
        [Display(Name = "名称")]
        public string Name { get; set; }
        [Required(ErrorMessage = "请输入薪水。")]
        [Display(Name = "薪水")]
        public decimal Pay { get; set; }
        
        [Display(Name = "入职时间")]
        public DateTime Date { get; set; }

        public virtual ICollection<Taskspersonnel> Taskspersonnels { get; set; }
    }

现在有员工、有任务,那么要将员工和任务联系起来,就是一个员工任务列表,是一个多对多的数据库关系。一个员工执行多项任务,一个任务由多个员工执行。如果没有Tasksdate(任务执行时间)的话,这个类可以不用建立。因为它只有两个外键。

 public class Taskspersonnel
    {
        public int TaskspersonnelId { get; set; }
        public int PersonnelsId { get; set; }
        public int TasksId { get; set; }
        
        public DateTime Tasksdate { get; set; }

        public virtual Personnels personnels { get; set; }
        public virtual Tasks tasks { get; set; }
    }

运行生成解决方案后,对这两个实体类新建控制器。

先对Tasks填入一些测试数据。

然后运行/Taskspersonnels/Create:

mark

因为最后一个日期格式,如果这样直接让用户输入,有可能会输错、报错。所以我们还是找一个日历包给它好了。

mark

安装JQuery.UI.Widgets.Datepicker,我在安装过程中发生了BUG,所以我直接去JQuery.UI官网上下载。

只要将jquery-ui.min.js和jquery-ui.css引入项目里面,对日期项的TEXT做一下修改

 @Html.EditorFor(model => model.Tasksdate, new { htmlAttributes = new { @class = "form-control datepick"} })

最后,在该视图中加入JQuery代码,完成!

<script>
    $(function () {
        $(".datepick").datepicker();
    });
</script>
mark

谢谢大家。转帖的时候请把凉风有兴或者AlexZeng.net进行署名。本文版权声明:自由转载-非商用-以非衍生-保持署名(创意共享3.0许可证

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,400评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • Swift版本点击这里欢迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh阅读 25,267评论 7 249
  • 谁都有情绪,谁都需要正常的宣泄,时不时倒倒垃圾,打扫下心房,很有必要,否则垃圾堆积久了,不知道会在什么地方出毛病!...
    爱读书写字的格格妈阅读 297评论 0 0
  • 到了市区,果然美女如云,也有好多棒棒的身材,男生女生都是。今天好累,明天回国了,这几天,不工作,确实很舒服
    DeathKnightR阅读 115评论 0 0