Post on 15-Jul-2015
transcript
Ido FlatowSenior Architect
Microsoft MVP
SELA Group
ASP.NET Web API and HTTP Fundamentals
@idoFLATOWhttp://bit.ly/flatow-blog
This presentation:http://sdrv.ms/1eKAsRd
http://www.asp.net/web-
api/overview/getting-started-with-
aspnet-web-api/tutorial-your-first-web-
api
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CRAMMING YOUR BRAINS WITH
HTTP & ASP.NET WEB API HTTP Fundamentals via Web API
HTTP Messages
URIs
Routing
Verbs
Controllers and Actions
Status Codes
HttpRequestMessage\HttpResponseMessage
Error Handling
Content Negotiation
Media Type Formatters
OData
Validations
Dependency Resolver
Hosting
HTTP.SYS
IIS 101
HTTP compression
Persisted Connections
Web API Self Hosting
More HTTP and Web API
Caching
Concurrency
Security
Streaming
WebSockets & SignalR
2
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ABOUT ME
Senior architect, Sela Group
Co-author of:
Developing Windows Azure and Web Services –Microsoft official course
WCF 4 – Microsoft official course
Pro .NET Performance – Apress
Microsoft MVP
Focus on server, services, and cloud technologies
Manager of the Israeli Web Developers User Group
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
WHY IS HTTP IMPORTANT?
HTTP is a first class application layer protocol
Unlike other protocols it was created to
support a single information system
That system happened to be the largest and
main information system of the human race:
4
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
NO REALLY, WHY?
Today's systems face new challenges:
Internet scale applications
Cloud-based applications
5
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
NO REALLY, WHY?
Today's systems face new challenges:
Broader reach of clients
6
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
WHAT ABOUT ASP.NET WEB API?
The .NET platform never had a first class
framework for HTTP-based services
WCF was created as a SOAP-based
framework and never really matured to
support HTTP
7
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
THE HISTORY OF ASP.NET WEB API
8
ASP.NET isOpen Source
ASP.NET Web API(Beta)
WCF Web API on CodePlex
6 Preview Versions
WCF WebHttpBinding (.NET 4)
ASP.NET Web API 4 Release
ASP.NET Web API 2 Release Candidate
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP MESSAGES 101
HTTP is a first class application protocol:
Widely supported across platforms and devices
Scalable
Simple
Uses the request-response messaging pattern
Define resource-based semantics and not
RPC (Remote Procedure Call) or methods
9
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP REQUEST MESSAGES
10
GET http://localhost:2300/api/agents/Bond HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US,en;q=0.7,he;q=0.3
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2;
WOW64; Trident/6.0)
Accept-Encoding: gzip, deflate
Host: localhost:2300
DNT: 1
Connection: Keep-Alive
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP RESPONSE MESSAGES
11
HTTP/1.1 200 OK
Cache-Control: public, max-age=300
Content-Type: application/json; charset=utf-8
ETag: "1"
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Date: Mon, 19 Nov 2012 17:49:40 GMT
Content-Length: 142
{
"Id": "Bond",
"FullName": "James Bond",
"Alias": "007",
"Version": 1,
"Image": "http://localhost:2300/api/agents/Bond.jpg"
}
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
URIS
HTTP is not an RPC protocol
HTTP uses URIs to identify resources over
the network
An HTTP URI has the following basic
structure:
12
Schema Host Port Absolute Path
Query
http://theagency.com:8080/agents?id=1
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CLEAN URLS AND ASP.NET
Using clean URLs can be a problem with IIS
IIS needs extensions to map requests to handlers
Without extensions, IIS is lost
ASP.NET Routing to the rescue with UrlRoutingModule
It’s all about patterns… and mapping them to handlers
The starting point of MVC, Dynamic Data, and Web API
System.Web.Routing.RouteTable.Routes.MapHttpRoute
13
RouteTable.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional }
);
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
THE BASICS OF WEB API - ROUTING
DEMO
14
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ROUTING WITH ATTRIBUTES
Why attributes over convention?
Child (sub) resources
Multiple type of parameters or return values
Versioning of actions and controllers
Start by enabling attribute routing
config.MapHttpAttributeRoutes();
15
[RoutePrefix("api/agents/{agentId}")]public class ObservationsController : ApiController{
// GET api/agents/bond/observations[HttpGet("observations/{date}")] public Observation Get(string agentId, DateTime date) { ... }
}
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
VERBS
HTTP defines a set of Methods or Verbs that
add an action-like semantics to requests
Verbs are defined as the first segment of the
request-line:
There are eight verbs defined in HTTP 1.1:
16
GET http://localhost:4392/travelers/1 HTTP/1.1
GET
POST
PUT
DELETE
HEAD
OPTIONS
TRACE
CONNECT
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
3, 2, 1, ACTIONS!
Actions are matched by HTTP verb
names and the existence of parameterspublic class ProductsController : ApiController{
public IEnumerable<Product> GetProducts() {...}public Product GetProductById(int id) {...}public HttpResponseMessage PostProduct(Product product) {...}
}
DELETE api/products/42
GET api/products
GET api/products/42
POST api/products
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HANDLING VERBS IN ASP.NET WEB API
DEMO
18
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
STATUS CODES
Status codes describe the result of the server’s effort to satisfy the request
Passed in the response's status-line as three digit alongside a textual description called reason phrase
HTTP has five different categories of status-codes:
1xx – Informational
2xx – Success
3xx – Redirection
4xx – Client Error
5xx – Server Error
19
(100 / 101)
(200 – 206)
(300 – 307)
(400 – 417)
(500 – 505)
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
STATUS CODE EXAMPLES
20
404?
401?
304?
503?
500?
200?
301?
302?
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP RESPONSE MESSAGE
Returning an HttpResponseMessage allows
more control over the response, including:
Status code
HTTP headers
Entity body
21
public HttpResponseMessage CreateAgent(Agent agent){
agent = _repository.Add(agent);var response = Request.CreateResponse<Agent>(HttpStatusCode.Created, agent);
response.Headers.Location = GetAgentLocation(agent.Id);return response;
}
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HANDLING STATUS CODES
DEMO
22
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ERROR HANDLING
In HTTP services errors are handled by
Returning an appropriate status code
Returning an entity body explaining the error (when applicable)
Web API allows you to handle exceptions by
Return an HttpResponseMessage with appropriate status code (404, 500 …)
Throw an HttpResponseException
Create a general exception handler by using Filters
23
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HANDLING ERRORS
DEMO
24
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
MEDIA TYPES
HTTP was originally designed to transfer
Hypertext
Hypertext documents contain references to
other resources including images, video, etc.
Multipurpose Internet Mail Extensions (MIME)
Types or Media-types allow HTTP to express
different formats:
25
Type Sub-
type
Type specific parameters
text/html; charset=UTF-8
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CONTENT NEGOTIATION
HTTP defines a process to best match the
server’s response to the client’s expectation
Negotiation can be done using:
Headers:
Accept, Accept- Language, Accept- Charset,
Accept-Encoding
URI:
File extensions (.jpeg, .html), host-name: (com, org),
path and query
26
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
MEDIA TYPE FORMATTERS
ASP.NET Web API uses Media Type Formatters to control serialization
Each media type formatter is associated with a media type, file extension, or query string
The host is configured with a collection of MediaTypeFormatter objects
Create custom formatters by deriving from:
MediaTypeFormatter – asynchronous read/write
BufferedMediaTypeFormatter – synchronous read/write
27
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CONTENT NEGOTIATION IN WEB API
DEMO
28
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
VALIDATING USER INPUT
Use System.ComponentModel.DataAnnotations
on entity classes to add validation rules
Validation rules can be check by calling
ModelState.IsValid
When validation fails, return a Bad Request (400)
ModelState is a dictionary of property name &
errors, use it to construct a meaningful response
29
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
VALIDATING USER INPUT
30
public class Contact {
[Required]
public string FullName { get; set;}
[Email]
public string Email { get; set;}
}
if (!this.ModelState.IsValid) {
var errors = this.ModelState.Where(s => s.Value.Errors.Count > 0)
.Select(s => new KeyValuePair<string, string>
(s.Key, s.Value.Errors.First().ErrorMessage));
response = Request.CreateResponse(
HttpStatusCode.BadRequest, errors);
}
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
VALIDATING USER INPUT
DEMO
31
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ODATA QUERYABLE ACTIONS
The Open Data Protocol (OData) provides a
RESTful standard for exposing data models
OData uses URIs to perform query operations:
Entity projection – $select, $expand
Sorting – $orderby
Entity sub-setting – $top, $skip
Filtering – $filter, logical operators: eq, ne, gt, lt
32
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
DEFINING ODATA ACTIONS
Install the Microsoft.AspNet.WebApi.OData NuGetpackage
Define an action with the following characteristics:
Returns IQueryable<T> or IEnumerable<T>
Decorated with the [Queryable] attribute
[Queryable]
public IQueryable<Agent> GetAgents()
{
}
33
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
WEB API AND ODATA
34
[Queryable]public IQueryable<Agent> GetAgents(){
return repository.GetAll().AsQueryable();}
api/agents?$orderby=Name
api/agents?$filter=salary gt 50000
api/agents?$skip=10
api/agents?$skip=50&$top=10
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ODATA ACTIONS
DEMO
35
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ODATA MODELS
OData also provides a mechanism for
exposing entity models:
Publishing the models metadata
Exposing relations between entities using the
Atom media-type
36
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CREATING AND EXPOSING ODATA
MODELS
Exposing an OData model requires the following configuration:
Creating an EDM model using the ODataConventionModelBuilder class
Adding a route using the MapODataRoutemethod
In addition, any controller exposed in the model should derive from the ODataController or EntitySetController<TEntity, TKey> classes
37
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CONSUMING ODATA SERVICES
Add a service reference to the OData service
Create a new instance of the generated Container class
Use LINQ to query the container
var client = new MyODataService.Container(new Uri("…"));
var agent = (from a in client.Agents
where a.Id == "Bond"
select a).Single();
38
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ODATA MODELS
DEMO
39
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
DEPENDENCY RESOLVER
AND THE API CONTROLLER
To be testable, the ApiController should support dependency injection
Web API supports dependency injection with the IDependencyResolver interface
Implement your custom resolver or use it to wrap a known IoC Container (Castle, Unity, MEF, Ninject…)
Register the dependency resolver through Web API global configuration
And Voilà!
4040
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP.SYS, WHAT’S THAT?
It’s the thing that handles HTTP on your machine
It’s a kernel mode device driver
Ever since Windows XP SP2 / Windows Server 2003
Responsible of
Routing requests to the correct application
Kernel mode SSL (full support as of Windows Server 2008)
Caching responses in kernel mode
Implementing QoS, such as connection limits and timeouts
Want to know more? netsh http show
41
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
IIS 101
Web application hosting
Comes in two flavors
IIS Express
Full IIS (or simply IIS)
Provides
Reliability
Manageability
Security
Performance
Scalability
42
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ENABLING COMPRESSION WITH IIS
Compression is something the client needs to request
Requests are not normally compressed
Accept-Encoding: gzip,deflate
Server is not obligated to compress the response
Content-Encoding: gzip / deflate
43
IIS Compression Modes
Scenarios Considerations
Dynamic Compression
Small number of requests
Limited network bandwidth
Uses CPU and memory
Not cached
Static CompressionImprove transmission times
Graphic-heavy sites
Can be cached
Uses some CPU
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP PERSISTENT CONNECTION
IT’S ALIVE Beginning with HTTP 1.1, clients and servers
must support persistent connections
Persistent is good
Less simultaneous opened connections = less CPU
Single connection can pipeline HTTP requests
Fewer TCP connections = less congestion
No re-handshaking = reduced latency
Send Connection: Keep-Alive in request and response headers to keep the underlying TCP connection open
Connection is dropped if either end lacks sending the Keep-Alive header
44
– Implementation Dependent
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
KEEPING IT ALIVE!
DEMO
45
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
KEEP IT ALIVE, BUT FOR HOW LONG?
IIS by default adds Keep-Alive to every response
HTTP.SYS has a default timeout of 120 seconds for idle connections
When expecting many clients with a small number of request, Keep-Alive may have an overhead
For short visits, consider disabling Keep-Alive or reduce the idle timeout to a couple of seconds (5? 2? 1?)
Use logs to check visits and frequency of idle connections:
IIS log files: C:\inetpub\logs\LogFiles
HTTP.SYS log files: %windir%\system32\LogFiles\HTTPERR
46
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
WHO NEEDS IIS? WE HAVE SELF-HOSTING
IIS is the natural hosting environment for the ASP.NET web stack, Web API included
When IIS is not an option or unwanted, use a self-hosted Web API
Just follow three basic steps:
Install the Microsoft ASP.NET Web API Self Host NuGet package
Create host configuration and routing rules
Start the self-hosted server
Under the covers, Web API self-hosting is handled by WCF
47
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CACHING
HTTP caches store copies of responses to
reduce network traffic
HTTP caches reduces call latency and
increases server throughput
Caches are a main factor for scalability
on the web
48
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
TYPES OF CACHES
Browser/Client CacheStores representations locally on the computer’s hard drive
Proxy Cache Corporates and ISPs provide shared proxies providing shared cache on their network
Gateway (Reverse Proxy) Cache Stores representations on behalf of the server. Content Delivery Networks (CDNs) use gateway cache distributed around the web
49
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CONTROLLING CACHE
HTTP headers can be used to control
cache behaviors
HTTP provides method the avoid
staleness of cached data
Expiration
Validation
Invalidation
50
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CONTROLLING CACHE
DEMO
51
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ETAG: VERSIONING & CONCURRENCY
When caching content, we need to identify when content has changed
The ETag (entity tag) header represents the version of the content
ETags are sent to the client with the response, and are re-sent to the server on subsequent requests
In the action, compare received and existing ETags, and return either:
A new entity if they are different
An HTTP 304 (Not Modified) if they are identical
When updating entities using POST/PUT, use the ETagfor concurrency (version) checks
52
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ETAG VERSIONING
53
public HttpResponseMessage Get(int id){HttpResponseMessage response;var etag = Request.Headers.IfNoneMatch.FirstOrDefault();Agent agent = _manager.GetAgentById(id);if (etag != null &&
etag.ToString().Replace(@"""", "") == agent.Version){response = new HttpResponseMessage(HttpStatusCode.NotModified);
}else{response = Request.CreateResponse(HttpStatusCode.OK, agent);response.Headers.ETag = new EntityTagHeaderValue(string.Format(@"""{0}""", agent.Version));
}return response;
}
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
SECURITY
HTTP messages are clear text, in order to have any form of secured connection they must be encrypted
This is what SSL is for
Once encrypted there are still several challenges remaining:
Authentication
Persisting authentication throughout the conversation
Authorization
54
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
1. Client requests a secured session
2. Server responds with an X.509 certificate
3. Client verifies certificate’s authenticity
4. Client sends a symmetric encryption key
(encrypted with the server’s public key)
6. Client and server exchange encrypted messages
(encrypted with the symmetric key)
5. Server decrypts the encryption key with its private key
HTTPS - HOW SECURE SOCKETS LAYER WORKS
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
CLASSIC HTTP AUTHENTICATION
HTTP uses the Authorization header to pass authentication data:
According to specs, HTTP supports only two schemas:
Basic (plain text)
Digest (hashed password)
Nowadays, it is common to find other schemas:
NTLM / Negotiate (Windows authentication)
Certificate
OAuth
56
Authorization: Basic eWFuaXY6eWFuaXY=
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
BASIC AUTHENTICATION
DEMO
57
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP STREAMING
Advantages
Less large memory allocation and buffering
Message can be handled before received completely
Connection can remain opened for a long time
Useful for
File download/upload
Live data feed (notifications, video streams, …)
It’s a chunking mechanism
Uses a persistent HTTP connection
The Content-Length HTTP header is omitted
Each chunk is sent as size + chunk
Chunk size can vary
Stream ends when last chunk is sent with size 0 (zero)
58
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP STREAMING AND WEB API
Reading a streamed request
Request.Content.ReadAsStreamAsync (File Stream )
Request.Content.ReadAsMultipartAsync (Multi-part Stream)
Writing a streamed response
Do you want to pull from an existing stream? Or pushyour own data down the stream?
Pull : StreamContent(inputStream)
Push: PushStreamContent(contentWritingAction)
When pushing data use Stream.Flush() to chunk
59
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
STREAMING WITH WEB API
DEMO
60
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
DUPLEX COMMUNICATION
WITH HTTP
HTTP is a request-response protocol
Updates are through server polling
Periodic polling (Anything new?)
Long polling (I’m waiting for you!)
Many disadvantages
Periodic polling inflicts high-latency on updates
Long polling is hard to implement
Can cause bandwidth overhead if used improperly
61
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
WEBSOCKETS IN A GLANCE
Bi-directional TCP channel (full-duplex)
Supports both HTTP and HTTPS (SSL)
Accessible through JavaScript API
Supports cross-domain calls
Client-side - IE10, Chrome, Firefox, .NET 4.5
Server-side – IIS 8, ASP.NET 4.5, SignalR
Standardization is still in progress!!
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ASP.NET SIGNALR 101
Real-time, persistent connection abstraction
over HTTP
Useful for dashboards & monitoring,
collaborative work, job progress, gaming…
SignalR works everywhere
WebSockets
Server Sent Events
Forever Frame
Long Polling
63
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ASP.NET SIGNALR 101
Supported clients:
Desktop applications using .NET 4/4.5
Web browsers using JavaScript
Windows Store and Windows Phone Apps
Supports scaling servers to Web farm with
Windows Azure Service Bus, Redis, and SQL
Server
64
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
SIGNALR API, CHOOSE WHAT WORKS
FOR YOU
Connections
Low level
Raw strings up and down (the “old way”)
Broadcast to all clients, groups, or individuals
Connect, reconnect & disconnect semantics
Hubs
Built on top of connections
Client-Server and Server-Client RPC
Automatic client proxy generation for JavaScript
65
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
ASP.NET SIGNALR
DEMO
66
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
HTTP Fundamentals via Web API
HTTP Messages
URIs
Routing
Verbs
Controllers and Actions
Status Codes
HttpRequestMessage\HttpResponseMessage
Error Handling
Content Negotiation
Media Type Formatters
OData
Validations
Dependency Resolver
Hosting
HTTP.SYS
IIS 101
HTTP compression
Persisted Connections
Web API Self Hosting
More HTTP and Web API
Caching
Concurrency
Security
Streaming
WebSockets & SignalR
SO WHAT DID WE LEARN TODAY?
67
You are now an HTTP ninja
Rank 1. Just 4 more ranks to go!!
www.devconnections.com
ASP.NET WEB API AND HTTP FUNDAMENTALS
RESOURCES
HTTP
www.ietf.org/rfc/rfc2616.txt
REST
www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
ASP.NET Web API
www.asp.net/web-api
www.asp.net/web-api/videos
webapibloggers.com (without www)
Fiddler
www.fiddler2.com
www.youtube.com/watch?v=7Tw5EHvTERc
“Debugging the Web with Fiddler”, Tuesday 2:00PM
68
This Presentation:
sdrv.ms/1eKAsRd