Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§...

130

Transcript of Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§...

Page 1: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°
Page 2: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

ASP.NET Web APIASP.NET Web API Http

Controller Action ASP.NET Web API

ASP.NET Web API

ASP.NET Web API ASP.NET Web APIASP.NET Web API

CIP ASP.NET Web API 2 . 2014.7 ISBN 978-7-121-23536-8

. A . . . TP393.092

CIP 2014 127439

173 100036

787 980 1/16 45.75 908 2014 7 1 2014 7 1 2500 108.00

010 88254888 [email protected] [email protected]

010 88258888

Page 3: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

Heterogeneous Web

Service Web Service

Web Web Service SOAP WSDL WS-*

Web REST Web API Windows

WCF REST Web API ASP.NET Web

API

Page 4: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

2

1.1 Web

Web World Wide Web WWW W3

W3C

WWW http://www.w3.org/WWW/ The

World Wide Web (known as "WWW, "Web" or "W3") is the universe of network-accessible information, the embodiment of human knowledge

Web

Web

Web

HTTP Hypertext Hypermedia

Web HTTP HTTP Web

1.1.1 TCP/IP HTTP

TCP/IP IP TCP

TCP/IP TCP/IP TCP/IP 1-1 4

/ HyperText/HyperMedia

Hyperlink

HTML /

4 TCP/IP

4 TCP/IP

7

Page 5: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.1 Web

ASP.NET Web API 2

3

1-1 TCP/IP

TCP/IP IP TCP

IP

IP

IP

Connectionless IP

IP

TCP TCP

Duplex

TCP

Page 6: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

4

TCP 16 Checksum

TCP

HTTP Hypertext Transfer Protocol TCP/IP

1-1 TCP

TCP HTTP

IP IP DNS

IP TCP Port

TCP IP HTTP

80 HTTPS TLS/SSL HTTP

443

1.1.2 Web

Web HTTP

Web

Web

XML

Page 7: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.1 Web

ASP.NET Web API 2

5

JSON

Media Type

MIME Multipurpose Internet Mail Extension MIME

ASCII

MIME HTTP

� text/html HTML

� text/xml application/xml XML

� text/json application/json JSON

� image/gif image/jpeg image/png GIF JPEG PNG

� audio/mp4 audio/mpeg audio/vnd.wave MP4 MPEG WAVE

� video/mp4 video/mpeg video/quicktime MP4 MPEG QUICKTIME

URI URL URN

GUID URI Web URI

Uniform Resource Identifier

URI URL

URL URI URI URL URL URI

URI

URL Uniform Resource Locator

URL

URL IP 5

http://www.artech.com:8080/images/photo.png?size=small URL

5 http www.artech.com 8080 /images/photo.png ?size=small

Page 8: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

6

URL URN URI URN Uniform

Resource Name URN

URN

1.1.3 HTTP

TCP

HTTP HTTP

/ HTTP Transaction

Web HTTP

HTTP

HTTP /

CRUD Create Retrieve Update Delete HTTP

URI HTTP HTTP Method HTTP Verb

HTTP GET POST PUT DELETE HEAD

OPTIONS TRACE CONNECTION PATCH REST

Web HTTP

3

W3C

� 100~199

� 200~299

� 300~399

� 400~499

Page 9: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.1 Web

ASP.NET Web API 2

7

� 500~599

1.1.4 HTTP

Web HTTP HTTP

HTTP

� HTTP HTTP

URI HTTP HTTP

� HTTP

/

HTTP

� HTTP

Chrome www.microsoft. com HTTP

HTTP HTTP

GET http://www.microsoft.com/en-us/default.aspx HTTP/1.1

GET http://www.microsoft.com/en-us/default.aspx HTTP/1.1 Host: www.microsoft.com Connection: keep-alive Cache-Control: max-age=0 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 Cookie: ...

Page 10: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

8

Host Cache-Control

User-Agent Accept Accept-Encoding

Accept-Language Accept-Charset

Web

HTTP HTTP/1.1

200 OK

Content-Type HTML

Content-Type text/html

HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Type: text/html; charset=utf-8 Content-Encoding: gzip Expires: -1 Vary: Accept-Encoding Server: Microsoft-IIS/7.5 X-AspNet-Version: 2.0.50727 VTag: 791897542300000000 P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI" X-Powered-By: ASP.NET Date: Wed, 18 Jan 2012 07:06:25 GMT Content-Length: 34237 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html>…</html>

1.2 RESTful Web API REST Web Service

RPC RPC REST

REST

REST Web RESTful Web API

Page 11: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.2 RESTful Web API

ASP.NET Web API 2

9

1.2.1

Web Service

Web Service SOAP REST Web Service

REST REST

2014 14

2000 Roy Thomas Fielding Architectural Styles and

the Design of Network-based Software Architectures REST

5

REST REpresentational State Transfer

SOAP REST

RESTful Fielding

Fielding REST Distributed Hypermedia

System HATEOAS Hypermedia As The Engine Of Application

State

Web

Application State Web

Representation

REpresentational State

REpresentational State Transfer REST

Web Service Web API Web Service RPC SOAP

Web Service Web SOAP Web Service Web API Web Service/Web API

RESTful

Page 12: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

10

1.2.2 RESTful Web API

REST

Web REST

REST REST

Lenoard Rechardson & Sam Ruby RESTful Web Services

ROA Resource Oriented Architecture

ROA Web API RESTful Web API

URI

SOAP Web Service RPC

RESTful Web API

Web

Web

Web API

URI URI

URI URI

� http://www.artech.com/employees/c001 C001

� http://www.artech.com/sales/2013/12/31 2013 12 31

� http://www.artech.com/orders/2013/q4 2013 4

URI

Addressability URI URI

URI URL URN

Page 13: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.2 RESTful Web API

ASP.NET Web API 2

11

URL

URI http://www.artech.com/employees/c001

http://www.artech.com/

orders/2013/q4 Composite

URI

URL

XML URL

<movie> <name> </name> <genre> | | </genre> <directors> <add ref="http://www.artech.com/directors/taylor-hackford"> . </add> </directors> <starring> <add ref = "http://www.artech.com/actors/al-pacino"> . </add> <add ref = "http://www.artech.com/actors/keanu-reeves "> . </add> </starring> <supportingActors> <add ref = "http://www.artech.com/actors/charlize-theron "> . </add> <add ref = "http://www.artech.com/actors/jeffrey-jones "> . </add> <add ref = "http://www.artech.com/actors/connie-nielsen"> . </add> </supportingActors> <scriptWriters> <add ref = "http://www.artech.com/scriptwriters/jonathan-lemkin"> · </add> <add ref = "http://www.artech.com/scriptwriters/tony-gilroy"> · </add> </scriptWriters> <language> </language> <poster ref = "http://www.artech.com/images/the-devil-s-advocate"/>

Page 14: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

12

<story>...</story> </movie>

/ Fielding REST

REST

REST Web API

CRUD Web API

Web API

Web API Web API

public class ResourceService { public IEnumerable<Resource>[] Get(); public void Create(Resource resource); public void Update(Resource resource); public void Delete(string id); }

RESTful Web API RPC SOAP Web Service

RPC Web API

Web API

Web API

CRUD / SOAP

Web Service

public class RoleService { public IEnumerable<string> GetAllRoles(); public void CreateRole(string roleName); public void DeleteRole(string roleName); public void AddRolesInUser(string userName, string[] roleNames); public void RemoveRolesFromUser(string userName, string[] roleNames); }

RESTful Web API

Page 15: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.2 RESTful Web API

ASP.NET Web API 2

13

CRUD Role Assignment

Web API

Web API

public class RolesService { public IEnumerable<string> Get(); public void Create(string roleName); public void Delete(string roleName); } public class RoleAssignmentsService { public void Create(RoleAssignment roleName); public void Delete(RoleAssignment roleName); }

HTTP

RESTful Web API

Web HTTP

Web API CRUD HTTP

HTTP Web API

ASP.NET Web API Action

HTTP Action

HTTP

public class ResourceService { public IEnumerable<Resource>[] Get(); public void Post(Resource resource); public void Put(Resource resource); public void Patch(Resource resource); public void Delete(string id); public void Head(string id); public void Options(); }

7 7 HTTP

GET HEAD OPTIONS HTTP

Page 16: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

14

GET

HEAD OPTIONS

HEAD

OPTIONS

HTTP

Preflight

HTTP OPTIONS

4 HTTP POST PUT PATCH DELETE

DELETE

HTTP

POST PUT

URI URI

URI

PUT URI URI POST

URI URI

PUT POST URI ID

ID PUT ID

POST

PUT http://www.artech.com/employees/300357 HTTP/1.1 ... <employee> <id>300357</id> <name> </name> <gender> <gender> <birthdate>1981-08-24</birthdate> <department>3041</department> </employee> POST http://www.artech.com/employeesHTTP/1.1 ... <employee>

Page 17: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.2 RESTful Web API

ASP.NET Web API 2

15

<name> </name> <gender> <gender> <birthdate>1981-08-24</birthdate> <department>3041</department> </employee>

POST PUT PUT

URI

URI

PUT

PUT http://www.artech.com/roles/admin HTTP/1.1 ...

PUT

URI

POST PUT HTTP POST

PUT PUT

PUT

PATCH

PATCH

HTTP

7 HTTP GET HEAD OPTIONS

Side Effect 4 HTTP

Idempotent

Side Effect

Side Effect

GET HEAD OPTIONS Side

Effect

Page 18: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

16

3 HTTP GET HEAD OPTIONS DELETE

PATCH PUT

POST POST

Web API HTTP

PUT PUT

LastUpdatedTime

Auditing

PUT

LastUpdatedTime

Representaion

K

Web API

Web XML

JSON

Web API

Page 19: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.2 RESTful Web API

ASP.NET Web API 2

17

XML JSON

Content-Type

� URI

en en-US URI

http://www.artech.com/en/orders/2013 2013

� Content Negotiation

Accept Accept-language

Web API

URI

URI

URI URI

URI

RESTful

RESTful

HTTP

Web API

JavaScript

URI GET

Page 20: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

18

� Web API

� Web API

Web API

Web API Web API

Affinity

1.3 ASP.NET Web API

ASP.NET Web API ASP.NET MVC

ASP.NET Web API ASP.NET

MVC ASP.NET Web API ASP.NET MVC

ASP.NET Web API

ASP.NET MVC

ASP.NET MVC 5

ASP.NET Web API

ASP.NET ASP.NET Web API

ASP.NET Web API

ASP.NET Web API Web

Ajax Web API CRUD S101

1.3.1

Visual Studio ASP.NET Web API

ASP.NET Web API

Page 21: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

19

Visual Studio

IDE

Visual Studio

1-2

1-2

1-2 6

Web WebApp

� Common

WebApi

ConsoleApp

� WebApi HttpController Web API

Common

� WebHost ASP.NET Web ASP.NET Web API

Web Host WebApi

� SelfHost ASP.NET Web API Self Host

WebApi

Page 22: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

20

� WebApp ASP.NET Web

Ajax Web API

� ConsoleApp

Web API Common

1.3.2 Web API

Web API Common

Contact Contact

ID

public class Contact { public string Id { get; set; } public string Name { get; set; } public string PhoneNo { get; set; } public string EmailAddress { get; set; } public string Address { get; set; } }

HttpController Web API WebApi ApiController

ApiController System.Web.Http.dll

%ProgramFiles%\Microsoft ASP.NET\ASP.NET Web Stack 5\Packages\

Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45

Web API ContactsController Get

Post Put Delete 4 Action

Action Get ID

ASP.NET Web API Action

HTTP HTTP

public class ContactsController: ApiController { static List<Contact> contacts;

static ContactsController() { contacts = new List<Contact>();

Page 23: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

21

contacts.Add(new Contact { Id = "001", Name = " ", PhoneNo = "0512-12345678", EmailAddress = "[email protected]", Address = " 328 " }); contacts.Add(new Contact { Id = "002", Name = " ", PhoneNo = "0512-23456789", EmailAddress = "[email protected]", Address = " 328 " }); } public IEnumerable<Contact> Get(string id = null) { return from contact in contacts where contact.Id == id || string.IsNullOrEmpty(id) select contact; } public void Post(Contact contact) { contact.Id = counter.ToString("D3"); contacts.Add(contact); } public void Put(Contact contact) { contacts.Remove(contacts.First(c => c.Id == contact.Id)); contacts.Add(contact); } public void Delete(string id) { contacts.Remove(contacts.First(c => c.Id == id)); } }

contacts Contacts

Controller ID 001 002

CRUD Action

1.3.3 Web Host Web API

ASP.NET Web API

ASP.NET Web API

Web API

Page 24: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

22

Web Host ASP.NET Web

Web API

1-2 Web Host Web API WebHost

ASP.NET ContactsController WebApi

System.Net.Http.dll .NET Framework

3 %ProgramFiles%\Microsoft ASP.NET\ASP.NET

Web Stack 5\Packages\

� System.Web.Http.dll \Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45\

� System.Net.Formatting.Http.dll \Microsoft.AspNet.WebApi.Client.5.0.0\lib\net45\

� System.Web.Http.WebHost.dll \Microsoft.AspNet.WebApi.WebHost.5.0.0\lib\net45\

� System.Net.Http.dll

ASP.NET MVC Web Host Web API ASP.NET

ASP.NET Web API

HttpController Action

Web Host

WebHost Global.asax

Application_Start api/{controller}/{id} 3

api {controller} HttpController

{id} Action ContactsController Get

id RouteParameter.Optional

public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configuration.Routes.MapHttpRoute( Name : "DefaultApi", routeTemplate : "api/{controller}/{id}", defaults : new { id = RouteParameter.Optional }); } }

HttpRouteCollection

MapHttpRoute GlobalConfiguration Configuration

Page 25: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

23

HttpConfiguration Routes

ASP.NET MVC

Action ASP.NET Web API Action

HTTP Action

Action {action}

Visual Studio VS 2012 VS 2013

Web IIS Express

IIS

1-3 WebHost IIS Web URL

http://localhost/WebHost

1-3 IIS Local IIS

Web API Web Host

Web API

HTTP-GET HTTP-GET

Action ContactsController Get

http://localhost/webhost/api/contacts

http://localhost/webhost/api/contacts/001

Ajax IIS Express

Web API Ajax

Page 26: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

24

ID 001 1-4

1-4 Web API

1-4 Chrome XML

REST

ASP.NET Web API Accept

Chrome http://localhost/webhost/api/

contacts/001 XML Accept

application/xml ASP.NET Web API IE

Accept JSON

GET http://localhost/webhost/api/contacts/001 HTTP/1.1 Host: localhost Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36

Page 27: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

25

Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4

ASP.NET Web API Fiddler

Web API HTTP 1-5 Fiddler

http://localhost/webhost/api/contacts/001 HTTP-GET application/

json Accept JSON

1-5 Fiddler Web API

PUT DELETE

ContactsController RESTful Web API

HTTP GET POST PUT DELETE

HTTP IIS PUT

DELETE

Page 28: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

26

1-6 Fiddler http://localhost/webhost/api/

contacts/001 HTTP-DELETE ID 001

405 Method Not Allowed

HTTP-DELETE

1-6 IIS DELETE

IIS PUT DELETE WebDAVModule

HttpModule WebDAV Web-based Distributed Authoring and Versioning

HTTP

Web Server

WebDAV HttpModule

IIS WebDAV WebDAVModule

HTTP PUT DELETE WebDAV

HttpModule

<configuration> ... <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <remove name="WebDAVModule" /> </modules> </system.webServer> </configuration>

Page 29: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

27

1.3.4 Self Host Web API

WCF Web API IIS Self Host

Windows Forms WPF Windows Service

SelfHost Self Host

SelfHost WebApi

4 System.Net.Http.dll .NET

Framework 3 %ProgramFiles%\Microsoft

ASP.NET\ASP.NET Web Stack 5\Packages\

� System.Web.Http.dll \Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45\

� System.Net.Formatting.Http.dll \Microsoft.AspNet.WebApi.Client.5.0.0\lib\net45\

� System.Web.Http.SelfHost.dll \Microsoft.AspNet.WebApi.SelfHost.5.0.0\lib\net45\

� System.Net.Http.dll

Web Host Web API

Self Host

HttpController

class Program { static void Main(string[] args) { Assembly.Load("WebApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); HttpSelfHostConfiguration configuration = new HttpSelfHostConfiguration("http://localhost/selfhost"); using (HttpSelfHostServer httpServer = new HttpSelfHostServer(configuration)) { httpServer.Configuration.Routes.MapHttpRoute( name : "DefaultApi", routeTemplate : "api/{controller}/{id}", defaults : new { id = RouteParameter.Optional });

Page 30: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

28

httpServer.OpenAsync(); Console.Read(); } } }

ASP.NET Web API Self Host HttpSelfHostServer

ContactsController WebApi.dll

http://localhost/selfhost URL

HttpSelfHostConfiguration HttpSelfHostServer

HttpSelfHostConfiguration HttpSelfHostServer

Configuration Routes MapHttpRoute

Web Host OpenAsync HttpSelfHostServer

WCF WCF

ASP.NET Web API Web Host Self

Host HttpController WCF

ASP.NET Web API

ASP.NET Web API HttpController

HttpController IHttpController

Web Host BuildManager

Self Host HttpController

ContactsController

Web API

http://localhost/selfhost/api/contacts

http://localhost/selfhost/api/contacts/001 1-4

1.3.5 HttpClient Web API

.NET HttpClient Web API Web API

/ HttpClient

Page 31: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

29

HTTP ConsoleApp HttpClient

Self Host Web API

Contact

Common HttpClient System.Net.Http.dll

System.Net.Formatting.Http.dll

Web API HttpClient Web API

HttpClient Task

async Process

await

class Program { static void Main(string[] args) { Process(); Console.Read(); } private async static void Process() { // HttpClient httpClient = new HttpClient(); HttpResponseMessage response = await httpClient .GetAsync("http://localhost/selfhost/api/contacts"); IEnumerable<Contact> contacts = await response.Content.ReadAsAsync<IEnumerable<Contact>>(); Console.WriteLine(" "); ListContacts(contacts); // Contact contact = new Contact { Name = " ", PhoneNo = "0512-34567890", EmailAddress = "[email protected]" }; await httpClient.PostAsJsonAsync<Contact>( "http://localhost/selfhost/api/contacts", contact); Console.WriteLine(" " " "); response = await httpClient.GetAsync( "http://localhost/selfhost/api/contacts"); contacts = await response.Content .ReadAsAsync<IEnumerable<Contact>> (); ListContacts(contacts);

Page 32: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

30

// response = await httpClient.GetAsync( "http://localhost/selfhost/api/contacts/001"); contact = (await response.Content .ReadAsAsync<IEnumerable<Contact>> ()) .First(); contact.Name = " "; contact.EmailAddress = "[email protected]"; await httpClient.PutAsJsonAsync<Contact>( "http://localhost/selfhost/api/contacts/001", contact); Console.WriteLine(" “001” "); response = await httpClient.GetAsync( "http://localhost/selfhost/api/contacts"); contacts = await response.Content .ReadAsAsync<IEnumerable<Contact>> (); ListContacts(contacts); // await httpClient.DeleteAsync( "http://localhost/selfhost/api/contacts/002"); Console.WriteLine(" "002" "); response = await httpClient.GetAsync( "http://localhost/selfhost/api/contacts"); contacts = await response.Content .ReadAsAsync<IEnumerable<Contact>> (); ListContacts(contacts);

}

private static void ListContacts(IEnumerable<Contact> contacts) { foreach (Contact contact in contacts) { Console.WriteLine("{0,-6}{1,-6}{2,-20}{3,-10}", contact.Id, contact.Name, contact.EmailAddress, contact.PhoneNo); } Console.WriteLine(); } }

HttpClient GetAsync

http://localhost/selfhost/api/contacts GET HttpResponse

Message HttpResponseMessage Content

HttpContent ReadAsAsync<T>

Contact Contact

HttpClient PostAsJsonAsync<T> http://localhost/

Page 33: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

31

selfhost/api/contacts POST

Contact JSON

http://localhost/selfhost/api/contacts/001 GET

ID 001

[email protected] HttpClient PutAsJsonAsync<T>

http://localhost/selfhost/api/contacts/001 PUT

HttpClient DeleteAsync http://localhost/selfhost/api/ contacts/002

DELETE ID 002

SelfHost ConsoleApp

HttpClient GetAsync PostAsJsonAsync PutAsJsonAsync

DeleteAsync

001 [email protected] 0512-12345678 002 [email protected] 0512-23456789

001 [email protected] 0512-12345678 002 [email protected] 0512-23456789 003 [email protected] 0512-34567890

001 002 [email protected] 0512-23456789 003 [email protected] 0512-34567890 001 [email protected] 0512-12345678

002 003 [email protected] 0512-34567890 001 [email protected] 0512-12345678

1.3.6

Web

Page 34: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

32

Ajax Web Host Web API CRUD

1-7

1-7

1-8

1-8

Web 3 Web

Page 35: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

33

jQuery Bootstrap KnockOut CSS

JavaScript

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title> </title> <link href="css/bootstrap.min.css" rel="stylesheet"> </head> <body> ... <script src="Scripts/jquery-1.10.2.min.js"></script> <script src="Scripts/bootstrap.min.js"></script> <script src="Scripts/knockout-3.0.0.js"></script> <script src="Scripts/viewmodel.js"></script> </body> </html>

jQuery JavaScript Bootstrap

HTML CSS JavaScript Twitter 2011 8

Web

Web Bootstrap ASP.NET MVC 5 Visual Studio

ASP.NET MVC Bootstrap CSS JavaScript

jQuery Ajax Web API

Bootstrap KnockOut Bootstrap

CSS Bootstrap JavaScript

MVVM Knockout

Knockout KO JavaScript

KO WPF/Silverlight MVVM Web

JavaScript Web MVVM

UI HTML

MVVM WPF/SL

Web MVVM Knockout KO

MVVM MVC Controller ViewModel

KO MVVM

ViewModel

Page 36: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

34

View UI HTML KO

View UI <button> click

ViewModel function

1-9 View

ViewModel EventHandler ViewModel

Model View ViewModel

ViewModel ViewModel

View JavaScript UI

View View HTML

1-9 MVVM

KO 1-10

<span>

1-10

Page 37: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

35

KO

ViewModel

View HTML data-bind

ViewModel ko.applyBindings

<div> <div><label> :</label><input data-bind="value: province" /></div> <div><label> :</label><input data-bind="value: city" /></div> <div><label> :</label><input data-bind="value: district"/></div> <div><label> :</label><input data-bind="value: street"/> <div><label> :</label><span data-bind="text: address"></span></div> <div><input type="button" data-bind="click: format" value=" "/></div> </div> <script type="text/javascript" > function AddressModel() { var self = this; self.province = ko.observable(" "); self.city = ko.observable(" "); self.district = ko.observable(" "); self.street = ko.observable(" 328 "); self.address = ko.observable(); self.format = function () { if (self.province() && self.city() && self.district() && self.street()){ var address = self.province() + " " + self.city() + " " + self.district() + " " + self.street(); self.address(address); } else { alert(" "); } }; self.format(); } ko.applyBindings(new AddressModel()); </script>

AddressModel

ViewModel AddressModel 5 province city district street address

4 Observable

Page 38: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

36

HTML Observable ko.observable

AddressModel format

address address Observable

HTML

AddressModel 6 6 HTML province city district

street Value data-bind="value: { }"

address <span> Text data-bind="text: {

}" format click

data-bind="click: { }" ko.applyBindings

ViewModel

Web

HTML JavaScript

ViewModel JavaScript viewmodel.js

function ViewModel() { self = this; self.contacts = ko.observableArray(); // self.contact = ko.observable(); // // self.load = function () { $.ajax({ url : "http://localhost/webhost/api/contacts", type : "GET", success : function (result) { self.contacts(result); } }); }; // self.showDialog = function (data) { // Id " / " if (!data.Id) { data = { ID: "", Name: "", PhoneNo: "", EmailAddress: "",

Page 39: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

37

Address: "" } } self.contact(data); $(".modal").modal('show'); }; // Web API / self.save = function () { $(".modal").modal('hide'); if (self.contact().Id) { $.ajax({ url : "http://localhost/webhost/api/contacts/" + self.contact.Id, type : "PUT", data : self.contact(), success : function () {self.load();} }); } else { $.ajax({ url : "http://localhost/webhost/api/contacts", type : "POST", data : self.contact(), success : function () {self.load();} }); } }; // self.delete = function (data) { $.ajax({ url : "http://localhost/webhost/api/contacts/" + data.Id, type : "DELETE", success : function () {self.load();} }); }; self.load(); } $(function () { ko.applyBindings(new ViewModel()); });

ViewModel ViewModel

contacts contact

contacts contact observableArray observable

Page 40: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

38

4

� load Ajax Web API

contacts

� showDialog

Id

contact

<div> modal Bootstrap

� save Ajax Web API

contact

Id load

� delete Ajax Web API

load

HTML

HTML ViewModel HTML

<!-- --> <div id="content"> <table class="table table-striped"> <thead> <tr> <th> </th> <th> </th> <th> </th> <th></th> </tr> </thead> <tbody data-bind="foreach: contacts"> <tr> <td data-bind="text: Name"></td> <td data-bind="text: PhoneNo"></td> <td data-bind="text: EmailAddress"></td> <td> <a href="#" data-bind="click: $root.showDialog"> </a> <a href="#" data-bind="click: $root.delete"> </a>

Page 41: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1.3 ASP.NET Web API

ASP.NET Web API 2

39

</td> </tr> </tbody> </table> <a href="#" class="btn btn-primary" data-bind="click: showDialog">

</a> </div> <!-- / --> <div class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <h4 class="modal-title"> </h4> </div> <div class="modal-body form-horizontal" data-bind="with: contact"> <div class="form-group"> <label for="name" class="col-sm-2 control-label"> :</label> <div class="col-sm-10"> <input type="text" class="form-control" id="name" placeholder=" " data-bind="value:Name"> </div> </div> <div class="form-group"> <label for="phoneNo" class="col-sm-2 control-label"> :</label> <div class="col-sm-10"> <input type="text" class="form-control" id="phoneNo" placeholder=" " data-bind="value:PhoneNo"> </div> </div> <div class="form-group"> <label for="emailAddress" class="col-sm-2 control-label"> :</label> <div class="col-sm-10"> <input type="text" class="form-control" id="emailAddress" placeholder=" " data-bind="value:EmailAddress"> </div> </div> <div class="form-group"> <label for="address" class="col-sm-2 control-label"> :</label> <div class="col-sm-10"> <input type="text" class="form-control" id="address" placeholder=" " data-bind="value:Address"> </div>

Page 42: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

1

ASP.NET Web API 2

40

</div> </div> <div class="modal-footer"> <a href="#" class="btn btn-default" data-dismiss="modal"> </a> <a href="#" class="btn btn-primary" data-bind="click: save"> </a> </div> </div> </div> </div>

<table> contacts

foreach <tbody data-bind="foreach: contacts"> <tr>

<td> text

<td data-bind="text: Name"></td>

showDialog delete

click <a href="#" data-bind="click: $root.showDialog"> </a>

$root KO

HTML foreach contacts

$root KO ViewModel

KO

with <div

data-bind="with: contact"> ViewModel contact 4

value <input type="text" data-bind="value:Name">

ViewModel / save click <

data-bind="click: save"> </a>

Page 43: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API

HttpMessageHandler

HttpMessageHandler HttpController

Action

HttpMessageHandler

Web API

Page 44: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

104

3.1 HttpMessageHandler

ASP.NET Web API

HttpMessageHandler

HttpMessageHandler

3.1.1 HttpMessageHandler

ASP.NET Web API HttpMessageHandler

ASP.NET Web API ASP.NET

Web API

HttpMessageHandler

HttpMessageHandler

HttpMessageHandler System.Net.Http 2

ASP.NET Web API HttpRequestMessage HttpResponseMessage

HttpMessageHandler

public abstract class HttpMessageHandler : IDisposable { public void Dispose(); protected virtual void Dispose(bool disposing); protected abstract Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken); }

Page 45: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

105

HttpMessageHandler

SendAsync Task

ASP.NET Web API

SendAsync request HttpMessageHandler

HttpRequestMessage cancellationToken

CancellationToken .NET

SendAsync

SendAsync

Task<HttpResponseMessage> HttpMessageHandler

3-1

3-1 HttpMessageHandler

HttpMessageHandler IDisposable Dispose

Dispose HttpMessageHandler

HttpMessageHandler

Dispose

public abstract class HttpMessageHandler : IDisposable {

Page 46: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

106

// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this);

}

protected virtual void Dispose(bool disposing) {} }

3.1.2 DelegatingHandler

ASP.NET Web API HttpMessageHandler

DelegatingHandler

DelegatingHandler

HttpMessageHandler DelegatingHandler

DelegatingHandler

DelegatingHandler HttpMessageHandler

HttpMessageHandler InnerHandler

DelegatingHandler SendAsync InnerHandler

public abstract class DelegatingHandler : HttpMessageHandler { protected internal override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken); public HttpMessageHandler InnerHandler get; set; } }

ASP.NET Web API DelegatingHandler

HttpMessageHandler InnerHandler

HttpMessageHandler 3-2 ASP.NET

Web API

Page 47: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

107

3-2 DelegatingHandler

3.1.3 HttpServer

ASP.NET Web API HttpMessageHandler

DelegatingHandler InnerHandler

HttpMessageHandler HttpMessageHandler HttpServer

System.Web.Http

HttpServer DelegatingHandler

Configuration Dispatcher

HttpConfiguration Dispatcher

HttpMessageHandler

public class HttpServer : DelegatingHandler { public HttpConfiguration Configuration { get; } public HttpMessageHandler Dispatcher { get; } public HttpServer(); public HttpServer(HttpMessageHandler dispatcher); public HttpServer(HttpConfiguration configuration); public HttpServer(HttpConfiguration configuration, HttpMessageHandler dispatcher); protected override void Dispose(bool disposing); protected virtual void Initialize();

Page 48: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

108

protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken); }

HttpServer Configuration Dispatcher

HttpServer

HttpServer HttpConfiguration Configuration

Dispatcher HttpRoutingDispatcher

System.Web.Http.Dispatcher HttpConfiguration IDisposable

HttpServer Dispose HttpConfiguration

HttpServer

HttpServer Dispatcher Http

MessageHandler ASP.NET Web API

HttpMessageHandler

3-3 HttpMessage

Handler

3-3 HttpServer HttpRoutingDispatcher

HttpConfiguration HttpMessageHandler

HttpConfiguration

MessageHandlers HttpMessageHandler

DelegatingHandler HttpMessageHandler

Page 49: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

109

DelegatingHandler

public class HttpConfiguration : IDisposable { // public Collection<DelegatingHandler> MessageHandlers { get; } }

HttpServer Initialize

SendAsync

Initialize

HttpServer S301

HttpServer

ASP.NET Web API 3

DelegatingHandler HttpMessageHandler FooHandler BarHandler

BazHandler

public class FooHandler: DelegatingHandler {} public class BarHandler : DelegatingHandler {} public class BazHandler : DelegatingHandler {}

HttpServer MyHttpServer

SendAsync MyHttpServer

HttpConfiguration

public class MyHttpServer: HttpServer { public MyHttpServer(HttpConfiguration configuration) : base(configuration) { } public new void Initialize() { base.Initialize(); } }

Page 50: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

110

ApiController DemoController

GetHandlerChain DelegatingHandler

HttpMessageHandler Action Get

MyHttpServer HttpConfiguration 3 DelegatingHandler

FooHandler BarHandler BazHandler

public class DemoController : ApiController { public Tuple<IEnumerable<string>, IEnumerable<string>> Get() { HttpConfiguration configuration = new HttpConfiguration(); configuration.MessageHandlers.Add(new FooHandler()); configuration.MessageHandlers.Add(new BarHandler()); configuration.MessageHandlers.Add(new BazHandler()); MyHttpServer httpServer = new MyHttpServer(configuration); IEnumerable<string> chain1 = this.GetHandlerChain(httpServer).ToArray(); httpServer.Initialize(); IEnumerable<string> chain2 = this.GetHandlerChain(httpServer).ToArray(); return new Tuple<IEnumerable<string>, IEnumerable<string>>( chain1, chain2); }

private IEnumerable<string> GetHandlerChain(DelegatingHandler handler) { yield return handler.GetType().Name; while (null != handler.InnerHandler) { yield return handler.InnerHandler.GetType().Name; handler = handler.InnerHandler as DelegatingHandler; if (null == handler) { break; } } } }

MyHttpServer Initialize

GetHandlerChain HttpMessageHandler

Tuple<IEnumerable<string> IEnumerable<string>> Get

Tuple HttpMessageHandler HttpServer

Page 51: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

111

DemoController Action Get

3-4 HttpServer

Initialize HttpMessageHandler

HttpConfiguration MessageHandlers

HttpRoutingDispatcher HttpServer

Dispatcher

3-4 HttpServer

HttpServer HttpServer

HttpConfiguration

HttpServer Configuration

HttpConfiguration

// 1 HttpConfiguration configuration = new HttpConfiguration(); configuration.MessageHandlers.Add(new FooHandler()); configuration.MessageHandlers.Add(new BarHandler()); configuration.MessageHandlers.Add(new BazHandler()); HttpServer httpServer = new HttpServer(configuration); // 2 HttpServer httpServer = new HttpServer(); httpServer.Configuration.MessageHandlers.Add(new FooHandler());

Page 52: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

112

httpServer.Configuration.MessageHandlers.Add(new BarHandler ()); httpServer.Configuration.MessageHandlers.Add(new BazHandler ());

Principal

Principal Identity Permission

HttpServer SendAsync

CurrentPrincipal Principal

Principal Principal

GenericPrincipal

HttpServer SendAsync Principal

ASP.NET Web API HttpServer

MyHttpServer SendAsync

public class MyHttpServer : HttpServer { public new Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken); } }

ApiController DemoController Action

Get MyHttpServer SendAsync

Principal Null

Artech GenericPrincipal Principal SendAsync

Principal GenericPrincipal Get

GenericPrincipal

public class DemoController : ApiController { public IEnumerable<string> Get() { MyHttpServer httpServer = new MyHttpServer(); //Thread.CurrentPrincipal == Null Thread.CurrentPrincipal = null;

Page 53: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

113

HttpRequestMessage request = new HttpRequestMessage(); httpServer.SendAsync(request, new CancellationToken(false)); GenericPrincipal principal = (GenericPrincipal)Thread.CurrentPrincipal; string identity1 = string.IsNullOrEmpty(principal.Identity.Name) ? "N/A" : principal.Identity.Name; //Thread.CurrentPrincipal = Null GenericIdentity identity = new GenericIdentity("Artech"); Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[0]); request = new HttpRequestMessage(); httpServer.SendAsync(request, new CancellationToken(false)); principal = (GenericPrincipal)Thread.CurrentPrincipal; string identity2 = string.IsNullOrEmpty(principal.Identity.Name) ? "N/A" : principal.Identity.Name; return new string[] { identity1, identity2 }; } }

DemoController Get 3-5

S302 Principal HttpServer

SendAsync GenericPrincipal

Principal

3-5 HttpServer Principal

HttpServer SendAsync HttpMessageHandler

SynchronizationContext Current

SynchronizationContext HttpRequest

Page 54: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

114

Message

HttpRequestMessage

HttpServer HttpRequestMessage

Configuration HttpConfiguration

GetConfiguration GetSynchronizationContext HttpRequestMessage

HttpConfiguration SynchronizationContext

public static class HttpRequestMessageExtensions { // public static HttpConfiguration GetConfiguration( this HttpRequestMessage request); public static SynchronizationContext GetSynchronizationContext( this HttpRequestMessage request); }

3.1.4 HttpRoutingDispatcher HttpServer Dispatcher

HttpRoutingDispatcher HttpMessageHandler

Web API HttpController Action

HttpController Action HttpRouting

Dispatcher HttpController Action

HttpRoutingDispatcher DelegatingHandler

HttpMessageHandler HttpRoutingDispatcher

HttpConfiguration defaultHandler HttpMessage

Handler HttpRoutingDispatcher HttpController

Action

public class HttpRoutingDispatcher : HttpMessageHandler { public HttpRoutingDispatcher(HttpConfiguration configuration); public HttpRoutingDispatcher(HttpConfiguration configuration, HttpMessageHandler defaultHandler); protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken); }

Page 55: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

115

ASP.NET Web API HttpContext

HttpRequestMessage

Properties

HttpServer SynchronizationContext

HttpConfiguration HttpRequestMessage

HttpRouteData HttpRequestMessage

HttpRequestMessage GetRouteData

SetRouteData HttpRouteData

public static class HttpRequestMessageExtensions { // public static IHttpRouteData GetRouteData(this HttpRequestMessage request); public static void SetRouteData(this HttpRequestMessage request, IHttpRouteData routeData); }

HttpRoutingDispatcher SendAsync HttpRequest

Message HttpRouteData HttpRouteData

HttpMessageHandler

Web Host

HttpRouteData HttpRequest

Message Self Host

HttpRoutingDispatcher HttpConfiguration

Routes HttpRequestMessage GetRouteData

GetRouteData HttpRouteData

HttpRoute HttpRoutingDispatcher HttpRouteData

HttpRequestMessage ASP.NET Web API

HttpMessageHandler GetRouteData Null

404 Not Found

Page 56: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

116

HttpControllerDispatcher

HttpRoutingDispatcher

Routing Dispatching

HttpRouteData HttpRouteData

HttpMessageHandler

HttpRoutingDispatcher defaultHandler

HttpMessageHandler HttpMessageHandler

HttpControllerDispatcher System.Web.

Http.Dispatcher HttpControllerDispatcher

HttpController Action HttpControllerDispatcher

public class HttpControllerDispatcher : HttpMessageHandler { public HttpControllerDispatcher(HttpConfiguration configuration); protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken); public HttpConfiguration Configuration { get; } }

HttpControllerDispatcher ASP.NET Web API

3-6 HttpControllerDispatcher

HttpMessageHandler

HttpControllerDispatcher HttpRoutingDispatcher HttpMessageHandler

HttpControllerDispatcher HttpRoutingDispatcher

HttpMessageHandler

N DelegatingHandler + 1 HttpMessageHandler

DelegatingHandler

Page 57: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.1 HttpMessageHandler

ASP.NET Web API 2

117

3-6 HttpControllerDispatcher

HttpRoutingDispatcher S303

HttpRoutingDispatcher HttpRoute

HttpRouteData HttpRouteData

HttpRequestMessage

ASP.NET Web API MyHttpRoutingDispatcher

HttpRoutingDispatcher SendAsync

public class MyHttpRoutingDispatcher : HttpRoutingDispatcher { public MyHttpRoutingDispatcher(HttpConfiguration configuration) : base(configuration) { } public new Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken); } }

ApiController DemoController Action Get

HttpConfiguration URL wheather/ {areaCode}/

{days} HttpRoute http://www.artech. com/wheather/

010/2 URL HttpRequestMessage

Page 58: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

118

public class DemoController : ApiController { public async Task<IDictionary<string, object>> Get() { HttpConfiguration configuration = new HttpConfiguration(); configuration.Routes.MapHttpRoute( "default", "wheather/{areaCode}/{days}"); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://www.artech.com/wheather/010/2"); MyHttpRoutingDispatcher dispatcher = new MyHttpRoutingDispatcher(configuration); await dispatcher.SendAsync(request, CancellationToken.None); IHttpRouteData routeData = request.GetRouteData(); return routeData.Values; } }

HttpConfiguration MyHttpRoutingDispatcher

HttpRequestMessage SendAsync

await HttpRequestMessage

GetRouteData HttpRouteData Values

DemoController Action Get

3-7 {areaCode} {days}

HttpRoutingDispatcher SendAsync

3-7 HttpRoutingDispatcher HttpRouteData

Page 59: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.2 Web Host

ASP.NET Web API 2

119

RouteParameter Optional

RouteParameter

public sealed class RouteParameter { public static readonly RouteParameter Optional; }

URL

HttpRouteData

Values

HttpRoutingDispatcher SendAsync

HttpRouteData HttpRequestMessage

HttpRoutingDispatcher ASP.NET Web API

Values RouteParameter.Optional

3.2 Web Host

ASP.NET Web API HTTP

HttpRequestMessage HttpResponseMessage HttpRequestMessage

HttpMessageHandler HttpResponseMessage

Web API Web API

HttpRequestMessage HttpResponseMessage

Web Host

3.2.1 HttpControllerHandler ASP.NET Web API HttpRouting

Dispatcher Web Host

Page 60: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

120

ASP.NET Web Host ASP.NET Web Web

API ASP.NET IIS

2 ASP.NET UrlRoutingModule

HttpModule HttpApplication PostResolveRequestCache

URL

RouteData UrlRoutingModule Route HttpHandler

HTTP

Web Host Web API UrlRoutingModule

HTTP HttpHandler HttpRequest

HttpRequestMessage

HttpRequestMessage HttpResponse

HttpHandler

2 Web Host

HttpRoute ASP.NET HttpWebRoute

Route HttpWebRoute RouteHandler HttpControllerRouteHandler

HttpHandler HttpControllerRouteHandler

HttpControllerRouteHandler GetHttpHandler HttpHandler

RouteData HttpControllerHandler

public class HttpControllerRouteHandler : IRouteHandler { // protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { return new HttpControllerHandler(requestContext.RouteData); } }

HttpControllerHandler System.Web.HttpTaskAsyncHandler

IHttpAsyncHandler HttpTaskAsyncHandler

Page 61: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.2 Web Host

ASP.NET Web API 2

121

Task ProcessRequestAsync IHttpAsyncHandler

BeginProcessRequest Task AsyncResult

EndProcessRequest Task

public abstract class HttpTaskAsyncHandler : IHttpAsyncHandler { public virtual void ProcessRequest(HttpContext context); IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData); void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result); public abstract Task ProcessRequestAsync(HttpContext context); public virtual bool IsReusable { get; } }

HttpTaskAsyncHandler HttpControllerHandler

HttpControllerHandler RouteData HttpControllerHandler

HttpMessageHandler

public class HttpControllerHandler : HttpTaskAsyncHandler { public HttpControllerHandler(RouteData routeData) : this(routeData, GlobalConfiguration.DefaultServer) {} public HttpControllerHandler(RouteData routeData, HttpMessageHandler handler); public override Task ProcessRequestAsync(HttpContext context); }

HttpControllerRouteHandler GetHttpHandler HttpControllerHandler

Global

Configuration DefaultServer HttpMessage

Handler HttpServer HttpControllerHandler

3-8

ASP.NET HttpControllerHandler

ASP.NET ASP.NET UrlRoutingModule

Route URL

TaskWrapperAsyncResult System.Web.dll

Page 62: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

122

Route RouteData RouteData Route

Route Route HttpWebRoute

3-8 HttpControllerHandler

UrlRoutingModule RouteData Route RouteHandler

RouteHandler HttpControllerRouteHandler UrlRoutingModule

RouteData HTTP RequestContext

HttpControllerRouteHandler GetHttpHandler

HttpHandler HTTP

HttpControllerRouteHandler GetHttpHandler

RequestContext RouteData HttpControllerHandler

HttpControllerHandler GlobalConfiguration

DefaultServer HttpMessageHandler

DefaultServer HttpServer HttpMessageHandler

HttpControllerHandler ProcessRequestAsync

HTTP HttpRequestMessage

RouteData HttpRouteData HostedHttpRouteData

HttpRequestMessage HttpRequestMessage

HttpServer SendAsync

HttpRequestMessage HttpRoutingDispatcher

HttpMessageHandler HttpRoute

Data HttpRouteData

Page 63: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.2 Web Host

ASP.NET Web API 2

123

HttpRouteData

Web Host HttpControllerHandler HttpRequestMessage

HttpRouteData

HttpServer SendAsync Task<HttpResponseMessage>

HttpControllerHandler Task

EndProcessRequest HttpControllerHandler Task

HttpResponseMessage HttpResponse

HttpControllerHandler S304

HttpRoutingDispatcher

Web Host HttpRouteData HttpControllerHandler

HttpRoutingDispatcher

HttpControllerHandler

ASP.NET MVC HttpRouteDataTraceHandler

HttpMessageHandler HttpRequestMessage

HttpRouteData SendAsync

GetRouteData HttpRequestMessage

HttpRouteData Values

HttpResponse

public class HttpRouteDataTraceHandler: HttpMessageHandler { protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { IHttpRouteData routeData = request.GetRouteData(); foreach (var item in routeData.Values) { HttpContext.Current.Response.Write(string.Format("{0}: {1}<br/>", item.Key, item.Value)); } return Task.FromResult<HttpResponseMessage>(null); } }

Page 64: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

124

HomeController Action Index ASP.NET

Web API wheather/{areaCode}/{days} HttpRoute

http://www.artech.com/wheather/010/2 HttpRequest

HttpContext HttpContext HttpContextWrapper

GetRouteData RouteData

HttpRouteDataTraceHandler RouteData

HttpControllerHandler HttpContext

ProcessRequestAsync HttpControllerHandler

public class HomeController : Controller { public void Index() { GlobalConfiguration.Configuration.Routes.MapHttpRoute( "wheather", "wheather/{areaCode}/{days}"); HttpRequest request = new HttpRequest("wheather.aspx", "http://www.artech.com/wheather/010/2", null); HttpResponse response = new HttpResponse(new StringWriter()); HttpContext context = new HttpContext(request, response); RouteData routeData = RouteTable.Routes.GetRouteData( new HttpContextWrapper(context)); HttpControllerHandler httpHandler = new HttpControllerHandler(routeData, new HttpRouteDataTraceHandler()); httpHandler.ProcessRequestAsync(context).Wait(); } }

3-9

HttpRouteDataTraceHandler SendAsync

HttpRequestMessage HttpControllerHandler RouteData

HttpRouteData HttpRequestMessage HttpRouteDataTraceHandler

RouteTable Routes ASP.NET HttpConfiguration Routes

ASP.NET Web API

Page 65: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.2 Web Host

ASP.NET Web API 2

125

3-9 ASP.NET MVC

HttpServer

ASP.NET Web API HttpMessageHandler

HttpServer HttpServer

HttpControllerHandler HttpServer

GlobalConfiguration DefaultServer HttpServer

GlobalConfiguration DefaultServer HttpServer

HttpServer HttpConfiguration

GlobalConfiguration Configuration Dispatcher

HttpMessageHandler DefaultHandler HttpRoutingDispatcher

public static class GlobalConfiguration { private static Lazy<HttpConfiguration> _configuration = new Lazy<HttpConfiguration>( () => { HttpConfiguration config = new HttpConfiguration( new HostedHttpRouteCollection(RouteTable.Routes)); // return config; }); private static Lazy<HttpMessageHandler> _defaultHandler = new Lazy<HttpMessageHandler>( () => new HttpRoutingDispatcher(_configuration.Value)); private static Lazy<HttpServer> _defaultServer = new Lazy<HttpServer>(

Page 66: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

126

() => new HttpServer(_configuration.Value, _defaultHandler.Value)); public static HttpConfiguration Configuration { get { return _configuration.Value; } } public static HttpMessageHandler DefaultHandler { get { return _defaultHandler.Value; } } public static HttpServer DefaultServer { get { return _defaultServer.Value; } } }

GlobalConfiguration DefaultServer DefaultHandler HttpServer

HttpRoutingDispatcher HttpMessageHandler

3.2.2 HttpMessageHandler HTTPS305

RESTful Web API HTTP

HTTP HTTP

GET POST

PUT

HTTP Proxy Gateway

HTTP

HTTP Web API

HTTP

HTTP GET POST HTTP

HTTP HTTP

HTTP X-HTTP-Method-Override

ASP.NET Web API HTTP

Page 67: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.2 Web Host

ASP.NET Web API 2

127

HTTP HttpMessageHandler

HttpRequestMessage Method

HTTP HttpMessageHandler

X-HTTP-Method-Override HttpRequestMessage Method

HTTP

HttpMethodOverrideHandler DelegatingHandler

SendAsync X-HTTP-Method-Override HTTP

HttpMessageHandler

public class HttpMethodOverrideHandler: DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { IEnumerable<string> methodOverrideHeader; if (request.Headers.TryGetValues("X-HTTP-Method-Override", out methodOverrideHeader)) { request.Method = new HttpMethod(methodOverrideHeader.First()); } return base.SendAsync(request, cancellationToken); } }

ASP.NET Web API ApiController

DemoController 4 Action Get Post Put

Delete ASP.NET Web API HTTP Action

4 Action HTTP

public class DemoController : ApiController { public string Get() { return "Get"; } public string Post() { return "Post"; } public string Put() {

Page 68: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

128

return "Put"; } public string Delete() { return "Delete"; } }

Global.asax HttpMethodOverrideHandler

ASP.NET Web API IIS Express

3721

public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configuration.MessageHandlers.Add( new HttpMethodOverrideHandler()); // } }

Web API

InvokeWebApi HttpClient HTTP

Web API HTTP Web API

HttpRequestMessage HttpClient SendAsync

Web API Web API Action

HTTP X-HTTP-Method-Override

class Program { static void Main(string[] args) { HttpClient httpClient1 = new HttpClient(); HttpClient httpClient2 = new HttpClient(); HttpClient httpClient3 = new HttpClient(); HttpClient httpClient4 = new HttpClient(); httpClient3.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "PUT"); httpClient4.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "DELETE"); Console.WriteLine("{0,-7}{1,-24}{2,-6}", "Method", "X-HTTP-Method-Override", "Action");

Page 69: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.2 Web Host

ASP.NET Web API 2

129

InvokeWebApi(httpClient1, HttpMethod.Get); InvokeWebApi(httpClient2, HttpMethod.Post); InvokeWebApi(httpClient3, HttpMethod.Post); InvokeWebApi(httpClient4, HttpMethod.Post); Console.Read(); } async static void InvokeWebApi(HttpClient httpClient, HttpMethod method) { string requestUri = "http://localhost:3721/api/demo"; HttpRequestMessage request = new HttpRequestMessage(method, requestUri); HttpResponseMessage response = await httpClient.SendAsync(request); IEnumerable<string> methodsOverride; httpClient.DefaultRequestHeaders.TryGetValues("X-HTTP-Method- Override", out methodsOverride); string actionName = response.Content.ReadAsStringAsync().Result; string methodOverride = methodsOverride == null ? "N/A" : methodsOverride.First(); Console.WriteLine("{0,-7}{1,-24}{2,-6}", method, methodOverride, actionName.Trim('"')); } }

Main 4 HttpClient httpClient1 httpClient2 httpClient3

httpClient4 X-HTTP-Method-Override httpClient3 httpClient4

HTTP PUT DELETE 4 HttpClient

InvokeWebApi Web API 4 1 GET

POST

Web API

X-HTTP-Method-Override Action

HTTP X-HTTP-Method-Override

HTTP Action

HttpMethodOverrideHandler HttpMessageHandler

Method X-HTTP-Method-Override Action POST PUT Put GET N/A Get

InvokeWebApi Web API

Page 70: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

130

POST N/A Post POST DELETE Delete

3.3 Self Host

ASP.NET Web API

Web Host ASP.NET Web

API ASP.NET ASP.NET

URL HttpControllerHandler HttpHandler ASP.NET

ASP.NET Web API Self Host

3.3.1 HttpBinding

WCF Self Host Web API

Windows Form WPF Windows

Service Self Host WCF ASP.NET Web API

Binding

WCF

Endpoint ABC

Address Binding Contract WCF

Channel WCF Channel ASP.NET Web API

HttpMessageHandler

WCF Binding Binding

Binding

WCF 3 Binding ASP.NET

Web API HttpBinding Binding

Page 71: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

131

Binding BindingElement

Channel BindingElement BindingElement

Channel ChannelListener Channel

ChannelListener 3-10 Binding

3-10 Binding

ChannelListener Binding Open

BindingElement ChannelListener ChannelListener

BindingElement ChannelListener

ChannelListener

Channel

Channel Channel

TransportChannel MessageEncoding

Channel TransportChannel

TransportChannelListener TransportBindingElement Message

EncodingBindingElement MessageEncodingChannelListener Message

EncodingChannel

Self Host HttpBinding Binding

ChannelListener

HttpBinding System.Web.Http.SelfHost.Channels

Page 72: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

132

HttpBinding

Binding

Channel BindingElement Binding

BindingElement BindingElement

ASP.NET Web API Self Host HttpBinding

BindingElement

3-11 HttpBinding BindingElement

TransportBindingElement HTTP

TransportBindingElement HttpTransportBindingElement HTTPS

TransportBindingElement HttpsTransportBindingElement

3-11 HttpBinding BindingElement

/ BindingElement 3-11

HttpMessageEncodingBindingElement HttpMessageEncodingBindingElement

System.Web.Http.SelfHost.dll

MessageEncoder /

ASP.NET Web API HttpRequestMessage HttpResponseMessage

WCF Message

Message System.ServiceModel.Channels

HttpMessageEncoder Message HttpRequestMessage

ASP.NET Web API HttpResponseMessage

Message HttpMessageEncoder

HttpMessage HttpMessage Message

Page 73: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

133

System.Web.Http.SelfHost.dll

HttpMessage HttpRequestMessage HttpResponseMessage

GetHttpRequestMessage GetHttpResponseMessage

HttpRequestMessage HttpResponseMessage

internal sealed class HttpMessage : Message { // public HttpMessage(HttpRequestMessage request); public HttpMessage(HttpResponseMessage response); public HttpRequestMessage GetHttpRequestMessage(bool extract); public HttpResponseMessage GetHttpResponseMessage(bool extract); }

extract

HttpRequestMessage/HttpResponseMessage True

HttpRequestMessage/HttpResponseMessage HttpMessage

Null

HttpBinding

HttpBinding ChannelListener

HTTP/HTTPS TransportChannel Message

Encoder HttpRequestMessage HttpMessage

HttpRequestMessage GetHttpRequestMessage

HttpMessage

ASP.NET Web API HttpResponse

Message HttpMessage

MessageEncoder

GetHttpResponseMessage HttpResponseMessage

HttpBinding S306

Self Host Web Web API

HttpBinding ChannelListener

ChannelListener

HttpBinding

Page 74: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

134

Self Host

HttpBinding

http://127.0.0.1:3721 BuildChannelListener<IReplyChannel> Channel

Listener ChannelListener Open

ChannelListener AcceptChannel

Channel Open While

Channel ReceiveRequest

class Program { static void Main(string[] args) { Uri listenUri = new Uri("http://127.0.0.1:3721"); Binding binding = new HttpBinding(); // IChannelListener<IReplyChannel> channelListener = binding.BuildChannelListener<IReplyChannel>(listenUri); channelListener.Open(); // IReplyChannel channel = channelListener.AcceptChannel(TimeSpan.MaxValue); channel.Open(); // while (true) { // RequestContext requestContext = channel.ReceiveRequest(TimeSpan.MaxValue); PrintRequestMessage(requestContext.RequestMessage); // requestContext.Reply(CreateResponseMessage()); } } }

PrintRequestMessage

HttpMessage

GetHttpRequestMessage

Page 75: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

135

HttpRequestMessage HttpRequestMessage

private static void PrintRequestMessage(Message message) { MethodInfo method = message.GetType().GetMethod("GetHttpRequestMessage"); HttpRequestMessage request = (HttpRequestMessage)method.Invoke(message, new object[]{false}); Console.WriteLine("{0, -15}:{1}", "RequestUri", request.RequestUri); foreach (var header in request.Headers) { Console.WriteLine("{0, -15}:{1}", header.Key, string.Join("," ,header.Value.ToArray())); } }

Message

CreateResponseMessage

200 OK HttpResponseMessage

Content ObjectContent<Employee> MediaTypeFormatter

JsonMediaTypeFormatter Employee JSON

HttpMessage HttpResponseMessage

HttpMessage

private static Message CreateResponseMessage() { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); Employee employee = new Employee("001","Zhang San","123456", "[email protected]"); response.Content = new ObjectContent<Employee>(employee, new JsonMediaTypeFormatter()); string httpMessageTypeName = "System.Web.Http.SelfHost.Channels.HttpMessage, System.Web.Http.SelfHost"; Type httpMessageType = Type.GetType(httpMessageTypeName); return (Message)Activator.CreateInstance(httpMessageType, new object[] { response }); } public class Employee { public string Id { get; set; }

Page 76: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

136

public string Name { get; set; } public string PhoneNo { get; set; } public string EmailAddress { get; set; } public Employee(string id, string name, string phoneNo, string emailAddress) { this.Id = id; this.Name = name; this.PhoneNo = phoneNo; this.EmailAddress = emailAddress; } }

http://127.0.0.1:3721

Web API

http://127.0.0.1:3721/employees/001

001 3-12

JSON

3-12 HttpBinding

3.3.2 HttpSelfHostServer

1 ASP.NET Web API Self Host

System.Web.Http.SelfHost.HttpSelfHostServer HttpSelfHostServer

Page 77: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

137

HttpBinding HttpSelfHostServer ASP.NET Web API

HttpSelfHostServer HttpServer Self Host

HttpSelfHostServer HttpSelfHostServer

public sealed class HttpSelfHostServer : HttpServer { public HttpSelfHostServer(HttpSelfHostConfiguration configuration); public HttpSelfHostServer(HttpSelfHostConfiguration configuration, HttpMessageHandler dispatcher); public Task OpenAsync(); public Task CloseAsync(); protected override void Dispose(bool disposing); }

ASP.NET Web API HttpServer Configuration

HttpConfiguration HttpSelfHostServer Configuration

HttpSelfHostConfiguration HttpSelfHostConfiguration System.Web.

Http.SelfHost

HttpSelfHostServer HttpSelfHostConfiguration

HttpSelfHostConfiguration

HttpSelfHostConfiguration HttpConfiguration

HttpSelfHostConfiguration Uri

BaseAddress

public class HttpSelfHostConfiguration : HttpConfiguration { public HttpSelfHostConfiguration(Uri baseAddress); public Uri BaseAddress { get; } public HostNameComparisonMode HostNameComparisonMode { get; set; } public TransferMode TransferMode { get; set; } public int MaxBufferSize { get; set; } public int MaxConcurrentRequests { get; set; } public long MaxReceivedMessageSize { get; set; }

Page 78: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

138

public TimeSpan ReceiveTimeout { get; set; } public TimeSpan SendTimeout { get; set; } public HttpClientCredentialType ClientCredentialType { get; set; } public UserNamePasswordValidator UserNamePasswordValidator { get; set; } public X509CertificateValidator X509CertificateValidator { get; set; } }

Self Host HttpBinding

HttpSelfHostConfiguration

HttpBinding HttpBinding HttpSelfHost

Configuration

public abstract class Binding : IDefaultCommunicationTimeouts { // public TimeSpan ReceiveTimeout { get; set; } public TimeSpan SendTimeout { get; set; } } public class HttpBinding : Binding, IBindingRuntimePreferences { // public HostNameComparisonMode HostNameComparisonMode { get; set; } public TransferMode TransferMode { get; set; } public long MaxBufferPoolSize { get; set; } public int MaxBufferSize { get; set; } public long MaxReceivedMessageSize { get; set; } public HttpBindingSecurity Security { get; set; } }

Binding WCF

HttpBinding Binding

3-1

3-1 HttpSelfHostConfiguration

HostNameComparisonMode

URL IPURL

System.ServiceModel.HostName ComparisonMode

Page 79: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

139

TransferMode MaxBufferSize

Streamed Buffered

System.ServiceModel.TransferMode

BufferedMaxBufferSize Buffered

65536 0x10000

MaxConcurrentRequests MaxReceivedMessageSize

100 655360x10000 MaxConcurrentRequests

ReceiveTimeout SendTimeout 10 1

ClientCredentialType UserNamePasswordValidator X509CertificateValidator

ClientCredentialTypeUserNamePasswordValidator

X509CertificateValidator +X.509

HttpSelfHostServer

Self Host Web API

HttpSelfHostConfiguration HttpSelfHostServer

OpenAsync HttpSelfHostServer HttpBinding

HttpSelfHostConfiguration HttpBinding

ChannelListener BeginOpen OpenAsync

HttpSelfHostServer CloseAsync

ChannelListener

ChannelListener

HttpBinding HttpMessage

Page 80: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

140

HttpRequestMessage

HttpSelfHostServer HttpMessage HttpRequestMessage

HttpMessageHandler

HttpResponseMessage HttpSelfHostServer HttpMessage

HttpMessage

HttpMessage HttpResponseMessage

HttpResponseMessage 3-13

Self Host

3-13 Self Host

HttpServer HttpSelfHostServer S307

Self Host

HttpServer

HttpSelfHostServer

HttpServer HttpSelfHostServer MyHttpSelf

HostServer

HttpSelfHostServer MyHttpSelfHostServer

public class MyHttpSelfHostServer: HttpServer { public Uri BaseAddress { get; private set; } public IChannelListener<IReplyChannel> ChannelListener { get; private set; }

Page 81: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

141

public MyHttpSelfHostServer(HttpConfiguration configuration, Uri baseAddress) : base(configuration) { this.BaseAddress = baseAddress; } public void Open() { HttpBinding binding = new HttpBinding(); this.ChannelListener = binding .BuildChannelListener<IReplyChannel>(this.BaseAddress); this.ChannelListener.Open(); IReplyChannel channnel = this.ChannelListener.AcceptChannel(); channnel.Open(); while (true) { RequestContext requestContext = channnel .ReceiveRequest(TimeSpan.MaxValue); Message message = requestContext.RequestMessage; MethodInfo method = message.GetType().GetMethod("GetHttpRequestMessage"); HttpRequestMessage request = (HttpRequestMessage)method.Invoke(message, new object[] {true}); Task<HttpResponseMessage> processResponse = base.SendAsync(request, new CancellationTokenSource().Token); processResponse.ContinueWith(task => { string httpMessageTypeName = "System.Web.Http.SelfHost.Channels.HttpMessage, System.Web.Http.SelfHost"; Type httpMessageType = Type.GetType(httpMessageTypeName); Message reply = (Message)Activator.CreateInstance( httpMessageType, new object[] { task.Result }); requestContext.Reply(reply); }); } } public void Close() { if (null != this.ChannelListener && this.ChannelListener.State == CommunicationState.Opened) { this.ChannelListener.Close(); } } }

Page 82: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

142

MyHttpSelfHostServer BaseAddress

HttpSelfHostServer MyHttpSelfHostServer

HttpConfiguration HttpSelfHostConfiguration

Open HttpBinding

ChannelListener MyHttpSelfHostServer ChannelListener

ChannelListener AccpetChannel

Channel Channel While

ReceiveRequest

HttpMessage

HttpRequestMessage SendAsync

HttpRequestMessage

SendAsync Task<HttpResponseMessage> Task

HttpResponseMessage

HttpMessage HttpMessage HttpSelfHost

Server OpenAsync CloseAsync Open

Close ChannelListener

MyHttpSelfHostServer

HttpSelfHostServer ApiController

ContactsController Action Get

ID

public class ContactsController : ApiController { private static List<Contact> contacts = new List<Contact> { new Contact{ Id="001", Name = " ", PhoneNo="123", EmailAddress="[email protected]"}, new Contact{ Id="002",Name = " ", PhoneNo="456", EmailAddress="[email protected]"} }; public IEnumerable<Contact> Get() { return contacts; }

Page 83: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3.3 Self Host

ASP.NET Web API 2

143

public Contact Get(string id) { return contacts.FirstOrDefault(c => c.Id == id); } } public class Contact { public string Id { get; set; } public string Name { get; set; } public string PhoneNo { get; set; } public string EmailAddress { get; set; } }

Main

HttpConfiguration http://127.0.0.1:3721

MyHttpSelfHostServer Open URL

http://127.0.0.1:3721 HttpRoute

class Program { static void Main(string[] args) { using (MyHttpSelfHostServer httpServer = new MyHttpSelfHostServer( new HttpConfiguration(), new Uri("http://127.0.0.1:3721"))) { httpServer.Configuration.Routes.MapHttpRoute( name : "DefaultApi", routeTemplate : "api/{controller}/{id}", defaults : new { id = RouteParameter.Optional }); httpServer.Open(); Console.Read(); } } }

ContactsController Action Get HttpRoute

HTTP Action URL http://127.0.0.1:

3721/api/contacts http://127.0.0.1:3721/api/contacts/001 3-14

XML MyHttpSelfHostServer

Page 84: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

3

ASP.NET Web API 2

144

3-14 MyHttpSelfHostServer Web API

Page 85: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

Web API HttpController

Action HttpController

URI HttpController

HttpRouteData

HttpRequestMessage ASP.NET Web API

HttpController HttpController

Page 86: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

146

4.1 HttpController Visual Studio ASP.NET Web API Controller

ApiController ASP.NET Web API IHttpController

HttpController

HttpController IHttpController

IHttpController

ExecuteAsync HttpController

Task<HttpResponseMessage>

public interface IHttpController { Task<HttpResponseMessage> ExecuteAsync( HttpControllerContext controllerContext, CancellationToken cancellationToken); }

HttpController ASP.NET Web API 3

HttpRoutingDispatcher SendAsync

HttpRoutingDispatcher HttpControllerDispatcher

HttpController ExecuteAsync Task<HttpResponse

Message> 4-1 HttpController

4-1 HttpController

Page 87: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.1 HttpController

ASP.NET Web API 2

147

4.1.1 HttpControllerContext

HttpMessageHandler SendAsync HttpController ExecuteAsync

HttpRequestMessage

HttpControllerContext HttpControllerContext System.Web.Http.

Controllers HttpController

HttpControllerContext

HttpConfiguration HttpRouteData

HttpRequestMessage HttpControllerContext

HttpControllerContext

public class HttpControllerContext { public HttpControllerContext(); public HttpControllerContext(HttpConfiguration configuration, IHttpRouteData routeData, HttpRequestMessage request); public HttpConfiguration Configuration { get; set; } public IHttpRouteData RouteData { get; set; } public HttpRequestMessage Request { get; set; }

public IHttpController Controller { get; set; } public HttpControllerDescriptor ControllerDescriptor { get; set; } }

HttpControllerContext HttpController

Controller HttpController

ControllerDescriptor HttpController HttpControllerDescriptor

HttpControllerDescriptor System.Web.Http.Controllers

4.1.2 HttpControllerDescriptor

HttpControllerDescriptor HttpController

HttpController HttpControllerDescriptor

HttpController ASP.NET Web API HttpController

HttpControllerDescriptor HttpController

Page 88: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

148

HttpControllerDescriptor Configuration

ControllerName ControllerType HttpConfiguration HttpController

HttpControllerDescriptor

HttpControllerDescriptor

public class HttpControllerDescriptor { public HttpControllerDescriptor(); public HttpControllerDescriptor(HttpConfiguration configuration, string controllerName, Type controllerType); public virtual IHttpController CreateController(HttpRequestMessage request);

public virtual Collection<T> GetCustomAttributes<T>() where T: class; public virtual Collection<T> GetCustomAttributes<T>(bool inherit) where T: class; public virtual Collection<IFilter> GetFilters(); public HttpConfiguration Configuration { get; set; } public string ControllerName { get; set; } public Type ControllerType { get; set; } public virtual ConcurrentDictionary<object, object> Properties { get; } }

HttpControllerDescriptor HttpController CreateController

HttpController

HttpControllerDescriptor CreateController

HttpControllerDescriptor GetCustomAttributes<T>

HttpController GetFilters

HttpController Filter Filter ASP.NET Web API

12 Filter

HttpControllerDescriptor Properties

HttpControllerDescriptor HttpRequestMessage

HttpConfiguration

Page 89: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.1 HttpController

ASP.NET Web API 2

149

4.1.3 ApiController

HttpController ApiController

IHttpController HttpController

IDisposable HttpController

Dispose

public abstract class ApiController : IHttpController, IDisposable { public virtual Task<HttpResponseMessage> ExecuteAsync( HttpControllerContext controllerContext, CancellationToken cancellationToken); protected virtual void Initialize(HttpControllerContext controllerContext); public void Dispose(); protected virtual void Dispose(bool disposing); public HttpControllerContext ControllerContext { get; set; } public HttpConfiguration Configuration { get; set; } public HttpRequestMessage Request { get; set; } public IHttpRouteData RouteData { get; set; } public ModelStateDictionary ModelState { get; } public UrlHelper Url { get; set; } public IPrincipal User { get; } }

ApiController Configuration Request RouteData HttpControllerContext

ApiController HttpControllerContext

ControllerContext

ControllerContext

ApiController ModelState ModelStateDictionary

Model Action

ModelStateDictionary Url

UrlHelper UrlHelper System.Web.Http.Routing

HttpRoute URL

Page 90: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

150

ApiController User Principal 3

HttpServer Principal Null

HttpServer SendAsync GenericPrincipal

Principal User HttpServer

GenericPrincipal

ApiController Initialize

HttpControllerContext

Initialize ApiController Initialize

ExecuteAsync

ASP.NET Web API HttpController

HttpController ApiController HttpController

ExecuteAsync ApiController

InvalidOperationException

ApiController DemoController

Initialize

public class DemoController : ApiController { public new void Initialize(HttpControllerContext controllerContext) { base.Initialize(controllerContext); } }

DemoController

ExecuteAsync Initialize

DemoController controller = new DemoController(); HttpControllerContext controllerContext = new HttpControllerContext( new HttpConfiguration(), new HttpRouteData(new HttpRoute()), new HttpRequestMessage()); controller.ControllerContext = controllerContext; controller.Initialize(controllerContext); controller.ExecuteAsync(controllerContext, new CancellationToken(false));

ApiController ExecuteAsync 4-2 InvalidOperation

Cannot reuse an 'ApiController' instance. 'ApiController' has to be constructed per

Page 91: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

151

incoming message. Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance. ApiController

ApiController

4-2 ApiController

4.2 HttpController

HttpController HttpRoutingDispatcher

HttpControllerDispatcher HttpController

HttpController

4.2.1

ASP.NET Web API HttpController AssembliesResolver

HttpController HttpController

AssembliesResolver IHttpController

AssembliesResolver IAssembliesResolver

System.Web.Http.Dispatcher

IAssembliesResolver

GetAssemblies

public interface IAssembliesResolver { ICollection<Assembly> GetAssemblies(); }

Page 92: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

152

AssembliesResolver DefaultAssembliesResolver

DefaultAssembliesResolver GetAssemblies

public class DefaultAssembliesResolver : IAssembliesResolver { public virtual ICollection<Assembly> GetAssemblies() { return AppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>(); } }

DefaultAssembliesResolver AssembliesResolver Assemblies

Resolver ASP.NET Web API

ServicesContainer System.Web.Http.Controllers

ServicesContainer

ASP.NET Web API

ServicesContainer

ServicesContainer

IoC

ServicesContainer

Add AddRange Insert Replace

GetService

GetServices

public abstract class ServicesContainer : IDisposable { public void Add(Type serviceType, object service); public void AddRange(Type serviceType, IEnumerable<object> services); public void Insert(Type serviceType, int index, object service); public void InsertRange(Type serviceType, int index, IEnumerable<object> services);

Page 93: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

153

public void Replace(Type serviceType, object service); public void ReplaceRange(Type serviceType, IEnumerable<object> services); public abstract object GetService(Type serviceType); public abstract IEnumerable<object> GetServices(Type serviceType); public int FindIndex(Type serviceType, Predicate<object> match); public abstract bool IsSingleService(Type serviceType); public bool Remove(Type serviceType, object service); public int RemoveAll(Type serviceType, Predicate<object> match); public void RemoveAt(Type serviceType, int index); public virtual void Clear(Type serviceType); public virtual void Dispose(); }

FindIndex

IsSingleService

Remove RemoveAll RemoveAt Clear

ServicesContainer IDisposable ServicesContainer

Dispose

ASP.NET Web API HttpConfiguration

HttpConfiguration

ServicesContainer Services ASP.NET Web API

ServicesContainer

ServicesContainer DefaultServices DefaultServices

System.Web.Http.Services

public class HttpConfiguration : IDisposable { // public HttpConfiguration(HttpRouteCollection routes) { // this.Services = new DefaultServices(this); } public ServicesContainer Services { get; } }

AssembliesResolver

ASP.NET Web API AssembliesResolver

Page 94: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

154

ServicesContainer DefaultServices

AssembliesResolver DefaultAssembliesResolver

public class DefaultServices : ServicesContainer { // public DefaultServices(HttpConfiguration configuration) { // this.SetSingle<IAssembliesResolver>(new DefaultAssembliesResolver()); } }

AssembliesResolver ServicesContainer

GetService ServicesContainer

GetAssembliesResolver

public static class ServicesExtensions { // public static IAssembliesResolver GetAssembliesResolver( this ServicesContainer services); }

AssembliesResolver S401 S402

DefaultAssembliesResolver

HttpController

Self Host HttpController

HttpController

HttpController

4-3 4 Foo Bar Baz HttpController

3 Hosting 3

Page 95: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

155

4-3 HttpController

Foo Bar Baz 3 ApiController HttpControllerFooController BarController BazController 3

HttpController Action Get HttpControllerAssemblyQualifiedName

public class FooController : ApiController { public string Get() { return this.GetType().AssemblyQualifiedName; } } public class BarController : ApiController { public string Get() { return this.GetType().AssemblyQualifiedName; } } public class BarController : ApiController { public string Get() { return this.GetType().AssemblyQualifiedName; } }

Hosting Self Host Web APIhttp://127.0.0.1:3721 HttpSelfHostServer

URL api/{controller}/{id}

class Program {

Page 96: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

156

static void Main(string[] args) { Uri baseAddress = new Uri("http://127.0.0.1:3721"); using (HttpSelfHostServer httpServer = new HttpSelfHostServer( new HttpSelfHostConfiguration(baseAddress))) { httpServer.Configuration.Routes.MapHttpRoute( name : "DefaultApi", routeTemplate : "api/{controller}/{id}", defaults : new { id = RouteParameter.Optional }); httpServer.OpenAsync().Wait(); Console.Read(); } } }

FooController BarController

BazController Action Get 4-4

S401

HttpController

4-4 HttpController

Page 97: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

157

DefaultAssemblies

Resolver AssembliesResolver

<configuration> <configSections> <section name="preLoadedAssemblies" type="Hosting.PreLoadedAssembliesSettings, Hosting"/> </configSections> <preLoadedAssemblies> <add assemblyName ="Foo.dll"/> <add assemblyName ="Bar.dll"/> <add assemblyName ="Baz.dll"/> </preLoadedAssemblies> </configuration>

AssembliesResolver

PreLoadedAssembliesSettings AssemblyElementCollection Assembly

Element

public class PreLoadedAssembliesSettings: ConfigurationSection { [ConfigurationProperty("", IsDefaultCollection = true)] public AssemblyElementCollection AssemblyNames { get { return (AssemblyElementCollection)this[""]; } } public static PreLoadedAssembliesSettings GetSection() { return ConfigurationManager.GetSection("preLoadedAssemblies") as PreLoadedAssembliesSettings; } } public class AssemblyElementCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { return new AssemblyElement(); } protected override object GetElementKey(ConfigurationElement element) { AssemblyElement serviceTypeElement = (AssemblyElement)element; return serviceTypeElement.AssemblyName;

Page 98: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

158

} } public class AssemblyElement : ConfigurationElement { [ConfigurationProperty("assemblyName", IsRequired = true)] public string AssemblyName { get { return (string)this["assemblyName"]; } set { this["assemblyName"] = value; } } }

AssembliesResolver DefaultAssembliesResolver

ExtendedDefaultAssembliesResolver ExtendedDefaultAssembliesResolverDefaultAssembliesResolver GetAssemblies

public class ExtendedDefaultAssembliesResolver : DefaultAssembliesResolver { public override ICollection<Assembly> GetAssemblies() { PreLoadedAssembliesSettings settings = PreLoadedAssembliesSettings.GetSection(); if (null != settings) { foreach (AssemblyElement element in settings.AssemblyNames) { AssemblyName assemblyName = AssemblyName.GetAssemblyName(element.AssemblyName); if(!AppDomain.CurrentDomain.GetAssemblies() .Any(assembly=>AssemblyName.ReferenceMatchesDefinition( assembly.GetName(),assemblyName))) { AppDomain.CurrentDomain.Load(assemblyName); } } } return base.GetAssemblies(); } }

Hosting ExtendedDefault Assemblies Resolver HttpConfiguration ServicesContainer

class Program {

Page 99: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

159

static void Main(string[] args) { Uri baseAddress = new Uri("http://127.0.0.1:3721"); using (HttpSelfHostServer httpServer = new HttpSelfHostServer( new HttpSelfHostConfiguration(baseAddress))) { httpServer.Configuration.Services.Replace( typeof(IAssembliesResolver), new ExtendedDefaultAssembliesResolver()); // } } }

FooController

BarController BazController Action Get 4-5

Action S402

4-5 AssembliesResolver HttpController

WebHostAssembliesResolver

DefaultAssembliesResolver HttpController

Page 100: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

160

HttpController

Self Host Web Host

AssembliesResolver

Web Host ASP.NET Web API

GlobalConfiguration Configuration HttpConfiguration

GlobalConfiguration Configuration

ServicesContainer AssembliesResolver

WebHostAssembliesResolver

public static class GlobalConfiguration { // static GlobalConfiguration() { _configuration = new Lazy<HttpConfiguration>(delegate { HttpConfiguration configuration = new HttpConfiguration( new HostedHttpRouteCollection(RouteTable.Routes)); configuration.Services.Replace(typeof(IAssembliesResolver), new WebHostAssembliesResolver()); // return configuration; }); // } public static HttpConfiguration Configuration { get { return _configuration.Value; } } }

WebHostAssembliesResolver System.Web.Http.WebHost.dll

WebHostAssembliesResolver GetAssemblies

BuildManager GetReferencedAssemblies

internal sealed class WebHostAssembliesResolver : IAssembliesResolver { ICollection<Assembly> IAssembliesResolver.GetAssemblies()

Page 101: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

161

{ return BuildManager.GetReferencedAssemblies().OfType<Assembly>() .ToList<Assembly>(); } }

BuildManager GetReferencedAssemblies

HttpController

Self Host

Web Host ASP.NET Web API HttpController

Foo.dll Bar.dll Baz.dll HttpController

4.2.2 HttpController

ServicesContainer AssembliesResolver HttpController

HttpController HttpController

TypeResolver HttpControllerTypeResolver IHttpController

TypeResolver GetControllerTypes

AssembliesResolver HttpController

public interface IHttpControllerTypeResolver { ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver); }

AssembliesResolver HttpControllerTypeResolver

HttpConfiguration ServicesContainer ServicesContainer

GetHttpControllerTypeResolver HttpController

TypeResolver

public static class ServicesExtensions { // public static IHttpControllerTypeResolver GetHttpControllerTypeResolver( this ServicesContainer services); }

HttpConfiguration DefaultServices

HttpControllerTypeResolver

Page 102: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

162

HttpControllerTypeResolver DefaultHttpControllerTypeResolver

public class DefaultServices : ServicesContainer { // public DefaultServices(HttpConfiguration configuration) { // this.SetSingle<IHttpControllerTypeResolver>( new DefaultHttpControllerTypeResolver()); } }

DefaultHttpControllerTypeResolver

DefaultHttpControllerTypeResolver Predicate<Type>

IsControllerTypePredicate

HttpController

public class DefaultHttpControllerTypeResolver : IHttpControllerTypeResolver { public DefaultHttpControllerTypeResolver(); public DefaultHttpControllerTypeResolver(Predicate<Type> predicate); public virtual ICollection<Type> GetControllerTypes( IAssembliesResolver assembliesResolver); protected Predicate<Type> IsControllerTypePredicate { get; } }

HttpController

DefaultHttpControllerTypeResolver Predicate<Type>

Predicate<Type> HttpController

HttpController

� IsVisible = true IsAbstract = false IsClass = true

� IHttpController

� Controller controller

Page 103: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

163

HttpController GetControllerTypesAssembliesResolver

HttpControllerDefaultHttpControllerTypeResolver HttpController

public class DefaultHttpControllerTypeResolver : IHttpControllerTypeResolver { // public virtual ICollection<Type> GetControllerTypes( IAssembliesResolver assembliesResolver) { List<Type> types = new List<Type>(); foreach (Assembly assembly in assembliesResolver.GetAssemblies()) { foreach (Type type in assembly.GetTypes()) { if (this.IsControllerTypePredicate(type)) { types.Add(type); } } } return types; } }

HttpController

HttpControllerASP.NET Web API HttpController

HttpControllerTypeCache System.Web. Http.dll

internal sealed class HttpControllerTypeCache { // internal Dictionary<string, ILookup<string, Type>> Cache { get; } }

HttpController Cache Dictionary<string, ILookup<string, Type>> Key HttpController HttpController

Controller Value ILookup<string, Type>

Page 104: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

164

HttpController Key HttpController

HttpControllerTypeCache HttpControllerTypeResolver

HttpController

HttpControllerTypeCache HttpController

4

ApiController HttpController HttpControllers1 Http

Controllers2 HttpController FooBarController FoobarController

4 HttpController FooBar

namespace HttpControllers1 { public class FooBarController : ApiController {} public class FoobarController : ApiController {} } namespace HttpControllers2 { public class FooBarController : ApiController {} public class FoobarController : ApiController {} }

HttpControllerTypeCache

HttpController Cache

Dictionary<string, ILookup<string, Type>>

class Program { static void Main(string[] args) { Type typeCacheType = Type.GetType( "System.Web.Http.Dispatcher.HttpControllerTypeCache, System.Web.Http"); object typeCache = Activator.CreateInstance(typeCacheType, new object[] { new HttpConfiguration() }); PropertyInfo cacheProperty = typeCacheType.GetProperty("Cache", BindingFlags.Instance | BindingFlags.NonPublic); Dictionary<string, ILookup<string, Type>> cachedTypes = (Dictionary<string, ILookup<string, Type>>) cacheProperty.GetValue(typeCache, null);

Page 105: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

165

Console.WriteLine("{0,-16}{1,-20}{2,-10}", "ControllerName", "Namespace","TypeName"); foreach (var item in cachedTypes) { foreach (string key in item.Value.Select( group => group.Key).Distinct()) { foreach (Type type in item.Value[key]) { Console.WriteLine("{0,-16}{1,-20}{2,-10}", item.Key, key, type.Name); } } } } }

4 HttpController

HttpControllerTypeCache S403 Dictionary<string, ILookup<string,

Type>> Key HttpController Controller

FooBarController FoobarController Key

Value ILookup<string, Type> Key HttpController

HttpControllers1 HttpControllers2

ControllerName Namespace TypeName FooBar HttpControllers1 FooBarController FooBar HttpControllers1 FoobarController FooBar HttpControllers2 FooBarController FooBar HttpControllers2 FoobarController

4.2.3 HttpController

AssembliesResolver HttpController

HttpController HttpController

HttpControllerSelector HttpControllerSelector

IHttpControllerSelector

public interface IHttpControllerSelector { IDictionary<string, HttpControllerDescriptor> GetControllerMapping(); HttpControllerDescriptor SelectController(HttpRequestMessage request); }

Page 106: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

166

GetControllerMapping SelectController

GetControllerMapping HttpController HttpControllerDescriptor

HttpController HttpController

SelectController HttpController HttpControllerDescriptor

DefaultHttpControllerSelector

HttpControllerSelector ServicesContainer

ServicesContainer GetHttpControllerSelector

HttpControllerSelector

public static class ServicesExtensions { // public static IHttpControllerSelector GetHttpControllerSelector( this ServicesContainer services); }

DefaultServices

HttpConfiguration DefaultHttpControllerSelector

HttpControllerSelector

public class DefaultServices : ServicesContainer { // public DefaultServices(HttpConfiguration configuration) { // this.SetSingle<IHttpControllerSelector>( new DefaultHttpControllerSelector(configuration)); } }

DefaultHttpControllerSelector IHttpController

Selector GetControllerName

HttpRequestMessage HttpController

public class DefaultHttpControllerSelector : IHttpControllerSelector { public DefaultHttpControllerSelector(HttpConfiguration configuration); public virtual IDictionary<string, HttpControllerDescriptor>

Page 107: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

167

GetControllerMapping(); public virtual HttpControllerDescriptor SelectController( HttpRequestMessage request); public virtual string GetControllerName(HttpRequestMessage request); }

HttpController

3 Web Host Http ControllerHandler HTTP HttpRequestMessage

ASP.NET RouteData HttpRouteDataHttpRequestMessage

Self Host HttpRoutingDispatcherASP.NET Web APIHttpRouteData HttpRouteData HttpRequestMessage

HttpRouteData HttpControllercontroller HttpRequestMessage HttpController

DefaultHttpControllerSelector GetControllerNameHttpRequestMessage HttpController

public class DefaultHttpControllerSelector : IHttpControllerSelector { // public virtual string GetControllerName(HttpRequestMessage request) { IHttpRouteData routeData = request.GetRouteData(); if (routeData == null) { return null; } string str = null; routeData.Values.TryGetValue<string>("controller", out str); return str; } }

HttpController HttpControllerDescriptor

DefaultHttpControllerSelector GetControllerMapping IDictionary

Page 108: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

168

<string, HttpControllerDescriptor> HttpController HttpController

Descriptor HttpController

public class DefaultHttpControllerSelector : IHttpControllerSelector { // private readonly HttpControllerTypeCache _controllerTypeCache; public virtual IDictionary<string, HttpControllerDescriptor> GetControllerMapping(); }

GetControllerMapping DefaultHttp

ControllerSelector HttpControllerTypeCache

HttpController GetControllerMapping HttpController

HttpControllerDescriptor

HttpController

HttpController HttpController

HttpController HttpControllerTypeCache

Dictionary<string, ILookup<string, Type>>

GetControllerMapping IDictionary<string, HttpController

Descriptor> HttpController DefaultHttpController

Selector HttpController HttpController

GetControllerMapping

HttpControllers1 FooController BarController

HttpControllers2 BarController BazController

namespace HttpControllers1 { public class FooController: ApiController {} public class BarController: ApiController {} } namespace HttpControllers2 { public class BarController: ApiController {}

Page 109: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

169

public class BazController: ApiController {} }

HttpController 4 DefaultHttpControllerSelector

GetControllerMapping HttpController

FooController BazController BarController

GetControllerMapping

public class DefaultHttpControllerSelector : IHttpControllerSelector { // private HttpControllerTypeCache _controllerTypeCache; private HttpConfiguration _configuration; public virtual IDictionary<string, HttpControllerDescriptor> GetControllerMapping() { Dictionary<string, HttpControllerDescriptor> mappings = new Dictionary<string, HttpControllerDescriptor>(); var keys = from item in _controllerTypeCache.Cache where item.Value.Count() == 1 select item.Key; foreach (string key in keys) { Type controllerType = _controllerTypeCache .Cache[key].First().First(); HttpControllerDescriptor descriptor = new HttpControllerDescriptor(_configuration, key, controllerType); mappings.Add(key, descriptor); } return mappings; } }

GetControllerMapping

GetControllerMapping DefaultHttp

ControllerSelector

3 ApiController HttpController

FooController BarController BazController

namespace HttpControllers {

Page 110: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

170

public class FooController : ApiController {} public class BarController : ApiController {} public class BazController : ApiController {} }

HttpConfiguration

ServicesContainer DefaultHttpControllerSelector

GetControllerMapping HttpController HttpControllerDescriptor

HttpController

class Program { static void Main(string[] args) { HttpConfiguration configuration = new HttpConfiguration(); IHttpControllerSelector controllerSelector = configuration.Services.GetHttpControllerSelector(); IDictionary<string, HttpControllerDescriptor> mappings = controllerSelector.GetControllerMapping(); Console.WriteLine("{0,-16}{1,-10}", "ControllerName", "TypeName"); foreach (var item in mappings) { Console.WriteLine("{0,-16}{1,-10}", item.Key, item.Value.ControllerType.Name); } } }

S404

HttpController

3 HttpController DefaultHttpControllerSelector

ControllerName TypeName Bar BarController Baz BazController Foo FooController

DefaultHttpControllerSelector HttpController

3 HttpController 4 HttpController Foo

Controller BazController HttpControllers1 HttpControllers2

Page 111: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

171

BarController

namespace HttpControllers1 { public class FooController: ApiController {} public class BarController : ApiController {} } namespace HttpControllers2 { public class BarController : ApiController {} public class BazController : ApiController {} }

S405

BarController DefaultHttpControllerSelector

BarController

ControllerName TypeName Baz BazController Foo FooController

URI HttpController

URI HttpController

HttpController ASP.NET Web API

HttpController

HttpController

HttpControllerSelector HttpController

SelectController DefaultHttpControllerSelector

SelectController GetControllerName

HttpRequestMessage HttpController

GetControllerMapping HttpControllerDescriptor

SelectController HttpController

Page 112: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

172

GetControllerName HttpController NullASP.NET Web Host ASP.NET Web

API Self HostHttpController DefaultHttpControllerSelector

HttpStatusCode.NotFound HttpResponseException404, Not Found

GetControllerMappingHttpController HttpControllerDescriptor

� AssembliesResolverHttpController

� AssembliesResolver HttpControllerHttpController

HttpController

GetControllerMappingHttpController HttpControllerTypeCache

DefaultHttpControllerSelector HttpStatusCode.NotFoundHttpResponseException InvalidOperationException

HttpController 4-6

4-6 HttpController

Page 113: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

173

4.2.4 HttpController

HttpControllerSelector

HttpRequestMessage HttpController HttpControllerDescriptor

HttpControllerDescriptor HttpController

HttpControllerDescriptor HttpController CreateController

CreateController HttpController

public class HttpControllerDescriptor { // public virtual IHttpController CreateController(HttpRequestMessage request); }

HttpControllerActivator

HttpController HttpControllerActivator

HttpControllerActivator IHttpControllerActivator

Create HttpRequestMessage

HttpController HttpControllerDescriptor HttpController

HttpController

public interface IHttpControllerActivator { IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType); }

ServicesContainer

HttpController ServicesContainer

GetHttpControllerActivator HttpControllerActivator

public static class ServicesExtensions { // public static IHttpControllerActivator GetHttpControllerActivator( this ServicesContainer services); }

Page 114: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

174

HttpControllerDescriptor CreateController

HttpControllerActivator Create HttpController

CreateController

public class HttpControllerDescriptor { // public virtual IHttpController CreateController(HttpRequestMessage request) { return this.Configuration.Services.GetHttpControllerActivator() .Create(request, this, this.ControllerType); } }

DefaultHttpControllerActivator

DefaultServices HttpController

Activator DefaultServices

DefaultHttpControllerActivator

public class DefaultServices : ServicesContainer { // public DefaultServices(HttpConfiguration configuration) { // this.SetSingle<IHttpControllerActivator>( new DefaultHttpControllerActivator()); } }

DefaultHttpControllerActivator Create

HttpController DefaultHttpControllerActivator

HttpController DependencyResolver

DependencyResolver

DependencyResolver IoC IoC

Dependency Injection DI IoC

IoC

Page 115: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

175

IoC HttpController

DependencyResolver

ASP.NET Web API IoC DependencyResolver

IDependencyResolver System.Web.Http.Dependencies

IDependencyScope BeginScope

IDependencyResolver IDependencyScope

IDisposable

public interface IDependencyResolver : IDependencyScope, IDisposable { IDependencyScope BeginScope(); } public interface IDependencyScope : IDisposable { object GetService(Type serviceType); IEnumerable<object> GetServices(Type serviceType); }

DependencyResolver BeginScope IDependencyScope

GetService GetServices

IDependencyScope IDisposable

Dispose

DependencyResolver

ServicesContainer HttpConfiguration

DependencyResolver HttpConfiguration Dependency

Resolver

public class HttpConfiguration : IDisposable { // public HttpConfiguration(HttpRouteCollection routes) { this._dependencyResolver = EmptyResolver.Instance;

}

public IDependencyResolver DependencyResolver { get

Page 116: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

176

{ return this._dependencyResolver; } set { this._dependencyResolver = value; } } }

HttpConfiguration Dependency

Resolver EmptyResolver Instance EmptyResolver

EmptyResolver System.Web.Http.dll

IoC BeginScope

GetService GetServices Null Dispose

internal class EmptyResolver : IDependencyResolver, IDependencyScope, IDisposable { public IDependencyScope BeginScope(); public void Dispose(); public object GetService(Type serviceType); public IEnumerable<object> GetServices(Type serviceType); public static IDependencyResolver Instance { get; } }

HttpRequestMessage DependencyResolver

DependencyResolver HttpConfiguration

HttpRequestMessage DependencyScope

HttpRequestMessage IDependencyScope

GetDependencyScope

public static class HttpRequestMessageExtensions { // public static IDependencyScope GetDependencyScope( this HttpRequestMessage request); }

DependencyScope

HttpRequestMessage DependencyScope

Page 117: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

177

HttpConfiguration DependencyResolver

DependencyScope HttpRequestMessage

DependencyScope HttpRequestMessage

DependencyResolver DefaultHttpControllerActivator

DependencyResolver DefaultHttpControllerActivator

Create HttpController

DefaultHttpControllerActivator HttpRequestMessage

GetDependencyScope DependencyResolver DependencyScope

HttpController GetService

HttpController Create

HttpController HttpController

DefaultHttpControllerActivator HttpController

public class DefaultHttpControllerActivator : IHttpControllerActivator { public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { IDependencyScope depedencyScope = request.GetDependencyScope(); object httpController = depedencyScope.GetService(controllerType) ?? Activator.CreateInstance(controllerType); return httpController as IHttpController; } }

HttpConfiguration DependencyResolver

EmptyResolver GetService Null HttpController

HttpController

HttpController Http

Controller HttpController HttpControllerDescriptor

HttpController HttpController

HttpController HttpController

Page 118: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

178

4.2.5 HttpController

HttpController

HttpController AssembliesResolver HttpController

TypeResolver HttpController HttpControllerSelector

HttpController HttpControllerActivator IoC Dependency

Resolver

4-7 UML

HttpController ASP.NET Web API HttpController

4-7 HttpController

Page 119: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

179

HttpController

ASP.NET Web API HttpMessage

Handler HttpRoutingDispatcher HttpRouting

Dispatcher Self Host Web Host

ASP.NET

HttpControllerDispatcher

HttpControllerDispatcher HttpController

HttpResponseMessage HttpRoutingDispatcher HttpResponse

Message

4-8 UML HttpController HttpControllerDispatcher

HttpControllerSelector SelectController

HttpController HttpControllerDescriptor

4-8 HttpController

HttpControllerSelector DefaultHttpControllerSelector

HttpControllerTypeResolver HttpController

HttpController HttpControllerDescriptor HttpController

SelectController HttpRouteData

HttpController HttpControllerDescriptor

HttpControllerDispatcher HttpControllerDescriptor CreateController

HttpController HttpControllerDescriptor

Page 120: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

180

CreateController HttpControllerActivator

Create HttpController

DefaultHttpControllerActivator DependencyResolver

HttpController HttpController

HttpController DefaultHttpControllerActivator

HttpController

DependencyResolver EmptyResolver

HttpController Null HttpController

HttpController

HttpController

HttpController ApiController IDisposable

Dispose

HttpRequestMessage

Properties HttpRequestMessage

HttpRequestMessage Properties

Key MS_DisposableRequestResources List

<IDisposable> HttpRequestMessage Get

ResourcesForDisposal RegisterForDispose

IDisposable

public static class HttpRequestMessageExtensions { // public static IEnumerable<IDisposable> GetResourcesForDisposal( this HttpRequestMessage request); public static void RegisterForDispose(this HttpRequestMessage request, IEnumerable<IDisposable> resources); public static void RegisterForDispose(this HttpRequestMessage request, IDisposable resource); public static void DisposeRequestResources(this HttpRequestMessage request); }

Page 121: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.2 HttpController

ASP.NET Web API 2

181

ASP.NET Web API HttpRequestMessage

DisposeRequestResources

Web Host 3

ASP.NET Web API HttpMessageHandler

HttpControllerHandler HTTP

HttpRequestMessage

HttpControllerHandler 3

� HttpRequestMessage DisposeRequestResources

� HttpRequestMessage Dispose

� HttpResponseMessage

Self Host 3

HttpBinding HttpMessage

HttpMessage HttpRequestMessage HttpResponseMessage

WCF Message

Close Dispose

HttpMessage Close Dispose

HttpRequestMessage HttpResponseMessage

HttpRequestMessage

Self Host HttpMessage

HttpRequestMessage 3

Foo Bar Baz DisposableObject IDisposable

Dispose

public class DisposableObject : IDisposable { public void Dispose() { Console.WriteLine("{0}.Dispose()", this.GetType().Name); }

Page 122: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

182

} public class Foo : DisposableObject {} public class Bar : DisposableObject {} public class Baz : DisposableObject {}

Main Foo

Bar Baz 3 RegisterForDispose

HttpRequestMessage HttpRequestMessage

HttpMessage Close

class Program { static void Main(string[] args) { HttpRequestMessage request = new HttpRequestMessage(); request.RegisterForDispose(new Foo()); request.RegisterForDispose(new Bar()); request.RegisterForDispose(new Baz()); Type httpMessageType = Type.GetType( "System.Web.Http.SelfHost.Channels.HttpMessage, System.Web.Http.SelfHost"); Message httpMessage = (Message)Activator.CreateInstance(httpMessageType, new object[] { request }); httpMessage.Close(); } }

RegisterForDispose HttpRequestMessage

S406

Foo.Dispose() Bar.Dispose() Baz.Dispose()

ApiController ExecuteAsync

RegisterForDispose HttpRequestMessage

ApiController HttpRequestMessage

Page 123: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.3 IoC

ASP.NET Web API 2

183

4.3 IoC

Inversion of Control IoCIoC

A B BA IoC Controller

4.3.1 Unity IoCIoC Dependency Injection DI

Martin FowlerInversion of Control Containers and the Dependency Injection pattern

31 3

� Type Mapping

/ /

� Constructor Injection IoCIoC

� Property InjectionIoC

� Method InjectionIoC

IoC Castle Windsor Unity Spring.NET StructureMapNinject Unity Patterns & Practices IoCCodeplex http://unity.codeplex.com/

Unity 2.1 UnityIoC Unity

Page 124: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

184

4 IA IB IC ID

A B C D A B C D 3 IB

IC ID B

C DependencyAttribute

D Initialize InjectionMethodAttribute

A IoC

namespace UnityDemo { public interface IA {} public interface IB {} public interface IC {} public interface ID {} public class A : IA { public IB B { get; set; } [Dependency] public IC C { get; set; } public ID D { get; set; } public A(IB b) { this.B = b; } [InjectionMethod] public void Initialize(ID d) { this.D = d; } } public class B: IB{} public class C: IC{} public class D: ID{} }

Unity

Unity

<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity. Configuration. UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections> <unity>

Page 125: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.3 IoC

ASP.NET Web API 2

185

<containers> <container> <register type="UnityDemo.IA, UnityDemo" mapTo="UnityDemo.A, UnityDemo"/> <register type="UnityDemo.IB, UnityDemo" mapTo="UnityDemo.B, UnityDemo"/> <register type="UnityDemo.IC, UnityDemo" mapTo="UnityDemo.C, UnityDemo"/> <register type="UnityDemo.ID, UnityDemo" mapTo="UnityDemo.D, UnityDemo"/> </container> </containers> </unity> </configuration>

Main IoC UnityContainer

Resolve

IA A B C D Null

class Program { static void Main(string[] args) { IUnityContainer container = new UnityContainer(); UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager .GetSection(UnityConfigurationSection.SectionName); configuration.Configure(container); A a = (A)container.Resolve<IA>(); Console.WriteLine("a.B == null ? {0}", a.B == null ? "Yes" : "No"); Console.WriteLine("a.C == null ? {0}", a.C == null ? "Yes" : "No"); Console.WriteLine("a.D == null ? {0}", a.D == null ? "Yes" : "No"); } }�

Resolve<IA>

A 3

B

C D S407

a.B == null ? No a.C == null ? No a.D == null ? No

4.3.2 IoC HttpControllerActivator

IoC HttpController IoC

HttpController HttpController HttpController

Page 126: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

186

Activator IoC ASP.NET Web API HttpController

HttpControllerActivator

HttpControllerActivator IoC

IoC Unity ASP.NET Web API

UnityHttpControllerActivator UnityHttpControllerActivator Unity

UnityContainer HttpController Create

UnityContainer Resolve HttpController

public class UnityHttpControllerActivator: IHttpControllerActivator { public IUnityContainer UnityContainer { get; private set; } public UnityHttpControllerActivator(IUnityContainer unityContainer) { this.UnityContainer = unityContainer; } public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { return (IHttpController)this.UnityContainer.Resolve(controllerType); } }

ApiController ContactsController

Action Get

id ID

public class ContactsController : ApiController { public IContactRepository Repository { get; private set; } public ContactsController(IContactRepository repository) { this.Repository = repository; } public IEnumerable<Contact> Get(string id = "") { return this.Repository.GetContacts(contact => string.IsNullOrEmpty(id) || id == contact.Id); } } public class Contact {

Page 127: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.3 IoC

ASP.NET Web API 2

187

public string Id { get; set; } public string Name { get; set; } public string PhoneNo { get; set; } public string EmailAddress { get; set; } public string Address { get; set; } }

Action Repository

IContactRepository IContactRepository

GetContacts

public interface IContactRepository { IEnumerable<Contact> GetContacts(Predicate<Contact> predicate); }

DefaultContactRepository IContactRepository

public class DefaultContactRepository : IContactRepository { private static List<Contact> contacts = new List<Contact> { new Contact{ Id="001", Name = " ", PhoneNo="123", EmailAddress = "[email protected]"}, new Contact{ Id="002", Name = " ", PhoneNo="456", EmailAddress = "[email protected]"} }; public IEnumerable<Contact> GetContacts(Predicate<Contact> predicate) { return contacts.Where(contact=>predicate(contact)); } }

Global.asax UnityHttpControllerActivator

Application_Start UnityContainer

RegisterType<TFrom,TTo> IContactRepository DefaultContactRepository

UnityContainer UnityHttpControllerActivator

ServicesContainer

public class WebApiApplication: System.Web.HttpApplication { protected void Application_Start()

Page 128: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

188

{ // IUnityContainer unityContainer = new UnityContainer(); unityContainer.RegisterType<IContactRepository, DefaultContactRepository>(); GlobalConfiguration.Configuration.Services.Replace( typeof(IHttpControllerActivator), new UnityHttpControllerActivator(unityContainer)); } }

ASP.NET Web API

/api/contacts ID 001 /api/contacts/001

4-9 S408

4-9 Web API

4.3.3 IoC DependencyResolver

DefaultHttpControllerActivator DependencyResolver

HttpController HttpControllerActivator IoC Http

Controller DependencyResolver

DependencyResolver Ninject IoC

Unity Ninject IoC IoC

Page 129: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4.3 IoC

ASP.NET Web API 2

189

http://www.ninject.org/ Ninject

public class NinjectDependencyResolver : IDependencyResolver { private List<IDisposable> disposableServices = new List<IDisposable>(); public IKernel Kernel { get; private set; } public NinjectDependencyResolver(NinjectDependencyResolver parent) { this.Kernel = parent.Kernel; } public NinjectDependencyResolver() { this.Kernel = new StandardKernel(); } public void Register<TFrom, TTo>() where TTo : TFrom { this.Kernel.Bind<TFrom>().To<TTo>(); } public IDependencyScope BeginScope() { return new NinjectDependencyResolver(this); } public object GetService(Type serviceType) { return this.Kernel.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { foreach (var service in this.Kernel.GetAll(serviceType)) { this.AddDisposableService(service); yield return service; } } public void Dispose() { foreach (IDisposable disposable in disposableServices) { disposable.Dispose(); } } private void AddDisposableService(object servie)

Page 130: Y - cnblogs.com · 2014-07-10 · 1.1 u Þweb asp.net web api 2 ´ v + 3 Ò1-1 tcp/ip #a 1Û õ4§ x ¶' Ú h þ #a 1Û q á tcp/ip Èfw ip `tcp 7¾' j Ô ,x ø þ #a z Ä Ø b5%4°

4 HttpController

ASP.NET Web API 2

190

{ IDisposable disposable = servie as IDisposable; if (null != disposable && !disposableServices.Contains(disposable)) { disposableServices.Add(disposable); } } }

NinjectDependencyResolver DependencyResolver

NinjectDependencyResolver IKernel Kernel

GetService GetServices Kernel TryGet GetAll

BeginScope NinjectDependencyResolver Kernel

Register<TFrom,TTo>

IDisposable

IDisposable

Dispose

NinjectDependencyResolver

Global.asax HttpControllerActivator Ninject

DependencyResolver ASP.NET Web API

4-9 S409

public class MvcApplication: System.Web.HttpApplication { protected void Application_Start() { // NinjectDependencyResolver dependencyResolver = new NinjectDependencyResolver(); dependencyResolver.Register<IContactRepository, DefaultContactRepository>(); GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver; } }