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

Microsoft Press

A Division of Microsoft Corporation


One Microsoft Way
Redmond, Washington 98052-6399
Copyright 2011 by Microsoft Corporation
.
- - .
(LCCN): 2010934433
Microsoft Press .

Microsoft Press
International (425) 936-7329. - www.microsoft.com/mspress.
mspinput@microsoft.com.
Microsoft

http://www.microsoft.com/about/legal/en/us/IntellectualProperty/ Trademarks/EN-US.aspx,
.
.
, , , ,
, , ,
, , , ,
, , , .
. , ,
- , . ,
,
, .
: Tom Draper Design
Body Part No. X17-13257


.............................................................................................................................................................................. viii
? ........................................................................................................................................................ viii
? ............................................................................................................................................................. viii
Visual Studio 2010? .............................................................................................. viii
.......................................................................................................... viii
- ............................................................................................................................................... ix
.................................................................................................................................................... ix
Plan My Night ................................................................................................................ ix
Plan My Night? ................................................................................................................................................. ix
Visual Studio 2010? ....................................................................................................................... xi
.................................................................................................................................................... xii
Microsoft Visual Studio 2003 Visual Studio 2010 ......................................................................................... 13
2003 2010: - ........................................................................................................................... 14
............................................................................................................................................... 14
Plan My Night Microsoft Visual Studio 2003 .................................................................................................. 15
Visual Studio 2003 Entity Framework............................................................. 16
EF: .................................................................................................................. 16
.................................................................................................... 19
................................................................................................ 24
EF: ...................................................................................................................................................... 26
........................................................................ 29
POCO- ........................................................................................................................................................... 32
ADO.NET POCO Entity Generator ................................................................................................................ 32
.................................................................................................... 34
............................................................................................................................................................ 35
........................................................................................................................... 35
- Bing Maps ......................................................................................................... 39
.................................................................................................................. 41
AppFabric .............................................................................................................................................. 42
...................................................................................................................................................................... 43
2003 2010: ........................................................................................ 44
PlanMyNight.Web ............................................................................................................................ 44
............................................................................................................................................................. 45
.......................................................................................................................... 46
.................................................................................................................................. 47
................................................................................................................................... 48
.................................................................................................... 52
..................................................................................................................................... 54
...................................................................................................................... 58

- ................................................................................................... 63
MEF ................................................................................................................... 70
............................................................................. 71
...................................................................................................................................................................... 73
2003 2010: ................................................................................................................................ 74
Visual Studio 2010 ................................................................................................................... 74
..................................................................................................................................... 75
......................................................................................................................................................... 78
....................................................................................................................... 81
Web.Config ....................................................................................................................................... 84
.................................................................................................................................... 84
Threads...................................................................................................................................................... 88
...................................................................................................................................................................... 88
2003 2010: ..................................................................................................................... 90
, Visual Studio 2010................................................................................. 90
Visual Studio 2010 ........................................................................................................ 91
Visual Studio 2010.................................................................................................................. 91
Web Deployment Packages? ........................................................................................................................ 94
One-Click ................................................................................................................................................. 96
...................................................................................................................................................................... 97
Microsoft Visual Studio 2005 Visual Studio 2010 ......................................................................................... 99
2005 2010: - ......................................................................................................................... 100
............................................................................................................................................. 100
Plan My Night Microsoft Visual Studio 2005 ................................................................................................ 101
Visual Studio 2010 Entity Framework........................................................... 103
EF: ................................................................................................................ 103
.................................................................................................. 106
.............................................................................................. 111
EF: .................................................................................................................................................... 113
...................................................................... 116
POCO- ......................................................................................................................................................... 119
ADO.NET POCO Entity Generator .............................................................................................................. 119
.................................................................................................. 121
.......................................................................................................................................................... 122
......................................................................................................................... 122
- Bing Maps ....................................................................................................... 125
................................................................................................................ 127
AppFabric ............................................................................................................................................ 128
.................................................................................................................................................................... 129
2005 2010: ...................................................................................... 130
PlanMyNight.Web .......................................................................................................................... 130

........................................................................................................................................................... 131
........................................................................................................................ 132
................................................................................................................................ 133
................................................................................................................................. 134
.................................................................................................. 138
................................................................................................................................... 140
.................................................................................................................... 144
- ................................................................................................. 149
MEF ................................................................................................................. 156
........................................................................... 157
.................................................................................................................................................................... 159
2005 2010: .............................................................................................................................. 160
Visual Studio 2010 ................................................................................................................. 160
................................................................................................................................... 161
....................................................................................................................................................... 163
..................................................................................................................... 167
Web.Config ..................................................................................................................................... 170
.................................................................................................................................. 170
Threads.................................................................................................................................................... 174
.................................................................................................................................................................... 174
Microsoft Visual Studio 2008 Visual Studio 2010 ....................................................................................... 176
2008 2010: - ......................................................................................................................... 177
............................................................................................................................................. 177
PlanMyNight Microsoft Visual Studio 2008 .................................................................................................. 178
Visual Studio 2008 Entity Framework........................................................... 180
EF: ................................................................................................................ 181
.................................................................................................. 184
.............................................................................................. 189
EF: .................................................................................................................................................... 191
...................................................................... 195
POCO- ......................................................................................................................................................... 197
ADO.NET POCO Entity Generator .............................................................................................................. 197
.................................................................................................. 199
.......................................................................................................................................................... 200
......................................................................................................................... 200
................................................................................................................ 202
AppFabric ............................................................................................................................................ 203
.................................................................................................................................................................... 205
2008 2010: ...................................................................................... 206
PlanMyNight.Web .......................................................................................................................... 206
........................................................................................................................................................... 208

........................................................................................................................ 208
................................................................................................................................ 209
................................................................................................................................. 211
.................................................................................................. 214
................................................................................................................................... 215
.................................................................................................................... 220
- ................................................................................................. 225
MEF ................................................................................................................. 231
........................................................................... 233
.................................................................................................................................................................... 234
2008 2010: .............................................................................................................................. 235
Visual Studio 2010 ................................................................................................................. 235
................................................................................................................................... 236
....................................................................................................................................................... 238
..................................................................................................................... 242
Web.Config ..................................................................................................................................... 245
.................................................................................................................................. 245
Threads.................................................................................................................................................... 249
.................................................................................................................................................................... 249
.......................................................................................................................................................................... 256

? !
.
. - microsoft
com/learning/booksurvey


Microsoft Visual Studio
, , , ,
.
(PDC), 2009 -, Visual Studio
. , . ,
, Visual Studio 2010, ,
, .
MSDN
,
Visual Studio. , Visual Studio 2010,
, .

?
,
Visual Studio Visual Studio 2010 Professional.

?
, , -
. ,
Visual Studio ( 2003) . Visual Studio 2010
.

.
Visual Studio 2010. Entity Framework
ASP.NET MVC 2, Visual Studio 2010
Visual Studio 2010.

Visual Studio 2010?


.
Visual Studio 2010 , .. ,
Visual Studio 2005, . ,
, . ,
, .
Plan My Night, .
,
:

I , Visual Studio 2003

II , Visual Studio 2005

III , Visual Studio 2008

, Visual Studio 2010



.
Visual Studio, ,
.
:

, I Microsoft Visual Studio 2003 Visual Studio 2010


2003 2010: . II Microsoft
Visual Studio 2005 Visual Studio 2010 2005 2010: .


,
Visual Studio. , ,

ix

,
. .

-

.
,
, .



, .
.

Plan My Night
I, , Visual Studio 2003,
, 2003 2010: .
, .
. , II III,
Visual Studio 2005 Visual Studio 2008, ,
.

Plan My Night?
Plan My Night (PMN) ( )
, (-):
Plan My Night
. ,
,
, , .
, , , ,
Plan My Night, . I-1.

. I-1 PMN

Plan My Night Visual Studio 2010 ASP.NET MVC 2.0 jQuery Ajax
.
Managed Extensibility Framework (MEF)
, , ..

Entity Framework; ,
Microsoft SQL Server 2008, Windows Server AppFabric (
Velocity).
, , , . I-2 ,
, . I-3 ,
Plan My Night.

. I-2 Plan My Night

. I-3 PMN 1.0 ,

xi

Visual Studio 2010?


Visual Studio 2010 Professional.
, ( - ):

Windows 7,
.

, Windows Presentation
Foundation (WPF) (. I4).

(Quick Search),
, .


SharePoint 2010 Windows Azure.


,
.

ASP.NET AJAX, IntelliSense


JavaScript, Visual Studio 2010 jQuery,
DOM.

.
(Scott Guthrie) (http://weblogs.asp.net/scottgu/archive/2009/08/27/multi-targetingsupport-vs-2010-and-net-4-series.aspx).

WPF Silverlight dragand-drop . ,



(
Visual Studio). WPF
Silverlight
WPF Silverlight.

Team Foundation Server (TFS) 2010 ( 1)


Team Explorer. ,
Visual Studio 2010,
,
.

.

. Visual Studio 2010
, Visual Studio 2010

.

TFS 2008 (. )

Microsoft Office 2010,

xii

. I-4 WPF Visual Studio

Visual Studio 2010 Professional.


.

:
http://msdn.microsoft.com/en-us/library/dd547188(VS.100).aspx

http://msdn.microsoft.com/en-us/library/bb386063(VS.100).aspx.

,
. Visual Studio 2010
, ,
, .


,
. , , Microsoft Press
Oreilly.com:
1. http://microsoftpress.oreilly.com.
2. ISBN .
3. .
4. .
5. View/Submit Errata (/ ).
.
Microsoft Press Book Support
mspinput@microsoft.com. ,

Microsoft Visual Studio 2010

Microsoft Visual Studio 2003 Visual Studio 2010


,
:
2003 2010: - ()
2003 2010: ()
2003 2010: ()
2003 2010: ()

Microsoft Visual Studio 2010

2003 2010: -

Entity Framework (EF)


-

Entity Data Model ( -)


POCO ADO.NET Entity Framework

Windows Server AppFabric (


Velocity)


PlanMyNight (PMN)
. Microsoft SQL Server.
- Bing Maps.
- (. 1-1).

. 1-1 PlanMyNight

, - ,
, , .
.
PMN:

IItinerariesRepository ( ) (
Microsoft SQL Server).

IActivitiesRepository ( ) (
- Bing Maps).

ICachingProvider ( )
( ASP.NET AppFabric Windows Server).
, PMN.

1 2003 2010: -

15

PMN SQL.
. . 1-2 ,
PMN.

. 1-2 PlanMyNight
PlanMyNight
ASP.NET. . 1-2
. MSDN ASP.NET 4
Introduction to Membership (ASP.NET 4 ) http://msdn.microsoft.com/enus/library/yh26yfzy(VS.100).aspx.

ZipCode ( )
.
.

Plan My Night Microsoft Visual Studio 2003


Visual Studio 2003 ,
PlanMyNight .
.
Visual Studio 2003 , DataSet
( ) DataReader ( ) ADO.NET (. 1-3).
, .
, :

SQL.

.
.

, ,
.

1 2003 2010: -

16

. 1-3 Insert ADO.NET

,
Visual Studio 2003. PMN
, ,
.

Visual Studio 2003 Entity Framework


ADO.NET Entity Framework (EF)
, . EF .NET
Framework.
, ADO.NET Entity Framework .NET 4,
(Data Developer Center) MSDN
(http://msdn.microsoft.com/en-us/data/aa937723.aspx).
PlanMyNight EF.

PMN. EF Entity Data Model (EDM) .
- (Model First), EF
, , EDM,
(Data Definition Language, DDL).

EF:
,
PMN. ,
%userprofile%\Documents\Microsoft Press\Moving to
Visual Studio 2010\Chapter 1\Code\ExistingDatabase. PlanMyNight.sln.
, (. 1-4):

PlanMyNight.Data:

PlanMyNight.Contracts:

PlanMyNight.Bing: Bing Map

PlanMyNight.Web:

PlanMyNight.AppFabricCaching: AppFabric

1 2003 2010: -

17

. 1-4 PlanMyNight

EF . .
EDM PlanMyNight.Data.
PlanMyNight.Data, Add () New Item ( ). ADO.NET
Entity Data Model PlanMyNight.edmx, . 1-5.

. 1-5 Add New Item ADO.NET Entity Data Model

Entity Data Model Wizard .


. Generate From Database (
) Next ().
. New Connection (
). Choose Data Source ( )
Microsoft SQL Server Database File ( Microsoft SQL Server).

1 2003 2010: -

%userprofile%\Documents\Microsoft
Press\Moving
to
1\ExistingDatabase\PlanMyNight.Web\App_Data\PlanMyNight.mdf (. 1-6).

18

Visual Studio 2010\Chapter

. 1-6 EDM,

Next.
,
. , No (),
.

Choose Your Database Objects ( )


Itinerary ( ), ItineraryActivities (), ItineraryComment (
), ItineraryRating ( ) ZipCode ( ),

UserProfile
(
).

RetrieveItinerariesWithinArea ( ). Model
Namespace ( ) Entities (), . 1-7.

1 2003 2010: -

19

. 1-7 EDM: Choose Your Database Objects

Finish (), EDM.


, ,
. ,
.
PMN ItineraryActivities,
Itinerary, .
ItineraryActivities Activities.
. 1-8.

1 2003 2010: -

20

. 1-8 , PlanMyNight

, ZipCode ZipCode1,
ZipCode, . ,
. Code, . 1-9.

. 1-9 ZipCode

, Ctrl+Shift+B.
EDM. , Location () PMN
. :
/ 'dbo.UserProfile' .
/ .
, .
UserProfile , ,
UserName ( ) .
UserProfile ,
EDM UserProfile.

1 2003 2010: -

21

PlanMyNight.edmx Open With


( ). Open With XML (Text) Editor (() XML),
. 1-10. OK, XML-, 1.

. 1-10 PlanMyNight.edmx XML


, PlanMyNight.edmx . Yes,

- .
UserProfile ,
UserProfile Key (). UserProfile .
, , UserName UserName
null. 1-1.
1-1 XML- UserProfile
<EntityType Name="UserProfile">
<Key>
<PropertyRef Name="UserName"/>
</Key>
<Property Name="UserName" Type="uniqueidentifier" Nullable="false" />
<Property Name="FullName" Type="varchar" MaxLength="500" />
<Property Name="City" Type="varchar" MaxLength="500" />
<Property Name="State" Type="varchar" MaxLength="500" />
<Property Name="PreferredActivityTypeId" Type="int" />
</EntityType>

XML- EDM, : The


Entity Data Model Designer is unable to display the file you requested. You can edit the model using the XML
Editor2.
Error List ( ) ,
:
Error 11002: Entity type UserProfile has no entity set.3
UserProfile,
. PlanMyNight.edmx XML. ,
Itinerary, XML-, 1-2.
1-2 XML- UserProfile
<EntitySet Name="UserProfile" EntityType="Entities.Store.UserProfile"
store:Type="Views" store:Schema="dbo" store:Name="UserProfile">
<DefiningQuery>
1

XML- (. )

Entity Data Model . XML


(. ).

'UserProfile' (. ).

1 2003 2010: -

22

SELECT
[UserProfile].[UserName] AS [UserName],
[UserProfile].[FullName] AS [FullName],
[UserProfile].[City] AS [City],
[UserProfile].[State] AS [State],
[UserProfile].[PreferredActivityTypeId] as [PreferredActivityTypeId]
FROM [dbo].[UserProfile] AS [UserProfile]
</DefiningQuery>
</EntitySet>

XML- EDM EDM. . 1-11


UserProfile Entities.Store (Model Browser).
Model Browser View (), Other Windows ( )
Entity Data Model Browser.

. 1-11 UserProfile Model Browser

, , UserProfile
UserProfile. EDM,
Add Entity. , . 1-12.

1 2003 2010: -

23

. 1-12 Add Entity

, . 1-12, OK, .
: City (), State () PreferedActiviyTypeId
( ).
UserProfile, Add Scalar Property ( ). ,
Type (), Max Length ( ) Unicode. . 1-1
.
1-1 UserProfile
Name

Type

Max Length

Unicode

FullName

String

500

False

City

String

500

False

State

String

500

False

PreferredActivityTypeId

Int32

, UserProfile , UserProfile.
UserProfile Table Mapping ( ),
. 1-13.

1 2003 2010: -

24

. 1-13 Table Mapping

UserProfile , . 1-14.
, .
UserProfile UserProfile.

. 1-14 UserProfile


Entity Data Model Wizard ( -)
RetrieveItinerariesWithinArea, .
, Function Import
( ).
Entities.Store Stored Procedures ( ).
RetrieveItineraryWithinArea Add Function Import (
). Add Function Import . 1-15.
Entities Itinerary .
OK.

1 2003 2010: -

25

. 1-15 Add Function Import

RetrieveItinerariesWithinArea,
. 1-16.

1 2003 2010: -

26

. 1-16

EDM,
Validate (). .

EF: 1
, EF
. EF Visual Studio 2003
Data Definition Language (DDL),
. ,
.
. Entity Data Model Wizard Empty model
( ), . 1-17.
, PlanMyNight.Data, Add
New Item. ADO.NET Entity Data Model.

- (. )

1 2003 2010: -

27

. 1-17 EDM: Empty model

PMN

%userprofile%\Documents\Microsoft
Press\Moving
Visual Studio 2010\Chapter 1\Code\ModelFirst, PlanMyNight.sln.

to

PlanMyNight.Data EDM- PlanMyNight.edmx


. , . 1-2.
Entity Model .
ZipCode. Entity,
. 1-18. ZipCode, Id Code
String.

. 1-18

City State. ZipCode,


Add Scalar Property. ,
. 1-2.

1 2003 2010: -

28

1-2 ZipCode
Name

Type

Fixed Length

Max Length

Unicode

Code

String

False

False

City

String

False

150

False

State

String

False

150

False

ItineraryComment Itinerary.
, Add Association (), . 1-19.

. 1-19 Add Association FK_ItineraryCommentItinerary

FK_ItineraryCommentItinerary,
, . 1-19. , ,
Referential Constraint ( ), . 1-20.

. 1-20 Association Referential Constraint

1 2003 2010: -

29

ItineraryRating Itinerary. ,
Add Association. FK_ItineraryItineraryRating.
, ,
ItineraryRating.
Referential Constraint, . 1-20. , Dependent ()
ItineraryComment, ItineraryRating.
ItineraryActivity Itinerary.
FK_ItineraryItineraryActivity Activities,
. 1-21. , Referential Constraint,
.

. 1-21 Add Association FK_ItineraryActivityItinerary


, . EF
.
Generate Database From Model (
), . 1-22.

1 2003 2010: -

30

. 1-22 Generate Database From Model

Generate Database Wizard .


DDL-
.
New Connection, Choose Data Source Microsoft SQL Server File
Continue (). ,
%userprofile%\Documents\Microsoft
Press\Moving
to
Visual Studio 2010\Chapter
1\Code\ModelFirst\Data\PlanMyNight.mdf (. 1-23).

1 2003 2010: -

31

. 1-23

, Next, ,
. 1-24. Finish T-SQL PlanMyNight.edmx.sql
. DDL- .

1 2003 2010: -

32

. 1-24 T-SQL

EDM , .
DDL- .
, ,
.
PMN ,
, . ,
, EF: .

POCO-
EDM T4.
.
PlanMyNight.Designer.cs, PlanMyNight.edmx.
EntityObject , EF
.
T4 Text Template Transformation Toolkit (
). T4 Visual Studio 2010
(, ).
Visual Studio 2010 Code Generation and
Text Templates ( ) http://msdn.microsoft.com/enus/library/bb126445(VS.100).aspx.

EF POCO. POCO-
. ( 1-3 POCO-
ZipCode.) EF
.
POCO Plain-Old CLR Objects1.

ADO.NET POCO Entity Generator


%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter
1\Code\ExistingDatabase\PlanMyNight.sln.
PlanMyNight.edmx, Add Code Generation Item
( ). , . 1-25,
. ADO.NET POCO
Entity Generator2 PlanMyNight.tt. Add.
,
. , OK,
.

CLR (. )

- . , Online Templates (- ),
POCO Search Online Templates ( - ) Enter,
, (. )

1 2003 2010: -

33

. 1-25 Add New Item

, PlanMyNight.tt PlanMyNight.Context.tt (. 1-26).


,
PlanMyNight.Designer.cs.

. 1-26

PlanMyNight.tt . 1-3
POCO- ZipCode.
1-3 POCO- ZipCode
namespace Microsoft.Samples.PlanMyNight.Data
{
public partial class ZipCode
{
#region Primitive Properties
public virtual string Code
{
get;
set;

1 2003 2010: -

34

}
public virtual string City
{
get;
set;
}
public virtual string State
{
get;
set;
}
#endregion
}
}

C# 2.0 ,
. .
. ,
.
.

# 3.0 , .
get set .

, PlanMyNight.Context.cs, ObjectContext ( )
PlanMyNight.edmx. .
POCO
.edmx.


PMN ,
.
, .
Visual Studio 2003 , Visual Studio 2003
, ,
. EF T4
, . .

POCO ADO.NET ,
.
PlanMyNight.tt PlanMyNight.Contracts.
PlanMyNight.tt, Cut (). Entities
PlanMyNight.Contracts Paste (). . 1-27.

1 2003 2010: -

35

. 1-27 POCO, Contracts

PlanMyNight.tt EDM.
, EDMX.
PlanMyNight.tt :
string inputFile = @"PlanMyNight.edmx";

, PlanMyNight.edmx PlanMyNight.Data:
string inputFile = @"..\..\PlanMyNight.Data\PlanMyNight.edmx";

, .
PlanMyNight.Context.tt PlanMyNight.Contracts,
Microsoft.Samples.PlanMyNight.Entities,
Microsoft.Samples.PlanMyNight.Data. PlanMyNight.Context.tt
using.
using
using
using
using

System;
System.Data.Objects;
System.Data.EntityClient;
Microsoft.Samples.PlanMyNight.Entities;

Ctrl+Shift+B, . .


SQL ,
PMN.
, Bing Maps
AppFabric Windows Server, PMN.
, .
,
, Bing Maps.
PlanMyNight.Data.Test PlanMyNight.Data.
Visual Studio 2010 3.


Itinerary
IItinerariesRepository. :

1 2003 2010: -

36

IItinerariesRepository:

SearchByActivity
.

SearchByZipCode
.

SearchByRadius
.

Add .

PMN, %userprofile%\Documents\Microsoft Press\Moving to


Visual Studio 2010\Chapter 1\Code\Final, PlanMyNight.sln.
PlanMyNight.Data ItinerariesRepository.cs.
IItinerariesRepository. PlanMyNightEntities,
LINQ , EF T-SQL,
.
LINQ Language Integrated Query1 .NET Framework 3.5.
.NET Framework,
SQL. LINQ
, Visual Studio IntelliSense
, , . 1-28. LINQ

.NET
Framework
Developer
Center
(http://msdn.microsoft.com/enus/netframework/aa904594.aspx).

. 1-28 IntelliSense LINQ

SearchByActivity.
, IsPublic () true, activityId
.
.
Visual Studio 2003 Visual Studio 2003
SQL-. EF LINQ ,
!

SearchByActivity LINQ, 1-4.


SearchByActivity.
Visual Studio 2003 2.0 C# CLR (
). ,
, .
, .
PMN .
Visual Studio 2003 ArrayList ( ):
1

(. )

1 2003 2010: -

37

public class PagingResult


{
private ArrayList items;
...
public PagingResult(Array items)
{
this.items = new ArrayList(items);
}
...
public ArrayList Items
{
get { return this.items; }
}
}
,
.
T , ,
:
public class PagingResult<T>
{
public PagingResult(IEnumerable<T> items)
{
this.Items = new List<T>(items);
}
...
public ICollection<T> Items { get; }
}
Generics in the .NET Framework
( .NET Framework) http://msdn.microsoft.com/en-us/library/ms172192.aspx.

1-4 SearchByActivity
public PagingResult<Itinerary> SearchByActivity(string activityId, int pageSize,
int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
var query = from itinerary in ctx.Itineraries.Include("Activities")
where itinerary.Activities.Any(t => t.ActivityId ==
activityId) && itinerary.IsPublic
orderby itinerary.Rating
select itinerary;
return PageResults(query, pageNumber, pageSize);
}
}

PageResults:
private static PagingResult<Itinerary>
int page, int pageSize)

PageResults(IQueryable<Itinerary>

{
int rowCount = rowCount = query.Count();
if (pageSize > 0)

query,

1 2003 2010: -

38

{
query = query.Skip((page - 1) * pageSize) .Take(pageSize);
}
var result = new PagingResult<Itinerary>(query.ToArray())
{
PageSize = pageSize,
CurrentPage = page,
TotalItems = rowCount
};
return result;
}
IQueryable<Itinerary>,
. IQueryable IEnumerable , T-SQL
query.ToArray().

SearchByZipCode SearchByActivity,
. , LINQ ,
1-5. SearchByZipCode.
1-5 SearchByZipCode
public PagingResult<Itinerary> SearchByZipCode(int activityTypeId, string zip, int
pageSize, int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
var query = from itinerary in ctx.Itineraries.Include("Activities")
where itinerary.Activities.Any(t => t.TypeId == activityTypeId
&& t.Zip == zip)
&& itinerary.IsPublic
orderby itinerary.Rating
select itinerary;
return PageResults(query, pageNumber, pageSize);
}
}

SearchByRadius RetrieveItinerariesWithinArea,
.
. 1-6 SearchByRadius
ItinerariesRepository.cs.
1-6 SearchByRadius
public PagingResult<Itinerary> SearchByRadius(int activityTypeId, double longitude,
double latitude, double radius, int pageSize, int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
//
var totalOutput = new ObjectParameter("total", typeof(int));
var items = ctx.RetrieveItinerariesWithinArea(activityTypeId,
latitude, longitude, radius, pageSize, pageNumber,
totalOutput).ToArray();
foreach (var item in items)
{
item.Activities.ToList().AddRange(this.Retrieve(item.Id).Activities);
}
int total = totalOutput.Value == DBNull.Value ? 0 :
(int)totalOutput.Value;

1 2003 2010: -

39

return new PagingResult<Itinerary>(items)


{
TotalItems = total,
PageSize = pageSize,
CurrentPage = pageNumber
};
}
}

Add .
,
. 1-7 Add.
1-7 Add
public void Add(Itinerary itinerary)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.Itineraries.AddObject(itinerary);
ctx.SaveChanges();
}
}

! ItinerariesRepository, ,
EF. , CTRL+R, A. ,
ItinerariesRepository, .

- Bing Maps
PMN
- Bing Maps. Bing Maps
PMN, Bing Maps.
Bing Maps (Bing
Maps Account Center) https://www.bingmapsportal.com/.
- Microsoft Bing Maps ,
Simple Object Access Protocol (SOAP)1,
,
, ,
- .
, Bing Maps Web Services
SDK2 (http://msdn.microsoft.com/en-us/library/cc980922.aspx).
Visual Studio 2003 Visual Studio 2003 -,
Add Web Service Reference ( -).
Add Web Reference ( -), (. 1-29.).

(. ).

- Bing Maps (. ).

1 2003 2010: -

40

. 1-29 Add Web Reference Visual Studio 2003

.NET Framework 3.0 Windows Communication Foundation (WCF) ASMX .


Visual Studio 2010 WCF.
Add Service Reference ( ),
Add Service Reference, . 1-30.
Address () Go
() .
OK, .

. 1-30 Add Service Reference


WCF, , Discover ().

Service Reference Settings (


), Advanced ().
WCF-. Add Web Service,
.NET Framework 2.0. MSDN

1 2003 2010: -

41

Configure Service Reference Dialog Box ( )


http://msdn.microsoft.com/en-us/library/bb514724(VS.100).aspx.
WCF , ASMX,
1-8.
1-8 -
public BingCoordinate GeocodeAddress(ActivityAddress address, string token)
{
...
Microsoft.Samples.PlanMyNight.Bing.VEGeocodingService.GeocodeResponse
geocodeResponse = null;
//
using (var geocodeService = new
Microsoft.Samples.PlanMyNight.Bing.VEGeocodingService.GeocodeServiceClient())
{
try
{
geocodeResponse = geocodeService.Geocode(geocodeRequest);
geocodeService.Close();
}
catch
{
geocodeService.Abort();
}
}
if (geocodeResponse != null && geocodeResponse.Results != null &&
geocodeResponse.Results.Length > 0)
{
var location = geocodeResponse.Results[0].Locations[0];
return new BingCoordinate { Latitude = (float)location.Latitude, Longitude
= (float)location.Longitude };
}
return default(BingCoordinate);
}



.
Visual Studio 2010 .NET Framework 4.0
. Task Parallel Library (TPL)1 Base Class Library (BCL)2
.NET Framework. , .NET- TPL
.
ItineraryActivity PMN Bing (Bing
Activity ID). Bing Activity ( Bing),
Bing Activity - Bing Maps ,
ItineraryActivity Itinerary.

Itinerary, 1-9. ,
RetrieveActivity ( ), ,
.
1-9
public void PopulateItineraryActivities(Itinerary itinerary)
{
foreach (var item in itinerary.Activities.Where(i =>i.Activity == null))
{
item.Activity = this.RetrieveActivity(item.ActivityId);
}
}
1

(. ).

(. ).

1 2003 2010: -

42


. , TPL,
Parallel.ForEach, ,
, 1-10.
1-10
public void PopulateItineraryActivities(Itinerary itinerary)
{
Parallel.ForEach(itinerary.Activities.Where(i => i.Activity == null),
item =>
{
item.Activity = this.RetrieveActivity(item.ActivityId);
});
}

.NET Framework 4.0 Parallel Linq (


System.Core.dll). PLinq .AsParallel
LINQ. .AsOrdered
, .
System.Collections.Concurrent .
Parallel Computing (
) MSDN http://msdn.microsoft.com/en-us/concurrency/default.aspx.

AppFabric
PMN ,
- Bing Maps. -

.
, .
, .
.
-
- Bing Maps. . 1-31
, -.

. 1-31 -

, -
, . -
, -
.
AppFabric Windows Server .
AppFabric
, ,
. 1-32. API get set,
(CLR). AppFabric
, ..
. ,
.

1 2003 2010: -

43

. 1-32 -, AppFabric Windows Server

AppFabric Windows Server


.NET Framework 4.0. , , Windows Server
AppFabric, Windows Server AppFabric (http://msdn.microsoft.com/enus/windowsserver/ee695849.aspx).
PMN
ASP.NET, AppFabric Windows Server.
, AppFabric Windows Server PMN PMN: Adding
Caching using Velocity ( Velocity)
http://channel9.msdn.com/learn/courses/VS2010/ASPNET/EnhancingAspNetMvcPlanMyNight/Exercise-1Adding-Caching-using-Velocity/.

Visual Studio 2010


PlanMyNight Entity Framework v4.0
. POCO ADO.NET Entity Framework AppFabric Windows Server.
-
ASP.NET MVC Managed Extensibility Framework ( ).

Microsoft Visual Studio 2010

2003 2010:

ASP.NET MVC,

ASP.NET MVC

Managed Extensibility
Framework

, ASP.NET 1.0, - Microsoft Visual Studio,


, . Visual Studio 2003 ,
( ),
.
, ,
Visual Studio 2010.
Plan My Night.
- ASP.NET MVC 2, Visual Studio 2010 -
ASP.NET, ASP.NET (
- (Web Forms)). ASP.NET 4.0
,
-.

-.
,
Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 2\
UserInterface-Start.

PlanMyNight.Web
Plan My Night Visual Studio 2010 ASP.NET MVC, , , , ,
- ASP.NET Visual Studio 2003. ( . 2-1)
( Global.asax), .
ASP.NET MVC.

. 2-1 PlanMyNight.Web

ASP.NET MVC:

Areas () ASP.NET MVC


- .

2 2003 2010: 45

Plan My Night, ,
MVC-.

Controllers () ASP.NET MVC


.

Views () Views .
Controllers.
Shared (). , ,
, .
ASP.NET MVC,
, - ASP.NET,
http://asp.net/mvc.

web.config .
Visual Studio 2010 : Web.config.
web.config web.config ,
, .
web.config, . 2-2.

. 2-2 Web.config
Visual Studio 2003 Visual Studio 2003 , web.config
. web.config
. Visual Studio 2010 .
web.config web.Release.config;
web.Debug.config.

Content

Helpers ( ) , ,
, .

Infrastructure () ,
ASP.NET MVC (,
).

ViewModels ( ) ,
(Controller) (Views) .

() , , .


, (. 2-3).

2 2003 2010: 46

. 2-3 Plan My Night

,
Windows Live ID,
404 Not Found ( ) ( . 2-4).

. 2-4 , Plan My Night

,
.


AccountController ( ) Plan My Night
:

( Windows Live ID).

ASP.NET MVC:
6. Solution Explorer ( ) Controllers PlanMyNight.Web
.
7. Add Controller.

8. , AccountController.

2 2003 2010: 47

Add Action Methods For Create, Update, And Delete Scenarios (


, ).
-, ,

Add Add Controller AccountController


Index ():
using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;
System.Web.Mvc;

namespace Microsoft.Samples.PlanMyNight.Web.Controllers
{
public class AccountController : Controller
{
//
// GET: /Account/
public ActionResult Index()
{
return View();
}
}
}

Visual Studio 2003 ASP.NET Web Forms Visual Studio 2003:


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


()
.
using:
using
using
using
using
using
using
using
using

System.IO;
Microsoft.Samples.PlanMyNight.Data;
Microsoft.Samples.PlanMyNight.Entities;
Microsoft.Samples.PlanMyNight.Infrastructure;
Microsoft.Samples.PlanMyNight.Infrastructure.Mvc;
Microsoft.Samples.PlanMyNight.Web.ViewModels;
System.Collections.Specialized;
WindowsLiveId;

. :
public class AccountController : Controller
{
private readonly IWindowsLiveLogin windowsLogin;
private readonly IMembershipService membershipService;
private readonly IFormsAuthentication formsAuthentication;

2 2003 2010: 48

private readonly IReferenceRepository referenceRepository;


private readonly IActivitiesRepository activitiesRepository;
.
.
.

.
,

, ,
.
:

IWindowsLiveLogin ( WindowsLive)
Windows Live ID.

IMembershipService ( )
. - ASP.NET Membership Service
( ).

IFormsAuthentication ( )
Authentication ( ).

IReferenceRepository ( ) ,
.

IActivitiesRepository ( )
.

ASP.NET Forms

: ,
ServiceFactory ( ) ,
.
public AccountController() :
this(
new ServiceFactory().GetMembershipService(),
new WindowsLiveLogin(true),
new FormsAuthenticationService(),
new ServiceFactory().GetReferenceRepositoryInstance(),
new ServiceFactory().GetActivitiesRepositoryInstance())
{
}
public AccountController(
IMembershipService membershipService,
IWindowsLiveLogin windowsLogin,
IFormsAuthentication formsAuthentication,
IReferenceRepository referenceRepository,
IActivitiesRepository activitiesRepository)
{
this.membershipService = membershipService;
this.windowsLogin = windowsLogin;
this.formsAuthentication = formsAuthentication;
this.referenceRepository = referenceRepository;
this.activitiesRepository = activitiesRepository;
}


, ,
. , ,
, .
:
Windows Live ID, ASP.NET Forms Authentication ASP.NET Membership Services.
LiveID, .
AccountController :
public ActionResult LiveId()
{
return Redirect("~/");
}

2 2003 2010: 49

Windows Live ID. ,


.
Redirect () RedirectResult ( ).
,

Windows Live ID ,
. Windows Live ID,
cookies Windows Live ID. Windows Live ID , URL
action,
.
LiveId return:
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out content);
return new FileStreamResult(new MemoryStream(content), type);
}

Windows Live ID
http://dev.live.com/.
Windows Live ID.
IFormsAuthentication cookie ASP.NET Forms
Authentication, http- ( )
. ,
cookies Windows Live ID (, , ).
,
(Membership Database).
, .
, Windows Live ID Windows Live ID,
WindowsLiveLogin.User:
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser = this.windowsLogin.ProcessLogin(tokenContext);

, , liveIdUser
WindowsLiveLogin.User, null. ,
, , liveIdUser
null:
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{

2 2003 2010: 50

this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser(userId, userId, string.Empty);
var profile = this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = null;
return RedirectToAction("Index", new { returnUrl = returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
return Redirect(returnUrl);
}
}
break;

ValidateUser ( ) IMembershipService
, .
Windows Live ID, ID ( GUID)
, ASP.NET Membership Service.
, CreateUser
( ). CreateProfile ( )
.
. , .
Controller.RedirectToAction , URL
. Index ()
URL-

ASP.NET Forms, ..
cookie ,
, .
ASP.NET Membership Services
web.config :
<system.web>

<profile enabled="true">
<properties>
<add name="FullName" type="string" />
<add name="State" type="string" />
<add name="City" type="string" />
<add name="PreferredActivityTypeId" type="int" />
</properties>
<providers>
<clear />
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider,
System.Web, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ApplicationServices"
applicationName="/" />
</providers>
</profile>

</system.web>

LiveID , .
Windows Live ID, ASP.NET
Membership Service ASP.NET Forms.
public ActionResult LiveId()
{
string action = Request.QueryString["action"];

2 2003 2010: 51

switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out content);
return new FileStreamResult(new MemoryStream(content), type);
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser = this.windowsLogin.ProcessLogin(tokenContext);
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser(userId, userId,
string.Empty);
var profile = this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = null;
return RedirectToAction("Index",
new { returnUrl = returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
return Redirect(returnUrl);
}
}
break;
}
return Redirect("~/");
}

, Windows
Live ID. Plan My Night Windows Live
ID. ,
. Login ():
public ActionResult Login(string returnUrl)
{
var redirect = HttpContext.Request.Browser.IsMobileDevice ?
this.windowsLogin.GetMobileLoginUrl(returnUrl) :
this.windowsLogin.GetLoginUrl(returnUrl);
return Redirect(redirect);

2 2003 2010: 52

URL- Windows Live


. ASP.NET Forms web.config
, , , :
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" name="XAUTH" timeout="2880" path="~/" />
</authentication>


, ,

.
Index
URL Global.asax. ,
, . Index,
AccountController, :
[Authorize()]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{
var profile = this.membershipService.GetCurrentProfile();
var model = new ProfileViewModel
{
Profile = profile,
ReturnUrl = returnUrl ?? this.GetReturnUrl()
};
this.InjectStatesAndActivityTypes(model);
return View("Index", model);
}

Visual Studio 2003 , [Authorize()],


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

Authorize (). ,
http-. ,
ASP.NET Forms Authentication, .
AcceptVerbs ( ) ,
Http-. HTTP GET.
returnUrl.
.
ASP.NET MVC (Model
Binding), . ,
returnUrl ( ,
) .
, null.
, null,
InvalidOperationException ( ).

2 2003 2010: 53

, : GetCurrentProfile (
) ASP.NET Membership Service
, . GetReturnUrl ( URL
) , PlanMyNight.Infrastructure.
Controller, (. 2-5).

. 2-5 MvcExtensions.cs
Visual Studio 2003 .NET Framework 1.1, Visual Studio 2003, .
this.GetReturnUrl(), IntelliSense .
MvcExtensions.GetReturnUrl(this), . ,
,
, . IntelliSense
using.

InjectStatesAndActivityTypes ( ) , .

. SelectListItem (HTML- MVC):
, , .
.
private void InjectStatesAndActivityTypes(ProfileViewModel model)
{
var profile = model.Profile;
var types = this.activitiesRepository.RetrieveActivityTypes().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Id.ToString(),
Selected = (profile != null && o.Id ==
profile.PreferredActivityTypeId)
}).ToList();
types.Insert(0, new SelectListItem { Text = "Select...", Value = "0" });
var states = this.referenceRepository.RetrieveStates().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Abbreviation,
Selected = (profile != null && o.Abbreviation ==
profile.State)
}).ToList();
states.Insert(0, new SelectListItem {
Text = "Any state",
Value = string.Empty
});
model.PreferredActivityTypes = types;
model.States = states;
}

2 2003 2010: 54

Visual Studio 2003 Visual Studio 2003 InjectStatesAndActivities ,


LINQ ( Select) ,
, Select .
.


,
, .
, . Update , ,
:
[Authorize()]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken()]
public ActionResult Update(UserProfile profile)
{
var returnUrl = Request.Form["returnUrl"];
if (!ModelState.IsValid)
{
//
return this.IsAjaxCall() ? new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet, Data = ModelState }
: this.Index(returnUrl);
}
this.membershipService.UpdateProfile(profile);
if (this.IsAjaxCall())
{
return new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet,
Data = new { Update = true,
Profile = profile,
ReturnUrl = returnUrl } };
}
else
{
return RedirectToAction("UpdateSuccess", "Account", new { returnUrl =
returnUrl });
}
}

ValidateAntiForgeryToken ( , ) ,
.
AntiForgeryToken (, ) .
ModelState ( ) .
, ASP.NET MVC ,
. UserProfile,
MVC,
System.ComponentModel.DataAnnotations.Required. MVC
DataAnnotation ( ) ModelState
.
, ModelState , Index, ModelState
. , AJAX-, JsonResult
ModelState.
Visual Studio 2003 ASP.NET MVC , .
URL
. Visual Studio 2003
URL

ModelState , , AJAX-
JSON- .
UpdateSuccess ( ) Account.
UpdateSuccess , :
public ActionResult UpdateSuccess(string returnUrl)
{

2 2003 2010: 55

var model = new ProfileViewModel


{
Profile = this.membershipService.GetCurrentProfile(),
ReturnUrl = returnUrl
};
return View(model);
}

,
,
.
, Account ,
:
using
using
using
using
using
using
using
using
using
using
using
using

System;
System.Collections.Specialized;
System.IO;
System.Linq;
System.Web;
System.Web.Mvc;
Microsoft.Samples.PlanMyNight.Data;
Microsoft.Samples.PlanMyNight.Entities;
Microsoft.Samples.PlanMyNight.Infrastructure;
Microsoft.Samples.PlanMyNight.Infrastructure.Mvc;
Microsoft.Samples.PlanMyNight.Web.ViewModels;
WindowsLiveId;

namespace Microsoft.Samples.PlanMyNight.Web.Controllers
{
[HandleErrorWithContentType()]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class AccountController : Controller
{
private readonly IWindowsLiveLogin windowsLogin;
private readonly IMembershipService membershipService;
private readonly IFormsAuthentication formsAuthentication;
private readonly IReferenceRepository referenceRepository;
private readonly IActivitiesRepository activitiesRepository;
public AccountController() :
this(
new ServiceFactory().GetMembershipService(),
new WindowsLiveLogin(true),
new FormsAuthenticationService(),
new ServiceFactory().GetReferenceRepositoryInstance(),
new ServiceFactory().GetActivitiesRepositoryInstance())
{
}
public AccountController(IMembershipService membershipService,
IWindowsLiveLogin windowsLogin,
IFormsAuthentication formsAuthentication,
IReferenceRepository referenceRepository,
IActivitiesRepository activitiesRepository)
{
this.membershipService = membershipService;
this.windowsLogin = windowsLogin;
this.formsAuthentication = formsAuthentication;
this.referenceRepository = referenceRepository;
this.activitiesRepository = activitiesRepository;
}
public ActionResult LiveId()
{
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");

2 2003 2010: 56

case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out
content);
return new FileStreamResult(new MemoryStream(content), type);
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new
NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser =
this.windowsLogin.ProcessLogin(tokenContext);
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser( userId, userId,
string.Empty);
var profile =
this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl =
null;
return RedirectToAction("Index", new { returnUrl =
returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl =
"~/";
return Redirect(returnUrl);
}
}
break;
}
return Redirect("~/");
}
public ActionResult Login(string returnUrl)
{
var redirect = HttpContext.Request.Browser.IsMobileDevice ?
this.windowsLogin.GetMobileLoginUrl(returnUrl) :
this.windowsLogin.GetLoginUrl(returnUrl);
return Redirect(redirect);
}
[Authorize()]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{

2 2003 2010: 57

var profile = this.membershipService.GetCurrentProfile();


var model = new ProfileViewModel
{
Profile = profile,
ReturnUrl = returnUrl ?? this.GetReturnUrl()
};
this.InjectStatesAndActivityTypes(model);
return View("Index", model);
}
[Authorize()]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken()]
public ActionResult Update(UserProfile profile)
{
var returnUrl = Request.Form["returnUrl"];
if (!ModelState.IsValid)
{
//
return this.IsAjaxCall() ?
new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet, Data = ModelState }
: this.Index(returnUrl);
}
this.membershipService.UpdateProfile(profile);
if (this.IsAjaxCall())
{
return new JsonResult {
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new {
Update = true,
Profile = profile,
ReturnUrl = returnUrl } };
}
else
{
return RedirectToAction("UpdateSuccess",
"Account", new { returnUrl = returnUrl });
}
}
public ActionResult UpdateSuccess(string returnUrl)
{
var model = new ProfileViewModel
{
Profile = this.membershipService.GetCurrentProfile(),
ReturnUrl = returnUrl
};
return View(model);
}
private void InjectStatesAndActivityTypes(ProfileViewModel model)
{
var profile = model.Profile;
var types = this.activitiesRepository.RetrieveActivityTypes()
.Select(o => new SelectListItem { Text = o.Name,
Value = o.Id.ToString(),
Selected = (profile != null &&
o.Id == profile.PreferredActivityTypeId) })
.ToList();
types.Insert(0, new SelectListItem { Text = "Select...",
Value = "0" });
var states = this.referenceRepository.RetrieveStates().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Abbreviation,
Selected = (profile != null &&
o.Abbreviation == profile.State) })
.ToList();
states.Insert(0, new SelectListItem { Text = "Any state",

2 2003 2010: 58

Value = string.Empty });


model.PreferredActivityTypes = types;
model.States = states;
}
}
}


,
. Visual Studio 2010,
, .
Index Account:
1. Views PlanMyNight.Web.
2. Views , Add New Folder.
3. Account.
4. Account, Add View.
5. Add View ( ), :

6. Add. HTML-
<asp:Content>:

2 2003 2010: 59

, , Visual Studio 2003.


ASP.NET MVC 2 - ASP.NET,
MVC - .
, page System.Web.Mvc.ViewPage<ProfileViewModel>,
. MVC , - ASP.NET,
. MVC, ,
. -
ASP.NET.
Account,
, :
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Plan My Night Profile
</asp:Content>

,
HtmlHeadContent ( HTML-):
<asp:Content ID="Content3" ContentPlaceHolderID="HtmlHeadContent" runat="server">
<% Ajax.RegisterClientScriptInclude(Url.Content("~/Content/Scripts/jquery1.4.1.min.js")); %>
<%
Ajax.RegisterCombinedScriptInclude(Url.Content("~/Content/Scripts/MicrosoftAjax.js"
), "pmn"); %>
<%
Ajax.RegisterCombinedScriptInclude(Url.Content("~/Content/Scripts/MicrosoftAjaxMvc.
js"), "pmn"); %>
<%
Ajax.RegisterCombinedScriptInclude(Url.Content("~/Content/Scripts/MicrosoftMvcValid
ation.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/ajax.common.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/ajax.profile.js"), "pmn"); %>
<%= Ajax.RenderClientScripts() %>
</asp:Content>

System.Web.Mvc.AjaxHelper,
PlanMyNight.Infrastructure MVC.
, :
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div class="panel" id="profileForm">
<div class="innerPanel">
<h2><span>My Profile</span></h2>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm("Update", "Account")) %>
<% { %>

2 2003 2010: 60

<%=Html.AntiForgeryToken()%>
<div class="items">
<fieldset>
<p>
<label for="FullName">Name:</label>
<%=Html.EditorFor(m => m.Profile.FullName)%>
<%=Html.ValidationMessage("Profile.FullName",
new { @class = "field-validation-error-wrapper" })%>
</p>
<p>
<label for="State">State:</label>
<%=Html.DropDownListFor(m => m.Profile.State,
Model.States)%>
</p>
<p>
<label for="City">City:</label>
<%=Html.EditorFor(m => m.Profile.City,
Model.Profile.City)%>
</p>
<p>
<label for="PreferredActivityTypeId">Preferred
activity:</label>
<%=Html.DropDownListFor(m =>
m.Profile.PreferredActivityTypeId,
Model.PreferredActivityTypes)%>
</p>
</fieldset>
<div class="submit">
<%=Html.Hidden("returnUrl", Model.ReturnUrl)%>
<%=Html.SubmitButton("submit", "Update")%>
</div>
</div>
<div class="toolbox"></div>
<% } %>
</div>
</div>
</asp:Content>

, HTML-.
, (
).
Visual Studio 2003 Visual Studio 2003
. ASP.NET MVC
, . -
ASP.NET Web Forms.
<asp:Content>. , , ASP.NET Web Forms
-

MVC HTML. ,
System.Web.Mvc.HtmlHelper, HTML-
. MVC-
, -,
. (HtmlHelper<TModel>)
ViewPage<TModel>.Html.
HTML- ( , ):

Html.EnableClientValidation ( )
ModelState

Html.BeginForm ( ) <form>
using. ,
, .
MVC URL
, URL .

Html.AntiForgeryToken ,
,
ValidateAntiForgeryToken. Update .

2 2003 2010: 61

Html.EditorFor ( ) ,
. Html.Editor.

Html.DropDownListFor ( ) ,
.
Html.DropDownList.

Html.ValidationMessage ( ) ,
,
ModelState.

Html.Hidden () .

Html.SubmitButton ( ) Submit ().


Index ,
UpdateSuccess, .

UpdateSuccess:
7. PlanMyNight.Web Solution Explorer Views.
8. Account.
9. Add View.
10. Add View, :

:
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">Plan My Night Profile Updated</asp:Content>

MainContent :
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div class="panel" id="profileForm">
<div class="innerPanel">
<h2><span>My Profile</span></h2>
<div class="items">
<p>Your profile has been successfully updated.</p>
<h3> <a href="<%=Html.AttributeEncode(Model.ReturnUrl ??
Url.Content("~/"))%>">Continue</a></h3>
</div>
<div class="toolbox">
</div>
</div>
</div>

2 2003 2010: 62

</asp:Content>

, Site.Master (
Views/Shared -). 33,
. :
<%=Html.ActionLink<AccountController>(c => c.Index(null), "My Profile")%>

, , .
Sign In (), . 2-6,
Windows Live ID.

. 2-6 Plan My Night

, , Index
Account (. 2-7).

. 2-7 , Index Account

, My Profile ( ),
.
, , Full Name
( ). (. 2-8).

2 2003 2010: 63

. 2-8 Model Binding

, .
, , Index.aspx
Account, Html.EnableClientValidation.
AJAX JavaScript MVC
, , , .
Visual Studio 2003 ASP.NET MVC ID HTML-
, ASP.NET Web Forms 1.0. Visual Studio 2003
UniqueID / JavaScript,
JavaScript. , ID,
ASP.NET 1.0 Web Forms
JavaScript. MVC , ID
. , ASP.NET 4.0 Web Forms
ID

Account
Plan My Night.
Visual Studio 2010 MVC 2.0. MVC
-. - ASP.NET ASP.NET
, Visual Studio 2010. - ASP.NET
MVC .

-
, -
. ,
. 2-9.

2 2003 2010: 64

. 2-9 Plan My Night

, , :
, .
(, .)
,
.
Plan My Night,
- ASP.NET,
Visual Studio. , .
-:
11. PlanMyNight.Web ( ),
Add New Item.
12. Add New Item Web Form using Master Page (-,
) Name : ErrorFeedback.aspx.

2 2003 2010: 65

13. , -.
, Project Folders ( ) PlanMyNight.Web,
WebForms.Master .

14. (Split
view), ( (Design view)).
( ,
Visual Studio). :

,
, , .

,
.
, View ().
drag-and-drop div ( HTML)
MainContent ( ) . div,
, .
div Properties () ( , F4).
Properties (Id) profileForm ( ) (
). Class () panel ().
, CSS.
Visual Studio 2003 -,
Visual Studio 2003, CSS.
.
Visual Studio 2003 search.aspx , . 2-10.

2 2003 2010: 66

. 2-10 - ASP.NET Visual Studio 2003

div class innerPanel ( ).


innerPanel :
<h2><span>Error Feedback</span></h2>

<h2>, . Insert Snippet (


) ASP.NET > formr. ,
- .
div, class items (), div fieldset
( ).
fieldset TextBox ( Standard ()
). ID FullName.
<label> (),
for ID Full Name: (
). <label> - , <label> </label>.
<p>, , . 2-11.

. 2-11 ErrorFeedback.aspx

, ID
EmailAddress ( ) Email Address: (
). TextBox ID Comments
().
TextBox. Comments ,
TextMode ( ) Multiline

2 2003 2010: 67

(), Rows () 5 Columns () 40.


, .
Insert Snippet Comments div with
class (HTML>divc). div submit.
div Button (). Text () Send Feedback
( ).
. 2-12.
, .

. 2-12 ErrorFeedback.aspx

.
,
ASP.NET. Full Name Comments
,
.
Validation ()
. RequiredFieldValidator (
) Full Name.
ControlToValidate (
) FullName. (
.) CssClass ( CSS) field-validation-error (
). ,
. , Error Message ( ) Name is
Required ( ) (. 2-13).

2 2003 2010: 68

. 2-13

Comments, ErrorMessage
( ) ControlToValidate.
Email
Address, RegularExpressionValidator
.
, .. ControlToValidate EmailAddress
CssClass field-validation-error.
, .
ValidationExpression ( ),
:
[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}

:
.
. ,
. Solution Explorer
PlanMyNight.Web Views Shared. Error.aspx
35.
, .
:
or <a href="/ErrorFeedback.aspx">send feedback</a>?


MVC . ,
.
Plan My Night:
15. .
16. , :
http://www.planmynight.net:48580/Itineraries/Details/38923828.
17. , ID,
.

2 2003 2010: 69

18. .
, .

ASP.NET (
), , .
,
Page.IsValid .
( ), true.
,
( Page.IsValid , -
):
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack && this.IsValid)
{
this.Response.Redirect("/", true);
}
}

, -
ASP.NET . PlanMyNight.Web . ,
, ,
, .
-
Managed Extensibility Framework (MEF). .

2 2003 2010: 70

MEF
Visual Studio 2010 .NET Framework 4 Managed Extensibility
Framework (MEF). Managed Extensibility Framework ,
,
. MEF
,
. MEF ,
, (), ,
(),
. ,
.
- MEF,
, http://mef.codeplex.com.
Plan My Night . Addins ()
(. 2-14).

. 2-14 Plan My Night

PlanMyNight.Addins.EmailItinerary ,
. PlanMyNight.Addins.PrintItinerary .
, PlanMyNight.Addins.Share (
), URL.
. ,
PlanMyNight.Contracts PlanMyNight.Infrastructure, (
) MEF,
.
- , ,
PlanMyNight.Web, .

, DeployAllAddins.bat,
PlanMyNight.sln.
Areas PlanMyNight.Web. , , ,
-.

. ,
PlanMyNight, .
, New () Save (),
(. 2-15).

2 2003 2010: 71

. 2-15

,
(. 2-16).

. 2-16
Visual Studio 2003 Visual Studio 2003 MEF.

. ,
.
MEF .NET Framework
.


PrintItinerary.Addin.
, . 2-17.

2 2003 2010: 72

. 2-17 PrintItinerary

PlanMyNight.Web (Controllers Views),


MVC Area.
PrintItineraryController.cs Controller, ,
, ( ), ,
PlanMyNight.Web.
:
[Export("PrintItinerary", typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]

MEF. , Export (),


IController PrintItinerary.
,
/singleton-.
, MEF. , PartCreationPolicy ( )
, ,
.
PrintItineraryController.cs ,
ImportingConstructor ( ):
[ImportingConstructor]
public PrintItineraryController(IServiceFactory serviceFactory) :
this(
serviceFactory.GetItineraryContainerInstance(),
serviceFactory.GetItinerariesRepositoryInstance(),
serviceFactory.GetActivitiesRepositoryInstance())
{
}

ImportingConstructor MEF
. MEF IServiceFactory
. this , ,

2 2003 2010: 73

. IServiceFactory
PlanMyNight.Web ServiceFactory.cs.
RouteTableConfiguration.cs URL,
PrintItineraryController. , ,
Application_Start, Global.asax.cs
PlanMyNight.Web:
// EF Controller
var controllerFactory = new MefControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
//
foreach (RouteCollection routes in container.GetExportedValues<RouteCollection>())
{
foreach (var route in routes)
{
RouteTable.Routes.Add(route);
}
}

controllerFactory MEF, Areas (


). .
, MEF, .
MEF MVC.
ItineraryContextualActionsExport.cs
, .
ViewModelExtensions.cs PlanMyNight.Web
:
//
var addinBoxes = new List<RouteValueDictionary>();
var addinLinks = new List<ExtensionLink>();
addinBoxes.AddRange(AddinExtensions.GetActionsFor("ItineraryToolbox", model.Id == 0
? null : new { id = model.Id }));
addinLinks.AddRange(AddinExtensions.GetLinksFor("ItineraryLinks", model.Id == 0 ?
null : new { id = model.Id }));

AddinExtensions.GetLinksFor
MEF ,
addinLinks ( ).
, .

,
Visual Studio 2010.
, , -
ASP.NET MVC -. , Managed Extensibility
Framework
. , Visual Studio 2010
.

Microsoft Visual Studio 2010

2003 2010:

Microsoft Visual Studio 2010

Visual Studio 2010

Visual Studio 2003 2010

,
Visual Studio.
Visual Studio 2010 ,
.

Visual Studio 2010


.
Plan My Night.
,
%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 3\Code.
PlanMyNight.sln.
,
:
19. Solution Explorer, PlanMyNight.Web .
, PlanMyNight.Web Set As StartUp
Project ( ).
20. PlanMyNight.Web Global.asax.cs,
Global.asax,
Global.asax.cs, . 3-1.

. 3-1 Solution Explorer Global.asax.cs

3 2003 2010:

75


Plan My Night ,
.

.
(intermediate language, IL),
.

, Global.ascx.cs.
.
21. Application_BeginRequest(object sender, EventArgs e)
var url = HttpContext.Current.Request.Url;, F9. . 3-2
, .

. 3-2

22. F5, .
- , ,
. Breakpoints ( )
, Debug ()
Windows () Breakpoints,
Ctrl+D+B.
Visual Studio 2003 Visual Studio 2003 Visual Studio 2010 , .
Visual Studio 2010, ,
Visual Studio 2003.
- Visual Studio 2003 .
, Configuration Manager
( ), IIS
Temporary ASP.NET Files Access Denied ( ASP.NET ).
,
. ,
- ASP.NET Internet Information Services (IIS) 5 6 Visual Studio 2003.
, , , ,
http://msdn.microsoft.com/en-us/library/aa290100(VS.71).aspx.
,
. , ,
, -.
, ASP.NET,
-.
- ( Cassini) ,
, Visual Studio 2010,
, IIS.
. Visual Studio 2010
, .

Breakpoints, . 3-3.

. 3-3 Breakpoints

3 2003 2010:

76

23. . Breakpoints ,
. 3-4.

. 3-4 Breakpoints
Visual Studio 2003 ,
Visual Studio 2003, , Breakpoints . ,
Visual Studio 2003 (. 3-5).

. 3-5 Breakpoints Visual Studio 2003

24. , Breakpoints Labels (),


. ,
Visual Studio 2010. ,
Breakpoints Edit Labels ( )
Alt+F9, L. . 3-6.

3 2003 2010:

77

. 3-6 Edit Labels

25. Edit Breakpoint Labels ( )


( Breakpoints). Type a New Label ( )
ContextRequestUrl Add.
Url. , OK. . 3-7 , Edit
Breakpoint Labels , Breakpoints .

. 3-7 , Breakpoints
,
Edit Labels.


, Or Choose Among Existing Labels (
) Edit Breakpoint Labels (. 3-7).

26. .
Breakpoints , . 3-8.

. 3-8 Breakpoints


.
Visual Studio 2010.
27. , url ,
, url.
, ,
. Visual Studio 2003
,
, ,
, .
Visual Studio 2010
, .
. ,
. , .

28. Breakpoints Export ()



. breakexports.xml.

3 2003 2010:

78

29. , Delete All Breakpoints Matching The Current Search


Criteria ( , )
,
Delete The Selected Breakpoints ( )
.
.
30. , Import ()

. ,
. .
Visual Studio 2003 (JavaScript)
. debugger ( stop VBScript)
. , IntelliSense .
Visual Studio 2010 JavaScript, jQuery.
Visual Studio 2008 , Visual Studio 2010 ,
, .


,
, . , ,
, printf WriteLn
? , , ,
, .
Visual Studio 2003 Visual Studio 2003 ,
,
. XML,
. ,
, .
. 3-9.

. 3-9 Visual Studio 2010


Visual Studio 2003

Visual Studio 2003 Visual Studio 2003 Watch


( ), Locals ( ) Quick Watch ( )
, .
. XML
, Notepad Visual Studio .
.

-
Visual Studio 2010, ,
.
Visual Studio 2010
. .
,

3 2003 2010:

79

, , . ,
:
31. Global.ascx.cs 89 91 , var
authority var pathAndQuery, .
32. .
, F5. , url
, . 3-10.

. 3-10

33. (
. 3-11 ). ,
( . 3-11 ).

. 3-11 ,
, ,
. :
.
, . , ,
. , .


, , . 3-12.
, X
.

. 3-12

34. ,
, .
, , url,
Add Expression ( ), authority , , (authority !=
null).
.
null false, .
35. F10, , ,
url . ,
. . 3-13 , .

3 2003 2010:

80

. 3-13 url

36. - ,
, .
. . 3-14.

. 3-14

37. , ,
.
, , , ,
. , ,
. ,
, , Solution Explorer,
, . . 3-15.

. 3-15 Solution Explorer Windows


,
, , .
, . 3-16.
,
. , ,
.

. 3-16 ,


, . 3-17.

3 2003 2010:

81

. 3-17 ,

,
. , -, Visual Studio,
.

. ,
url, (+). ,
, . 3-18.

. 3-18 url

38. , Global.ascx.cs, ,
. ,
Stop Debugging ( ) (
)
Shift+F5. ,
.
. . 3-19 , .

. 3-19
, .
Debug Export DataTips Import DataTips, .


,
. ,
. Visual Studio 2010
.
Visual Studio 2003 Visual Studio 2003
SOS,
(Immediate). , .
, (Locals).
SOS . ,
, .
Bug Slayer
( ) MSDN http://msdn.microsoft.com/en-us/magazine/cc164138.aspx.

3 2003 2010:

82

, . ,
:
39. Solution Explorer PlanMyNight.Web Default.aspx DefaultA.aspx
( A, Default).
40. , . Breakpoints
.
41. F5, .

HttpException. ,
. . 3-20 ,
.

. 3-20 ,

42. . Debug Save Dump


As ( ), . 3-21. ,
. Cassini Personal Web Server Visual Studio.
(WebDev.WebServer40.dmp)
. , ,
300 MB.

. 3-21

43. , Shift+F5 Stop Debugging.

3 2003 2010:

83

44. File .
45. WebDev.WebServer40.dmp, File Open
. Minidump File Summary (
), ,
(. 3-22). ,
, , , CLR, ,
, .
. , (Modules) ,
. CLR 4.0, ..

Visual Studio 2010.


. 3-22

46. , Actions () Minidump File Summary


Debug With Mixed ( ).
47. ,
. 3-23. , , .
, Break ().

. 3-23

48. , ,
. , Autos ( )
, controllerExport ( ) null.
, null ,
HttpException. , Locals
controllerName ( ), Default.aspx. Locals Autos
, ,
. , ,
.

3 2003 2010:

84

, .
. 3-24 .

. 3-24 Autos, Locals Call Stack

49. , . Shift+F5 Stop Debugging.


, PlanMyNight default.aspx.
Build, Rebuild Solution ( )
. F5,
.

Web.Config
, , ,
. Web.Config ,
. ,
. ,
ASP.NET () web.config
. ,
, MSDN: http://go.microsoft.com/fwlink/?LinkId=125889.


Visual Studio 2010 Professional
. Visual Studio 2010
. Visual Studio 2010 Premium Visual Studio 2010 Ultimate
, , IntelliTrace
Microsoft Test Manager 2010.
MSDN http://msdn.microsoft.com/en-us/library/ee789810(VS.100).aspx.
Visual Studio 2003 Visual Studio 2003
, nUnit,
, .

,
Plan My Night. ,
. , Visual Studio 2010.
Plan My Night Print Itinerary.
, .
, , .
, :
50. Solution Explorer PlanMyNight.Web Helpers.
ViewHelper.cs, . . 3-25 ,
.

3 2003 2010:

85

. 3-25 PlanMyNight.Web ViewHelper.cs Solution Explorer

51. .
Create Unit Tests (
). Test () New Test ( ).
, Visual Studio
. GetFriendlyTime (
) Create Unit Tests (. 3-26).

. 3-26

52. Create Unit Tests ,


, .
, .
PlanMyNight.Web.Tests. ,
Create A New Visual C# Test Project ( Visual C#). . 3-27
, .

3 2003 2010:

86

. 3-27 ,

53. OK ,
. TimeHelperTest.cs,
, .
54. , .
1:
/// <summary>
/// GetFriendlyTime
///</summary>
// TODO: , UrlToTest
// URL ASP.NET (, http://.../Default.aspx).
// , -
// , ,
// - WCF-.
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\Users\\< >\\Documents\\Microsoft
Press\\Moving to Visual Studio 2010\\Chapter 3\\code\\PlanMyNight.Web", "/")]
[UrlToTest("http://localhost:48580/")]
public void GetFriendlyTimeTest()
{
int totalMinutes = 0; // TODO:
string expected = string.Empty; // TODO:

string actual; actual = TimeHelper.GetFriendlyTime(totalMinutes);


Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method2.");
}

55. ,
PlanMyNight. ,
5:
[TestMethod]
public void ZeroReturnsSlash()

AspNetDevelopmentServerHost ,
(. )

(. ).

3 2003 2010:

87

{
Assert.AreEqual("-", TimeHelper.GetFriendlyTime(0));
}
[TestMethod]
public void LessThan60MinutesReturnsValueInMinutes()
{
Assert.AreEqual("10m", TimeHelper.GetFriendlyTime(10));
}
[TestMethod()]
public void MoreThan60MinutesReturnsValueInHoursAndMinutes()
{
Assert.AreEqual("2h 3m", TimeHelper.GetFriendlyTime(123));
}

56. PlanMyNight.Web.Tests Helpers.


TimeHelperTests.cs . , . 3-28.

. 3-28 TimeHelperTest.cs Helpers

57. . ,
, public class TimeHelperTest.
Test, Run Tests In Current Context (
); CTRL+R, T (. 329).

. 3-29

3 2003 2010:

88

58. .
Test Results ( ) (. 330).

. 3-30 Test Results


Tests In Current
Context . , , ZeroReturnsSlash,
. , ,
All Tests In Solution ( ).

Threads
,
, : .
Threads ()
, ,
Process Monitor SysInternals (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx).
Threads Debug, Windows (),
Threads (). . 3-31 Threads Plan My
Night.

. 3-31 Threads Plan My Night

Threads , .
, .
, . Visual Studio 2010,
, , ,
.
Visual Studio 2003 Visual Studio 2003 Thread .
. -
, Visual Studio 2003 .
, , . .
, , . ,
.NET Framework , ,
.NET 4.0 , PLINQ.


. ,
,
, . ,

3 2003 2010:

89

Visual Studio 2010 Professional.


,
. , Visual Studio 2010
.
, , Visual Studio 2010 Professional


. Visual Studio 2003 . ,
, ,
, ,
Visual Studio 2010 , Visual Studio.
Visual Studio 2010 .
Visual Studio 2003 Visual Studio 2010 ,
. , , ,
,
. ,
-, , IIS .
Visual Studio 2010 ,
. IntelliTrace http://msdn.microsoft.com/enus/library/dd264915(VS.100).aspx Visual Studio 2010 Ultimate Microsoft Test
Manager. IntelliTrace
Visual Studio 2010 Visual Studio 2010 Team Foundation Server http://msdn.microsoft.com/enus/library/bb385901(VS.100).aspx.

Microsoft Visual Studio 2010

2003 2010:
, :

- SQL

- ; ,
. ,
, - ,
FTP,
.zip-. , , .
( )
-. ,
. ,
Microsoft Visual Studio.

, Visual Studio 2010


-
(Web Deployment Packages). ,
Visual Studio. ,
,
. ,
Visual Studio, 2003.
, Plan My Night
%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 4\Code.
PlanMyNight.sln.
,
. -
:
59. , , ,
, FTP
. , ,
, .
60. , ,
. Internet
Information Services (IIS) .
IIS, ..
61. SQL, , ,
, SQL-.
62. SQL .
63. , , web.config, ,
, , .

, ,
. ,
,
. , ,
.
,
. ,
,
.

4 2003 2010:

91


.
, .
Visual Studio 2010 Web Deployment Tool ( ).

Visual Studio 2010


Plan My Night Visual Studio 2010 ,
- .
, IIS

.
, MSBuild TFSBuild.

Visual Studio 2010


-
Visual Studio 2003 :
64. xcopy, XCOPY-.
65. Copy Project ( ).
66. Web Setup Project ( ).
1 2 .
3 InstallShield.
xcopy.
, - .
,
, .
FrontPage ; ,
, , . , .
MSI -,
IIS, SQL ,
-. , ,
.
. 4-1, 4-2 4-3 -
Visual Studio 2003. . 4-1 .

. 4-1 XCOPY-

. 4-2 , .. Copy Project.

4 2003 2010:

92

. 4-2 Copy Project

, , Web Setup Project, . 4-3.

. 4-3 New Project Web Setup Project

Visual Studio 2005 2008 , -.


Visual Studio 2005, - : -
( ) Web
Application Project (-), .. .
Web Application Project Visual Studio 2005
. : -
Web Application Project,
, Visual Studio 2003.
, MSBuild.

Web Deployment Project ( ) Visual Studio 2005 2008


. ,
Visual Studio 2008 .
Web Deployment Project - Web Application Project.
. ,
,
. Web Deployment Project .

4 2003 2010:

93

,
.
, ,
-. aspnet_compiler aspnet_merge.
, , -,
, IIS.
( )
. . 4-4
Web Deployment Project.

. 4-4 Add Web Deployment Project

Web Deployment Project Visual Studio 2008. . 4-5


.

. 4-5 Web Deployment Project

MSBuild, ,
, , .
MSBuild. , . 46 Web Deployment Project PlanMyNight
Visual Studio 2008.

4 2003 2010:

94

. 4-6 Web Deployment Packages

Web Deployment Project ,


Visual Studio 2003, , , - ,
. .
Web Deployment Packages -
Visual Studio 2010.

Web Deployment Packages?


.zip-,
IIS, ,
IIS, , , ,
, , , .
msdeploy.
http://blogs.iis.net/msdeploy/default.aspx.
MSI Windows.
, InstallShield Wix Toolset.
, .
msdeploy , , .
( 2010) Wix 3.5 ,
IIS 7. - ,
2010. ( Wix (Rob Mensching)
http://robmensching.com/blog/.) Wix,
IIS 6. InstallShield , Visual Studio 2010 ,
, -.
.

Visual Studio 2010 Package/Publish Web


(/ ) . ,
, . .
67. PlanMyNight. PlanMyNight.Web
Package/Publish Settings ( /), . 4-7.

4 2003 2010:

95

. 4-7 Package/Publish Settings

68. . 4-8 Package/Publish Web ,


PlanMyNight.Web.

. 4-8 Package/Publish Web

69. Package/Publish SQL ,


. Package/Publish SQL Open Settings ( )
Package/Publish Web.
70. Import From Web.Config ( Web.Config)
- -.
SQL . 4-9. .

4 2003 2010:

96

. 4-9 Package/Publish SQL

71. . Build Deployment


Package ( ). .
. ,
, .
72. .zip- ; , Web Deploy
( ) ; SetParameters.xml
, Web Deploy; SourceManifest.xml ,
Visual Studio 2010 .
, Visual Studio 2010.
MSBuild MSBuild Windows PowerShell TFSBuild.
.
, ,
. One-Click.

One-Click
One-Click Visual Studio 2010,
. , ,
, Web Deploy. FTP FrontPage Extension.
, Publish Profile ( ). PlanMyNight.Web Publish (). ,
. 4-10, Publish Profile.

4 2003 2010:

97

. 4-10 Publish Profile

,
, Web Deploy, URL
. : https:< >:8172/MsDeploy.axd.
, . , site/application
(/) IIS/IIS.
. 4-10 ,
-.
, , IIS , .

, .
TFSBuild MSBuild .
. , Visual Studio 2010
.

-. ,
Visual Studio, , Visual Studio 2010
. Web Deploy , ,
.
, .
XCOPY-,
ASP.NET.

4 2003 2010:

98

msdeploy,
http://blogs.iis.net/msdeploy/default.aspx. Wix Toolset
Visual Studio , , .

Microsoft Visual Studio 2010

II

Microsoft Visual Studio 2005 Visual Studio 2010


,
:
2005 2010: - ()
2005 2010: ()
2005 2010: ()

Microsoft Visual Studio 2010

2005 2010: -

Entity Framework (EF)


-

Entity Data Model ( -)


POCO ADO.NET Entity Framework

Windows Server AppFabric (


Velocity)


PlanMyNight (PMN)
. Microsoft SQL Server.
- Bing Maps
- (. 5-1).

. 5-1 PlanMyNight

, - ,
, , .
.
PMN:

IItinerariesRepository ( ) (
Microsoft SQL Server).

IActivitiesRepository ( ) (
- Bing Maps).

ICachingProvider ( )
( ASP.NET AppFabric Windows Server).
, PMN.

5 2005 2010: -

101

PMN SQL.
. . 5-2 ,
PMN.

. 5-2 PlanMyNight
PlanMyNight
ASP.NET. . 5-2 .
MSDN ASP.NET 4 Introduction to
Membership
(ASP.NET 4

http://msdn.microsoft.com/enus/library/yh26yfzy(VS.100).aspx.

ZipCode ( )
.
.

Plan My Night Microsoft Visual Studio 2005


Visual Studio 2005 ,
PlanMyNight .
.
, Visual Studio 2005.
DataSet ( ) DataReader (
) ADO.NET (. 5-3). ,
. , :

SQL.

.
.

, ,
.

5 2005 2010: -

102

. 5-3 Insert ADO.NET

DataSet, Visual Studio 2005.


PMN, TableAdapter Configuration Wizard (
TableAdapter) , . 5-4.
DataSet.
,
. , , :

- SQL, DataSet
.

- SQL-,
.

. ,
DataSet
TableAdapter , .

.

, , ,
,
. .

5 2005 2010: -

103

. 5-4 DataSet Visual Studio 2005

,
Visual Studio 2010. PMN
, ,
.

Visual Studio 2010 Entity Framework


ADO.NET Entity Framework (EF)
, . EF .NET
Framework 4.
, ADO.NET Entity Framework .NET 4,
(Data Developer Center) MSDN
(http://msdn.microsoft.com/en-us/data/aa937723.aspx).
PlanMyNight EF.

PMN. EF Entity Data Model (EDM) .
- (Model First), EF
, , EDM,
(Data Definition Language, DDL).

EF:
,
PMN. ,
%userprofile%\Documents\Microsoft Press\Moving to Visual
Studio 2010\Chapter 5\Code\ExistingDatabase. PlanMyNight.sln.
, (. 5-5):

PlanMyNight.Data:

PlanMyNight.Contracts:

PlanMyNight.Bing: Bing Map

PlanMyNight.Web:

PlanMyNight.AppFabricCaching: AppFabric

5 2005 2010: -

104

. 5-5 PlanMyNight

EF . .
EDM PlanMyNight.Data.
PlanMyNight.Data, Add () New Item ( ). ADO.NET
Entity Data Model PlanMyNight.edmx, . 5-6.

. 5-6 Add New Item ADO.NET Entity Data Model

Entity Data Model Wizard .


. Generate From Database (
) Next ().
. New Connection (
). Choose Data Source ( )
Microsoft SQL Server Database File ( Microsoft SQL Server).

5 2005 2010: -

%userprofile%\Documents\Microsoft
Press\Moving
to
Visual
5\ExistingDatabase\PlanMyNight.Web\App_Data\PlanMyNight.mdf (. 5-7).

Studio

105

2010\Chapter

. 5-7 EDM,

Next.
,
. , No (),
.

Choose Your Database Objects ( )


Itinerary ( ), ItineraryActivities (), ItineraryComment (
), ItineraryRating ( ) ZipCode ( ),

UserProfile
(
).

RetrieveItinerariesWithinArea ( ). Model
Namespace ( ) Entities (), . 5-8.

5 2005 2010: -

106

. 5-8 EDM: Choose Your Database Objects

Finish (), EDM.


, ,
. ,
.
PMN ItineraryActivities,
Itinerary, .
ItineraryActivities Activities.
. 5-9.

5 2005 2010: -

107

. 5-9 , PlanMyNight

, ZipCode ZipCode1,
ZipCode, . ,
. Code, . 5-10.

. 5-10 ZipCode

, Ctrl+Shift+B.
EDM. , Location () PMN
. :
/ 'dbo.UserProfile' .
/ .
, .
UserProfile , ,
UserName ( ) .
UserProfile ,
EDM UserProfile.

5 2005 2010: -

108

PlanMyNight.edmx Open With


( ). Open With XML (Text) Editor (() XML),
. 5-11. OK, XML-, 1.

. 5-11 PlanMyNight.edmx XML


, PlanMyNight.edmx . Yes,

- .
UserProfile ,
UserProfile Key (). UserProfile .
, , UserName UserName
null. 5-1.
5-1 XML- EntityType UserProfile
<EntityType Name="UserProfile">
<Key>
<PropertyRef Name="UserName"/>
</Key>
<Property Name="UserName" Type="uniqueidentifier" Nullable="false" />
<Property Name="FullName" Type="varchar" MaxLength="500" />
<Property Name="City" Type="varchar" MaxLength="500" />
<Property Name="State" Type="varchar" MaxLength="500" />
<Property Name="PreferredActivityTypeId" Type="int" />
</EntityType>

XML- EDM, : The


Entity Data Model Designer is unable to display the file you requested. You can edit the model using the XML
Editor2.
Error List ( ) ,
:
Error 11002: Entity type UserProfile has no entity set. 3
UserProfile,
. PlanMyNight.edmx XML. ,
Itinerary, XML-, 5-2.
5-2 XML- EntitySet UserProfile
<EntitySet Name="UserProfile" EntityType="Entities.Store.UserProfile"
store:Type="Views" store:Schema="dbo" store:Name="UserProfile">
<DefiningQuery>
1

XML- (. )

Entity Data Model . XML


(. ).

'UserProfile' (. ).

5 2005 2010: -

109

SELECT
[UserProfile].[UserName] AS [UserName],
[UserProfile].[FullName] AS [FullName],
[UserProfile].[City] AS [City],
[UserProfile].[State] AS [State],
[UserProfile].[PreferredActivityTypeId] as [PreferredActivityTypeId]
FROM [dbo].[UserProfile] AS [UserProfile]
</DefiningQuery>
</EntitySet>

XML- EDM EDM. . 5-12


UserProfile Entities.Store (Model Browser).
Model Browser View (), Other Windows ( )
Entity Data Model Browser.

. 5-12 UserProfile Model Browser

, , UserProfile
UserProfile. EDM,
Add Entity. , . 5-13.

5 2005 2010: -

110

. 5-13 Add Entity

, . 5-13, OK, .
: City (), State () PreferedActiviyTypeId
( ).
UserProfile, Add Scalar Property ( ). ,
Type (), Max Length ( ) Unicode. . 5-1
.
5-1 UserProfile
Name

Type

Max Length

Unicode

FullName

String

500

False

City

String

500

False

State

String

500

False

PreferredActivityTypeId

Int32

, UserProfile , UserProfile.
UserProfile Table Mapping ( ),
. 5-14.

5 2005 2010: -

111

. 5-14 Table Mapping

UserProfile , . 5-15.
, .
UserProfile UserProfile.

. 5-15 UserProfile


Entity Data Model Wizard ( -)
RetrieveItinerariesWithinArea, .
, Function Import
( ).
Entities.Store Stored Procedures ( ).
RetrieveItineraryWithinArea Add Function Import (
). Add Function Import . 5-16.
Entities Itinerary .
OK.

5 2005 2010: -

112

. 5-16 Add Function Import

RetrieveItinerariesWithinArea,
. 5-17.

5 2005 2010: -

113

. 5-17

EDM,
Validate (). .

EF: 1
, EF
. EF Visual Studio 2010
Data Definition Language (DDL),
. ,
.
. Entity Data Model Wizard Empty model
( ), . 5-18.
, PlanMyNight.Data, Add
New Item. ADO.NET Entity Data Model.

- (. )

5 2005 2010: -

114

. 5-18 EDM: Empty model

PMN %userprofile%\Documents\Microsoft Press\Moving to Visual Studio


2010\Chapter 5\Code\ModelFirst, PlanMyNight.sln.
PlanMyNight.Data EDM- PlanMyNight.edmx
. , . 5-2.
Entity Model .
ZipCode. Entity,
. 5-19. ZipCode, Id Code
String.

. 5-19

City State. ZipCode,


Add Scalar Property. ,
. 5-2.

5 2005 2010: -

115

5-2 ZipCode
Name

Type

Fixed Length

Max Length

Unicode

Code

String

False

False

City

String

False

150

False

State

String

False

150

False

ItineraryComment Itinerary.
, Add Association (), . 5-20.

. 5-20 Add Association FK_ItineraryCommentItinerary

FK_ItineraryCommentItinerary,
, . 5-20. , ,
Referential Constraint ( ), . 5-21.

. 5-21 Association Referential Constraint

ItineraryRating Itinerary. ,
Add Association. FK_ItineraryItineraryRating.
, ,

5 2005 2010: -

116

ItineraryRating.
Referential Constraint, . 5-21. , Dependent ()
ItineraryComment, ItineraryRating.
ItineraryActivity Itinerary.
FK_ItineraryItineraryActivity Activities,
. 5-22. , Referential Constraint,
.

. 5-22 Add Association FK_ItineraryActivityItinerary


, . EF
.
Generate Database From Model (
), . 5-23.

5 2005 2010: -

117

. 5-23 Generate Database From Model

Generate Database Wizard .


DDL-
.
New Connection, Choose Data Source Microsoft SQL Server File
Continue (). ,
%userprofile%\Documents\Microsoft
Press\Moving
to
Visual
Studio
2010\Chapter
5\Code\ModelFirst\Data\PlanMyNight.mdf (. 5-24).

5 2005 2010: -

118

. 5-24

, Next, ,
. 5-25. Finish T-SQL PlanMyNight.edmx.sql
. DDL- .

. 5-25 T-SQL

5 2005 2010: -

119

EDM , .
DDL- .
, ,
.
PMN ,
, . ,
, EF: .

POCO-
EDM T4.
.
PlanMyNight.Designer.cs, PlanMyNight.edmx.
EntityObject , EF
.
T4 Text Template Transformation Toolkit (
). T4 Visual Studio 2010
(, ).
Visual Studio 2010 Code Generation and
Text Templates ( ) http://msdn.microsoft.com/enus/library/bb126445(VS.100).aspx.

EF POCO. POCO-
. ( 5-3 POCO-
ZipCode.) EF
.
POCO Plain-Old CLR Objects1.

ADO.NET POCO Entity Generator


%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter
5\Code\ExistingDatabase\PlanMyNight.sln.
PlanMyNight.edmx, Add Code Generation Item
( ). , . 5-26,
. ADO.NET POCO
Entity Generator2 PlanMyNight.tt. Add.
,
. , OK,
.

CLR (. )

- . , Online Templates (- ),
POCO Search Online Templates ( - ) Enter,
, (. )

5 2005 2010: -

120

. 5-26 Add New Item

, PlanMyNight.tt PlanMyNight.Context.tt (. 5-27).


,
PlanMyNight.Designer.cs.

. 5-27

PlanMyNight.tt . 5-3
POCO- ZipCode.
5-3 POCO- ZipCode
namespace Microsoft.Samples.PlanMyNight.Data
{
public partial class ZipCode
{
#region Primitive Properties
public virtual string Code
{
get;
set;

5 2005 2010: -

121

}
public virtual string City
{
get;
set;
}
public virtual string State
{
get;
set;
}
#endregion
}
}

# 3.0 , .
get set .

, PlanMyNight.Context.cs, ObjectContext ( )
PlanMyNight.edmx. .
POCO
.edmx.


PMN ,
.
, .
Visual Studio 2005 , XSD
,
. EF T4 ,
. .

POCO ADO.NET ,
.
PlanMyNight.tt PlanMyNight.Contracts.
PlanMyNight.tt, Cut (). Entities
PlanMyNight.Contracts Paste (). . 5-28.

5 2005 2010: -

122

. 5-28 POCO, Contracts

PlanMyNight.tt EDM.
, EDMX.
PlanMyNight.tt :
string inputFile = @"PlanMyNight.edmx";

, PlanMyNight.edmx PlanMyNight.Data:
string inputFile = @"..\..\PlanMyNight.Data\PlanMyNight.edmx";

, .
PlanMyNight.Context.tt PlanMyNight.Contracts,
Microsoft.Samples.PlanMyNight.Entities,
Microsoft.Samples.PlanMyNight.Data. PlanMyNight.Context.tt
using.
using
using
using
using

System;
System.Data.Objects;
System.Data.EntityClient;
Microsoft.Samples.PlanMyNight.Entities;

Ctrl+Shift+B, . .


, SQL ,
PMN.
, Bing Maps
AppFabric Windows Server, PMN.
, .
,
, Bing Maps.
PlanMyNight.Data.Test PlanMyNight.Data.
Visual Studio 2010 7.


Itinerary
IItinerariesRepository. :

5 2005 2010: -

123

IItinerariesRepository:

SearchByActivity
.

SearchByZipCode
.

SearchByRadius
.

Add .

PMN, %userprofile%\Documents\Microsoft Press\Moving to


Visual Studio 2010\Chapter 5\Code\Final, PlanMyNight.sln.
PlanMyNight.Data ItinerariesRepository.cs.
IItinerariesRepository. PlanMyNightEntities,
LINQ , EF T-SQL,
.
LINQ Language Integrated Query1 .NET Framework 3.5.
.NET Framework,
SQL. LINQ
, Visual Studio IntelliSense
, , . 5-29. LINQ

.NET
Framework
Developer
Center
(http://msdn.microsoft.com/enus/netframework/aa904594.aspx).

. 1-28 IntelliSense LINQ

SearchByActivity.
, IsPublic () true, activityId
.
.
Visual Studio 2005 Visual Studio 2005
SQL-. EF LINQ ,
!

SearchByActivity LINQ, 5-4.


SearchByActivity.
5-4 SearchByActivity
public PagingResult<Itinerary> SearchByActivity(string activityId, int pageSize,
int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;

(. )

5 2005 2010: -

124

var query = from itinerary in ctx.Itineraries.Include("Activities")


where itinerary.Activities.Any(t => t.ActivityId ==
activityId) && itinerary.IsPublic
orderby itinerary.Rating
select itinerary;
return PageResults(query, pageNumber, pageSize);
}
}
PageResults:
private static PagingResult<Itinerary>
int page, int pageSize)

PageResults(IQueryable<Itinerary>

query,

{
int rowCount = rowCount = query.Count();
if (pageSize > 0)
{
query = query.Skip((page - 1) * pageSize) .Take(pageSize);
}
var result = new PagingResult<Itinerary>(query.ToArray())
{
PageSize = pageSize,
CurrentPage = page,
TotalItems = rowCount
};
return result;
}
IQueryable<Itinerary>,
. IQueryable IEnumerable , T-SQL
query.ToArray().

SearchByZipCode SearchByActivity,
. , LINQ ,
5-5. SearchByZipCode.
5-5 SearchByZipCode
public PagingResult<Itinerary> SearchByZipCode(int activityTypeId, string zip, int
pageSize, int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
var query = from itinerary in ctx.Itineraries.Include("Activities")
where itinerary.Activities.Any(t => t.TypeId == activityTypeId
&& t.Zip == zip)
&& itinerary.IsPublic
orderby itinerary.Rating
select itinerary;
return PageResults(query, pageNumber, pageSize);
}
}

SearchByRadius RetrieveItinerariesWithinArea,
.
. 5-6 SearchByRadius
ItinerariesRepository.cs.
5-6 SearchByRadius

5 2005 2010: -

125

public PagingResult<Itinerary> SearchByRadius(int activityTypeId, double longitude,


double latitude, double radius, int pageSize, int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
//
var totalOutput = new ObjectParameter("total", typeof(int));
var items = ctx.RetrieveItinerariesWithinArea(activityTypeId,
latitude, longitude, radius, pageSize, pageNumber,
totalOutput).ToArray();
foreach (var item in items)
{
item.Activities.ToList().AddRange(this.Retrieve(item.Id).Activities);
}
int total = totalOutput.Value == DBNull.Value ? 0 :
(int)totalOutput.Value;
return new PagingResult<Itinerary>(items)
{
TotalItems = total,
PageSize = pageSize,
CurrentPage = pageNumber
};
}
}

Add .
,
. 5-7 Add.
5-7 Add
public void Add(Itinerary itinerary)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.Itineraries.AddObject(itinerary);
ctx.SaveChanges();
}
}

! ItinerariesRepository, ,
EF. , CTRL+R, A. ,
ItinerariesRepository, .

- Bing Maps
PMN
- Bing Maps. Bing Maps
PMN, Bing Maps.
Bing Maps (Bing
Maps Account Center).
- Microsoft Bing Maps ,
Simple Object Access Protocol (SOAP)1,
,
, ,
- .
, Bing Maps Web Services
SDK2 (http://msdn.microsoft.com/en-us/library/cc980922.aspx).
Visual Studio 2005 Visual Studio 2005 -,
Add Web Service Reference ( -).
1

(. ).

- Bing Maps (. ).

5 2005 2010: -

126

Add Web Reference ( -), (. 5-30.).

. 5-30 Add Web Reference Visual Studio 2005

.NET Framework 3.0 Windows Communication Foundation (WCF) ASMX .


Visual Studio 2010 WCF.
Add Service Reference ( ),
Add Service Reference, . 5-31.
Address () Go
() . Namespace
OK,
.

. 5-31 Add Service Reference


WCF, , Discover ().

Service Reference Settings (


), Advanced ().
WCF-. Add Web Service,
.NET Framework 2.0. MSDN

5 2005 2010: -

127

Configure Service Reference Dialog Box ( )


http://msdn.microsoft.com/en-us/library/bb514724(VS.100).aspx.
WCF , ASMX,
5-8.
5-8 -
public BingCoordinate GeocodeAddress(ActivityAddress address, string token)
{
...
Microsoft.Samples.PlanMyNight.Bing.VEGeocodingService.GeocodeResponse
geocodeResponse = null;
//
using (var geocodeService = new
Microsoft.Samples.PlanMyNight.Bing.VEGeocodingService.GeocodeServiceClient())
{
try
{
geocodeResponse = geocodeService.Geocode(geocodeRequest);
geocodeService.Close();
}
catch
{
geocodeService.Abort();
}
}
if (geocodeResponse != null && geocodeResponse.Results != null &&
geocodeResponse.Results.Length > 0)
{
var location = geocodeResponse.Results[0].Locations[0];
return new BingCoordinate { Latitude = (float)location.Latitude, Longitude
= (float)location.Longitude };
}
return default(BingCoordinate);
}



.
Visual Studio 2010 .NET Framework 4.0
. Task Parallel Library (TPL)1 Base Class Library (BCL)2
.NET Framework. , .NET- TPL
.
ItineraryActivity PMN Bing (Bing
Activity ID). Bing Activity ( Bing),
Bing Activity - Bing Maps ,
ItineraryActivity Itinerary.

Itinerary, 5-9. ,
RetrieveActivity ( ), ,
.
5-9
public void PopulateItineraryActivities(Itinerary itinerary)
{
foreach (var item in itinerary.Activities.Where(i =>i.Activity == null))
{
item.Activity = this.RetrieveActivity(item.ActivityId);
}
}
1

(. ).

(. ).

5 2005 2010: -

128


. , TPL,
Parallel.ForEach, ,
, 5-10.
5-10
public void PopulateItineraryActivities(Itinerary itinerary)
{
Parallel.ForEach(itinerary.Activities.Where(i => i.Activity == null),
item =>
{
item.Activity = this.RetrieveActivity(item.ActivityId);
});
}

.NET Framework 4.0 Parallel Linq (


System.Core.dll). PLinq .AsParallel
LINQ. .AsOrdered
, .
System.Collections.Concurrent .
Parallel Computing (
) MSDN http://msdn.microsoft.com/en-us/concurrency/default.aspx.

AppFabric
PMN ,
- Bing Maps. -

.
, .
, .
.
-
- Bing Maps. . 5-32
, -.

. 5-32 -

, -
, . -
, -
.

5 2005 2010: -

129

AppFabric Windows Server .


AppFabric
, ,
. 5-33. API get set,
(CLR). AppFabric
, ..
. ,
.

. 5-33 -, AppFabric Windows Server

AppFabric Windows Server


.NET Framework 4.0. , , Windows Server
AppFabric, Windows Server AppFabric (http://msdn.microsoft.com/enus/windowsserver/ee695849.aspx).
PMN
ASP.NET, AppFabric Windows Server.
, AppFabric Windows Server PMN PMN: Adding
Caching using Velocity ( Velocity)
http://channel9.msdn.com/learn/courses/VS2010/ASPNET/EnhancingAspNetMvcPlanMyNight/Exercise-1Adding-Caching-using-Velocity/.

Visual Studio 2010


PlanMyNight Entity Framework v4.0
. POCO ADO.NET Entity Framework AppFabric Windows Server.
-
ASP.NET MVC Managed Extensibility Framework ( ).

Microsoft Visual Studio 2010

2005 2010:

ASP.NET MVC,

ASP.NET MVC

Managed Extensibility
Framework

, ASP.NET 1.0, - Microsoft Visual Studio,


, . Visual Studio 2005 .NET Framework 2.0
, , ,
,
.
, ,
Visual Studio 2010.
Plan My Night.
- ASP.NET MVC 2, Visual Studio 2010 -
ASP.NET, ASP.NET (
- (Web Forms)). ASP.NET 4.0
,
-.

-.
,
Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 6\
UserInterface-Start.

PlanMyNight.Web
Plan My Night Visual Studio 2010 ASP.NET MVC, , , , ,
- ASP.NET Visual Studio 2005. ( . 6-1)
( Global.asax), .
ASP.NET MVC.

. 6-1 PlanMyNight.Web

ASP.NET MVC:

6 2005 2010: 131

Areas () ASP.NET MVC


- .
Plan My Night, ,
MVC-.

Controllers () ASP.NET MVC


.

Views () Views .
Controllers.
Shared (). , ,
, .
ASP.NET MVC,
, - ASP.NET,
http://asp.net/mvc.

web.config .
Visual Studio 2010 : Web.config.
web.config web.config ,
, .
web.config, . 6-2.

. 6-2 Web.config
Visual Studio 2005 Visual Studio 2005 , web.config
. web.config
. Visual Studio 2010 .
web.config web.Release.config;
web.Debug.config.

Content

Helpers ( ) , ,
, .

Infrastructure () ,
ASP.NET MVC (,
).

ViewModels ( ) ,
(Controller) (Views) .

() , , .


, (. 6-3).

6 2005 2010: 132

. 6-3 Plan My Night

,
Windows Live ID,
404 Not Found ( ) ( . 6-4).

. 6-4 , Plan My Night

,
.


AccountController ( ) Plan My Night
:

( Windows Live ID).

ASP.NET MVC:
73. Solution Explorer ( ) Controllers PlanMyNight.Web
.
74. Add Controller.

75. , AccountController.

6 2005 2010: 133

Add Action Methods For Create, Update, And Delete Scenarios (


, ).
-, ,

Add Add Controller AccountController


Index ():
using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;
System.Web.Mvc;

namespace Microsoft.Samples.PlanMyNight.Web.Controllers
{
public class AccountController : Controller
{
//
// GET: /Account/
public ActionResult Index()
{
return View();
}
}
}

Visual Studio 2005 ASP.NET Web Forms Visual Studio 2005:


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


()
.
using:
using
using
using
using
using
using
using
using

System.IO;
Microsoft.Samples.PlanMyNight.Data;
Microsoft.Samples.PlanMyNight.Entities;
Microsoft.Samples.PlanMyNight.Infrastructure;
Microsoft.Samples.PlanMyNight.Infrastructure.Mvc;
Microsoft.Samples.PlanMyNight.Web.ViewModels;
System.Collections.Specialized;
WindowsLiveId;

. :
public class AccountController : Controller
{
private readonly IWindowsLiveLogin windowsLogin;
private readonly IMembershipService membershipService;
private readonly IFormsAuthentication formsAuthentication;
private readonly IReferenceRepository referenceRepository;

6 2005 2010: 134

private readonly IActivitiesRepository activitiesRepository;


.
.
.

.
,

, ,
.
:

IWindowsLiveLogin ( WindowsLive)
Windows Live ID.

IMembershipService ( )
. - ASP.NET Membership Service
( ).

IFormsAuthentication ( )
Authentication ( ).

IReferenceRepository ( ) ,
.

IActivitiesRepository ( )
.

ASP.NET Forms

: ,
ServiceFactory ( ) ,
.
public AccountController() :
this(
new ServiceFactory().GetMembershipService(),
new WindowsLiveLogin(true),
new FormsAuthenticationService(),
new ServiceFactory().GetReferenceRepositoryInstance(),
new ServiceFactory().GetActivitiesRepositoryInstance())
{
}
public AccountController(
IMembershipService membershipService,
IWindowsLiveLogin windowsLogin,
IFormsAuthentication formsAuthentication,
IReferenceRepository referenceRepository,
IActivitiesRepository activitiesRepository)
{
this.membershipService = membershipService;
this.windowsLogin = windowsLogin;
this.formsAuthentication = formsAuthentication;
this.referenceRepository = referenceRepository;
this.activitiesRepository = activitiesRepository;
}


, ,
. , ,
, .
:
Windows Live ID, ASP.NET Forms Authentication ASP.NET Membership Services.
LiveID, .
AccountController :
public ActionResult LiveId()
{
return Redirect("~/");
}

Windows Live ID. ,


.

6 2005 2010: 135

Redirect () RedirectResult ( ).
,

Windows Live ID ,
. Windows Live ID,
cookies Windows Live ID. Windows Live ID , URL
action,
.
LiveId return:
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out content);
return new FileStreamResult(new MemoryStream(content), type);
}

Windows Live ID
http://dev.live.com/.
Windows Live ID.
IFormsAuthentication cookie ASP.NET Forms
Authentication, http- ( )
. ,
cookies Windows Live ID (, , ).
,
(Membership Database).
, .
, Windows Live ID Windows Live ID,
WindowsLiveLogin.User:
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser = this.windowsLogin.ProcessLogin(tokenContext);

, , liveIdUser
WindowsLiveLogin.User, null. ,
, , liveIdUser
null:
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser(userId, userId, string.Empty);

6 2005 2010: 136

var profile = this.membershipService.CreateProfile(userId);


profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = null;
return RedirectToAction("Index", new { returnUrl = returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
return Redirect(returnUrl);
}
}
break;

ValidateUser ( ) IMembershipService
, .
Windows Live ID, ID ( GUID)
, ASP.NET Membership Service.
, CreateUser
( ). CreateProfile ( )
.
. , .
Controller.RedirectToAction , URL
. Index ()
URL-

ASP.NET Forms, ..
cookie ,
, .
ASP.NET Membership Services
web.config :
<system.web>

<profile enabled="true">
<properties>
<add name="FullName" type="string" />
<add name="State" type="string" />
<add name="City" type="string" />
<add name="PreferredActivityTypeId" type="int" />
</properties>
<providers>
<clear />
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider,
System.Web, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ApplicationServices"
applicationName="/" />
</providers>
</profile>

</system.web>

LiveID , .
Windows Live ID, ASP.NET
Membership Service ASP.NET Forms.
public ActionResult LiveId()
{
string action = Request.QueryString["action"];
switch (action)
{

6 2005 2010: 137

case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out content);
return new FileStreamResult(new MemoryStream(content), type);
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser = this.windowsLogin.ProcessLogin(tokenContext);
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser(userId, userId,
string.Empty);
var profile = this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = null;
return RedirectToAction("Index",
new { returnUrl = returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
return Redirect(returnUrl);
}
}
break;
}
return Redirect("~/");
}

, Windows
Live ID. Plan My Night Windows Live
ID. ,
. Login ():
public ActionResult Login(string returnUrl)
{
var redirect = HttpContext.Request.Browser.IsMobileDevice ?
this.windowsLogin.GetMobileLoginUrl(returnUrl) :
this.windowsLogin.GetLoginUrl(returnUrl);
return Redirect(redirect);
}

6 2005 2010: 138

URL- Windows Live


. ASP.NET Forms web.config
, , , :
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" name="XAUTH" timeout="2880" path="~/" />
</authentication>


, ,

.
Index
URL Global.asax. ,
, . Index,
AccountController, :
[Authorize()]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{
var profile = this.membershipService.GetCurrentProfile();
var model = new ProfileViewModel
{
Profile = profile,
ReturnUrl = returnUrl ?? this.GetReturnUrl()
};
this.InjectStatesAndActivityTypes(model);
return View("Index", model);
}
Visual Studio 2005 , [Authorize()],
Visual Studio 2005, ASP.NET MVC . ,
. (
) .

Authorize (). ,
http-. ,
ASP.NET Forms Authentication, .
AcceptVerbs ( ) ,
Http-. HTTP GET.
returnUrl.
.
ASP.NET MVC (Model
Binding), . ,
returnUrl ( ,
) .
, null.
, null,
InvalidOperationException ( ).

, : GetCurrentProfile (
) ASP.NET Membership Service
, . GetReturnUrl ( URL
) , PlanMyNight.Infrastructure.
Controller, (. 6-5).

6 2005 2010: 139

. 6-5 MvcExtensions.cs
Visual Studio 2005 .NET Framework 2.0, Visual Studio 2005, .
this.GetReturnUrl(), IntelliSense .
MvcExtensions.GetReturnUrl(this), . ,
,
, . IntelliSense
using.

InjectStatesAndActivityTypes ( ) , .

. SelectListItem (HTML- MVC):
, , .
.
private void InjectStatesAndActivityTypes(ProfileViewModel model)
{
var profile = model.Profile;
var types = this.activitiesRepository.RetrieveActivityTypes().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Id.ToString(),
Selected = (profile != null && o.Id ==
profile.PreferredActivityTypeId)
}).ToList();
types.Insert(0, new SelectListItem { Text = "Select...", Value = "0" });
var states = this.referenceRepository.RetrieveStates().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Abbreviation,
Selected = (profile != null && o.Abbreviation ==
profile.State)
}).ToList();
states.Insert(0, new SelectListItem {
Text = "Any state",
Value = string.Empty
});
model.PreferredActivityTypes = types;
model.States = states;
}
Visual Studio 2005 Visual Studio 2005 InjectStatesAndActivities ,
LINQ ( Select) ,
, Select .
.

6 2005 2010: 140


,
, .
, . Update , ,
:
[Authorize()]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken()]
public ActionResult Update(UserProfile profile)
{
var returnUrl = Request.Form["returnUrl"];
if (!ModelState.IsValid)
{
//
return this.IsAjaxCall() ? new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet, Data = ModelState }
: this.Index(returnUrl);
}
this.membershipService.UpdateProfile(profile);
if (this.IsAjaxCall())
{
return new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet,
Data = new { Update = true,
Profile = profile,
ReturnUrl = returnUrl } };
}
else
{
return RedirectToAction("UpdateSuccess", "Account", new { returnUrl =
returnUrl });
}
}

ValidateAntiForgeryToken ( , ) ,
.
AntiForgeryToken (, ) .
ModelState ( ) .
, ASP.NET MVC ,
. UserProfile,
MVC,
System.ComponentModel.DataAnnotations.Required. MVC
DataAnnotation ( ) ModelState
.
, ModelState , Index, ModelState
. , AJAX-, JsonResult
ModelState.
Visual Studio 2005 ASP.NET MVC , .
URL
. Visual Studio 2005
URL

ModelState , , AJAX-
JSON- .
UpdateSuccess ( ) Account.
UpdateSuccess , :
public ActionResult UpdateSuccess(string returnUrl)
{
var model = new ProfileViewModel
{
Profile = this.membershipService.GetCurrentProfile(),
ReturnUrl = returnUrl
};
return View(model);
}

6 2005 2010: 141

,
,
.
, Account ,
:
using
using
using
using
using
using
using
using
using
using
using
using

System;
System.Collections.Specialized;
System.IO;
System.Linq;
System.Web;
System.Web.Mvc;
Microsoft.Samples.PlanMyNight.Data;
Microsoft.Samples.PlanMyNight.Entities;
Microsoft.Samples.PlanMyNight.Infrastructure;
Microsoft.Samples.PlanMyNight.Infrastructure.Mvc;
Microsoft.Samples.PlanMyNight.Web.ViewModels;
WindowsLiveId;

namespace Microsoft.Samples.PlanMyNight.Web.Controllers
{
[HandleErrorWithContentType()]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class AccountController : Controller
{
private readonly IWindowsLiveLogin windowsLogin;
private readonly IMembershipService membershipService;
private readonly IFormsAuthentication formsAuthentication;
private readonly IReferenceRepository referenceRepository;
private readonly IActivitiesRepository activitiesRepository;
public AccountController() :
this(
new ServiceFactory().GetMembershipService(),
new WindowsLiveLogin(true),
new FormsAuthenticationService(),
new ServiceFactory().GetReferenceRepositoryInstance(),
new ServiceFactory().GetActivitiesRepositoryInstance())
{
}
public AccountController(IMembershipService membershipService,
IWindowsLiveLogin windowsLogin,
IFormsAuthentication formsAuthentication,
IReferenceRepository referenceRepository,
IActivitiesRepository activitiesRepository)
{
this.membershipService = membershipService;
this.windowsLogin = windowsLogin;
this.formsAuthentication = formsAuthentication;
this.referenceRepository = referenceRepository;
this.activitiesRepository = activitiesRepository;
}
public ActionResult LiveId()
{
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out
content);
return new FileStreamResult(new MemoryStream(content), type);
default:

6 2005 2010: 142

//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new
NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser =
this.windowsLogin.ProcessLogin(tokenContext);
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser( userId, userId,
string.Empty);
var profile =
this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl =
null;
return RedirectToAction("Index", new { returnUrl =
returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl =
"~/";
return Redirect(returnUrl);
}
}
break;
}
return Redirect("~/");
}
public ActionResult Login(string returnUrl)
{
var redirect = HttpContext.Request.Browser.IsMobileDevice ?
this.windowsLogin.GetMobileLoginUrl(returnUrl) :
this.windowsLogin.GetLoginUrl(returnUrl);
return Redirect(redirect);
}
[Authorize()]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{
var profile = this.membershipService.GetCurrentProfile();
var model = new ProfileViewModel
{
Profile = profile,
ReturnUrl = returnUrl ?? this.GetReturnUrl()
};
this.InjectStatesAndActivityTypes(model);

6 2005 2010: 143

return View("Index", model);


}
[Authorize()]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken()]
public ActionResult Update(UserProfile profile)
{
var returnUrl = Request.Form["returnUrl"];
if (!ModelState.IsValid)
{
//
return this.IsAjaxCall() ?
new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet, Data = ModelState }
: this.Index(returnUrl);
}
this.membershipService.UpdateProfile(profile);
if (this.IsAjaxCall())
{
return new JsonResult {
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new {
Update = true,
Profile = profile,
ReturnUrl = returnUrl } };
}
else
{
return RedirectToAction("UpdateSuccess",
"Account", new { returnUrl = returnUrl });
}
}
public ActionResult UpdateSuccess(string returnUrl)
{
var model = new ProfileViewModel
{
Profile = this.membershipService.GetCurrentProfile(),
ReturnUrl = returnUrl
};
return View(model);
}
private void InjectStatesAndActivityTypes(ProfileViewModel model)
{
var profile = model.Profile;
var types = this.activitiesRepository.RetrieveActivityTypes()
.Select(o => new SelectListItem { Text = o.Name,
Value = o.Id.ToString(),
Selected = (profile != null &&
o.Id == profile.PreferredActivityTypeId) })
.ToList();
types.Insert(0, new SelectListItem { Text = "Select...",
Value = "0" });
var states = this.referenceRepository.RetrieveStates().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Abbreviation,
Selected = (profile != null &&
o.Abbreviation == profile.State) })
.ToList();
states.Insert(0, new SelectListItem { Text = "Any state",
Value = string.Empty });
model.PreferredActivityTypes = types;
model.States = states;
}
}
}

6 2005 2010: 144


,
. Visual Studio 2010,
, .
Index Account:
76. Views PlanMyNight.Web.
77. Views , Add New Folder.
78. Account.
79. Account, Add View.
80. Add View ( ), :

81. Add. HTML-


<asp:Content>:

, , Visual Studio 2005.


ASP.NET MVC 2 - ASP.NET,
MVC - .
, page System.Web.Mvc.ViewPage<ProfileViewModel>,

6 2005 2010: 145

. MVC , - ASP.NET,
. MVC, ,
. -
ASP.NET.
Account,
, :
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Plan My Night Profile
</asp:Content>

,
HtmlHeadContent ( HTML-):
<asp:Content ID="Content3" ContentPlaceHolderID="HtmlHeadContent" runat="server">
<% Ajax.RegisterClientScriptInclude(
Url.Content("~/Content/Scripts/jquery-1.3.2.min.js"),
"http://ajax.Microsoft.com/ajax/jQuery/jquery-1.3.2.min.js"); %>
<% Ajax.RegisterClientScriptInclude(
Url.Content("~/Content/Scripts/jquery.validate.js"),
"http://ajax.microsoft.com/ajax/jquery.validate/1.5.5/jquery.validate.min.js"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/MicrosoftMvcJQueryValidation.js"), "pmn");
%>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/ajax.common.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/ajax.profile.js"), "pmn"); %>
<%= Ajax.RenderClientScripts() %>
</asp:Content>

System.Web.Mvc.AjaxHelper,
PlanMyNight.Infrastructure MVC.
, :
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div class="panel" id="profileForm">
<div class="innerPanel">
<h2><span>My Profile</span></h2>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm("Update", "Account")) %>
<% { %>
<%=Html.AntiForgeryToken()%>
<div class="items">
<fieldset>
<p>
<label for="FullName">Name:</label>
<%=Html.EditorFor(m => m.Profile.FullName)%>
<%=Html.ValidationMessage("Profile.FullName",
new { @class = "field-validation-error-wrapper" })%>
</p>
<p>
<label for="State">State:</label>
<%=Html.DropDownListFor(m => m.Profile.State,
Model.States)%>
</p>
<p>
<label for="City">City:</label>
<%=Html.EditorFor(m => m.Profile.City,
Model.Profile.City)%>
</p>
<p>
<label for="PreferredActivityTypeId">Preferred
activity:</label>
<%=Html.DropDownListFor(m =>
m.Profile.PreferredActivityTypeId,
Model.PreferredActivityTypes)%>
</p>
</fieldset>
<div class="submit">

6 2005 2010: 146

<%=Html.Hidden("returnUrl", Model.ReturnUrl)%>
<%=Html.SubmitButton("submit", "Update")%>
</div>
</div>
<div class="toolbox"></div>
<% } %>
</div>
</div>
</asp:Content>

, HTML-.
, (
).
Visual Studio 2005 Visual Studio 2005
. ASP.NET MVC
, . -
ASP.NET Web Forms.
<asp:Content>. , , ASP.NET Web Forms
-

MVC HTML. ,
System.Web.Mvc.HtmlHelper, HTML-
. MVC-
, -,
. (HtmlHelper<TModel>)
ViewPage<TModel>.Html.
HTML- ( , ):

Html.EnableClientValidation ( )
ModelState

Html.BeginForm ( ) <form>
using. ,
, .
MVC URL
, URL .

Html.AntiForgeryToken ,
,
ValidateAntiForgeryToken. Update .

Html.EditorFor ( ) ,
. Html.Editor.

Html.DropDownListFor ( ) ,
.
Html.DropDownList.

Html.ValidationMessage ( ) ,
,
ModelState.

Html.Hidden () .

Html.SubmitButton ( ) Submit ().


Index ,
UpdateSuccess, .

UpdateSuccess:
82. PlanMyNight.Web Solution Explorer Views.
83. Account.
84. Add View.

6 2005 2010: 147

85. Add View, :

:
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">Plan My Night Profile Updated</asp:Content>

MainContent :
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div class="panel" id="profileForm">
<div class="innerPanel">
<h2><span>My Profile</span></h2>
<div class="items">
<p>Your profile has been successfully updated.</p>
<h3> <a href="<%=Html.AttributeEncode(Model.ReturnUrl ??
Url.Content("~/"))%>">Continue</a></h3>
</div>
<div class="toolbox">
</div>
</div>
</div>
</asp:Content>

, Site.Master (
Views/Shared -). 33,
. :
<%=Html.ActionLink<AccountController>(c => c.Index(null), "My Profile")%>

6 2005 2010: 148

, , .
Sign In (), . 6-6,
Windows Live ID.

. 6-6 Plan My Night

, , Index
Account (. 6-7).

. 6-7 , Index Account

, My Profile ( ),
.
, , Full Name
( ). (. 6-8).

6 2005 2010: 149

. 6-8 Model Binding

, .
, , Index.aspx
Account, Html.EnableClientValidation.
AJAX JavaScript MVC
, , , .
Visual Studio 2005 ASP.NET MVC ID HTML-
, ASP.NET Web Forms 2.0. Visual Studio 2005
UniqueID / JavaScript,
JavaScript. , ID,
ASP.NET 2.0 Web Forms
JavaScript. MVC , ID
. , ASP.NET 4.0 Web Forms
ID

Account
Plan My Night.
Visual Studio 2010 MVC 2.0. MVC
-. - ASP.NET ASP.NET
, Visual Studio 2010. - ASP.NET
MVC .

-
, -
. ,
. 6-9.

6 2005 2010: 150

. 6-9 Plan My Night

, , :
, .
(, .)
,
.
Plan My Night,
- ASP.NET,
Visual Studio. , .
-:
86. PlanMyNight.Web ( ),
Add New Item.
87. Add New Item Web Form using Master Page (-,
) Name : ErrorFeedback.aspx.

88. , -.
, Project Folders ( ) PlanMyNight.Web,
WebForms.Master .

6 2005 2010: 151

89. (Split
view), ( (Design view)).
( ,
Visual Studio). :

,
, , .

,
.
, View ().
drag-and-drop div ( HTML)
MainContent ( ) . div,
, .
div Properties () ( , F4).
Properties (Id) profileForm ( ) (
). Class () panel ().
, CSS.
Visual Studio 2005 -,
Visual Studio 2005, CSS.
.
Visual Studio 2005 search.aspx , . 6-10.

6 2005 2010: 152

. 6-10 - ASP.NET Visual Studio 2005

div class innerPanel ( ).


innerPanel :
<h2><span>Error Feedback</span></h2>

<h2>, . Insert Snippet (


) ASP.NET > formr. ,
- .
div, class items (), div fieldset
( ).
fieldset TextBox ( Standard ()
). ID FullName.
<label> (),
for ID , .. Full Name: ( ). <label> -
, <label> </label>. <p>,
, . 6-11.

. 6-11 ErrorFeedback.aspx

, ID
EmailAddress ( ) Email Address: (
). TextBox ID Comments
().
TextBox. Comments ,

6 2005 2010: 153

TextMode ( ) Multiline
(), Rows () 5 Columns () 40.
, .
Insert Snippet Comments div with
class (HTML>divc). div submit.
div Button (). Text () Send Feedback
( ).
. 6-12.
, .

. 6-12 ErrorFeedback.aspx

.
,
ASP.NET. Full Name Comments
,
.
Validation ()
. RequiredFieldValidator (
) Full Name.
ControlToValidate (
) FullName. (
.) CssClass ( CSS) field-validation-error (
). ,
. , Error Message ( ) Name is
Required ( ) (. 6-13).

6 2005 2010: 154

. 6-13

Comments, ErrorMessage
( ) ControlToValidate.
Email
Address, RegularExpressionValidator
.
, .. ControlToValidate EmailAddress
CssClass field-validation-error.
, .
ValidationExpression ( ),
:
[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}

:
.
. ,
. Solution Explorer
PlanMyNight.Web Views Shared. Error.aspx
35.
, .
:
or <a href="/ErrorFeedback.aspx">send feedback</a>?


MVC . ,
.
Plan My Night:
90. .
91. , :
http://www.planmynight.net:48580/Itineraries/Details/38923828.

6 2005 2010: 155

92. , ID,
.

93. .
, .

ASP.NET (
), , .
,
Page.IsValid .
( ), true.
,
( Page.IsValid , -
):
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack && this.IsValid)
{
this.Response.Redirect("/", true);
}
}

, -
ASP.NET . PlanMyNight.Web . ,
, ,
, .
-
Managed Extensibility Framework (MEF).

6 2005 2010: 156

MEF
Visual Studio 2010 .NET Framework 4 Managed Extensibility
Framework (MEF). Managed Extensibility Framework ,
,
. MEF
,
. MEF ,
, (), ,
(),
. ,
.
- MEF,
, http://mef.codeplex.com.
Plan My Night . Addins ()
(. 6-14).

. 6-14 Plan My Night

PlanMyNight.Addins.EmailItinerary ,
. PlanMyNight.Addins.PrintItinerary .
, PlanMyNight.Addins.Share (
), URL.
. ,
PlanMyNight.Contracts PlanMyNight.Infrastructure, (
) MEF,
.
- , ,
PlanMyNight.Web, .

, DeployAllAddins.bat,
PlanMyNight.sln.
Areas PlanMyNight.Web. , , ,
-.

. ,
PlanMyNight, .
, New () Save (),
(. 6-15).

6 2005 2010: 157

. 6-15

,
(. 6-16).

. 6-16
Visual Studio 2005 Visual Studio 2005 MEF.

. ,
.
MEF .NET Framework
.


PrintItinerary.Addin.
, . 6-17.

6 2005 2010: 158

. 6-17 PrintItinerary

PlanMyNight.Web (Controllers Views),


MVC Area.
PrintItineraryController.cs Controller, ,
, ( ), ,
PlanMyNight.Web.
:
[Export("PrintItinerary", typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]

MEF. , Export (),


IController PrintItinerary.
,
/singleton-.
, MEF. , PartCreationPolicy ( )
, ,
.
PrintItineraryController.cs ,
ImportingConstructor ( ):
[ImportingConstructor]
public PrintItineraryController(IServiceFactory serviceFactory) :
this(
serviceFactory.GetItineraryContainerInstance(),
serviceFactory.GetItinerariesRepositoryInstance(),
serviceFactory.GetActivitiesRepositoryInstance())
{
}

ImportingConstructor MEF
. MEF IServiceFactory
. this , ,

6 2005 2010: 159

. IServiceFactory
PlanMyNight.Web ServiceFactory.cs.
RouteTableConfiguration.cs URL,
PrintItineraryController. , ,
Application_Start, Global.asax.cs
PlanMyNight.Web:
// EF Controller
var controllerFactory = new MefControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
//
foreach (RouteCollection routes in container.GetExportedValues<RouteCollection>())
{
foreach (var route in routes)
{
RouteTable.Routes.Add(route);
}
}

controllerFactory MEF, Areas (


). .
, MEF, .
MEF MVC.
ItineraryContextualActionsExport.cs
, .
ViewModelExtensions.cs PlanMyNight.Web
:
//
var addinBoxes = new List<RouteValueDictionary>();
var addinLinks = new List<ExtensionLink>();
addinBoxes.AddRange(AddinExtensions.GetActionsFor("ItineraryToolbox", model.Id == 0
? null : new { id = model.Id }));
addinLinks.AddRange(AddinExtensions.GetLinksFor("ItineraryLinks", model.Id == 0 ?
null : new { id = model.Id }));

AddinExtensions.GetLinksFor
MEF ,
addinLinks ( ).
, .

,
Visual Studio 2010.
, , -
ASP.NET MVC -. , Managed Extensibility
Framework
. , Visual Studio 2010
.

Microsoft Visual Studio 2010

2005 2010:

Microsoft Visual Studio 2010

Visual Studio 2010

Visual Studio 2005 2010

,
Visual Studio.
Visual Studio 2010 ,
.

Visual Studio 2010


.
Plan My Night.
,
%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 7\Code.
PlanMyNight.sln.
,
:
94. Solution Explorer, PlanMyNight.Web .
, PlanMyNight.Web Set As StartUp
Project ( ).
95. PlanMyNight.Web Global.asax.cs,
Global.asax,
Global.asax.cs, . 7-1.

. 7-1 Solution Explorer Global.asax.cs

7 2005 2010:

161


Plan My Night ,
.

.
(intermediate language, IL),
.

, Global.ascx.cs.
.
96. Application_BeginRequest(object sender, EventArgs e)
var url = HttpContext.Current.Request.Url;, F9. . 7-2
, .

. 7-2

97. F5, .
- , ,
. Breakpoints ( )
, Debug ()
Windows () Breakpoints,
Ctrl+D+B.
Breakpoints, . 7-3.

. 7-3 Breakpoints

98. . Breakpoints ,
. 7-4.

. 7-4 Breakpoints

7 2005 2010:

162

Visual Studio 2005 ,


Visual Studio 2005, , Breakpoints . ,
Visual Studio 2005 (. 7-5).

. 7-5 Breakpoints Visual Studio 2005

99. , Breakpoints Labels (),


. ,
Visual Studio 2010. ,
Breakpoints Edit Labels ( )
Alt+F9, L. . 7-6.

. 7-6 Edit Labels

100. Edit Breakpoint Labels ( )


( Breakpoints). Type a New Label ( )
ContextRequestUrl Add.
url. , OK. . 7-7 , Edit
Breakpoint Labels , Breakpoints .

. 7-7 , Breakpoints

7 2005 2010:

163

,
Edit Labels.


, Or Choose Among Existing Labels (
) Edit Breakpoint Labels (. 7-7).

101. .
Breakpoints , . 7-8.

. 7-8 Breakpoints


.
Visual Studio 2010.
102. , url ,
, url.
, ,
. Visual Studio 2005
,
, ,
, .
Visual Studio 2010
, .
. ,
. , .

103. Breakpoints Export ()



. breakexports.xml.
104.
, Delete All Breakpoints Matching The Current
Search Criteria ( , ),
Delete The Selected Breakpoints ( )
.
.
105. , Import ()

. ,
. .


,
, . , ,
, printf WriteLn
? , , ,
, .
Visual Studio 2005 Visual Studio 2005 ,
,
. XML,

7 2005 2010:

164

. ,
, .
. 7-9.

. 7-9 Visual Studio 2010


Visual Studio 2005

-
Visual Studio 2010, ,
.
Visual Studio 2010
. .
,
, , . ,
:
106. Global.ascx.cs 89 91 , var
authority var pathAndQuery, .
107. .
, F5. , url
, . 7-10.

. 7-10

108. (
. 7-11 ). ,
( . 7-11 ).

. 7-11 ,
, ,
. :
.
, . , ,
. , .


, , . 7-12.

7 2005 2010:

165

, X
.

. 7-12

109. ,
, .
, , url,
Add Expression ( ), authority , , (authority !=
null).
.
null false, .
110. F10, , ,
url . ,
, . 7-13.

. 7-13 url

111. - ,
, .
, . 7-14.

. 7-14

112. , ,
.
, , , ,
. , ,
. ,
, , Solution Explorer,
, . . 7-15.

7 2005 2010:

166

. 7-15 Solution Explorer Windows


,
, , .
, . 7-16.
,
. , ,
.

. 7-16 ,


, . 7-17.

. 7-17 ,

,
. , -, Visual Studio,
.

. ,
url, (+). ,
, . 7-18.

7 2005 2010:

167

. 7-18 url

113. , Global.ascx.cs, ,
. ,
Stop Debugging ( ) (
)
Shift+F5. ,
.

. . 7-19 , .
. 7-19
, .
Debug Export DataTips Import DataTips, .


,
. ,
. Visual Studio 2010
.
Visual Studio 2005 Visual Studio 2005
SOS,
(Immediate). , .
, (Locals).
SOS . ,
, .
Bug Slayer
( ) MSDN http://msdn.microsoft.com/en-us/magazine/cc164138.aspx.

, . ,
:
114. Solution Explorer PlanMyNight.Web Default.aspx DefaultA.aspx
( A, Default).
115. , . Breakpoints
.
116. F5, .

HttpException. ,
. . 7-20 ,
.

. 7-20 ,

7 2005 2010:

168

117. . Debug Save


Dump As ( ), . 7-21. ,
. Cassini Personal Web Server Visual
Studio. (WebDev.WebServer40.dmp)
. ,
, 300 MB.

. 7-21

118. , Shift+F5 Stop Debugging.


119. File .
120. WebDev.WebServer40.dmp, File Open
. Minidump File Summary (
), ,
(. 7-22). ,
, , , CLR, ,
, .
. , (Modules) ,
. CLR 4.0, ..
Visual Studio 2010.

7 2005 2010:

169

. 7-22

121. , Actions () Minidump File Summary


Debug With Mixed ( ).
122. ,
. 7-23. , , .
, Break ().

. 7-23

123. , ,
. , Autos ( )
, controllerExport ( ) null.
, null ,
HttpException. , Locals
controllerName ( ), Default.aspx. Locals Autos
, ,
. , ,
.
, .
. 7-24 .

7 2005 2010:

170

. 7-24 Autos, Locals Call Stack

124. , . Shift+F5 Stop Debugging.


, PlanMyNight default.aspx.
Build, Rebuild Solution ( )
. F5,
.

Web.Config
, , ,
. Web.Config ,
. ,
. ,
ASP.NET () web.config
. ,
, MSDN: http://go.microsoft.com/fwlink/?LinkId=125889.


Visual Studio 2010 Professional
. Visual Studio 2010
. Visual Studio 2010 Premium Visual Studio 2010 Ultimate
, , IntelliTrace
Microsoft Test Manager 2010.
MSDN http://msdn.microsoft.com/en-us/library/ee789810(VS.100).aspx.
Visual Studio 2005 , Visual Studio 2005,
Visual Studio 2005 Team System Visual Studio 2005 Team Test.
, Nunit.

, Plan
My Night. ,
. , Visual Studio 2010.
Plan My Night Print Itinerary.
, .
, , .
, :
125. Solution Explorer PlanMyNight.Web Helpers.
ViewHelper.cs, . . 7-25 ,
.

7 2005 2010:

171

. 7-25 PlanMyNight.Web ViewHelper.cs Solution Explorer

126. .
Create Unit Tests (
). Test () New Test ( ).
, Visual Studio
. GetFriendlyTime (
) Create Unit Tests (. 7-26).

. 7-26

127. Create Unit Tests ,


, .
, .
PlanMyNight.Web.Tests. ,
Create A New Visual C# Test Project ( Visual C#). . 7-27
, .

7 2005 2010:

172

. 7-27 ,

128. OK ,
. TimeHelperTest.cs,
, .
129. , .
:
/// <summary>
/// GetFriendlyTime
///</summary>
// TODO: , UrlToTest URL
// ASP.NET (, http://.../Default.aspx).
// , -
// , ,
// - WCF-.
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\Users\\Patrice\\Documents\\Chapter
7\\code\\PlanMyNight.Web", "/")]
[UrlToTest("http://localhost:48580/")]
public void GetFriendlyTimeTest()
{
int totalMinutes = 0; // TODO:
string expected = string.Empty; // TODO:

string actual; actual = TimeHelper.GetFriendlyTime(totalMinutes);


Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method1.");
}

130. , Plan My
Night. ,
5:
[TestMethod]
public void ZeroReturnsSlash()
{
Assert.AreEqual("-", TimeHelper.GetFriendlyTime(0));
}
1

(. ).

7 2005 2010:

173

[TestMethod]
public void LessThan60MinutesReturnsValueInMinutes()
{
Assert.AreEqual("10m", TimeHelper.GetFriendlyTime(10));
}
[TestMethod()]
public void MoreThan60MinutesReturnsValueInHoursAndMinutes()
{
Assert.AreEqual("2h 3m", TimeHelper.GetFriendlyTime(123));
}

131. PlanMyNight.Web.Tests Helpers.


TimeHelperTests.cs . , . 7-28.

. 7-28 TimeHelperTest.cs Helpers

132. . ,
, public class TimeHelperTest.
Test, Run Tests In Current Context (
); CTRL+R, T (. 729).

. 7-29

133. .
Test Results ( ) (. 730).

7 2005 2010:

174

. 7-30 Test Results


Tests In Current
Context . , , ZeroReturnsSlash,
. , ,
All Tests In Solution ( ).

Threads
,
, : .
Threads ()
, ,
Process Monitor SysInternals (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx).
Threads Debug, Windows And
Threads ( ). . 7-31 Threads Plan My
Night.

. 7-31 Threads Plan My Night

Threads , .
, .
, . Visual Studio 2010,
, , ,
.
Visual Studio 2005 Visual Studio 2005 Visual Studio
.
- .


. ,
,
, . ,
Visual Studio 2010 Professional.
,
. , Visual Studio 2010
.
, , Visual Studio 2010 Professional

7 2005 2010:

175

. Visual Studio 2005 . ,


, ,
, ,
Visual Studio 2010 , Visual Studio.
Visual Studio 2010 .
Visual Studio 2010 ,
. IntelliTrace http://msdn.microsoft.com/enus/library/dd264915(VS.100).aspx Visual Studio 2010 Ultimate Microsoft Test
Manager. IntelliTrace
Visual Studio 2010 Visual Studio 2010 Team Foundation Server http://msdn.microsoft.com/enus/library/bb385901(VS.100).aspx.

Microsoft Visual Studio 2010

III

Microsoft Visual Studio 2008 Visual Studio 2010


,
:
2008 2010: - ()
2008 2010: ()
2008 2010: ()

Microsoft Visual Studio 2010

2008 2010: -

Entity Framework (EF)


-

Entity Data Model (EDM) POCO


ADO.NET Entity Framework

Microsoft Windows Server AppFabric (


Velocity)


Plan My Night (PMN)
. Microsoft SQL Server.
- Bing Maps.
- (. 8-1).

. 8-1 PlanMyNight

, - ,
, , .
.
PMN:

IItinerariesRepository ( ) (
Microsoft SQL Server).

IActivitiesRepository ( ) (- Bing
Map).

ICachingProvider ( )
( ASP.NET AppFabric Windows Server).
, PMN.

8 2008 2010: -

178

PMN SQL.
. . 8-2 ,
PMN.

. 8-2 PlanMyNight

Plan My Night
ASP.NET. . 8-2 .
MSDN ASP.NET 4 Introduction to
Membership
(ASP.NET 4

http://msdn.microsoft.com/enus/library/yh26yfzy(VS.100).aspx.

ZipCode ( )
.
.

PlanMyNight Microsoft Visual Studio 2008


Visual Studio 2008 ,
PlanMyNight .
.
, Visual Studio 2008.
DataSet ( ) DataReader ( )
ADO.NET (. 8-3). ,
. , :

SQL.

.
.

, ,
.

8 2008 2010: -

179

. 8-3 Insert ADO.NET Insert

DataSet, Visual Studio 2008.


PMN, TableAdapter Configuration Wizard (
TableAdapter) , . 8-4.
DataSet.
,
. , , :

- SQL, DataSet
.

- SQL-,
.

. ,
DataSet
TableAdapter , .
.

, , ,
,
. .

8 2008 2010: -

180

. 8-4 DataSet Visual Studio 2008

, Visual Studio 2008 LINQ to SQL (L2S). -


(Object Relational Designer) L2S
.
LINQ , .. SQL .
:

LINQ to SQL SQL Server.

.
.

, .
.NET 4.0 Entity Framework
LINQ .

,
Visual Studio 2010.
, ,
.

Visual Studio 2008 Entity Framework


ADO.NET Entity Framework (EF)
, . EF .NET Framework 4.
PlanMyNight
EF.
PMN. EF Entity Data Model (EDM) .
- , EF
, , EDM,
(Data Definition Language, DDL).

8 2008 2010: -

181

Visual Studio 2008 Entity Framework Visual Studio 2008 Service Pack 1.
EF, .NET Framework 4.0, ,
. :

T4,
.

POCO (Plain Old CLR Objects1),


.

- , .. ,
Visual Studio 2010 .

, Entity Framework,
POCO, EDMX.

,
.

,
.

ADO.NET Entity Framework .NET 4


MSDN Data Developer Center ( )
http://msdn.microsoft.com/en-us/data/aa937723.aspx.

EF:
,
PMN. ,
%userprofile%\Documents\Microsoft Press\Moving to
Visual Studio 2010\Chapter 8\Code\ExistingDatabase. PlanMyNight.sln.
, . 8-5.

PlanMyNight.Data: .

PlanMyNight.Contracts: .

PlanMyNight.Bing: Bing Map.

PlanMyNight.Web: .

PlanMyNight.AppFabricCaching: AppFabric.

8 2008 2010: -

182

. 8-5 PlanMyNight

EF . .
EDM PlanMyNight.Data.
PlanMyNight.Data, Add () New Item ( ). ADO.NET
Entity Data Model PlanMyNight.edmx, . 8-6.

. 8-6 Add New Item ADO.NET Entity Data Model

Entity Data Model Wizard .


. Generate From Database (
) Next ().
. New Connection (
). Choose Data Source ( )

Microsoft
SQL
Server

Continue
().

%userprofile%\Documents\Microsoft
Press\Moving
to
Visual Studio 2010\Chapter
8\ExistingDatabase\PlanMyNight.Web\App_Data\PlanMyNight.mdf (. 8-7)

8 2008 2010: -

183

. 8-7 EDM,

Next.
,
. , No (),
.

Choose Your Database Objects ( )


Itinerary ( ), ItineraryActivities (), ItineraryComment (
), ItineraryRating ( ) ZipCode ( ),

UserProfile
(
).

RetrieveItinerariesWithinArea ( ). Model
Namespace ( ) Entities (), . 8-8.

8 2008 2010: -

184

. 8-8 EDM,

Finish (), EDM.


Visual Studio 2008 EF , EntityType
( ), EntitySet ( ) NavigationProperty ( ),
, . ,
, ItineraryActivities, ,
: ItineraryActivity. - Pluralize or singularize generated object names (
), . 8-8,
, .


, ,
. ,
.
PMN ItineraryActivies Itinerary,
.
ItineraryActivities Activities. . 8-9.

8 2008 2010: -

185

. 8-9 , PlanMyNight

, ZipCode ZipCode1,
ZipCode, . ,
. Code, . 8-10.

. 8-10 ZipCode

, Ctrl+Shift+B.
EDM. , Location () PMN
. :
/ 'dbo.UserProfile' .
/ .
, .
UserProfile , ,
UserName ( ) .
EDM, UserProfile,
UserProfile .

8 2008 2010: -

186

PlanMyNight.edmx Open With


( ). Open With XML (Text) Editor (() XML),
. 8-11. OK, XML-, 1.

. 8-11 PlanMyNight.emdx XML


, PlanMyNight.edmx . Yes,
.

- .
UserProfile ,
UserProfile Key (). UserProfile .
, , UserName UserName
null. 8-1.
8-1 XML- UserProfile
<EntityType Name="UserProfile">
<Key>
<PropertyRef Name="UserName"/>
</Key>
<Property Name="UserName" Type="uniqueidentifier" Nullable="false" />
<Property Name="FullName" Type="varchar" MaxLength="500" />
<Property Name="City" Type="varchar" MaxLength="500" />
<Property Name="State" Type="varchar" MaxLength="500" />
<Property Name="PreferredActivityTypeId" Type="int" />
</EntityType>

XML- EDM, : The


Entity Data Model Designer is unable to display the file you requested. You can edit the model using the XML
Editor2.
Error List ( ) ,
:
Error 11002: Entity type 'UserProfile' has no entity set. 3
UserProfile,
. PlanMyNight.edmx XML. ,
Itinerary, XML-, 8-2.
8-2 XML- UserProfile
<EntitySet Name="UserProfile" EntityType="Entities.Store.UserProfile"
store:Type="Views" store:Schema="dbo" store:Name="UserProfile">
<DefiningQuery>

XML- (. )

Entity Data Model . XML


(. ).

'UserProfile' (. ).

8 2008 2010: -

187

SELECT
[UserProfile].[UserName] AS [UserName],
[UserProfile].[FullName] AS [FullName],
[UserProfile].[City] AS [City],
[UserProfile].[State] AS [State],
[UserProfile].[PreferredActivityTypeId] as [PreferredActivityTypeId]
FROM [dbo].[UserProfile] AS [UserProfile]
</DefiningQuery>
</EntitySet>

XML- EDM EDM. . 8-12


UserProfile Entities.Store (Model Browser).
Model Browser View (), Other Windows ( )
Entity Data Model Browser.

. 8-12 UserProfile Model Browser

, , UserProfile
UserProfile. EDM,
Add Entity. , . 8-13.

8 2008 2010: -

188

. 8-13 Add Entity

, . 8-13, OK, .
: City (), State () PreferedActiviyTypeId
( ).
UserProfile, Add Scalar Property ( ). ,
Type (), Max Length ( ) Unicode. . 8-1
.
8-1 UserProfile
Name

Type

Max Length

Unicode

FullName

String

500

False

City

String

500

False

State

String

500

False

PreferedActivityTypeId

Int32

, UserProfile , UserProfile.
UserProfile Table Mapping ( ),
. 8-14.

8 2008 2010: -

189

. 8-14 Table Mapping

UserProfile , . 8-15.
, .
UserProfile UserProfile.

. 8-15 UserProfile


Entity Data Model Wizard ( -)
RetrieveItinerariesWithinArea, .
, Function Import
( ).
Entities.Store Stored Procedures ( ).
RetrieveItineraryWithinArea Add Function Import (
). Add Function Import . 8-16.
, Entities, Itinerary . OK.

8 2008 2010: -

190

. 8-16 Add Function Import


RetrieveItinerariesWithinArea,
. 8-17.

8 2008 2010: -

191

. 8-17

EDM,
Validate (). .

EF: 1
, EF
. EF Visual Studio 2010
Data Definition Language (DDL),
. ,
.
. Entity Data Model Wizard Empty model
( ).
, PlanMyNight.Data, Add
New Item. ADO.NET Entity Data Model.

- (. )

8 2008 2010: -

192

. 8-18 EDM: Empty model

PMN

%userprofile%\Documents\Microsoft
Press\Moving
Visual Studio 2010\Chapter 8\Code\ModelFirst, PlanMyNight.sln.

to

PlanMyNight.Data EDM- PlanMyNight.edmx


. , . 8-2.
Entity Model .
ZipCode. Entity,
. 8-19. ZipCode, Id Code
String.

. 8-19

City State.
ZipCode, Add Scalar Property. ,
. 8-2.

8 2008 2010: -

193

8-2 ZipCode
Name

Type

Fixed Length

Max length

Unicode

Code

String

False

False

City

String

False

150

False

State

String

False

150

False

ItineraryComment Itinerary.
, Add Association ().

. 8-20 Add Association FK_ItineraryCommentItinerary


Visual Studio 2008 Entity Framework .NET 4.0 Foreign Key Associations (
). . Foreign Key Associations
, .NET 3.5 Independent Associations ( ) .

FK_ItineraryCommentItinerary,
, . 8-20. , ,
Referential Constraint ( ), . 8-21.

8 2008 2010: -

194

. 8-21 Association Referential Constraint

ItineraryRating Itinerary. ,
Add Association. FK_ItineraryItineraryRating.
, ,
ItineraryRating.
Referential Constraint, . 8-21. , Dependent ()
ItineraryComment, ItineraryRating.
ItineraryActivity Itinerary. FK_ItineraryItineraryActivity
Activities, . 8-22. , Referential
Constraint, .

. 8-22 Add Association FK_ItineraryActivityItinerary

8 2008 2010: -

195


, . EF
.
Generate Database From Model
( ), . 8-23.

. 8-23 Generate Database from Model

Generate Database Wizard .


DDL-
.
New Connection. Choose Data Source Microsoft SQL Server Database
File

Continue.

%userprofile%\Documents\Microsoft
Press\Moving
to
Visual Studio 2010\Chapter
8\Code\ModelFirst\Data\PlanMyNight.mdf (. 8-24).

8 2008 2010: -

196

. 8-24

, Next, ,
. 8-24. Finish T-SQL PlanMyNight.edmx.sql
. DDL- .

. 8-25 T-SQL

8 2008 2010: -

197

EDM , .
DDL- ,
, ,
.
PMN ,
, . ,
, EF: .

POCO-
EDM T4.
.
PlanMyNight.Designer.cs, PlanMyNight.edmx.
EntityObject , EF
.
T4 Text Template Transformation Toolkit (
). T4 Visual Studio 2010
(, ).
Visual Studio 2010 Code Generation and
Text Template ( ) http://msdn.microsoft.com/enus/library/bb126445(VS.100).aspx.

EF POCO. POCO-
. ( 8-3 POCO-
ZipCode.) EF
.
POCO Plain-Old CLR Objects.

ADO.NET POCO Entity Generator


%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter
8\Code\ExistingDatabase\PlanMyNight.sln.
PlanMyNight.edmx, Add Code Generation
Item ( ). , . 8-26,
. ADO.NET POCO
Entity Generator1 PlanMyNight.tt. Add.
,
. , OK,
.

. , Online Templates (- ),
POCO Search Online Templates ( - ) Enter,
, (. )

8 2008 2010: -

198

. 8-26 Add New Item

, PlanMyNight.tt PlanMyNight.Context.tt (. 8-27).


,
PlanMyNight.Designer.cs.

. 8-27

PlanMyNight.tt . 8-3
POCO- ZipCode.
8-3 POCO- ZipCode
namespace Microsoft.Samples.PlanMyNight.Data
{
public partial class ZipCode
{
#region Primitive Properties
public virtual string Code
{
get;

8 2008 2010: -

199

set;
}
public virtual string City
{
get;
set;
}
public virtual string State
{
get;
set;
}
#endregion
}
}

, PlanMyNight.Context.cs, ObjectContext ( )
PlanMyNight.edmx. .
POCO
.edmx.


PMN ,
.
, .
Visual Studio 2008 XSD
,
. EF T4 , .
.

POCO ADO.NET ,
.
PlanMyNight.tt PlanMyNight.Contracts.
PlanMyNight.tt, Cut (). Entities
PlanMyNight.Contracts Paste (). . 8-28.

. 8-28 POCO, Contracts

8 2008 2010: -

200

PlanMyNight.tt EDM.
, EDMX.
PlanMyNight.tt :
string inputFile = @"PlanMyNight.edmx";

, PlanMyNight.edmx PlanMyNight.Data:
string inputFile = @"..\..\PlanMyNight.Data\PlanMyNight.edmx";

, .
PlanMyNight.Context.tt PlanMyNight.Contracts,
Microsoft.Samples.PlanMyNight.Entities,
Microsoft.Samples.PlanMyNight.Data. PlanMyNight.Context.tt
using.
using
using
using
using

System;
System.Data.Objects;
System.Data.EntityClient;
Microsoft.Samples.PlanMyNight.Entities;

Ctrl+Shift+B, . .


SQL ,
PMN.
, Bing Maps
AppFabric Microsoft Windows Server, PMN.
, .
,
, Bing Maps.
PlanMyNight.Data.Test PlanMyNight.Data.
Visual Studio 2010 10.


Itinerary
IltinerariesRepository. :

IltinerariesRepository:

SearchByActivity
.

SearchByZipCode
.

SearchByRadius
.

Add .

PMN, %userprofile%\Documents\Microsoft Press\Moving to


Visual Studio 2010\Chapter 8\Code\Final, PlanMyNight.sln.
PlanMyNight.Data ItinerariesRepository.cs.
IltinerariesRepository.
PlanMyNightEntities, LINQ , EF T-SQL,
.
SearchByActivity. ,
( IsPublic true), activId
.
.

8 2008 2010: -

201

SearchByActivity LINQ, 8-4.


SearchByActivity.
8-4 SearchByActivity
public PagingResult<Itinerary> SearchByActivity(string activityId, int pageSize,
int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
var query = from itinerary in ctx.Itineraries.Include("Activities")
where itinerary.Activities.Any(t => t.ActivityId ==
activityId) && itinerary.IsPublic
orderby itinerary.Rating
select itinerary;
return PageResults(query, pageNumber, pageSize);
}
}

PageResults.
private static PagingResult<Itinerary>
int page, int pageSize)

PageResults(IQueryable<Itinerary>

query,

{
int rowCount = rowCount = query.Count();
if (pageSize > 0)
{
query = query.Skip((page - 1) * pageSize)
.Take(pageSize);
}
var result = new PagingResult<Itinerary>(query.ToArray())
{
PageSize = pageSize,
CurrentPage = page,
TotalItems = rowCount
};
return result;
}
IQueryable<Itinerary>,
. IQueryable IEnumerable , T-SQL
query.ToArray().

SearchByZipCode SearchByActivity,
. , LINQ ,
8-5. SearchByZipCode.
8-5 SearchByZipCode
public PagingResult<Itinerary> SearchByZipCode(int activityTypeId, string zip, int
pageSize, int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
var query = from itinerary in ctx.Itineraries.Include("Activities")
where itinerary.Activities.Any(t => t.TypeId == activityTypeId
&& t.Zip == zip)
&& itinerary.IsPublic
orderby itinerary.Rating

8 2008 2010: -

202

select itinerary;
return PageResults(query, pageNumber, pageSize);
}
}

SearchByRadius RetrieveItinerariesWithinArea,
.
. 8-6 SearchByRadius
ItinerariesRepository.cs.
8-6 SearchByRadius
public PagingResult<Itinerary> SearchByRadius(int activityTypeId, double longitude,
double latitude, double radius, int pageSize, int pageNumber)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.ContextOptions.ProxyCreationEnabled = false;
//
var totalOutput = new ObjectParameter("total", typeof(int));
var items = ctx.RetrieveItinerariesWithinArea(activityTypeId, latitude,
longitude, radius, pageSize, pageNumber, totalOutput).ToArray();
foreach (var item in items)
{
item.Activities.AddRange(this.Retrieve(item.Id).Activities);
}
int total = totalOutput.Value == DBNull.Value ? 0 : (int)totalOutput.Value;
return new PagingResult<Itinerary>(items)
{
TotalItems = total,
PageSize = pageSize,
CurrentPage = pageNumber
};
}
}

Add .
,
. 8-7 Add.
8-7 Add
public void Add(Itinerary itinerary)
{
using (var ctx = new PlanMyNightEntities())
{
ctx.Itineraries.AddObject(itinerary);
ctx.SaveChanges();
}
}

! ItinerariesRepository, ,
EF. , CTRL+R, A. ,
ItinerariesRepository, .



.
Visual Studio 2010 .NET Framework 4.0
. Task Parallel Library (TPL)1 Base Class Library (BCL)2
.NET Framework. , .NET- TPL
.
1

(. ).

(. ).

8 2008 2010: -

203

ItineraryActivity PMN Bing (Bing


Activity Id). Bing Activity ( Bing),
Bing Activity - Bing Maps ,
ItineraryActivity Itinerary.

Itinerary, 8-8. ,
RetrieveActivity ( ), ,
.
8-8
public void PopulateItineraryActivities(Itinerary itinerary)
{
foreach (var item in itinerary.Activities.Where(i => i.Activity == null))
{
item.Activity = this.RetrieveActivity(item.ActivityId);
}
}


. , TPL,
Parallel.ForEach, ,
, 8-9.
8-9
public void PopulateItineraryActivities(Itinerary itinerary)
{
Parallel.ForEach(itinerary.Activities.Where(i => i.Activity == null),
item =>
{
item.Activity = this.RetrieveActivity(item.ActivityId);
});
}

.NET Framework 4.0 Parallel LINQ (


System.Core.dll). PLINQ .AsParallel
LINQ. .AsOrdered
, .
System.Collections.Concurrent .
Parallel Computing (
) MSDN http://msdn.microsoft.com/en-us/concurrency/default.aspx.

AppFabric
PMN ,
- Bing Maps. -

.
, .
, .
.
-
- Bing Maps. . 8-29
, -.

8 2008 2010: -

204

. 8-29 -

, -
, . -
, -
.
AppFabric Windows Server .
AppFabric
, ,
. 8-30. API get set,
(CLR). AppFabric
, ..
.
, .

. 8-30 -, AppFabric Windows Server

AppFabric Windows Server


.NET Framework 4.0. , , Windows Server
AppFabric, Windows Server AppFabric http://msdn.microsoft.com/enus/windowsserver/ee695849.aspx.
PMN
ASP.NET, AppFabric Windows Server.
, AppFabric Windows Server PMN PMN: Adding

8 2008 2010: -

205

Caching using Velocity ( Velocity)


http://channel9.msdn.com/learn/courses/VS2010/ASPNET/EnhancingAspNetMvcPlanMyNight/Exercise-1Adding-Caching-using-Velocity/.

Visual Studio 2010


Plan My Night Entity Framework 4.0
.
POCO- ADO.NET Entity Framework AppFabric Windows Server.
-
ASP.NET MVC Managed Extensibility Framework ( ).

Microsoft Visual Studio 2010

2008 2010:

ASP.NET MVC,

ASP.NET MVC

Managed Extensibility
Framework

, ASP.NET 1.0, - Microsoft Visual Studio,


, . Visual Studio 2008 -
AJAX, Language Integrated Query (LINQ)34 ,
.
, ,
Visual Studio 2010.
Plan My Night.
- ASP.NET MVC 2, Visual Studio 2010 -
ASP.NET, ASP.NET (
- (Web Forms)). ASP.NET 4.0
,
-.

-.
,
Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 9\
UserInterface-Start.

PlanMyNight.Web
ASP.NET MVC 1.0 Framework Visual Studio 2008.
, ,
Visual Studio 2008, ASP.NET Web Forms 3.5.

Plan My Night Visual Studio 2010 ASP.NET MVC, , , , ,


- ASP.NET Visual Studio 2008. ( . 9-1)
( Global.asax), .
ASP.NET MVC.

34

(. ).

9 2008 2010: 207

. 9-1 PlanMyNight.Web

ASP.NET MVC:

Areas () ASP.NET MVC


- .
Plan My Night, ,
MVC-.

Controllers () ASP.NET MVC


.

Views () Views .
Controllers.
Shared (). , ,
, .
ASP.NET MVC,
, - ASP.NET,
http://asp.net/mvc.

web.config . Visual Studio


2010 : Web.config.
web.config web.config ,
, .
web.config, . 9-2.

. 9-2 Web.config

9 2008 2010: 208

Visual Studio 2008 Visual Studio 2008 , web.config


. web.config
. Visual Studio 2010 .
web.config web.Release.config.retail;
web.Debug.config.

Content

Helpers ( ) , ,
, .

Infrastructure () ,
ASP.NET MVC (,
).

ViewModels ( ) ,
(Controller) (Views) .

() , , .


, (. 9-3).

. 9-3 Plan My Night

,
Windows Live ID,
404 Not Found ( ) ( . 9-4).

. 9-4 , Plan My Night

,
.


AccountController ( ) Plan My Night
:

( Windows Live ID).

9 2008 2010: 209

ASP.NET MVC:
134. Solution Explorer ( ) Controllers PlanMyNight.Web
.
135. Add Controller.

136. , AccountController.
Add Action Methods For Create, Update, And Delete Scenarios (
, ).
-, ,

Add Add Controller AccountController


Index:
using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web;
System.Web.Mvc;

namespace Microsoft.Samples.PlanMyNight.Web.Controllers
{
public class AccountController : Controller
{
//
// GET: /Account/
public ActionResult Index()
{
return View();
}
}
}
Visual Studio 2008 ASP.NET Web Forms Visual Studio 2008:
ASP.NET MVC .aspx . ,
, ,
. -,
ASP.NET MVC.


()
.
using:

9 2008 2010: 210

using
using
using
using
using
using
using
using

System.IO;
Microsoft.Samples.PlanMyNight.Data;
Microsoft.Samples.PlanMyNight.Entities;
Microsoft.Samples.PlanMyNight.Infrastructure;
Microsoft.Samples.PlanMyNight.Infrastructure.Mvc;
Microsoft.Samples.PlanMyNight.Web.ViewModels;
System.Collections.Specialized;
WindowsLiveId;

. :
public class AccountController : Controller
{
private readonly IWindowsLiveLogin windowsLogin;
private readonly IMembershipService membershipService;
private readonly IFormsAuthentication formsAuthentication;
private readonly IReferenceRepository referenceRepository;
private readonly IActivitiesRepository activitiesRepository;
.
.
.

.
,

, ,
.
:

IWindowsLiveLogin ( WindowsLive)
Windows Live ID.

IMembershipService ( )
. - ASP.NET Membership Service
( ).

IFormsAuthentication ( )
ASP.NET Forms Authentication ( ).

IReferenceRepository ( ) ,
.

IActivitiesRepository ( )
.

: ,
ServiceFactory ( ) ,
.
public AccountController() :
this(
new ServiceFactory().GetMembershipService(),
new WindowsLiveLogin(true),
new FormsAuthenticationService(),
new ServiceFactory().GetReferenceRepositoryInstance(),
new ServiceFactory().GetActivitiesRepositoryInstance())
{
}
public AccountController(
IMembershipService membershipService,
IWindowsLiveLogin windowsLogin,
IFormsAuthentication formsAuthentication,
IReferenceRepository referenceRepository,
IActivitiesRepository activitiesRepository)
{
this.membershipService = membershipService;
this.windowsLogin = windowsLogin;
this.formsAuthentication = formsAuthentication;
this.referenceRepository = referenceRepository;
this.activitiesRepository = activitiesRepository;
}

9 2008 2010: 211


, ,
. , ,
, .
:
Windows Live ID, ASP.NET Forms Authentication ASP.NET Membership Services.
LiveID, .
AccountController :
public ActionResult LiveId()
{
return Redirect("~/");
}

Windows Live ID. ,


.
Redirect () RedirectResult ( ).
,

Windows Live ID ,
. Windows Live ID,
cookies Windows Live ID. Windows Live ID , URL
action,
.
LiveId return:
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out content);
return new FileStreamResult(new MemoryStream(content), type);
}

Windows Live ID
http://dev.live.com/.
Windows Live ID.
IFormsAuthentication cookie ASP.NET Forms
Authentication, http- ( )
. ,
cookies Windows Live ID (, , ).
,
(Membership Database).
, .
, Windows Live ID Windows Live ID,
WindowsLiveLogin.User:
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new NameValueCollection(Request.QueryString);
tokenContext["stoken"] =

9 2008 2010: 212

System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser = this.windowsLogin.ProcessLogin(tokenContext);

, , liveIdUser
WindowsLiveLogin.User, null. ,
, , liveIdUser
null:
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser(userId, userId, string.Empty);
var profile = this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = null;
return RedirectToAction("Index", new { returnUrl = returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
return Redirect(returnUrl);
}
}
break;

ValidateUser ( ) IMembershipService
, .
Windows Live ID, ID ( GUID)
, ASP.NET Membership Service.
, CreateUser
( ). CreateProfile ( )
.
. , .
Controller.RedirectToAction , URL
. Index ()
URL-

ASP.NET Forms, ..
cookie ,
, .
ASP.NET Membership Services
web.config :
<system.web>

<profile enabled="true">
<properties>
<add name="FullName" type="string" />
<add name="State" type="string" />
<add name="City" type="string" />
<add name="PreferredActivityTypeId" type="int" />
</properties>
<providers>
<clear />
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider,

9 2008 2010: 213

System.Web, Version=4.0.0.0, Culture=neutral,


PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ApplicationServices"
applicationName="/" />
</providers>
</profile>

</system.web>

LiveID , .
Windows Live ID, ASP.NET
Membership Service ASP.NET Forms.
public ActionResult LiveId()
{
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out content);
return new FileStreamResult(new MemoryStream(content), type);
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")
{
tokenContext = Request.Form;
}
else
{
tokenContext = new NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser = this.windowsLogin.ProcessLogin(tokenContext);
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser(userId, userId,
string.Empty);
var profile = this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = null;
return RedirectToAction("Index",
new { returnUrl = returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
return Redirect(returnUrl);
}
}

9 2008 2010: 214

break;
}
return Redirect("~/");
}

, Windows
Live ID. Plan My Night Windows Live
ID. ,
. Login ():
public ActionResult Login(string returnUrl)
{
var redirect = HttpContext.Request.Browser.IsMobileDevice ?
this.windowsLogin.GetMobileLoginUrl(returnUrl) :
this.windowsLogin.GetLoginUrl(returnUrl);
return Redirect(redirect);
}

URL- Windows Live


. ASP.NET Forms web.config
, , , :
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" name="XAUTH" timeout="2880" path="~/" />
</authentication>


, ,

.
Index
URL Global.asax. ,
, . Index,
AccountController, :
[Authorize()]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{
var profile = this.membershipService.GetCurrentProfile();
var model = new ProfileViewModel
{
Profile = profile,
ReturnUrl = returnUrl ?? this.GetReturnUrl()
};
this.InjectStatesAndActivityTypes(model);
return View("Index", model);
}
Visual Studio 2008 , [Authorize()],
Visual Studio 2008, ASP.NET MVC . ,
. (
) .

Authorize (). ,
http-. ,
ASP.NET Forms Authentication, .
AcceptVerbs ( ) ,
http-. HTTP GET.
returnUrl.
.
ASP.NET MVC (Model
Binding), . ,
returnUrl ( ,
) .
, null.

9 2008 2010: 215

, null,
InvalidOperationException ( ).

, : GetCurrentProfile (
) ASP.NET Membership Service
, . GetReturnUrl ( URL
) , PlanMyNight.Infrastructure.
Controller, (. 9-5).

. 9-5 MvcExtensions.cs

InjectStatesAndActivityTypes ( ) ,
AccountController.
. SelectListItem (HTML- MVC):
, , .
.
private void InjectStatesAndActivityTypes(ProfileViewModel model)
{
var profile = model.Profile;
var types = this.activitiesRepository.RetrieveActivityTypes().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Id.ToString(),
Selected = (profile != null && o.Id ==
profile.PreferredActivityTypeId)
}).ToList();
types.Insert(0, new SelectListItem { Text = "Select...", Value = "0" });
var states = this.referenceRepository.RetrieveStates().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Abbreviation,
Selected = (profile != null && o.Abbreviation ==
profile.State)
}).ToList();
states.Insert(0, new SelectListItem {
Text = "Any state",
Value = string.Empty
});
model.PreferredActivityTypes = types;
model.States = states;
}


,
, .

9 2008 2010: 216

, . Update , ,
:
[Authorize()]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken()]
public ActionResult Update(UserProfile profile)
{
var returnUrl = Request.Form["returnUrl"];
if (!ModelState.IsValid)
{
//
return this.IsAjaxCall() ? new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet, Data = ModelState }
: this.Index(returnUrl);
}
this.membershipService.UpdateProfile(profile);
if (this.IsAjaxCall())
{
return new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet,
Data = new { Update = true,
Profile = profile,
ReturnUrl = returnUrl } };
}
else
{
return RedirectToAction("UpdateSuccess", "Account", new { returnUrl =
returnUrl });
}
}

ValidateAntiForgeryToken ( , ) ,
.
AntiForgeryToken (, ) .
ModelState ( ) .
, ASP.NET MVC ,
. UserProfile,
MVC,
System.ComponentModel.DataAnnotations.Required. MVC
DataAnnotation ( ) ModelState
.
, ModelState , Index, ModelState
. , AJAX-, JsonResult
ModelState.
Visual Studio 2008 ASP.NET MVC , .
URL
. Visual Studio 2008
URL

ModelState , , AJAX-
JSON- .
UpdateSuccess ( ) Account.
UpdateSuccess , :
public ActionResult UpdateSuccess(string returnUrl)
{
var model = new ProfileViewModel
{
Profile = this.membershipService.GetCurrentProfile(),
ReturnUrl = returnUrl
};
return View(model);
}

,
,
.

9 2008 2010: 217

, Account ,
:
using
using
using
using
using
using
using
using
using
using
using
using

System;
System.Collections.Specialized;
System.IO;
System.Linq;
System.Web;
System.Web.Mvc;
Microsoft.Samples.PlanMyNight.Data;
Microsoft.Samples.PlanMyNight.Entities;
Microsoft.Samples.PlanMyNight.Infrastructure;
Microsoft.Samples.PlanMyNight.Infrastructure.Mvc;
Microsoft.Samples.PlanMyNight.Web.ViewModels;
WindowsLiveId;

namespace Microsoft.Samples.PlanMyNight.Web.Controllers
{
[HandleErrorWithContentType()]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class AccountController : Controller
{
private readonly IWindowsLiveLogin windowsLogin;
private readonly IMembershipService membershipService;
private readonly IFormsAuthentication formsAuthentication;
private readonly IReferenceRepository referenceRepository;
private readonly IActivitiesRepository activitiesRepository;
public AccountController() :
this(
new ServiceFactory().GetMembershipService(),
new WindowsLiveLogin(true),
new FormsAuthenticationService(),
new ServiceFactory().GetReferenceRepositoryInstance(),
new ServiceFactory().GetActivitiesRepositoryInstance())
{
}
public AccountController(IMembershipService membershipService,
IWindowsLiveLogin windowsLogin,
IFormsAuthentication formsAuthentication,
IReferenceRepository referenceRepository,
IActivitiesRepository activitiesRepository)
{
this.membershipService = membershipService;
this.windowsLogin = windowsLogin;
this.formsAuthentication = formsAuthentication;
this.referenceRepository = referenceRepository;
this.activitiesRepository = activitiesRepository;
}
public ActionResult LiveId()
{
string action = Request.QueryString["action"];
switch (action)
{
case "logout":
this.formsAuthentication.SignOut();
return Redirect("~/");
case "clearcookie":
this.formsAuthentication.SignOut();
string type;
byte[] content;
this.windowsLogin.GetClearCookieResponse(out type, out
content);
return new FileStreamResult(new MemoryStream(content), type);
default:
//
NameValueCollection tokenContext;
if ((Request.HttpMethod ?? "GET").ToUpperInvariant() == "POST")

9 2008 2010: 218

{
tokenContext = Request.Form;
}
else
{
tokenContext = new
NameValueCollection(Request.QueryString);
tokenContext["stoken"] =
System.Web.HttpUtility.UrlEncode(tokenContext["stoken"]);
}
var liveIdUser =
this.windowsLogin.ProcessLogin(tokenContext);
if (liveIdUser != null)
{
var returnUrl = liveIdUser.Context;
var userId = new Guid(liveIdUser.Id).ToString();
if (!this.membershipService.ValidateUser(userId, userId))
{
this.formsAuthentication.SignIn(userId, false);
this.membershipService.CreateUser( userId, userId,
string.Empty);
var profile =
this.membershipService.CreateProfile(userId);
profile.FullName = "New User";
profile.State = string.Empty;
profile.City = string.Empty;
profile.PreferredActivityTypeId = 0;
this.membershipService.UpdateProfile(profile);
if (string.IsNullOrEmpty(returnUrl)) returnUrl =
null;
return RedirectToAction("Index", new { returnUrl =
returnUrl });
}
else
{
this.formsAuthentication.SignIn(userId, false);
if (string.IsNullOrEmpty(returnUrl)) returnUrl =
"~/";
return Redirect(returnUrl);
}
}
break;
}
return Redirect("~/");
}
public ActionResult Login(string returnUrl)
{
var redirect = HttpContext.Request.Browser.IsMobileDevice ?
this.windowsLogin.GetMobileLoginUrl(returnUrl) :
this.windowsLogin.GetLoginUrl(returnUrl);
return Redirect(redirect);
}
[Authorize()]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{
var profile = this.membershipService.GetCurrentProfile();
var model = new ProfileViewModel
{
Profile = profile,
ReturnUrl = returnUrl ?? this.GetReturnUrl()
};
this.InjectStatesAndActivityTypes(model);
return View("Index", model);
}

9 2008 2010: 219

[Authorize()]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken()]
public ActionResult Update(UserProfile profile)
{
var returnUrl = Request.Form["returnUrl"];
if (!ModelState.IsValid)
{
//
return this.IsAjaxCall() ?
new JsonResult { JsonRequestBehavior =
JsonRequestBehavior.AllowGet, Data = ModelState }
: this.Index(returnUrl);
}
this.membershipService.UpdateProfile(profile);
if (this.IsAjaxCall())
{
return new JsonResult {
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new {
Update = true,
Profile = profile,
ReturnUrl = returnUrl } };
}
else
{
return RedirectToAction("UpdateSuccess",
"Account", new { returnUrl = returnUrl });
}
}
public ActionResult UpdateSuccess(string returnUrl)
{
var model = new ProfileViewModel
{
Profile = this.membershipService.GetCurrentProfile(),
ReturnUrl = returnUrl
};
return View(model);
}
private void InjectStatesAndActivityTypes(ProfileViewModel model)
{
var profile = model.Profile;
var types = this.activitiesRepository.RetrieveActivityTypes()
.Select(o => new SelectListItem { Text = o.Name,
Value = o.Id.ToString(),
Selected = (profile != null &&
o.Id == profile.PreferredActivityTypeId) })
.ToList();
types.Insert(0, new SelectListItem { Text = "Select...",
Value = "0" });
var states = this.referenceRepository.RetrieveStates().Select(
o => new SelectListItem {
Text = o.Name,
Value = o.Abbreviation,
Selected = (profile != null &&
o.Abbreviation == profile.State) })
.ToList();
states.Insert(0, new SelectListItem { Text = "Any state",
Value = string.Empty });
model.PreferredActivityTypes = types;
model.States = states;
}
}
}

9 2008 2010: 220


,
. Visual Studio 2010,
, .
Index Account:
137.

Views PlanMyNight.Web.

138.

Views , Add New Folder.

139.

Account.

140.

Account, Add View.

141.

Add View ( ), :

142. Add. HTML-


<asp:Content>:

, , Visual Studio 2008.


ASP.NET MVC 2 - ASP.NET,
MVC - .
, page System.Web.Mvc.ViewPage<ProfileViewModel>,

9 2008 2010: 221

. MVC , - ASP.NET,
. MVC, ,
. -
ASP.NET.
Account,
, :
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Plan My Night Profile
</asp:Content>

,
HtmlHeadContent ( HTML-):
<asp:Content ID="Content3" ContentPlaceHolderID="HtmlHeadContent" runat="server">
<% Ajax.RegisterClientScriptInclude(
Url.Content("~/Content/Scripts/jquery-1.4.1.min.js")); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/MicrosoftAjax.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/MicrosoftAjaxMvc.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/MicrosoftMvcValidation.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/ajax.common.js"), "pmn"); %>
<% Ajax.RegisterCombinedScriptInclude(
Url.Content("~/Content/Scripts/ajax.profile.js"), "pmn"); %>
<%= Ajax.RenderClientScripts() %>
</asp:Content>

System.Web.Mvc.AjaxHelper,
PlanMyNight.Infrastructure MVC.
, :
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div class="panel" id="profileForm">
<div class="innerPanel">
<h2><span>My Profile</span></h2>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm("Update", "Account")) %>
<% { %>
<%=Html.AntiForgeryToken()%>
<div class="items">
<fieldset>
<p>
<label for="FullName">Name:</label>
<%=Html.EditorFor(m => m.Profile.FullName)%>
<%=Html.ValidationMessage("Profile.FullName",
new { @class = "field-validation-error-wrapper" })%>
</p>
<p>
<label for="State">State:</label>
<%=Html.DropDownListFor(m => m.Profile.State,
Model.States)%>
</p>
<p>
<label for="City">City:</label>
<%=Html.EditorFor(m => m.Profile.City,
Model.Profile.City)%>
</p>
<p>
<label for="PreferredActivityTypeId">Preferred
activity:</label>
<%=Html.DropDownListFor(m =>
m.Profile.PreferredActivityTypeId,
Model.PreferredActivityTypes)%>
</p>
</fieldset>
<div class="submit">
<%=Html.Hidden("returnUrl", Model.ReturnUrl)%>

9 2008 2010: 222

<%=Html.SubmitButton("submit", "Update")%>
</div>
</div>
<div class="toolbox"></div>
<% } %>
</div>
</div>
</asp:Content>

, HTML-.
, (
).
Visual Studio 2008 Visual Studio 2008
. ASP.NET MVC
, . -
ASP.NET Web Forms.
<asp:Content>. , , ASP.NET Web Forms
-

MVC HTML. ,
System.Web.Mvc.HtmlHelper, HTML-
. MVC-
, -,
. (HtmlHelper<TModel>)
ViewPage<TModel>.Html.
HTML- ( , ):

Html.EnableClientValidation ( )
ModelState

Html.BeginForm ( ) <form>
using. ,
, .
MVC URL
, URL .

Html.AntiForgeryToken ,
,
ValidateAntiForgeryToken. Update .

Html.EditorFor ( ) ,
. Html.Editor.

Html.DropDownListFor ( ) ,
.
Html.DropDownList.

Html.ValidationMessage ( ) ,
,
ModelState.

Html.Hidden () .

Html.SubmitButton ( ) Submit ().


Index ,
UpdateSuccess, .

UpdateSuccess:
143. PlanMyNight.Web Solution Explorer Views.
144. Account.
145. Add View.

9 2008 2010: 223

146. Add View, :

:
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">Plan My Night Profile Updated</asp:Content>

MainContent :
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div class="panel" id="profileForm">
<div class="innerPanel">
<h2><span>My Profile</span></h2>
<div class="items">
<p>Your profile has been successfully updated.</p>
<h3> <a href="<%=Html.AttributeEncode(Model.ReturnUrl ??
Url.Content("~/"))%>">Continue</a></h3>
</div>
<div class="toolbox">
</div>
</div>
</div>
</asp:Content>

, Site.Master (
Views/Shared -). 33,
. :
<%=Html.ActionLink<AccountController>(c => c.Index(null), "My Profile")%>

9 2008 2010: 224

, , .
Sign In (), . 9-6,
Windows Live ID.

. 9-6 Plan My Night

, , Index
Account (. 9-7).

. 9-7 , Index Account

, My Profile ( ),
.
, , Full Name
( ). (. 9-8).

9 2008 2010: 225

. 9-8 Model Binding

, .
, , Index.aspx
Account, Html.EnableClientValidation.
AJAX JavaScript MVC
, , , .
Visual Studio 2008 ASP.NET MVC ID HTML-
, ASP.NET Web Forms 3.5. Visual Studio 2008
UniqueID / JavaScript,
JavaScript. , ID,
ASP.NET 3.5 Web Forms
JavaScript. MVC , ID
. , ASP.NET 4.0 Web Forms
ID

Account
Plan My Night.
Visual Studio 2010 MVC 2.0. MVC
-. - ASP.NET ASP.NET
, Visual Studio 2010. - ASP.NET
MVC .

-
, -
. ,
. 9-9.

9 2008 2010: 226

. 9-9 Plan My Night

, , :
, .
(, .)
,
.
Plan My Night,
- ASP.NET,
Visual Studio. , .
-:
147. PlanMyNight.Web ( ),
Add New Item.
148. Add New Item Web Form using Master Page (-,
) Name : ErrorFeedback.aspx.

149. , -.
, Project Folders ( ) PlanMyNight.Web,
WebForms.Master .

9 2008 2010: 227

150. (Split
view), ( (Design view)).
( ,
Visual Studio). :

,
, , .

,
.
, View ().
drag-and-drop div ( HTML)
MainContent ( ) . div,
, .
div Properties () ( , F4).
Properties (Id) profileForm ( ) (
). Class () panel ().
, CSS.
div class innerPanel ( ).
innerPanel :
<h2><span>Error Feedback</span></h2>

<h2>, . Insert Snippet (


) ASP.NET > formr. ,
- .
div, class items (), div fieldset
( ).

9 2008 2010: 228

fieldset TextBox ( Standard ()


). ID FullName.
<label> (),
for ID , .. Full Name: ( ). <label> -
, <label> </label>. <p>,
, . 9-10.

. 9-10 ErrorFeedback.aspx

, ID
EmailAddress ( ) Email Address: (
). TextBox ID Comments
().
TextBox. Comments ,
TextMode ( ) Multiline
(), Rows () 5 Columns () 40.
, .
Insert Snippet Comments div with
class (HTML>divc). div submit.
div Button (). Text () Send Feedback
( ).
. 9-11.
, .

. 9-11 ErrorFeedback.aspx

.
,

9 2008 2010: 229

ASP.NET. Full Name Comments


,
.
Validation ()
. RequiredFieldValidator (
) Full Name.
ControlToValidate (
) FullName. (
.) CssClass ( CSS) field-validation-error (
). , .
, Error Message ( ) Name is Required (
) (. 9-12).

. 9-12

Comments, ErrorMessage
( ) ControlToValidate.
Email
Address, RegularExpressionValidator
.
, .. ControlToValidate EmailAddress
CssClass field-validation-error.
, .
ValidationExpression ( ),
:
[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}

:
.
. ,
. Solution Explorer
PlanMyNight.Web Views Shared. Error.aspx
35.
, .
:
or <a href="/ErrorFeedback.aspx">send feedback</a>?


MVC . ,
.
Plan My Night:
151. .
152. , :
http://www.planmynight.net:48580/Itineraries/Details/38923828.

9 2008 2010: 230

153. , ID,
.
, .
( F5),
:

154. .
, .

ASP.NET (
), , .
,
Page.IsValid .
( ), true.
,
( Page.IsValid , -
):
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack && this.IsValid)
{
this.Response.Redirect("/", true);
}
}

, -
ASP.NET . PlanMyNight.Web . ,

9 2008 2010: 231

, ,
, .
-
Managed Extensibility Framework (MEF).

MEF
Visual Studio 2010 .NET Framework 4 Managed Extensibility
Framework (MEF). Managed Extensibility Framework ,
,
. MEF
,
. MEF ,
, (), ,
(),
. ,
.
- MEF,
, http://mef.codeplex.com.
Plan My Night . Addins ()
(. 9-13).

. 9-13 Plan My Night

PlanMyNight.Addins.EmailItinerary ,
. PlanMyNight.Addins.PrintItinerary .
, PlanMyNight.Addins.Share (
), URL.
. ,
PlanMyNight.Contracts PlanMyNight.Infrastructure, (
) MEF,
.
- , ,
PlanMyNight.Web, .

9 2008 2010: 232

, DeployAllAddins.bat,
PlanMyNight.sln.
Areas PlanMyNight.Web. , , ,
-.

. ,
PlanMyNight, .
, New () Save (),
(. 9-14).

. 9-14

,
(. 9-15).

. 9-15
Visual Studio 2008 Visual Studio 2008 MEF.

. ,
.
MEF .NET Framework
.

9 2008 2010: 233


PrintItinerary.Addin.
, . 9-16.

. 9-16 PrintItinerary

PlanMyNight.Web (Controllers Views),


MVC Area.
PrintItineraryController.cs Controller, ,
, ( ), ,
PlanMyNight.Web.
:
[Export("PrintItinerary", typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]

MEF. , Export (),


IController PrintItinerary.
,
/singleton-.
, MEF. , PartCreationPolicy ( )
, ,
.
PrintItineraryController.cs ,
ImportingConstructor ( ):
[ImportingConstructor]
public PrintItineraryController(IServiceFactory serviceFactory) :
this(
serviceFactory.GetItineraryContainerInstance(),
serviceFactory.GetItinerariesRepositoryInstance(),
serviceFactory.GetActivitiesRepositoryInstance())
{
}

9 2008 2010: 234

ImportingConstructor MEF
. MEF IServiceFactory
. this , ,
. IServiceFactory
PlanMyNight.Web ServiceFactory.cs.
RouteTableConfiguration.cs URL,
PrintItineraryController. , ,
Application_Start, Global.asax.cs
PlanMyNight.Web:
// EF Controller
var controllerFactory = new MefControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
//
foreach (RouteCollection routes in container.GetExportedValues<RouteCollection>())
{
foreach (var route in routes)
{
RouteTable.Routes.Add(route);
}
}

controllerFactory MEF, Areas (


). .
, MEF, .
MEF MVC.
ItineraryContextualActionsExport.cs
, .
ViewModelExtensions.cs PlanMyNight.Web
:
//
var addinBoxes = new List<RouteValueDictionary>();
var addinLinks = new List<ExtensionLink>();
addinBoxes.AddRange(AddinExtensions.GetActionsFor("ItineraryToolbox", model.Id == 0
? null : new { id = model.Id }));
addinLinks.AddRange(AddinExtensions.GetLinksFor("ItineraryLinks", model.Id == 0 ?
null : new { id = model.Id }));

AddinExtensions.GetLinksFor
MEF ,
addinLinks ( ).
, .

,
Visual Studio 2010.
, , -
ASP.NET MVC -. , Managed Extensibility
Framework
. , Visual Studio 2010
.

Microsoft Visual Studio 2010

10

2008 2010:

Microsoft Visual Studio 2010

Visual Studio 2010

Visual Studio 2008 2010

,
Visual Studio.
Visual Studio 2010 ,
.

Visual Studio 2010


.
Plan My Night.
,
%userprofile%\Documents\Microsoft Press\Moving to Visual Studio 2010\Chapter 10\Code.
PlanMyNight.sln.
,
:
155. Solution Explorer, PlanMyNight.Web .
, PlanMyNight.Web Set As StartUp
Project ( ).
156. PlanMyNight.Web Global.asax.cs,
Global.asax,
Global.asax.cs, . 10-1.

. 10-1 Solution Explorer Global.asax.cs

10 2008 2010:

236


Plan My Night ,
.

.
(intermediate language, IL),
.

, Global.ascx.cs.
.
157. Application_BeginRequest(object sender, EventArgs e)
var url = HttpContext.Current.Request.Url;, F9. . 10-2
, .

. 10-2

158. F5, .
- , ,
. Breakpoints ( )
, Debug ()
Windows () Breakpoints,
Ctrl+D+B.
Breakpoints, . 10-3.

. 10-3 Breakpoints

159. . Breakpoints ,
. 10-4.

. 10-4 Breakpoints

10 2008 2010:

237

Visual Studio 2008 ,


Visual Studio 2008, , Breakpoints . ,
Visual Studio 2008 (. 10-5).

. 10-5 Breakpoints Visual Studio 2008

160. , Breakpoints Labels (),


. ,
Visual Studio 2010. ,
Breakpoints Edit Labels ( )
Alt+F9, L. . 10-6.

. 10-6 Edit Labels

161. Edit Breakpoint Labels ( )


( Breakpoints). Type a New Label ( )
ContextRequestUrl Add.
url. , OK. . 10-7 , Edit
Breakpoint Labels , Breakpoints .

10 2008 2010:

238

. 10-7 , Breakpoints
,
Edit Labels.


, Or Choose Among Existing Labels (
) Edit Breakpoint Labels (. 10-7).

162. .
Breakpoints , . 10-8.

. 10-8 Breakpoints


.
Visual Studio 2010.
163. , url ,
, url.
, ,
. Visual Studio 2008
,
, ,
, .
Visual Studio 2010
, .
. ,
. , .

164. Breakpoints Export ()



. breakexports.xml.
165.
, Delete All Breakpoints Matching The Current
Search Criteria ( , ),
Delete The Selected Breakpoints ( )
.
.
166. , Import ()

. ,
. .
Visual Studio 2008 Visual Studio 2008 , Visual Studio 2010 ,
JavaScript jQuery. Visual Studio 2008 , Visual Studio 2010
, , .


,
, . , ,

10 2008 2010:

239

, printf WriteLn
? , , ,
, .
Visual Studio 2005 Visual Studio 2005 ,
Visual Studio 2008, ,
.
XML, . ,
,
. . 10-9.

. 10-9 Visual Studio 2008

Visual Studio 2008 Visual Studio 2008 .


LINQ
, , Locals ( ) Watch
( ) QuickWatch ( ).
LINQ LINQ
. , , .
,
.

-
Visual Studio 2010, ,
.
Visual Studio 2010
. .
,
, , . ,
:
167. Global.ascx.cs 89 91 , var
authority var pathAndQuery, .
168. .
, F5. , url
, . 10-10.

. 10-10

169. (
. 10-11 ). ,
( . 10-11 ).

10 2008 2010:

240

. 10-11 ,
, ,
. :
.
, . , ,
. , .


, , . 10-12.
, X
.

. 10-12

170. ,
, .
, , url,
Add Expression ( ), authority , , (authority !=
null).
.
null false, .
171. F10, , ,
url . ,
. . 10-13 , .

. 10-13 url

172. - ,
, .
. . 10-14.

. 10-14

173. , ,
.
, , , ,
. , ,
. ,

10 2008 2010:

241

, , Solution Explorer,
, . . 10-15.

. 10-15 Solution Explorer Windows


,
, , .
, . 10-16.
,
. , ,
.

. 10-16 ,


, . 10-17.

. 10-17 ,

,
. , -, Visual Studio,
.

. ,
url, (+). ,
, . 10-18.

10 2008 2010:

242

. 10-18 url

174. , Global.ascx.cs, ,
. ,
Stop Debugging ( ) (
)
Shift+F5. ,
.
. . 10-19 , .

. 10-19
, .
Debug Export DataTips Import DataTips, .


,
. ,
. Visual Studio 2010
.
Visual Studio 2008 Visual Studio 2008
SOS,
(Immediate). , .
, (Locals).
SOS . ,
, .
Bug Slayer
( ) MSDN http://msdn.microsoft.com/en-us/magazine/cc164138.aspx.

, . ,
:
175. Solution Explorer PlanMyNight.Web Default.aspx DefaultA.aspx
( A, Default).
176. , . Breakpoints
.
177. F5, .

HttpException. ,
. . 10-20 ,
.

. 10-20 ,

10 2008 2010:

243

178. . Debug Save


Dump As ( ), . 10-21. ,
. Cassini Personal Web Server
Visual Studio. (WebDev.WebServer40.dmp)
. ,
, 300 MB.

. 10-21

179. , Shift+F5 Stop Debugging.


180. File .
181. WebDev.WebServer40.dmp, File Open
. Minidump File Summary (
), ,
(. 10-22). ,
, , , CLR, ,
, .
. , (Modules) ,
. CLR 4.0, ..
Visual Studio 2010.

10 2008 2010:

244

. 10-22

182. , Actions () Minidump File Summary


Debug With Mixed ( ).
183. ,
. 10-23. , , .
, Break ().

. 10-23

184. , ,
. , Autos ( )
, controllerExport ( ) null.
, null ,
HttpException. , Locals
controllerName ( ), Default.aspx. Locals Autos
, ,
. , ,
.
, .
. 10-24 .

10 2008 2010:

245

. 10-24 Autos, Locals Call Stack

185. , . Shift+F5 Stop Debugging.


, PlanMyNight default.aspx.
Build, Rebuild Solution ( )
. F5,
.

Web.Config
, , ,
. Web.Config ,
. ,
. ,
ASP.NET () web.config
. ,
, MSDN: http://go.microsoft.com/fwlink/?LinkId=125889.


Visual Studio 2010 Professional
. Visual Studio 2010
. Visual Studio 2010 Premium Visual Studio 2010 Ultimate
, , IntelliTrace
Microsoft Test Manager 2010.
MSDN http://msdn.microsoft.com/en-us/library/ee789810(VS.100).aspx.
Visual Studio 2008 , Visual Studio 2008,
Visual Studio 2008 Team System Visual Studio 2008 Team Test.
, Nunit.

,
Plan My Night. ,
. , Visual Studio 2010.
Plan My Night Print Itinerary.
, .
, , .
, :
186. Solution Explorer PlanMyNight.Web Helpers.
ViewHelper.cs, . . 10-25 ,
.

10 2008 2010:

246

. 10-25 PlanMyNight.Web ViewHelper.cs Solution Explorer

187. .
Create Unit Tests (
). Test () New Test ( ).
, Visual Studio
. GetFriendlyTime (
) Create Unit Tests (. 10-26).

. 10-26

188. Create Unit Tests ,


, .
, .
PlanMyNight.Web.Tests. ,
Create A New Visual C# Test Project ( Visual C#). . 1027 , .

10 2008 2010:

247

. 10-27 ,

189. OK ,
. TimeHelperTest.cs,
, .
190. , .
:
/// <summary>
/// GetFriendlyTime
///</summary>
// TODO: , UrlToTest URL
// ASP.NET (, http://.../Default.aspx).
// , -
// , ,
// - WCF-.
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\Users\\Patrice\\Documents\\Chapter
10\\code\\PlanMyNight.Web", "/")]
[UrlToTest("http://localhost:48580/")]
public void GetFriendlyTimeTest()
{
int totalMinutes = 0; // TODO:
string expected = string.Empty; // TODO:

string actual; actual = TimeHelper.GetFriendlyTime(totalMinutes);


Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method1.");
}

191. , Plan My
Night. ,
5:
[TestMethod]
public void ZeroReturnsSlash()
{
Assert.AreEqual("-", TimeHelper.GetFriendlyTime(0));
}
1

(. ).

10 2008 2010:

248

[TestMethod]
public void LessThan60MinutesReturnsValueInMinutes()
{
Assert.AreEqual("10m", TimeHelper.GetFriendlyTime(10));
}
[TestMethod()]
public void MoreThan60MinutesReturnsValueInHoursAndMinutes()
{
Assert.AreEqual("2h 3m", TimeHelper.GetFriendlyTime(123));
}

192. PlanMyNight.Web.Tests Helpers.


TimeHelperTests.cs . , . 10-28.

. 10-28 TimeHelperTest.cs Helpers

193. . ,
, public class TimeHelperTest.
Test, Run Tests In Current Context (
); CTRL+R, T
(. 10-29).

. 10-29

194. .
Test Results ( ) (. 1030).

10 2008 2010:

249

. 10-30 Test Results


Tests In Current
Context . , , ZeroReturnsSlash,
. , ,
All Tests In Solution ( ).

Threads
,
, : .
Threads ()
, ,
Process Monitor SysInternals (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx).
Threads Debug, Windows And
Threads ( ). . 10-31 Threads Plan My
Night.

. 10-31 Threads Plan My Night

Threads , .
, .
, . Visual Studio 2010,
, , ,
.
Visual Studio 2008 Visual Studio 2008 , , .
, , .
. , ID
.


. ,
,
, . ,
Visual Studio 2010 Professional.
,
. , Visual Studio 2010
.

10 2008 2010:

250

, , Visual Studio 2010 Professional




. Visual Studio 2008 . ,
, ,
, ,
Visual Studio 2010 , Visual Studio.
Visual Studio 2010 .
Visual Studio 2008 Visual Studio 2010 ,
.
Visual Studio 2010 ,
. IntelliTrace http://msdn.microsoft.com/enus/library/dd264915(VS.100).aspx Visual Studio 2010 Ultimate Microsoft Test
Manager. IntelliTrace
Visual Studio 2010 Visual Studio 2010 Team Foundation Server http://msdn.microsoft.com/enus/library/bb385901(VS.100).aspx.

251

.NET Framework 4.0, 2003 2010


Managed Extensibility Framework (MEF), 69
PLINQ, 42, 89
AppFabric, 43
, 4142
.NET Framework 4.0, 2005 2010
Managed Extensibility Framework (MEF), 156
PLINQ, 129
AppFabric, 130
, 4142
.NET Framework 4.0, 2008 2010
Managed Extensibility Framework (MEF), 232
PLINQ, 204
AppFabric, 2046
, 2034
AcceptVerbs, , 52, 139, 215
Add Web Service Reference, 3940, 3940
Add, , 36, 124, 126, 201, 203
ADO.NET Entity Framework (EF). . Entity
Framework
ADO.NET POCO Entity Generator, 3234, 3234, 3234
AJAX, 54, 141, 217
AntiForgeryToken, 54, 141, 217
AppFabric, , 4243, 4243, 2046
Areas, , 44, 132, 208
ASP.NET MVC, 2003 2010
, 54
, 4647
, 42
, 44
, 4445
, 52, 54
-, 47
ASP.NET MVC, 2005 2010
, 141
, 4647
, 130
, 44
, 4445
, 139, 141
-, 134
ASP.NET MVC, 2008 2010
, 217
, 4647
, 2046
, 44
, 4445
, 215, 217
-, 210
ASP.NET Web Forms. . -
Authorize, , 52, 139, 215
Controller.RedirectToAction, 50, 137, 213
Copy Project, , 92
CreateProfile, 50, 137, 213
CreateUser, , 50, 137, 213
CSS, , 65, 152, 228
Entity Framework (EF), 2003 2010
PlanMyNight, , 16
, 1635
- , , 2635

, 16
, , 1626
Entity Framework (EF), 2005 2010
PlanMyNight, , 104
, 1635
- , , 2635
, 104
, , 1626
Entity Framework (EF), 2008 2010
PlanMyNight, , 182
Visual Studio 2008, 182
, 1635
- , , 181,
2635
, 181
, , 18292
EntitySet, 109, 185, 187
EntityType, 109, 185, 187
GetCurrentProfile, 53, 139, 216
GetReturnUrl, 53, 139, 216
HTML-, 6061, 6061, 6061
IActivitiesRepository, , 14, 48, 101, 135, 178,
211
ICachingProvider, , 14, 101, 178
ID, , 63, 150, 226
IFormsAuthentication, 48, 135, 211
IItinerariesRepository, , 14, 35, 101, 123, 178,
201
IMembershipService, 48, 135, 211
Index, , 52, 139, 215
Index, , 5861, 5861, 5861
InjectStatesAndActivityTypes, , 5354, 5354, 53
54
InstallShield, 95
IReferenceRepository, 48, 135, 211
ItineraryActivities, , 19, 107,
185
IWindowsLiveLogin, 48, 135, 211
jQuery, 78, 239
JsonResult, 54, 141, 217
Language Integrated Query (LINQ), 36, 124, 240
LiveID, , 5051, 5051, 5051
Login, , 51, 138, 215
Managed Extensibility Framework (MEF), 69, 156, 232
MSBuild, 92, 93, 94, 98
msdeploy, , 95, 99
NavigationProperty, 185
one-click, , 9798
Plain-Old CLR Objects. . POCO-
PLINQ, , 42, 89, 129, 204
POCO-, 32, 182, 32
PrintIntinerary.Addin, , 7173, 7173, 7173
SearchByActivity, 3638, 124, 3638, 2012
SearchByRadius, 36, 3839, 124, 3839, 201, 203
SearchByZipCode, 36, 38, 124, 38, 201, 202
SOS, , 81, 168, 243
T4 (Text Template Transformation Toolkit), ,
32, 34, 32, 122, 182, 32, 200
TFSBuild, 92, 97, 98
Threads, , 89

252

Update, , 54
UpdateSuccess, , 6163, 6163, 6163
UserProfile, 2024, 2024, 2024
ValidateAntiForgeryToken, , 54, 141, 217
ValidateUser, , 50, 137, 213
ViewModels, 45, 132, 209
Visual Studio 2003
Add Web Service Reference, 3940
jQuery, 78
, 52, 63
-, 47
Plan My Night, 1516
, 54
SOS, 81
InjectStatesAndActivityTypes, 5354
, 53
, 85

, 34
, 36
Breakpoints, 76
, 75, 78, 81
, 71
CSS, 65
, 60
, 3637
web.config, 45
Visual Studio 2005
Add Web Service Reference, 3940
, 139, 150
-, 134
Plan My Night, 1516
, 141
SOS, 168
InjectStatesAndActivityTypes, 5354
, 139
, 171
, 124
XSD, 122
Breakpoints, 163
, 163, 164, 168, 175
, 158
Plan My Night, 2005 2010, 1516
CSS, 152
, 147
web.config, 45
Visual Studio 2008
jQuery, 239
, 215, 226
-, 210
, 217
SOS, 243
, 246
XSD, 200
Breakpoints, 238
, 240, 243, 250
LINQ, 240
, 233
,
, 185
, 194
, 223
Entity Framework, 182

web.config, 45
WCF. . Windows Communication Foundation
(WCF)
Web Application Project, 9293, 93
web.config, , 85, 171, 246
web.config, , 45
Windows Communication Foundation (WCF), 4041,
4041
Windows Server AppFabric. .
AppFabric
WindowsLiveLogin.User, , 4950, 4950, 4950
Wix Toolset, 95, 99
XCOPY-, 9197
XSD, , 200
, 1415, 1415, 1415

2003 2010, 52, 54, 63


2005 2010, 139, 141, 150
2008 2010, 215, 217, 226
ASP.NET Forms, 4852, 4852, 4852
Windows Live ID, 4852, 4852, 4852
, 4852, 4852, 4852
, , 17, 105,
183
- , 2003 2010
, 1415
Entity Framework, 1635
Plan My Night, 1516
- Bing Maps, 3941
, 3539
AppFabric, 4243
, 4142
- , 2005 2010
, 1415
Entity Framework, 1635
Plan My Night, 1516
- Bing Maps, 3941
, 3539
AppFabric, 4243
, 4142
- , 2008 2010
, 1415
Entity Framework, 1635
Plan My Night, 1516
, 2013
AppFabric, 2046
, 2034
- PlanMyNight, 4446, 4446, 4446
- Bing Maps, , 3941, 3941
-
Visual Studio 2003, 47
Visual Studio 2005, 134
Visual Studio 2008, 210
, 6369, 6369, 6369
ASP.NET MVC, 47, 134,
210
, , 78
81, 7881, 7881
, 45, 132, 209
, 6369, 6369, 6369
Entity Data Model (EDM), 2003 2010
ADO.NET POCO Entity Generator, 3234
POCO-, 32

253

, 16
26
, 1719, 2629
Entity Data Model (EDM), 2005 2010
ADO.NET POCO Entity Generator, 3234
POCO-, 32
, 16
26
, 2024
, 1719, 2635
Entity Data Model (EDM), 2008 2010
ADO.NET POCO Entity Generator, 3234
POCO-, 182, 32
,
18292
, 2024
, 2629, 2635
, ASP.NET MVC, 54, 141, 217
-, 3941, 3941
, 3539, 3539,
2013
, 5254, 5254, 52
54

, 5254, 5254, 5254
, 2003
2010
, 2426
,
2003 2010
, 1619
,
1924
, 2426
,
2005 2010
, 2426
, 1619
,
1924
, 2426
,
2008 2010
, 19092
, 1619
,
18590
, 19092
, 81, 168, 243
, 78, 164, 239
, 2426, 2426, 19092

IActivitiesRepository, 14, 48, 101, 135, 178, 211


ICachingProvider, 14, 101, 178
IFormsAuthentication, 48, 135, 211
IItinerariesRepository, 14, 35, 101, 123, 178, 201
IMembershipService, 48, 135, 211
IReferenceRepository, 48, 135, 211
IWindowsLiveLogin, 48, 135, 211
, 14, 101, 178
, , 34
35, 3435, 3435
, 45, 132, 209

, 89,
175, 250

ASP.NET MVC, 4647, 4647, 4647
, 2003 2010
, 4852
, , 5458

, 5254
, , 5863
, 4748
, 4658
, 2005 2010
, 4852
, , 5458

, 5254
, , 5863
, 4748
, 4658
, 2008 2010
, 4852
, , 5458

, 5254
, , 5863
, 4748
, 4658
, 45, 132, 208
, 4243, 4243, 2046
Generate Database, 3032, 3032, 3032
, ,
7677, 7677, 7677
, 53, 139
, 89, 175, 250
- , 2003 2010
ADO.NET POCO Entity Generator, 3234
POCO-, 32

, 2932
, 2629
,
3435
- , 2005 2010
ADO.NET POCO Entity Generator, 3234
POCO-, 32

, 2932
, 2629
,
3435
- , 2008 2010
ADO.NET POCO Entity Generator, 182, 3234
POCO-, 182, 32
Visual Studio 2008, 181

, 2932
, 2629
,
3435
, 8589, 8589, 8589
, 19, 29, 107, 117, 185, 195
, 36, 124

254

, 194
, 6369, 6369, 6369
XSD, 122
, 6369, 6369, 6369, .
,
, 8185, 8185, 8185
, 2003 2010
, 8589
, 74
Threads, 89
, 8185
web.config, 85
, 7881

, 7578
, 7589
, 2005 2010
, 8589
, 74
Threads, 89
, 8185
web.config, 171
, 7881

, 7578
, 7589
, 2008 2010
, 8589
, 74
Threads, 89
, 8185
web.config, 246
, 7881

, 7578
, 7589
, 182
, 9197
, 4445, 4445, 4445
, 45, 132, 209

, 78, 165, 240
, 71, 158, 233
, 47, 134, 210
, , 5863, 58
63, 5863
, 45, 132, 208
, 52, 54, 139, 141, 215, 217
Plan My Night, 2003 2010
Visual Studio 2003, 1516
, 1415
, 16
, 1516
Entity Framework, 1635
- Bing Maps, 3941
, 3539
AppFabric, 4243
ASP.NET, 43
, 7071
, 4142
Plan My Night, 2005 2010
Visual Studio 2005, 1516
, 1415

, 104
, 1516
Entity Framework, 1635
- Bing Maps, 3941
, 3539
AppFabric, 4243
ASP.NET, 130
, 7071
, 4142
Plan My Night, 2008 2010
, 1415
, 1516
, 2013
AppFabric, 2046
ASP.NET, 205
, 7071
, 2034
, 182
Plan My Night,
, 9198
,
, 185
,
, 91
, 7881, 7881, 7881
, , , 34
35, 3435, 3435

, 2003 2010
- PlanMyNight, 4446
, 6369
, 4658
, 44
, , 5863
MEF, 7073

, 2005 2010
- PlanMyNight, 4446
, 6369
, 4658
, 44
, , 5863
MEF, 7073

, 2008 2010
- PlanMyNight, 4446
, 6369
, 4658
, 44
, , 5863
MEF, 7073
, 7071, 7071, 7071
-, 41, 128
, 47, 134, 210

CreateProfile, 50, 137, 213


UserProfile, 2024, 2024, 2024
, 5254,
5254, 5254
, 5458, 5458, 5458
, 2003 2010
/ , 91
, 9197

255

one-click, 9798
, 91
, 4142, 41
42, 2034
MEF, 7073, 70
73, 7073
, 182
, 194
, 60, 147, 223
ASP.NET, 4852, 4852, 4852
, 78, 165, 78
, 2932, 2932, 2932
, , 8589, 8589, 8589

, , 182

, 7578, 7578, 7578
, Visual Studio 2003, 3637
, 59, 60, 146, 147, 222, 223
, 77, 164, 239
, 2426, 2426, 19092
/ ,
, 91
/,
, 91
, 81, 168, 243
, 77, 164, 239

Microsoft Visual Studio 2010


(Ken Haines) ,
(Consumer and Online Division) .

, .
12 ,
-, , -.
,
- .
, , ,
, . , .
(Pascal Par) 2006
.
.
13 , ,
.
( - ,
).
, . . Lotus Elise
-. ,
.
(Patrice Pelland)
. ,
.
;
, .
17 ,
, -, ,
- , , .
.
, ,
, , , ,
Porsche, , . ,
.

Оценить