您的位置:首页 > 编程语言 > ASP

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

2011-01-23 14:38 471 查看
在产品详细页需要使用到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操作去了,这样就会发生错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: