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

在产品详细页需要使用到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. }   

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

  
  
  
  
  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 >  

码第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. }   

代码首先获取产品类别的父类编号,然后查询出父类进行显示。右键单击“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 } ) ; }   

代码第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. }   

代码中第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 >   

代码中第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. }  

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

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

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

  
  
  
  
  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. }   

代码第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. ) ;   

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

你可能感兴趣的:(jquery,产品,ExtShop)