Asp.net MVC 3实例学习之ExtShop(五)——产品详细页

本文介绍了一个产品详细信息页面的设计过程,包括使用ASP.NET MVC实现产品信息展示、利用jQuery UI的tab控件展示不同内容区域、通过Ajax加载产品评论并实现评论的动态提交等功能。

在产品详细页需要使用到tab控件,在jquery的ui包已包含改控件,因而将相应文件链接加到母版页就可以了。

打开“ProductController”文件,在里面添加一个Details操作,代码如下:

1 public ActionResult Details ( int id )
2 {
3 var q = dc . T_Products . Single ( m = > m . ProductID = = id ) ;
4 return View ( q ) ;
5 }
6

完成后创建对应的视图页,并完成整个页面框架,代码如下:

1 @ model Extshop . Models . T_Products
2
3 @ {
4 ViewBag . Title = Model . Title ;
5 PageData [ " id " ] = Model . CategoryID ;
6 }
7
8 < div class = " nav " >
9 < a href = " @Url.Action( " " , " Catalog " ) " > 产品 < / a >
10 @ { Html . RenderAction ( " Navbar " , " Catalog " , new { id = PageData [ " id " ] } ) ; }
11 @ Html . Raw ( " >> " )
12 @ Model . Title
13 < / div > < br / >
14 < div id = " contentMain " style = " width:760px; " >
15 < span class = " header " style = " width:750px; " id = " producttitle " > @ Model . Title < / span >
16 < div class = " img " >
17 < a href = " /images/products/@Model.LargeImageUrl " rel = " lightbox " > < img src = " /images/products/@Model.SamllImageUrl " alt = " @Model.Title " width = " 170 " height = " 190 " / > < / a >
18 < / div >
19 < div class = " details " >
20 < ul >
21 < li > 市场价格: < del > @ Model . MarketPrice . ToString ( " C " ) < / del > < / li >
22 < li id = ' unitprice ' > 当前价格: @ Model . UnitPrice . ToString ( " C " ) < / li >
23 < li > < span > 用户评价: < / span >
24 < div class = ' rating ' id = ' rating1 ' >
25 < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 1 " @ ( Model . TotalRating = = 1 ? " checked='checked' " : " " ) / >
26 < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 2 " @ ( Model . TotalRating = = 2 ? " checked='checked' " : " " ) / >
27 < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 3 " @ ( Model . TotalRating = = 3 ? " checked='checked' " : " " ) / >
28 < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 4 " @ ( Model . TotalRating = = 4 ? " checked='checked' " : " " ) / >
29 < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 5 " @ ( Model . TotalRating = = 5 ? " checked='checked' " : " " ) / >
30 < / div >
31 < / li >
32 < li > 制造厂商: @ Model . Manufacturers < / li >
33 < li > 产品型号: @ Model . Model < / li >
34 < li > 库存情况: @ ( Model . Stock > 0 ? @ Html . Raw ( " color='blue'>有货 " ) : @ Html . Raw ( " color='red'>缺货 " ) ) < / li >
35 < li > < hr / > < / li >
36 < li > < a href = ' # ' class = ' cart ' onclick = ' ' > < img alt = " " width = " 50 " height = " 22 " src = ' / images / buy . jpg ' / > < / a > < / li >
37 < / ul >
38 < / div >
39 < div class = ' clear ' > < / div >
40 < div id = " tabs " style = " width:740px;margin:auto; " >
41 < ul style = " width:727px; " >
42 < li > < a href = " #tabs-1 " > 产品描述 < / a > < / li >
43 < li > < a href = " #tabs-2 " > 规格参数 < / a > < / li >
44 < li > < a href = " #tabs-3 " > 保修条款 < / a > < / li >
45 < li > < a href = " #tabs-4 " > 评论 < / a > < / li >
46 < / ul >
47 < div id = " tabs-1 " >
48 < p > @ Model . Description < / p >
49 < / div >
50 < div id = " tabs-2 " style = " border:0; " >
51 < br / > < br / >
52 < table id = " " width = " 100% " cellpadding = " 0 " cellspacing = " 0 " border = " 0 " > @ Html . Raw ( @ Model . Specification ) < / table >
53 < / div >
54 < div id = " tabs-3 " >
55 < p > @ Model . Warranty < / p >
56 < / div >
57 < div id = " tabs-4 " >
58 < / div >
59 < / div >
60 < br / >
61 < / div >
62
63
码第10行从一个分布视图获取导航信息,这个等会再创建。从第40行到59行是创建一个tab控件,评论页的内容暂时为空,等下再创建。第52行中的产品描述数据是已html代码保存在数据库的,所以要用Html的Raw方法直接显示,不需要进行编码输出。要tab控件正确显示,还需要在模版页jquery函数内加入以下代码:
1 $ ( " #tabs " ) . tabs ( ) ;

现在要完成导航信息,打开CatalogController文件,添加一个Navbar操作,代码如下:

1 [ ChildActionOnly ]
2 public ActionResult Navbar ( string id )
3 {
4 List < string > idlist = new List < string > ( ) ;
5 idlist . Add ( id ) ;
6 for ( int i = 0 ; i < ( id . Length - 2 ) ; i = i + 3 )
7 {
8 idlist . Add ( id . Substring ( 0 , i + 3 ) ) ;
9 }
10 var q = dc . T_Categories . Where ( m = > idlist . Contains ( m . CategoryID ) ) . OrderBy ( m = > m . CategoryID ) ;
11 return PartialView ( q ) ;
12 }
13

代码首先获取产品类别的父类编号,然后查询出父类进行显示。右键单击“Navbar”创建分页页面,页面的内容如下:

1 @ model IEnumerable < Extshop . Models . T_Categories >
2
3 @ {
4 foreach ( var c in Model )
5 {
6 @ Html . Raw ( " >> " ) < a href = ' @ Url . Action ( " List " , " Catalog " , new { id = c . CategoryID } ) ' > @ c . Titel < / a >
7 }
8 }

现在要完成评论的显示。评论我们使用分别页面很容易显示。首先在产品详细信息页内的id为“tabs-4”的div下添加以下代码:

1 < div style = " clear:both; " > < / div >
2 < div id = " CommentList " >
3 @ { Html . RenderAction ( " Index " , " Comment " , new { id = @ Model . ProductID , page = 1 } ) ; }
4 < / div >
5 < br / >
6 @ { Html . RenderAction ( " AddComment " , " Comment " , new { id = @ Model . ProductID } ) ; }
7

代码第3行使用一个分部页面显示评论内容。第6行就用分部页面显示评论添加表单。

新建一个名称为“CommentController”的控制器,并修改index操作代码如下:

1 public ActionResult Index ( int id , int ? page )
2 {
3 ViewData [ " ProdcutID " ] = id ;
4 PagedList < T_Comment > q = dc . T_Comment . Where ( m = > m . ProductID = = id ) . OrderByDescending ( m = > m . CreateTime ) . ToPagedList ( page ? ? 1 , 2 ) ;
5 return PartialView ( q ) ;
6 }
7

代码中第1个参数id表示的是产品的id,第2个参数是评论的当前页。和产品列表一样,使用mvcPager进行分页。完成后创建分部视图页,并将其代码修改如下:

1 @ using Webdiyer . WebControls . Mvc ;
2 @ model PagedList < Extshop . Models . T_Comment >
3 @ {
4 foreach ( var c in Model )
5 {
6 < div class = " row " >
7 < div class = " title " > @ c . Title < / div >
8 < b > @ c . Username < / b > & nbsp ; 发表于 @ ( c . CreateTime ) < br / >
9 @ c . Description
10 < / div >
11 }
12 }
13 < br / >
14 < div class = ' pagenav ' > @ Ajax . Pager ( Model , new PagerOptions { PageIndexParameterName = " page " } , new AjaxOptions { UpdateTargetId = " CommentList " } ) < / div >
15

代码中第14行使用了Ajax分页的方法,这样,就可以使用Ajax自动更新该部分。在AjaxOption中定义了UpdateTargetId参数为“CommentList”,意味着当Ajax加载数据后,会自动更新id为“CommentList”的html元素内的内容。

最后要完成的是评论添加分部视图。首先需要创建一个表单模型。在Models目录创建一个名称为“CommentModels”的类,并将类代码修改如下:

1 public class CommentModels
2 {
3
4 [ Display ( Name = " 评分 " ) ]
5 public int Rating { get ; set ; }
6
7 [ Required ( ErrorMessage = " 请输入“标题” " ) ]
8 [ Display ( Name = " 标题 " ) ]
9 public string Title { get ; set ; }
10
11 [ Required ( ErrorMessage = " 请输入“内容” " ) ]
12 [ Display ( Name = " 内容 " ) ]
13 public string Description { get ; set ; }
14
15 }
16

我们只定义需要用户输入的3个项就行了,产品编号和发表用户这些可以从其它地方获取。完成后,切换到CommentController控制器文件,添加显示表单的控制器,其代码如下:

1 [ ChildActionOnly ]
2 public ActionResult AddComment ( int id )
3 {
4 ViewData [ " ProductID " ] = id ;
5 return PartialView ( ) ;
6 }
7

在这里需要注意的是要将产品编号带到分部视图。然后创建分部视图,代码如下:

1 @ model Extshop . Models . CommentModels
2
3 @ using ( Ajax . BeginForm ( " AddComment " , " Comment " , new { id = ViewData [ " ProductID " ] } , new AjaxOptions { OnSuccess = " CommentSuccess " , LoadingElementId = " CommentLoad " , UpdateTargetId = " CommentMsg "
4 , OnBegin = " CommentBegin " } , new { id = " CommentForm " } ) )
5 {
6 < div >
7 < fieldset >
8 < legend > < / legend >
9 < div style = " width:600px;display:block;height:30px; " >
10 < div id = ' rating - select ' style = " width:300px; " >
11 @ Html . LabelFor ( m = > m . Rating )
12 @ Html . DropDownListFor ( m = > m . Rating , new SelectList ( new Dictionary < string , string > {
13 { " 1 " , " 1 " } ,
14 { " 2 " , " 2 " } ,
15 { " 3 " , " 3 " } ,
16 { " 4 " , " 4 " } ,
17 { " 5 " , " 5 " }
18 } , " Key " , " Value " ) , new { @ class = " star " , width = " 120 " } )
19 < / div >
20 < div class = " error " >
21 @ Html . ValidationMessageFor ( m = > m . Rating )
22 < / div >
23 < / div >
24 < p style = " width:600px;display:block; " >
25 @ Html . LabelFor ( m = > m . Title )
26 @ Html . TextBoxFor ( m = > m . Title , new { style = " width:500px; " } )
27 < / p >
28 < div class = " error " >
29 @ Html . ValidationMessageFor ( m = > m . Title )
30 < / div >
31 < p style = " width:600px;display:block; " >
32 @ Html . LabelFor ( m = > m . Description )
33 @ Html . TextAreaFor ( m = > m . Description , new { style = " width:500px; " } )
34 < / p >
35 < div class = " error " >
36 @ Html . ValidationMessageFor ( m = > m . Description )
37 < / div >
38 < p style = " text-align:center;width:600px; " >
39 < input id = " ComentSubmit " type = " submit " value = " 保存 " / >
40 < / p >
41 < p style = " text-align:center;display:none; " id = " CommentLoad " > < img src = " /Images/blue-loading.gif " alt = " 正在保存…… " / > < / p >
42 < p style = " text-align:center;color:Red; " id = " CommentMsg " > < / p >
43 < / fieldset >
44 < / div >
45 }
46
47 < script type = " text/javascript " >
48 function CommentSuccess ( e ) {
49 $ ( " #CommentForm input " ) . removeAttr ( " readonly " ) ;
50 $ ( " #CommentSubmit " ) . removeAttr ( " disabled " ) ;
51 if ( e . Success ) {
52 $ ( " #CommentForm " ) [ 0 ] . reset ( ) ;
53 $ ( " #CommentMsg " ) . html ( e . Message ) ;
54 var url = window . location ;
55 re = / ( [ 0 - 9 ] * ) [ # ] ? $ / ig ;
56 var r = re . exec ( url )
57 if ( r ) {
58 for ( var i = 0 ; i < r . length - 1 ; i + + ) {
59 if ( ! isNaN ( r [ i ] ) ) {
60 $ ( " #CommentList " ) . load ( " /Comment/ " + r [ i ] + " /1 " ) ;
61 }
62 }
63 }
64 } else {
65 $ ( " #CommentMsg " ) . html ( e . Message ) ;
66 }
67 }
68
69 function CommentBegin ( e ) {
70 $ ( " #CommentForm input " ) . attr ( " readonly " , true ) ;
71 $ ( " #CommentSubmit " ) . attr ( " disabled " , " disabled " ) ;
72 $ ( " #CommentMsg " ) . html ( " " ) ;
73 }
74
75 < / script >

表单将已Ajax的方式提交,所以在这里使用的是Ajax.BeginForm,而不是Html.BeginForm。表单提交的路径将会是“/Comment/AddComment/{id}”,其中的id是产品的编号。代码第12行到18行将创建一个select元素用来生成评价输入控件。代码54行到62行的作用是评论保存后,通过页面路径获取产品编号,然后通过Ajax更新一下评论分部视图的显示。

余下的工作是完成评论保存控制器,其代码如下:

1 [ HttpPost ]
2 public JsonResult AddComment ( int id , CommentModels model )
3 {
4 if ( ModelState . IsValid )
5 {
6 if ( User . Identity . IsAuthenticated )
7 {
8 try
9 {
10 T_Comment comment = new T_Comment ( ) ;
11 comment . Description = model . Description ;
12 comment . ProductID = id ;
13 comment . Rating = model . Rating ;
14 comment . Title = model . Title ;
15 comment . Username = User . Identity . Name ;
16 comment . CreateTime = DateTime . Now ;
17 try
18 {
19 dc . T_Comment . InsertOnSubmit ( comment ) ;
20 dc . SubmitChanges ( ) ;
21 return Json ( new { Success = true , Message = " 评论已保存! " } , JsonRequestBehavior . AllowGet ) ;
22 }
23 catch ( Exception e )
24 {
25 return Json ( new { Success = false , Message = " 评论保存失败:数据错误! " } , JsonRequestBehavior . AllowGet ) ;
26 }
27 }
28 catch
29 {
30 return Json ( new { Success = false , Message = " 评论保存失败:数据错误! " } , JsonRequestBehavior . AllowGet ) ;
31 }
32 }
33 else
34 {
35 return Json ( new { Success = false , Message = " 评论保存失败:请先登录! " } , JsonRequestBehavior . AllowGet ) ;
36 }
37 }
38 return Json ( new { Success = false , Message = " 添加评论失败:提交的数据存在错误! " } , JsonRequestBehavior . AllowGet ) ;
39 }
40

代码第1行表示改操作是接收Post的操作。AddComment操作将接收两个参数,第1个是产品编号,第2个是用户提交的评论内容。因为使用Ajax提交,所以该操作不需要返回视图,只需要返回Json数据,所以操作的返回值是JsonResult。第4句判断用户的输入是否符合要求。第6句判断用户是否已经登录,如果没有登录,发送错误信息提示用户登录。

这样,整个产品详细信息页就完成了。不过,要使程序正常运行,还需要修改路由表,打开Global.asax.cs文件,在路由中加入以下路由:

1 routes . MapRoute (
2 " Comment1 " , // Route name
3 " Comment/AddComment/{id} " , // URL with parameters
4 new { controller = " Comment " , action = " AddComment " , id = 1 } // Parameter defaults
5 ) ;
6
7 routes . MapRoute (
8 " Comment " , // Route name
9 " Comment/{id}/{page} " , // URL with parameters
10 new { controller = " Comment " , action = " Index " , page = 1 } // Parameter defaults
11 ) ;
12

第1个路由指示添加评论是如何路由的,如果没有这个,则全部会按第2个路由执行,全部操作转到Index操作去了,这样就会发生错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值