本文轉自: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 {
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