[转]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.UseNoFROM Bonus.dbo.[User] A WITH(NOLOCK)LEFT JOIN Bonus.dbo.UerInfo B WITH(NOLOCK) ON A.UseNo = B.UseNoWHERE (@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 @UserTempTableSELECT UseNo, Name, Age, MarriedFROM( 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) NWHERE 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 { get; set; } [DataMapping("Name", DbType.AnsiString)] public string UserName { get; set; } [DataMapping("Age", DbType.Int32)] public int Age { get; set; } [DataMapping("Married", DbType.String)] public string Married { get; set; } }} |
在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
[转]ASP.NET MVC4+BootStrap 实战(一)的更多相关文章
- ASP.NET MVC4+BootStrap 实战(一)
好久没有写关于web开发的文章了,进到这个公司一直就是winform和Silverlight,实在是没有实战web项目的机会.大D也辞职了,去搞web app了.自己也该闲暇时间多学习学习,每天进步一 ...
- 介绍我最近做的网站 Asp.Net MVC4 + BootStrap
一.前言 最近一直在做一个多站SEO数据分析的站点(www.easyyh.com),用了一些新技术,如Asp.Net MVC4,BootStrap,EasyUI,这些都是以前没有搞过的,最近搞得差不多 ...
- ASP.NET MVC4企业级实战目录
http://www.cnblogs.com/jiekzou/p/5625762.html#!comments ******************************************** ...
- Asp.Net MVC4 + Oracle + EasyUI + Bootstrap
Asp.Net MVC4 + Oracle + EasyUI + Bootstrap --操作数据和验证 本文链接:http://www.cnblogs.com/likeli/p/4234238.ht ...
- Asp.net MVC4 Knockoutjs BootStrap Ace NinJect Jqgrid sqlserver2008
Asp.net MVC4 Knockoutjs BootStrap Ace NinJect Jqgrid sqlserver2008
- Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 1
Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 序章 Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 序章 -- 新建微软实 ...
- 使用bootstrap+asp.net mvc4+IBatis.Net实现的小程序
这个项目用到了三个技术点 1.bootstap 3.0 2.asp.net mvc4 3.IBatis.Net 这个三个技术点分别解决前端界面展示.中间mvc路由控制.实体框架映射数据访问 重点分页问 ...
- ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存
ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 part 1:给我点时间,允许我感慨一下2016年 正好有时间,总结一下最近使用的一些技术,也算是为2016年画上一个完 ...
- Asp.Net Core 项目实战之权限管理系统(0) 无中生有
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
随机推荐
- 【NodeJS 学习笔记01】不学就老了
前言 再不学nodeJs,我们就老了......在HTML5大浪袭来的时候,很多先辈就开始了NodeJs之旅,而那时我还在做服务器端的程序后来转成前端,和梯队的距离已经很大了,因为我会服务器端语言,还 ...
- 【iScroll源码学习03】iScroll事件机制与滚动条的实现
前言 想不到又到周末了,周末的时间要抓紧学习才行,前几天我们学习了iScroll几点基础知识: 1. [iScroll源码学习02]分解iScroll三个核心事件点 2. [iScroll源码学习01 ...
- 浅析字符串操作方法slice、substr、substring及其IE兼容性
在截取字符串时常常会用到substr().substring().slice()方法,有时混淆之间的用法,故总结下. slice() 定义:接受一个或者两个参数,第一个参数指定子字符串的开始位置. ...
- iOS开发-canOpenURL: failed for URL: "xx" - error:"This app is not allowed to query for scheme xx"
转载自:http://www.jianshu.com/p/e38a609f786e
- 听云数据库管理平台NetopGO简介
➠更多技术干货请戳:听云博客 断断续续写了将近一个月,听云第一版数据库管理平台终于写完了,期间来来回回的改了好多次小毛病,现在已经部署到生产环境上去了. 在刚开始的时候,后端的数据库集群只有10多个节 ...
- 安装和使用cocoapods
第一步:查看自己电脑的Ruby环境:gem sources -l 1.如果已经是taobao镜像了[https://ruby.taobao.org/],此时不需要环境的修改了,直接进入第二步 2.(1 ...
- 【Android市场】提交应用的一点经验分享
前言 如果只有一个或者少许的两三个Android市场,本文也没用存在的必要性,本文谨献给同在Android奋战的同仁. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnbl ...
- java反射机制一个例子
import java.lang.reflect.*; public class DumpMethods { public static void main(String args[]) { try ...
- 十大广泛使用的Linux发行版
回到上世纪90年代,Mandrake Linux还是唯一的Linux发行版:而今天,Linux发行版的数量变得数不胜数.本文为大家整理出了十大广泛使用的Linux发行版,希望能帮助大家在选择合适的Li ...
- igraph安装(R/Python)
python-igraph:啥都不说了,用Ubuntu吧,虽然按照官方的流程还是会出错,但是排错会比较少,一般找不了多久就能找到解决方案 R-igraph:一般需要升级R版本,用3.3吧.升级R的方法 ...