[轉]ASP.NET MVC4+BootStrap 實戰(一)


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

 

好久沒有寫關於web開發的文章了,進到這個公司一直就是winform和Silverlight,實在是沒有實戰web項目的機會。大D也辭職了,去搞web app了。自己也該閑暇時間多學習學習,每天進步一點點。

 

OK,不多說了,看一下Solution的截圖

wKiom1SEGYbjvyd9AACadjvVi1Q564.jpg

基本上一看就明白了,控制器調用Biz層,Biz層調用DAL層,DAL層進行數據的CURD。Utility是一些公用的類庫。ok,為什么程序集的命名都是以Bruce開頭呢,因為我在公司的英文名叫這個。廢話不多說,我們先看一下頁面

wKiom1SEGqCST0eWAAFI-YZmIi4175.jpg

我們引入了BootStrap,主要是為了頁面布局。在Views中Partial下面放的都是部分頁。

我們先看一下運行效果,今天主要是講頁面初始化部分。

wKioL1SEHMmQN3aBAAJuC6gCl4I512.jpg

其實查詢條件就是婚否,出生日期,姓名的模糊查詢。我們先看一下頁面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的網格系統,看如下的解釋

wKiom1SEHgqig1sEAAL6wBcgw9U665.jpg

 

OK,我們怎么看是否是響應式的布局呢,我們打開谷歌瀏覽器,現將瀏覽器縮小到一定程度。

wKioL1SEH9rgdj-jAAHg2oPG2L8475.jpg

看到了吧,即使設備瀏覽器這么小,我們還是能用。那我們在手機模擬器中測試一下,打開谷歌瀏覽器,按F12,點擊手機模擬器樣的東西,然后Device選擇iphone6。

wKiom1SEIAngkqOvAAMP1bmprLg719.jpg

我們看到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程序集下。

wKioL1SELgGinSrUAABc8KMeEz0396.jpg

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM