好久没有写关于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://blog.51cto.com/leelei/1587301

ASP.NET MVC4+BootStrap 实战(一)的更多相关文章

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

    本文转自:http://leelei.blog.51cto.com/856755/1587301 好久没有写关于web开发的文章了,进到这个公司一直就是winform和Silverlight,实在是没 ...

  2. 介绍我最近做的网站 Asp.Net MVC4 + BootStrap

    一.前言 最近一直在做一个多站SEO数据分析的站点(www.easyyh.com),用了一些新技术,如Asp.Net MVC4,BootStrap,EasyUI,这些都是以前没有搞过的,最近搞得差不多 ...

  3. ASP.NET MVC4企业级实战目录

    http://www.cnblogs.com/jiekzou/p/5625762.html#!comments ******************************************** ...

  4. Asp.Net MVC4 + Oracle + EasyUI + Bootstrap

    Asp.Net MVC4 + Oracle + EasyUI + Bootstrap --操作数据和验证 本文链接:http://www.cnblogs.com/likeli/p/4234238.ht ...

  5. Asp.net MVC4 Knockoutjs BootStrap Ace NinJect Jqgrid sqlserver2008

    Asp.net MVC4 Knockoutjs  BootStrap Ace NinJect  Jqgrid sqlserver2008

  6. Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 1

    Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 序章 Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 序章 -- 新建微软实 ...

  7. 使用bootstrap+asp.net mvc4+IBatis.Net实现的小程序

    这个项目用到了三个技术点 1.bootstap 3.0 2.asp.net mvc4 3.IBatis.Net 这个三个技术点分别解决前端界面展示.中间mvc路由控制.实体框架映射数据访问 重点分页问 ...

  8. ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存

    ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 part 1:给我点时间,允许我感慨一下2016年 正好有时间,总结一下最近使用的一些技术,也算是为2016年画上一个完 ...

  9. Asp.Net Core 项目实战之权限管理系统(0) 无中生有

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

随机推荐

  1. maven更换阿里云仓库

    本来不想写,网上到处都是,不过好多到我这不行,自己记录下,省的到处找 D:\apache-maven-3.6.1\conf目录下setting.xml文件(这是我的解压的位置) <mirrors ...

  2. 常用公共DNS服务器地址

    DNS,全称Domain Name System,即域名解析系统,帮助用户在互联网上寻找路径,它在互联网的作用是把域名转换成为网络可以识别的IP地址.目前国内电信运营商通过使用DNS劫持和DNS污染的 ...

  3. Java开发笔记(一百零四)普通线程池的运用

    前面介绍了线程的基本用法,以及多线程并发的问题处理,但实际开发中往往存在许多性质相似的任务,比如批量发送消息.批量下载文件.批量进行交易等等.这些同类任务的处理流程一致,不存在资源共享问题,相互之间也 ...

  4. JDK1.5新特性:

    1.自动装箱与拆箱: 自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中. 自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取出来,没必要再去调用i ...

  5. Working With Push Buttons In Oracle Forms

    Managing push buttons at run time in Oracle Forms is very simple and in this tutorial you will learn ...

  6. C# 格式化 中文星期 显示

    最近有些小忙,直接贴代码吧, /// <summary> /// 获取系统的星期 /// </summary> /// <param name="dt" ...

  7. 【spring boot】6.idea下springboot打包成jar包和war包,并且可以在外部tomcat下运行访问到

    接着上一章走呗:http://www.cnblogs.com/sxdcgaq8080/p/7712874.html 然后声明一点,下面打包的过程中,scope一直都是使用默认的范围 <!--用于 ...

  8. Ubuntu -- 配置Nginx和https及frp

    使用 sudo apt -get nginx安装最方便. 要确认80端口未被占用. 上传域名的证书. 然后要配置nginx配置文件.

  9. mac 配置sencha touch环境

    1 安装 java 2 安装 node js 为使用npm作准备 3 用npm命令安装 cordova npm install -g cordova

  10. DB2 SQL Error: SQLCODE=-805, SQLSTATE=51002 解决方法

    在操作大量数据时如果发生这种错误,说明不是db2 使用的 package没有绑定,而是 因为资源未释放,导致可以使用此package的资源不足,致使不能连接资源. 在程序中,对PreparedStat ...