在产品详细页需要使用到tab控件,在jquery的ui包已包含改控件,因而将相应文件链接加到母版页就可以了。
打开“ProductController”文件,在里面添加一个Details操作,代码如下:
- public ActionResult Details ( int id )
- {
- var q = dc . T_Products . Single ( m = > m . ProductID = = id ) ;
- return View ( q ) ;
- }
完成后创建对应的视图页,并完成整个页面框架,代码如下:
- @ model Extshop . Models . T_Products
- @ {
- ViewBag . Title = Model . Title ;
- PageData [ " id " ] = Model . CategoryID ;
- }
- < div class = " nav " >
- < a href = " @Url.Action( " " , " Catalog " ) " > 产品 < / a >
- @ { Html . RenderAction ( " Navbar " , " Catalog " , new { id = PageData [ " id " ] } ) ; }
- @ Html . Raw ( " >> " )
- @ Model . Title
- < / div > < br / >
- < div id = " contentMain " style = " width:760px; " >
- < span class = " header " style = " width:750px; " id = " producttitle " > @ Model . Title < / span >
- < div class = " img " >
- < a href = " /images/products/@Model.LargeImageUrl " rel = " lightbox " > < img src = " /images/products/@Model.SamllImageUrl " alt = " @Model.Title " width = " 170 " height = " 190 " / > < / a >
- < / div >
- < div class = " details " >
- < ul >
- < li > 市场价格: < del > @ Model . MarketPrice . ToString ( " C " ) < / del > < / li >
- < li id = ' unitprice ' > 当前价格: @ Model . UnitPrice . ToString ( " C " ) < / li >
- < li > < span > 用户评价: < / span >
- < div class = ' rating ' id = ' rating1 ' >
- < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 1 " @ ( Model . TotalRating = = 1 ? " checked='checked' " : " " ) / >
- < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 2 " @ ( Model . TotalRating = = 2 ? " checked='checked' " : " " ) / >
- < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 3 " @ ( Model . TotalRating = = 3 ? " checked='checked' " : " " ) / >
- < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 4 " @ ( Model . TotalRating = = 4 ? " checked='checked' " : " " ) / >
- < input name = " @Model.ProductID.ToString( " Star0 " ) " type = " radio " class = " star " disabled = " disabled " value = " 5 " @ ( Model . TotalRating = = 5 ? " checked='checked' " : " " ) / >
- < / div >
- < / li >
- < li > 制造厂商: @ Model . Manufacturers < / li >
- < li > 产品型号: @ Model . Model < / li >
- < li > 库存情况: @ ( Model . Stock > 0 ? @ Html . Raw ( " color='blue'>有货 " ) : @ Html . Raw ( " color='red'>缺货 " ) ) < / li >
- < li > < hr / > < / li >
- < li > < a href = ' # ' class = ' cart ' onclick = ' ' > < img alt = " " width = " 50 " height = " 22 " src = ' / images / buy . jpg ' / > < / a > < / li >
- < / ul >
- < / div >
- < div class = ' clear ' > < / div >
- < div id = " tabs " style = " width:740px;margin:auto; " >
- < ul style = " width:727px; " >
- < li > < a href = " #tabs-1 " > 产品描述 < / a > < / li >
- < li > < a href = " #tabs-2 " > 规格参数 < / a > < / li >
- < li > < a href = " #tabs-3 " > 保修条款 < / a > < / li >
- < li > < a href = " #tabs-4 " > 评论 < / a > < / li >
- < / ul >
- < div id = " tabs-1 " >
- < p > @ Model . Description < / p >
- < / div >
- < div id = " tabs-2 " style = " border:0; " >
- < br / > < br / >
- < table id = " " width = " 100% " cellpadding = " 0 " cellspacing = " 0 " border = " 0 " > @ Html . Raw ( @ Model . Specification ) < / table >
- < / div >
- < div id = " tabs-3 " >
- < p > @ Model . Warranty < / p >
- < / div >
- < div id = " tabs-4 " >
- < / div >
- < / div >
- < br / >
- < / div >
码第10行从一个分布视图获取导航信息,这个等会再创建。从第40行到59行是创建一个tab控件,评论页的内容暂时为空,等下再创建。第52行中的产品描述数据是已html代码保存在数据库的,所以要用Html的Raw方法直接显示,不需要进行编码输出。要tab控件正确显示,还需要在模版页jquery函数内加入以下代码:
- $ ( " #tabs " ) . tabs ( ) ;
现在要完成导航信息,打开CatalogController文件,添加一个Navbar操作,代码如下:
- [ ChildActionOnly ]
- public ActionResult Navbar ( string id )
- {
- List < string > idlist = new List < string > ( ) ;
- idlist . Add ( id ) ;
- for ( int i = 0 ; i < ( id . Length - 2 ) ; i = i + 3 )
- {
- idlist . Add ( id . Substring ( 0 , i + 3 ) ) ;
- }
- var q = dc . T_Categories . Where ( m = > idlist . Contains ( m . CategoryID ) ) . OrderBy ( m = > m . CategoryID ) ;
- return PartialView ( q ) ;
- }
代码首先获取产品类别的父类编号,然后查询出父类进行显示。右键单击“Navbar”创建分页页面,页面的内容如下:
- @ model IEnumerable < Extshop . Models . T_Categories >
- @ {
- foreach ( var c in Model )
- {
- @ Html . Raw ( " >> " ) < a href = ' @ Url . Action ( " List " , " Catalog " , new { id = c . CategoryID } ) ' > @ c . Titel < / a >
- }
- }
现在要完成评论的显示。评论我们使用分别页面很容易显示。首先在产品详细信息页内的id为“tabs-4”的div下添加以下代码:
- < div style = " clear:both; " > < / div >
- < div id = " CommentList " >
- @ { Html . RenderAction ( " Index " , " Comment " , new { id = @ Model . ProductID , page = 1 } ) ; }
- < / div >
- < br / >
- @ { Html . RenderAction ( " AddComment " , " Comment " , new { id = @ Model . ProductID } ) ; }
代码第3行使用一个分部页面显示评论内容。第6行就用分部页面显示评论添加表单。
新建一个名称为“CommentController”的控制器,并修改index操作代码如下:
- public ActionResult Index ( int id , int ? page )
- {
- ViewData [ " ProdcutID " ] = id ;
- PagedList < T_Comment > q = dc . T_Comment . Where ( m = > m . ProductID = = id ) . OrderByDescending ( m = > m . CreateTime ) . ToPagedList ( page ? ? 1 , 2 ) ;
- return PartialView ( q ) ;
- }
代码中第1个参数id表示的是产品的id,第2个参数是评论的当前页。和产品列表一样,使用mvcPager进行分页。完成后创建分部视图页,并将其代码修改如下:
- @ using Webdiyer . WebControls . Mvc ;
- @ model PagedList < Extshop . Models . T_Comment >
- @ {
- foreach ( var c in Model )
- {
- < div class = " row " >
- < div class = " title " > @ c . Title < / div >
- < b > @ c . Username < / b > & nbsp ; 发表于 @ ( c . CreateTime ) < br / >
- @ c . Description
- < / div >
- }
- }
- < br / >
- < div class = ' pagenav ' > @ Ajax . Pager ( Model , new PagerOptions { PageIndexParameterName = " page " } , new AjaxOptions { UpdateTargetId = " CommentList " } ) < / div >
代码中第14行使用了Ajax分页的方法,这样,就可以使用Ajax自动更新该部分。在AjaxOption中定义了UpdateTargetId参数为“CommentList”,意味着当Ajax加载数据后,会自动更新id为“CommentList”的html元素内的内容。
最后要完成的是评论添加分部视图。首先需要创建一个表单模型。在Models目录创建一个名称为“CommentModels”的类,并将类代码修改如下:
- public class CommentModels
- {
- [ Display ( Name = " 评分 " ) ]
- public int Rating { get ; set ; }
- [ Required ( ErrorMessage = " 请输入“标题” " ) ]
- [ Display ( Name = " 标题 " ) ]
- public string Title { get ; set ; }
- [ Required ( ErrorMessage = " 请输入“内容” " ) ]
- [ Display ( Name = " 内容 " ) ]
- public string Description { get ; set ; }
- }
我们只定义需要用户输入的3个项就行了,产品编号和发表用户这些可以从其它地方获取。完成后,切换到CommentController控制器文件,添加显示表单的控制器,其代码如下:
- [ ChildActionOnly ]
- public ActionResult AddComment ( int id )
- {
- ViewData [ " ProductID " ] = id ;
- return PartialView ( ) ;
- }
在这里需要注意的是要将产品编号带到分部视图。然后创建分部视图,代码如下:
- @ model Extshop . Models . CommentModels
- @ using ( Ajax . BeginForm ( " AddComment " , " Comment " , new { id = ViewData [ " ProductID " ] } , new AjaxOptions { OnSuccess = " CommentSuccess " , LoadingElementId = " CommentLoad " , UpdateTargetId = " CommentMsg "
- , OnBegin = " CommentBegin " } , new { id = " CommentForm " } ) )
- {
- < div >
- < fieldset >
- < legend > < / legend >
- < div style = " width:600px;display:block;height:30px; " >
- < div id = ' rating - select ' style = " width:300px; " >
- @ Html . LabelFor ( m = > m . Rating )
- @ Html . DropDownListFor ( m = > m . Rating , new SelectList ( new Dictionary < string , string > {
- { " 1 " , " 1 " } ,
- { " 2 " , " 2 " } ,
- { " 3 " , " 3 " } ,
- { " 4 " , " 4 " } ,
- { " 5 " , " 5 " }
- } , " Key " , " Value " ) , new { @ class = " star " , width = " 120 " } )
- < / div >
- < div class = " error " >
- @ Html . ValidationMessageFor ( m = > m . Rating )
- < / div >
- < / div >
- < p style = " width:600px;display:block; " >
- @ Html . LabelFor ( m = > m . Title )
- @ Html . TextBoxFor ( m = > m . Title , new { style = " width:500px; " } )
- < / p >
- < div class = " error " >
- @ Html . ValidationMessageFor ( m = > m . Title )
- < / div >
- < p style = " width:600px;display:block; " >
- @ Html . LabelFor ( m = > m . Description )
- @ Html . TextAreaFor ( m = > m . Description , new { style = " width:500px; " } )
- < / p >
- < div class = " error " >
- @ Html . ValidationMessageFor ( m = > m . Description )
- < / div >
- < p style = " text-align:center;width:600px; " >
- < input id = " ComentSubmit " type = " submit " value = " 保存 " / >
- < / p >
- < p style = " text-align:center;display:none; " id = " CommentLoad " > < img src = " /Images/blue-loading.gif " alt = " 正在保存…… " / > < / p >
- < p style = " text-align:center;color:Red; " id = " CommentMsg " > < / p >
- < / fieldset >
- < / div >
- }
- < script type = " text/javascript " >
- function CommentSuccess ( e ) {
- $ ( " #CommentForm input " ) . removeAttr ( " readonly " ) ;
- $ ( " #CommentSubmit " ) . removeAttr ( " disabled " ) ;
- if ( e . Success ) {
- $ ( " #CommentForm " ) [ 0 ] . reset ( ) ;
- $ ( " #CommentMsg " ) . html ( e . Message ) ;
- var url = window . location ;
- re = / ( [ 0 - 9 ] * ) [ # ] ? $ / ig ;
- var r = re . exec ( url )
- if ( r ) {
- for ( var i = 0 ; i < r . length - 1 ; i + + ) {
- if ( ! isNaN ( r [ i ] ) ) {
- $ ( " #CommentList " ) . load ( " /Comment/ " + r [ i ] + " /1 " ) ;
- }
- }
- }
- } else {
- $ ( " #CommentMsg " ) . html ( e . Message ) ;
- }
- }
- function CommentBegin ( e ) {
- $ ( " #CommentForm input " ) . attr ( " readonly " , true ) ;
- $ ( " #CommentSubmit " ) . attr ( " disabled " , " disabled " ) ;
- $ ( " #CommentMsg " ) . html ( " " ) ;
- }
- < / script >
表单将已Ajax的方式提交,所以在这里使用的是Ajax.BeginForm,而不是Html.BeginForm。表单提交的路径将会是“/Comment/AddComment/{id}”,其中的id是产品的编号。代码第12行到18行将创建一个select元素用来生成评价输入控件。代码54行到62行的作用是评论保存后,通过页面路径获取产品编号,然后通过Ajax更新一下评论分部视图的显示。
- [ HttpPost ]
- public JsonResult AddComment ( int id , CommentModels model )
- {
- if ( ModelState . IsValid )
- {
- if ( User . Identity . IsAuthenticated )
- {
- try
- {
- T_Comment comment = new T_Comment ( ) ;
- comment . Description = model . Description ;
- comment . ProductID = id ;
- comment . Rating = model . Rating ;
- comment . Title = model . Title ;
- comment . Username = User . Identity . Name ;
- comment . CreateTime = DateTime . Now ;
- try
- {
- dc . T_Comment . InsertOnSubmit ( comment ) ;
- dc . SubmitChanges ( ) ;
- return Json ( new { Success = true , Message = " 评论已保存! " } , JsonRequestBehavior . AllowGet ) ;
- }
- catch ( Exception e )
- {
- return Json ( new { Success = false , Message = " 评论保存失败:数据错误! " } , JsonRequestBehavior . AllowGet ) ;
- }
- }
- catch
- {
- return Json ( new { Success = false , Message = " 评论保存失败:数据错误! " } , JsonRequestBehavior . AllowGet ) ;
- }
- }
- else
- {
- return Json ( new { Success = false , Message = " 评论保存失败:请先登录! " } , JsonRequestBehavior . AllowGet ) ;
- }
- }
- return Json ( new { Success = false , Message = " 添加评论失败:提交的数据存在错误! " } , JsonRequestBehavior . AllowGet ) ;
- }
代码第1行表示改操作是接收Post的操作。AddComment操作将接收两个参数,第1个是产品编号,第2个是用户提交的评论内容。因为使用Ajax提交,所以该操作不需要返回视图,只需要返回Json数据,所以操作的返回值是JsonResult。第4句判断用户的输入是否符合要求。第6句判断用户是否已经登录,如果没有登录,发送错误信息提示用户登录。
这样,整个产品详细信息页就完成了。不过,要使程序正常运行,还需要修改路由表,打开Global.asax.cs文件,在路由中加入以下路由:
- routes . MapRoute (
- " Comment1 " , // Route name
- " Comment/AddComment/{id} " , // URL with parameters
- new { controller = " Comment " , action = " AddComment " , id = 1 } // Parameter defaults
- ) ;
- routes . MapRoute (
- " Comment " , // Route name
- " Comment/{id}/{page} " , // URL with parameters
- new { controller = " Comment " , action = " Index " , page = 1 } // Parameter defaults
- ) ;
第1个路由指示添加评论是如何路由的,如果没有这个,则全部会按第2个路由执行,全部操作转到Index操作去了,这样就会发生错误。