[转]ASP.NET MVC4+BootStrap 实战(一)

本文转自:http://leelei.blog.51cto.com/856755/1587301

好久没有写关于web开发的文章了,进到这个公司一直就是winform和Silverlight,实在是没有实战web项目的机会。大D也辞职了,去搞web app了。自己也该闲暇时间多学习学习,每天进步一点点。

OK,不多说了,看一下Solution的截图

基本上一看就明白了,控制器调用Biz层,Biz层调用DAL层,DAL层进行数据的CURD。Utility是一些公用的类库。ok,为什么程序集的命名都是以Bruce开头呢,因为我在公司的英文名叫这个。废话不多说,我们先看一下页面

我们引入了BootStrap,主要是为了页面布局。在Views中Partial下面放的都是部分页。

我们先看一下运行效果,今天主要是讲页面初始化部分。

其实查询条件就是婚否,出生日期,姓名的模糊查询。我们先看一下页面Index.cshtml的代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

    <meta name="viewport" content="width=device-width;initial-scale=1" />

    <title>Compare data between Solr and DB</title>

    <link rel="stylesheet" type="text/css" href="~/BootStrap/css/bootstrap-theme.css" />

    <link rel="stylesheet" type="text/css" href="~/BootStrap/css/bootstrap.css" />

          @*@Styles.Render("~/css")*@

          @Scripts.Render("~/bundles/BootStrap")

          @Scripts.Render("~/bundles/Scripts")

    <style type="text/css">

        .pre-Scrollable {

            max-height: 700px;

            overflow-y: scroll;

        }

    </style>

</head>

<body>

    <div class="container">

        <form id="formsync">

            <div class="row">

                <div class="col-md-12">

                    <h1 style="color:red"><b>Compare Data Between Solr and DB</b></h1>

                </div>

            </div>

            <div class="row" id="divloding" style="display:none;text-align:center">

                <div class="col-md-6">

                    <img src="~/Images/ajaxLoading.gif" alt="load failed" />

                    <label>getting,please wait......</label>

                </div>

            </div>

            <div class="row" id="divcompare" style="display:none;text-align:center">

                <div class="col-md-6">

                    <img src="~/Images/ajaxLoading.gif" alt="load failed" />

                    <label>comparing,please wait......</label>

                </div>

            </div>

            <div class="row" id="divfix" style="display:none;text-align:center">

                <div class="col-md-6">

                    <img src="~/Images/ajaxLoading.gif" alt="load failed" />

                    <label>fixing,please wait......</label>

                </div>

            </div>

            <div class="row" style="margin-top:10px">

                <div class="col-md-12 form-inline">

                    <div class="form-group input-group">

                        <span class="input-group-addon">IsMarried:</span>

                        @Html.DropDownList("ddlMarried", ViewBag.MarriedList as SelectList, null, new { id = "ddlMarried", @class = "form-control" })

                    </div>

                    <div class="form-group" style="margin-left:10px">

                        <label class="control-label">BirthDay:</label>

                        <input type="date" id="txtdatestart" class="form-control">

                        <label class="control-label">-</label>

                        <input type="date" id="txtdateend" class="form-control">

                    </div>

                    <div class="form-group input-group" style="margin-left:10px">

                        <span class="input-group-addon">Name:</span>

                        <input id="txtusername" type="text" class="form-control" placeholder="input name..." style="width:120px" />

                    </div>

                    <div class="form-group" style="margin-left:10px">

                        <input id="btnsearch" type="button" class="btn btn-info" value="Get" style="width:70px" />

                    </div>

                </div>

            </div>

            <div class="row" style="margin-top:10px">

                <div id="divresult" class="col-md-7 form-inline  pre-Scrollable">

                    @{Html.RenderPartial("~/Views/Partial/UserInfoPartial.cshtml");}

                </div>

                <div class="col-md-5">

                    @{Html.RenderPartial("~/Views/Partial/DiffAndSameWithSolrPartial.cshtml");}

                </div>

            </div>

        </form>

    </div>

</body>

</html>

我们使用html5+BootStrap布局,这里用到了BootStrap的网格系统,将浏览器平分为12份,即12列,很容易构造出响应式布局系统。那么什么是BootStrap的网格系统,看如下的解释

OK,我们怎么看是否是响应式的布局呢,我们打开谷歌浏览器,现将浏览器缩小到一定程度。

看到了吧,即使设备浏览器这么小,我们还是能用。那我们在手机模拟器中测试一下,打开谷歌浏览器,按F12,点击手机模拟器样的东西,然后Device选择iphone6。

我们看到iphone6下面的效果是这样的。说到这里我最近很讨厌两个广告,一个是“这个是iphone6,这个是iphone6 plus,它们都有一个叫健康的东西.....但是好吃啊”,还有一个是“当牛魔王变成一个饺子,我愿意变成一双筷子”。看到这两个广告,我想砸电视。

那为什么不同的设备不同的浏览器都是可以正常浏览的呢,原因就在于这段代码


1

<meta name="viewport" content="width=device-width;initial-scale=1" />

这段代码的意思是网页宽度默认等于屏幕宽度,缩放比例默认为1(网页初始比例占屏幕的100%)。

ok,我们接下来看head部分css和js的引用,这里有个新东西叫Bundle,用来打包压缩js或者css的。通过它打包压缩的js或者css客户端只需要下载一次包即可,而且可以在客户端缓存起来,当检测到有更新时,才会重新下载。

下面是Bundle.cs的代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

using System.Web;

using System.Web.Optimization;

namespace Brue.GRLC.Web

{

    public class BundleConfig

    {

        // 有关 Bundling 的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=254725

        public static void RegisterBundles(BundleCollection bundles)

        {

            bundles.Add(new ScriptBundle("~/bundles/BootStrap").Include(

                        "~/Scripts/jquery-1.11.1.js","~/BootStrap/js/bootstrap.js"));

            bundles.Add(new ScriptBundle("~/bundles/Scripts").Include("~/Js/Index.js"));

            bundles.Add(new StyleBundle("~/css").Include("~/BootStrap/css/bootstrap-theme.css"

                "~/BootStrap/css/bootstrap.css"));

        }

    }

}

注意,在这里引用js的时候不要引用压缩过的js,比如xxx.min.js。当Bundle在遇到这种js命名文件的时候,直接就忽略掉了。那么我们在Head中只需要使用如下代码来引用即可。


1

2

@Scripts.Render("~/bundles/BootStrap")

@Scripts.Render("~/bundles/Scripts")

OK,在这我碰到一个问题,就是我的css通过这种方式引用,始终提示Index out of range。如果哪位大牛知道原因的话麻烦留个言,谢谢!

OK,我们接下来看一下控制器代码,页面刚进来,会走Home/Index。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

public ActionResult Index()

        {

            List<object> marriedList = GRLCBiz.GetInstance().GetMarriedList();

            SelectList selectList = new SelectList(marriedList, "MarriedID""DisplayContent""-1");

            ViewBag.MarriedList = selectList;

            DataResponse<UserDBEntity> dataResponse = GRLCBiz.GetInstance().GetUserInfoEntityList();

            UserInfoViewModel userInfoViewModel = new UserInfoViewModel();

            userInfoViewModel.DataResponse = dataResponse;

            userInfoViewModel.DataResponse.PageIndex = ConstValues.CONN_DefaultPageIndex;

            userInfoViewModel.DataResponse.PageSize = ConstValues.CONN_DefaultPageSize;

            userInfoViewModel.DataResponse.StartPageIndex = 1;

            return View(userInfoViewModel);

        }

首先我们构造了一个SelectList用于下拉列表,Biz层的代码很简单


1

2

3

4

5

6

7

8

9

public dynamic GetMarriedList()

        {

            IList<object> marriedList = new List<object>();

            marriedList.Add(new { MarriedID = -1, DisplayContent = "No Selection" });

            marriedList.Add(new { MarriedID = 0, DisplayContent = "Married" });

            marriedList.Add(new { MarriedID = 1, DisplayContent = "UnMarried" });

            return marriedList;

        }

用匿名类去构造一个List。接下来就是DataReponse的获取,Biz层的代码如下


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public DataResponse<UserDBEntity> GetUserInfoEntityList(UserInfoRequest request = null)

        {

            if(request==null)

            {

                request = new UserInfoRequest();

                request.PageIndex = ConstValues.CONN_DefaultPageIndex;

                request.PageSize = ConstValues.CONN_DefaultPageSize;

            }

          

            int totalCount=0;

            List<UserDBEntity> userDBEntityList = GRLCDAL.GetInstance().GetUserInfoEntityList(request, out totalCount);

            DataResponse<UserDBEntity> dataResponse = new DataResponse<UserDBEntity>();

            dataResponse.DataList = userDBEntityList;

            dataResponse.TotalCount = totalCount;

            return dataResponse;

        }

没什么可说的,ConstValues类中是一些静态只读属性


1

2

3

4

5

6

7

8

public class ConstValues

    {

        public static readonly string CON_DBConnection = ConfigurationManager.ConnectionStrings["DB_ConnectionStr"].ToString();

        public static readonly string CON_DbScriptXmlFolder = ConfigurationManager.AppSettings["DbScriptXmlFolder"];

        public static readonly int CONN_DefaultPageSize = int.Parse(ConfigurationManager.AppSettings["DefaultPageSize"]);

        public static readonly int CONN_DefaultPageIndex = 1;

        public static readonly int CONN_PagerDisplayCount = int.Parse(ConfigurationManager.AppSettings["PagerDisplayCount"]);

    }

看一下DAL层。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

public List<UserDBEntity> GetUserInfoEntityList(UserInfoRequest request, out int totalCount)

        {

            totalCount = 0;

            string sqlScript = string.Empty;

            try

            {

                sqlScript = DBScriptManager.GetScript(this.GetType(), "GetUserInfo");

                SqlParameter[] sqlParameters = 

                {

                    new SqlParameter("@IsMarried",SqlDbType.Char,1),

                    new SqlParameter("@StartDate",SqlDbType.DateTime),

                    new SqlParameter("@EndDate",SqlDbType.DateTime),

                    new SqlParameter("@UserName",SqlDbType.NVarChar,20),

                    new SqlParameter("@PageIndex",SqlDbType.Int),

                    new SqlParameter("@PageSize",SqlDbType.Int),

                    new SqlParameter("@TotalCount",SqlDbType.Int)

                };

                sqlParameters[0].Value = request.IsMarried;

                sqlParameters[1].Value = request.StartDate;

                sqlParameters[2].Value = request.EndDate;

                sqlParameters[3].Value = request.UserName;

                sqlParameters[4].Value = request.PageIndex;

                sqlParameters[5].Value = request.PageSize;

                sqlParameters[6].Direction = ParameterDirection.Output;

                DataSet ds = SqlHelper.ExecuteDataset(ConstValues.CON_DBConnection, CommandType.Text, sqlScript, sqlParameters);

                if (ds != null && ds.Tables.Count > 0)

                {

                    totalCount = Convert.ToInt32(sqlParameters[6].Value);

                    return ds.Tables[0].ToEntityList<UserDBEntity>();

                }

                return new List<UserDBEntity>();

            }

            catch (Exception ex)

            {

                LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex);

                return null;

            }

        }

OK,我们看一下这个GetUserInfo脚本,在Bruce.GRLC.DbScriptXml程序集下。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

<?xml version="1.0" encoding="utf-8" ?>

<Scripts>

  <Script Key="GetUserInfo">

    <![CDATA[

DECLARE @UserTempTable TABLE

(  

    ID INT IDENTITY(1,1) NOT NULL,

    UserNo CHAR(25) NOT NULL

)

INSERT INTO @UserTempTable

(

    UserNo

)

SELECT

    A.UseNo

FROM Bonus.dbo.[User] A WITH(NOLOCK)

LEFT JOIN Bonus.dbo.UerInfo B WITH(NOLOCK)

    ON A.UseNo = B.UseNo

WHERE (@IsMarried IS NULL OR @IsMarried = ‘‘ OR B.Temper = @IsMarried)

    AND

    (

        @StartDate IS NULL 

        OR @EndDate IS NULL 

        OR B.BirthDay BETWEEN @StartDate AND @EndDate

    )

    AND 

    (

        @UserName IS NULL 

        OR @UserName = ‘‘ 

        OR B.Name LIKE ‘%‘ + @UserName + ‘%‘

    )

ORDER BY A.UseNo ASC

    

SELECT @TotalCount = COUNT(1) FROM @UserTempTable

SELECT

    UseNo,

    Name,

    Age,

    Married

FROM(

    SELECT

        ID = ROW_NUMBER() OVER(ORDER BY UseNo ASC),

        A.UseNo,

        B.Name,

        B.Age,

        Married = CASE WHEN B.Temper = ‘1‘

                        THEN ‘已婚‘

                       ELSE ‘未婚‘

                  END

        FROM Bonus.dbo.[User] A WITH(NOLOCK)

    LEFT JOIN Bonus.dbo.UerInfo B WITH(NOLOCK)

        ON A.UseNo = B.UseNo

    INNER JOIN @UserTempTable C

        ON C.UserNo = A.UseNo

) N

WHERE ID BETWEEN (@PageIndex - 1)* @PageSize + 1 AND @PageIndex * @PageSize

   ]]>

  </Script>

</Scripts>

脚本很简单,就是传入参数查分页数据。

在DAL层我们将DataTable通过ToEntityList转化为了实体List,在Utility中我们定义了一个扩展用来转化。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

public static class DataTableToEntityExtension

    {

        public static List<T> ToEntityList<T>(this DataTable dt) where T : class,new()

        {

            List<T> entityList = new List<T>();

            Type entityType = typeof(T);

            PropertyInfo[] propertys = entityType.GetProperties();

            DataMappingAttribute mappingAttribute = null;

            foreach (DataRow dr in dt.Rows)

            {

                T tEntity = new T();

                foreach (PropertyInfo pi in propertys)

                {

                    mappingAttribute = pi.GetCustomAttribute(typeof(DataMappingAttribute)) as DataMappingAttribute;

                    if (mappingAttribute != null && dt.Columns.Contains(mappingAttribute.mappingName))

                    

                        if (!pi.CanWrite) continue;

                        object value = dr[mappingAttribute.mappingName];

                        if (value != DBNull.Value)

                            pi.SetValue(tEntity, value, null);

                    }

                }

                entityList.Add(tEntity);

            }

            return entityList;

        }

    }

值那么转化的时候是怎么让DataTable的列和实体匹配起来,你可以将列别名和实体定义成一样的,还有一种你可以使用Attribute。那我们使用后者,因为后者更灵活。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

[AttributeUsage(AttributeTargets.Property)]

    public class DataMappingAttribute : Attribute

    {

        public string mappingName;

        public DbType dbType;

        public DataMappingAttribute()

        { }

        public DataMappingAttribute(string mappingName, DbType dbType)

        {

            this.mappingName = mappingName;

            this.dbType = dbType;

        }

    }

定义好Attribute之后,我们设置其能使用的目标只能是Property。然后我们在实体类里面的属性上加上这个Attribute。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

namespace Bruce.GRLC.Model.Entity

{

    public class UserDBEntity

    {

        [DataMapping("UseNo", DbType.AnsiString)]

        public string UserID { getset; }

        [DataMapping("Name", DbType.AnsiString)]

        public string UserName { getset; }

        [DataMapping("Age", DbType.Int32)]

        public int Age { getset; }

        [DataMapping("Married", DbType.String)]

        public string Married { getset; }

    }

}

在DataTableToEntityExtension这个扩展中我们得到属性的Attribute去和DataTable的列名去匹配,反射赋值。

OK,拿到数据后,我们在控制器构造viewModel,传递给界面来绑定。我们看一下部分页UserInfoPartial.cshtml的代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

@using Bruce.GRLC.Model.ViewModel;

@model UserInfoViewModel

<table id="tabuserinfo" class="table table-bordered table-hover">

    <thead>

        <tr style="#2aabd2;color:white">

            <th>帐号</th>

            <th>姓名</th>

            <th>年龄</th>

            <th>婚否</th>

        </tr>

    </thead>

    <tbody>

        @if (Model != null && Model.DataResponse != null && Model.DataResponse.DataList != null)

        {

            foreach (var userEntity in Model.DataResponse.DataList)

            {

                <tr>

                    <td>

                        @userEntity.UserID

                    </td>

                    <td>

                        @userEntity.UserName

                    </td>

                    <td>

                        @userEntity.Age

                    </td>

                    <td>

                        @userEntity.Married

                    </td>

                </tr>

            }

        }

    </tbody>

</table>

<div id="divpagination">

    @{Html.RenderPartial("~/Views/Partial/PaginationPartial.cshtml", Model.DataResponse);}

</div>

其实也就是一个应用了BoootStrap样式的表格,有边框和鼠标经过的样式。关于BootStrap的样式的使用,请参考BootStrap官网。代码很简单,就是循环遍历,展示数据。

本文出自 “技术创造价值” 博客,请务必保留此出处http://leelei.blog.51cto.com/856755/1587301

时间: 2024-10-13 19:59:50

[转]ASP.NET MVC4+BootStrap 实战(一)的相关文章

ASP.NET MVC4+BootStrap 实战(二)

上一篇文章我们讲述了页面初始加载数据的一些东西,本篇我们来讲一下查询按钮和分页按钮.在很久以前我写过一篇ASP.NET MVC4切近实战的文章,有关于分页的代码,本篇我们不采用微软的AJAX框架. 先看一下查询效果,在点击Get按钮之后,会进行AJAX请求. js代码如下 jQuery(document).ready(function () {     setRowBackColor();     $("#btnsearch").click(function () {         

ASP.NET MVC4+BootStrap 实战(七)

连续三年年会中奖,第一年二等奖,价值2600元的魔音耳机,到现在才用了10几次.第二年中了个价值260元的飞利浦烧水壶,到现在还没用.今年中了个飞利浦挂烫机,也没查是多少钱,反正觉得奖项一年不如一年.在此我就给大家上一张年会热图. 男人的肚皮舞,嗨爆全场.好了,废话不多说,我们进入正题吧. 今天我们要说的就是主页面以及用户注册界面,功能做的都比较简单,我们先看一下Index界面. <div id="div_navigation" style="margin-top:10

ASP.NET MVC4+BootStrap 实战(六)

最近面试了一个西安电子科技大学刚毕业的,不是计算机系毕业,却喜欢编程.除了书本上的知识以外,其他一窍不通,笔试题答得不错.经验欠佳,编程也只懂书本上的一些例子.本来不打算录用,但是后来聊到高等数学和物理是她学的最好的两门,那必须收下.人家都说了能考上西电,就能证明她的学习能力,我和项目经理也就相信人家了.毕竟当年面试的时候我面试的是南京擎天科技,有个西电的面试的是南京联创,人家和我聊了两句,得知我是二本院校的,人家说了句他同学面试的都是腾讯,阿里,百度,新浪,说完直接放弃面试,我去南京擎天还害怕

ASP.NET MVC4+BootStrap 实战(三)

上节我们剩余Compare和Fix按钮没有讲,本节我们就来讲一下Compare按钮的功能,年底了,要开年会了,一个个积极的跟邱少云似得,给员工涨工资的时候能不能也积极点.不说了,说多了都是泪. 还记得我之前写的大数据实战之环境搭建,我们今天主要是拿DB的数据和solr的数据作比较,得出比较结果.首先,先启动centOS,启动tomcat,这样我们才能利用SolrNet调用solr公开的API.关于solr的启动再次我就不再赘述. OK,我们将solr实例启动起来后,用firefox浏览管理界面,

ASP.NET MVC4+BootStrap 实战(十)

年过完了,也该收心了.想想过年这几天都是每天睡到12:00,实在是腐化.大家都沉浸在抢红包的喜悦之中. 不说了,今天我们主要看一下新闻链接管理界面.先上图,无图无真相. 上半部分主要是对已经添加的外链接进行修改删除,设置优先级,下半部分是新增外链接网站. 首先我们先看一下上半部分. <div id="div_newsManage" class="panel panel-primary" ng-app="newsLinkManageModule&quo

ASP.NET MVC4+BootStrap 实战(八)

今天西安下雪了,贼冷,我去.今年的年终奖还没发,都快揭不开锅了. 今天的话我们来看一下用户删除和修改,天太冷,先调一下胃口,上图,无图无真相. 看到了吧,新增了选择列,操作列,以及页面最下面的全选,反选,新增,删除按钮. 我们先来看一下全选反选吧,经过修改之后,我们的Table变成如下的代码 <table class="table table-bordered table-striped table-hover" ng-init="load()">   

ASP.NET MVC4+BootStrap 实战(九)

哄孩子睡觉哄到现在,要两个孩子真的是不容易.孩子不睡觉,我没办法写博客.孩子睡着了,我一写就要写到半夜2点.6点起床,6:30骑自行车去上班,呼吸着雾霾,头皮冻得僵硬.到了软件园楼底下,还要排队买胡辣汤,排队上电梯.唉,生活不易. 今天,我们要说的当然是用户信息修改,请看下图. 看到一龙了么,重庆功夫盛典和日本变装拳手战成平手,打裂了日本拳手的眉骨.OK,我们点击铅笔,弹出用户信息修改界面.那么,我们在弹出用户信息修改界面之前,先要给弹出界面的form赋值.那么这一步要怎么做,当然了,是使用an

ASP.NET MVC4+BootStrap 实战(十三)

最近公司来了一个陕北的实习妹子,据说家里是开矿的,人长得一般,但很有气质.开矿的,当然钱很多了.以前在大学有个同学,家里是开油田的,有节毛概课,老师说西安的房价都是陕北人轰起来的,西安人都怨陕北人.我这个同学听了不开心了,周末直接在东西南北各买一套.牛逼啊,让你老师多嘴.这几天周围的同事心思都在这个姑娘身上,装作喝咖啡过去瞄一眼,或者站起来瞅瞅背影.IT爷们真的是空虚,IT界无美女啊,还是吉日嘎啦说的好,公司有美女,可以提升爷们的战斗力. OK,今天我们来看一下新闻审核界面,本来这节是要说ued

ASP.NET MVC4+BootStrap 实战(十一)

最近一天真的都不知道自己在忙什么,当了回Scrum Master.给自己的感觉就是像大学时期,饭堂经理看员工给学生打饭太慢,自己抡起大勺子给学生打菜,偶尔有些学生有情绪还要忍着.说到饭堂,最近都不知道该吃啥.黄焖鸡,biangbiang面,镇川碗托,麻辣香锅,自助餐都吃的没啥可吃了.偶尔咥一碗麦利鸡汤刀削面或者米线凉皮沙县.不说了,这会也确实有些饿,洗个苹果吃一下. 上面这一碗就是我经常吃的biangbiang面. 今天我们主要是来看一下新闻链接的修改和新增,先上图,无图无真相. 看到了吧,这个