open pdf and draw c# : Accessible links in pdf Library software component asp.net windows wpf mvc %5BO%60Reilly%5D%20-%20JavaScript.%20The%20Definitive%20Guide,%206th%20ed.%20-%20%5BFlanagan%5D51-part1583

in §18.2 because of the 
<script>
element’s ability to circumvent same-origin
restrictions.
The XML Is Optional
The X in “Ajax” stands for  XML, the primary client-side API for HTTP
(XMLHttpRequest) features XML in its name, and we’ll see later that one of the prop-
erties of the XMLHttpRequest object is named 
responseXML
. It would seem that XML
is an important part of scripted HTTP. But it’s not: these names are the historical legacy
of the days when XML was a powerful buzzword. Ajax techniques work with XML
documents, of course, but the use of XML is purely optional and has actually become
relatively rare. The XMLHttpRequest specification lays out the inadequacies of the
name we’re stuck with:
The name of the object is XMLHttpRequest for compatibility with the Web,
though each component of this name is potentially misleading. First, the object
supports any text based format, including XML. Second, it can be used to make
requests over both HTTP and HTTPS (some implementations support protocols
in addition to HTTP and HTTPS, but that functionality is not covered by this
specification). Finally, it supports “requests” in a broad sense of the term as it
pertains to HTTP; namely all activity involved with HTTP requests or responses
for the defined HTTP methods.
Transport mechanisms for Comet are trickier than Ajax, but all require the client to
establish (and re-establish as necessary) a connection to the server, and require the
server to keep that connection open so that it can send asynchronous messages over it.
A hidden 
<iframe>
can serve as a Comet transport, for example, if the server sends each
message in the form of a 
<script>
element to be executed in the 
<iframe>
. A more
reliably cross-platform approach to implementing Comet is for the client to establish
a connection to the server (using an Ajax transport) and for the server to keep this
connection open until it needs to push a message. Each time the server sends a message,
it closes the connection, which helps to ensure that the message is properly received by
the client. After processing the message, the client then immediately establishes a new
connection for future messages.
Implementing a reliable cross-platform Comet transport is hard to do, and most web
app developers who use the Comet architecture rely on the transports in web frame-
work libraries such as Dojo. At the time of this writing, browsers are beginning to
implement an HTML5-related draft specification known as Server-Sent Events that
defines a simple Comet API in the form of an EventSource object. §18.3 covers the
EventSource API and demonstrates a simple emulation of it using XMLHttpRequest.
It is possible to build higher-level communication protocols on top of Ajax and Comet.
These client/server communication techniques can be used as the basis of an RPC
(remote procedure call) mechanism or a publish/subscribe event system, for example.
Scripted HTTP | 493
Client-Side
JavaScript
Accessible links in pdf - insert, remove PDF links in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Free C# example code is offered for users to edit PDF document hyperlink (url), like inserting and deleting
add links to pdf acrobat; pdf hyperlink
Accessible links in pdf - VB.NET PDF url edit library: insert, remove PDF links in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Help to Insert a Hyperlink to Specified PDF Document Page
add link to pdf acrobat; pdf link to email
This chapter does not describe higher-level protocols like this, however, and instead
focuses on the APIs that enable Ajax and Comet.
18.1  Using XMLHttpRequest
Browsers define their HTTP API on an XMLHttpRequest class. Each instance of this
class represents a single request/response pair, and the properties and methods of the
object allow you to specify request details and extract response data. XMLHttpRequest
has been supported by web browsers for many years, and the API is in the final stages
of standardization through the W3C. At the same time, the W3C is working on a draft
“XMLHttpRequest Level 2” standard. This section covers the core XMLHttpRequest
API and also those portions of the Level 2 draft (which I’ll call XHR2) that are currently
implemented by at least two browsers.
The first thing you must do to use this HTTP API, of course, is to instantiate an
XMLHttpRequest object:
var request = new XMLHttpRequest();
You can also reuse an existing XMLHttpRequest object, but note that doing so will
abort any request pending through that object.
XMLHttpRequest in IE6
Microsoft introduced the XMLHttpRequest object to the world in IE5, and in IE5 and
IE6 it is available only as an ActiveX object. The now-standard 
XMLHttpRequest()
con-
structor is not supported before IE7, but it can be emulated like this:
// Emulate the XMLHttpRequest() constructor in IE5 and IE6
if (window.XMLHttpRequest === undefined) {
window.XMLHttpRequest = function() {
try {
// Use the latest version of the ActiveX object if available
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
}
catch (e1) {
try {
// Otherwise fall back on an older version
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
}
catch(e2) {
// Otherwise, throw an error
throw new Error("XMLHttpRequest is not supported");
}
}
};
}
494 | Chapter 18: Scripted HTTP
An HTTP request consists of four parts:
• the HTTP request method or “verb”
• the URL being requested
• an optional set of request headers, which may include authentication information
• an optional request body
The HTTP response sent by a server has three parts:
• a numeric and textual status code that indicates the success or failure of the request
• a set of response headers
• the response body
The first two subsections below demonstrate how to set each of the parts of an HTTP
request and how to query each of the parts of an HTTP response. Those key sections
are followed by coverage of more specialized topics.
The basic request/response architecture of HTTP is pretty simple and easy to work
with. In practice, however, there are all sorts of complications: clients and server ex-
change cookies, servers redirect browsers to other servers, some resources are cached
and others are not, some clients send all their requests through proxy servers, and so
on. XMLHttpRequest is not a protocol-level HTTP API but instead a browser-level API.
The browser takes care of cookies, redirects, caching, and proxies and your code need
worry only about requests and responses.
XMLHttpRequest and Local Files
The ability to use relative URLs in web pages usually means that we can develop and
test our HTML using the local file system and then deploy it unchanged to a web server.
This is generally not possible when doing Ajax programming with XMLHttpRequest,
however. XMLHttpRequest is designed to work with the HTTP and HTTPS protocols.
In theory, it could be made to work with other protocols, such as FTP, but parts of the
API, such as the request method and the response status code, are HTTP-specific. If
you load a web page from a local file, the scripts in that page will not be able to use
XMLHttpRequest with relative URLs, since those URLs will be relative to a 
file://
URL rather than an 
http://
URL. And the same-origin policy will often prevent you
from using absolute 
http://
URLs. (But see §18.1.6.) The upshot is that when working
with XMLHttpRequest, you generally have to upload your files to a web server (or run
a server locally) in order to test them.
18.1.1  Specifying the Request
After creating an XMLHttpRequest object, the next step in making an HTTP request
is to call the 
open()
method of your XMLHttpRequest object to specify the two required
parts of the request, the method and the URL:
18.1  Using XMLHttpRequest | 495
Client-Side
JavaScript
request.open("GET",        // Begin a HTTP GET request
"data.csv");  // For the contents of this URL
The first argument to 
open()
specifies the HTTP method or verb. This is a case-
insensitive string, but uppercase letters are typically used to match the HTTP protocol.
The “GET” and “POST” methods are universally supported. “GET” is used for most
“regular” requests, and it is appropriate when the URL completely specifies the re-
quested resource, when the request has no side effects on the server, and when the
server’s response is cacheable. The “POST” method is what is typically used by HTML
forms. It includes additional data (the form data) in the request body and that data is
often stored in a database on the server (a side effect). Repeated POSTs to the same
URL may result in different responses from the server, and requests that use this method
should not be cached.
In addition to “GET” and “POST”, the XMLHttpRequest specification also allows
“DELETE”, “HEAD”, “OPTIONS”, and “PUT” as the first argument to 
open()
. (The
“HTTP CONNECT”, “TRACE”, and “TRACK” methods are explicitly forbidden as
security risks.) Older browsers may not support all of these methods, but “HEAD”, at
least, is widely supported and Example 18-13 demonstrates its use.
The second argument to 
open()
is the URL that is the subject of the request. This is
relative to the URL of the document that contains the script that is calling 
open()
. If
you specify an absolute URL, the protocol, host, and port must generally match those
of the containing document: cross-origin HTTP requests normally cause an error. (But
the XMLHttpRequest Level 2 specification allows cross-origin requests when the server
explicitly allows it; see §18.1.6.)
The next step in the request process is to set the request headers, if any. POST requests,
for example, need a “Content-Type” header to specify the MIME type of the request
body:
request.setRequestHeader("Content-Type", "text/plain");
If you call 
setRequestHeader()
multiple times for the same header, the new value does
not replace the previously specified value: instead, the HTTP request will include mul-
tiple copies of the header or the header will specify multiple values.
You cannot specify the “Content-Length”, “Date”, “Referer”, or “User-Agent” headers
yourself: XMLHttpRequest will add those automatically for you and will not allow you
to spoof them. Similarly, XMLHttpRequest object automatically handles cookies, and
connection lifetime, charset, and encoding negotiations, so you’re not allowed to pass
any of these headers to 
setRequestHeader()
:
Accept-Charset       Content-Transfer-Encoding    TE
Accept-Encoding      Date                         Trailer
Connection           Expect                       Transfer-Encoding
Content-Length       Host                         Upgrade
Cookie               Keep-Alive                   User-Agent
Cookie2              Referer                      Via
496 | Chapter 18: Scripted HTTP
You can specify an “Authorization” header with your request, but you do not normally
need to do so. If you are requesting a password-protected URL, pass the username and
password as the fourth and fifth arguments to 
open()
, and XMLHttpRequest will set
appropriate headers for you. (We’ll learn about the optional third argument to
open()
below. The optional username and password arguments are described in the
reference section.)
The final step in making an HTTP request with XMLHttpRequest is to specify the
optional request body and send it off to the server. Do this with the 
send()
method:
request.send(null);
GET requests never have a body, so you should pass 
null
or omit the argument. POST
requests do generally have a body, and it should match the “Content-Type” header you
specified with 
setRequestHeader()
.
Order Matters
The parts of an HTTP request have a specific order: the request method and URL must
come first, then the request headers, and finally the request body. XMLHttpRequest
implementations generally do not initiate any networking until the 
send()
method is
called. But the XMLHttpRequest API is designed as if each method was writing to a
network stream. This means that the XMLHttpRequest method must be called in an
order that matches the structure of an HTTP request. 
setRequestHeader()
, for example,
must be called after you call 
open()
and before you call 
send()
or it will throw an
exception.
Example 18-1 uses each of the XMLHttpRequest methods we’ve described so far. It
POSTs a string of text to a server and ignores any response the server sends.
Example 18-1. POSTing plain text to a server
function postMessage(msg) {
var request = new XMLHttpRequest();      // New request
request.open("POST", "/log.php");        // POST to a server-side script
// Send the message, in plain-text, as the request body
request.setRequestHeader("Content-Type", // Request body will be plain text
"text/plain;charset=UTF-8");
request.send(msg);                       // Send msg as the request body
// The request is done. We ignore any response or any error.    
}
Note that the 
send()
method in Example 18-1 initiates the request and then returns: it
does not block while waiting for the server’s response. HTTP responses are almost
always handled asynchronously, as demonstrated in the following section.
18.1  Using XMLHttpRequest | 497
Client-Side
JavaScript
18.1.2  Retrieving the Response
A complete HTTP response consists of a status code, a set of response headers, and a
response body.  These  are  available  through  properties  and  methods  of  the
XMLHttpRequest object:
• The 
status
and 
statusText
properties return the HTTP status in numeric and tex-
tual forms. These properties hold standard HTTP values like 200 and “OK” for
successful requests and 404 and “Not Found” for URLs that don’t match any re-
source on the server.
• The  response  headers  can  be  queried  with 
getResponseHeader()
and
getAllResponseHeaders()
. XMLHttpRequest handles cookies automatically: it fil-
ters cookie headers out of the set returned by 
getAllResponseHeaders()
and returns
null
if you pass “Set-Cookie” or “Set-Cookie2” to 
getResponseHeader()
.
• The response body is available in textual form from the 
responseText
property or
in Document form from the 
responseXML
property. (The name of that property is
historical: it actually works for XHTML documents as well as XML documents,
and XHR2 says that it should work for ordinary HTML documents as well.) See
§18.1.2.2 for more on 
responseXML
.
The XMLHttpRequest object is usually (but see §18.1.2.1) used asynchronously: the
send()
method returns immediately after sending the request, and the response meth-
ods and properties listed above aren’t valid until the response is received. To be notified
when the response is ready, you must listen for readystatechange events (or the new
XHR2 progress events described in §18.1.4) on the XMLHttpRequest object. But to
understand this event type, you must first understand the 
readyState
property.
readyState
is an integer that specifies the status of an HTTP request, and its possible
values are enumerated in Table 18-1. The symbols in the first column are constants
defined on the XMLHttpRequest constructor. These constants are part of the
XMLHttpRequest specification, but older browsers and IE8 do not define them, and
you’ll often see code that hardcodes the value 4 instead of 
XMLHttpRequest.DONE
.
Table 18-1. XMLHttpRequest readyState values
Constant
Value Meaning
UNSENT
0
open()
has not been called yet
OPENED
1
open()
has been called
HEADERS_RECEIVED
2
Headers have been received
LOADING
3
The response body is being received
DONE
4
The response is complete
In theory, the readystatechange event is triggered every time the 
readyState
property
changes. In practice, the event may not be fired when 
readyState
changes to 0 or 1. It
is often fired when 
send()
is called, even though 
readyState
remains at 
OPENED
when
498 | Chapter 18: Scripted HTTP
that happens. Some browsers fire the event multiple times during the 
LOADING
state to
give progress feedback. All browsers do fire the readystatechange event when 
ready
State
has changed to the value 4 and the server’s response is complete. Because the
event is also fired before the response is complete, however, event handlers should
always test the 
readyState
value.
To listen for readystatechange events, set the 
onreadystatechange
property of the
XMLHttpRequest  object to  your event handler function.  You  can  also  use
addEventListener()
(or 
attachEvent()
in IE8 and before), but you generally need only
one handler per request and it is easier to simply set 
onreadystatechange
.
Example 18-2 defines a 
getText()
function that demonstrates how to listen for ready-
statechange events. The event handler first ensures that the request is complete. If so,
it checks the response status code to ensure that the request was successful. Then it
looks at the “Content-Type” header to verify that the response was of the expected
type. If all three conditions are satisfied, it passes the response body (as text) to a speci-
fied callback function.
Example 18-2. Getting an HTTP response onreadystatechange
// Issue an HTTP GET request for the contents of the specified URL.
// When the response arrives successfully, verify that it is plain text
// and if so, pass it to the specified callback function
function getText(url, callback) {
var request = new XMLHttpRequest();         // Create new request
request.open("GET", url);                   // Specify URL to fetch
request.onreadystatechange = function() {   // Define event listener
// If the request is compete and was successful
if (request.readyState === 4 && request.status === 200) {
var type = request.getResponseHeader("Content-Type");
if (type.match(/^text/))            // Make sure response is text
callback(request.responseText); // Pass it to callback
}
};
request.send(null);                         // Send the request now
}
18.1.2.1  Synchronous responses
By their very nature, HTTP responses are best handled asynchronously. Nevertheless,
XMLHttpRequest also supports synchronous responses. If you pass 
false
as the third
argument to 
open()
, the 
send()
method will block until the request completes. In this
case, there is no need to use an event handler: once 
send()
returns, you can just check
the 
status
and 
responseText
properties of the XMLHttpRequest object. Compare this
synchronous code to the 
getText()
function in Example 18-2:
// Issue a synchronous HTTP GET request for the contents of the specified URL.
// Return the response text or throw an error if the request was not successful
// or if the response was not text.
function getTextSync(url) {
var request = new XMLHttpRequest();  // Create new request
request.open("GET", url, false);     // Pass false for synchronous
18.1  Using XMLHttpRequest | 499
Client-Side
JavaScript
request.send(null);                  // Send the request now
// Throw an error if the request was not 200 OK 
if (request.status !== 200) throw new Error(request.statusText);
// Throw an error if the type was wrong
var type = request.getResponseHeader("Content-Type");
if (!type.match(/^text/)) 
throw new Error("Expected textual response; got: " + type);
return request.responseText;
}
Synchronous requests are tempting, but they should be avoided. Client-side JavaScript
is single-threaded and when the 
send()
method blocks, it typically freezes the entire
browser UI. If the server you are connecting to is responding slowly, your user’s browser
will freeze up. See §22.4 for one context in which it is acceptable to make synchronous
requests, however.
18.1.2.2  Decoding the response
In the examples above, we assume that the server has sent a textual response, with a
MIME type like “text/plain”, “text/html”, or “text/css”, and we retrieve it with the
responseText
property of the XMLHttpRequest object.
There are other ways to handle the server’s response, however. If the server sends an
XML or XHTML document as its response, you can retrieve a parsed representation of
the XML document through the 
responseXML
property. The value of this property is a
Document object, and you can search and traverse it using the techniques shown in
Chapter 15. (The XHR2 draft specification says that browsers should also automatically
parse responses of type “text/html” and make them available as Document objects
through 
responseXML
as well, but browsers current at the time of this writing do not
do that.)
If the server wants to send structured data, such as an object or array, as its response,
it might transmit that data as a JSON-encoded (§6.9) string. When you receive it, you
would then pass the 
responseText
property to 
JSON.parse()
Example 18-3 is a gener-
alization of Example 18-2: it makes a GET request for the specified URL and passes
the contents of that URL to the specified callback function when they are ready. But
instead of always passing text, it passes a Document, or an object decoded with
JSON.parse()
, or a string.
Example 18-3. Parsing the HTTP response
// Issue an HTTP GET request for the contents of the specified URL.
// When the response arrives, pass it to the callback function as a 
// parsed XML Document object, a JSON-parsed object, or a string.
function get(url, callback) {
var request = new XMLHttpRequest();         // Create new request
request.open("GET", url);                   // Specify URL to fetch
request.onreadystatechange = function() {   // Define event listener
500 | Chapter 18: Scripted HTTP
// If the request is compete and was successful
if (request.readyState === 4 && request.status === 200) {
// Get the type of the response
var type = request.getResponseHeader("Content-Type");
// Check type so we don't get HTML documents in the future
if (type.indexOf("xml") !== -1 && request.responseXML) 
callback(request.responseXML);              // Document response
else if (type === "application/json")
callback(JSON.parse(request.responseText)); // JSON response
else 
callback(request.responseText);             // String response
}
};
request.send(null);                         // Send the request now
}
Example 18-3 checks the “Content-Type” header of the response and handles
“application/json” responses specially. Another response type that you might want to
“decode” specially is “application/javascript” or “text/javascript”. You can use an
XMLHttpRequest to request a JavaScript script, and then use a global 
eval()
(§4.12.2) to execute that script. Using an XMLHttpRequest object is unnecessary in
this case, however, since the HTTP scripting capabilities of the 
<script>
element itself
are sufficient to download and execute a script. See Example 13-4, and keep in mind
that the 
<script>
element can make cross-origin HTTP requests that are prohibited to
the XMLHttpRequest API.
Web servers often respond to HTTP requests with binary data (image files, for exam-
ple). The 
responseText
property is for text only, and it cannot properly handle binary
responses, even if you use the 
charCodeAt()
method of the resulting string. XHR2 de-
fines a way to handle binary responses, but at the time of this writing, browser vendors
have not implemented it. See §22.6.2 for further details.
Proper decoding of a server’s response assumes that the server sends a “Content-Type”
header with the correct MIME type for the response. If a server sends an XML document
without setting the appropriate MIME type, for example, the XMLHttpRequest object
will not parse it and set the responseXML property. Or if a server includes an incorrect
“charset” parameter in the content-type header, the XMLHttpRequest will decode the
response using the wrong encoding and the characters in 
responseText
may be wrong.
XHR2 defines an 
overrideMimeType()
method to address this problem and a number
of browsers have already implemented it. If you know the MIME type of a resource
better than the server does, pass the type of 
overrideMimeType()
before you call 
send()
this will make XMLHttpRequest ignore the content-type header and use the type you
specify instead. Suppose you’re downloading an XML file that you’re planning to treat
as plain text. You can use 
setOverrideMimeType()
to let the XMLHttpRequest know
that it does not need to parse the file into an XML document:
// Don't process the response as an XML document
request.overrideMimeType("text/plain; charset=utf-8")
18.1  Using XMLHttpRequest | 501
Client-Side
JavaScript
18.1.3  Encoding the Request Body
HTTP POST requests include a request body that contains data the client is passing to
the server. In Example 18-1, the request body was simply a string of text. Often, how-
ever, we want to send more complicated data along with an HTTP request. This section
demonstrates a number of ways to do that.
18.1.3.1  Form-encoded requests
Consider HTML forms. When the user submits a form, the data in the form (the names
and values of each of the form elements) is encoded into a string and sent along with
the request. By default, HTML forms are POSTed to the server, and the encoded form
data is used as the body of the request. The encoding scheme used for form data is
relatively simple: perform normal URI encoding (replacing special characters with
hexadecimal escape codes) on the name and value of each form element, separate the
encoded name and value with an equals sign, and separate these name/value pairs with
ampersands. The encoding of a simple form might look like this:
find=pizza&zipcode=02134&radius=1km
This form data encoding format has a formal MIME type:
application/x-www-form-urlencoded
You must set the “Content-Type” request header to this value when POSTing form
data of this sort.
Note that this kind of encoding does not require an HTML form, and we won’t actually
work directly with forms in this chapter. In Ajax applications, you are likely to have a
JavaScript object that you want to send to the server. (That object may be derived from
the user input in an HTML form, but that does not matter here.) The data shown above
might be the form-encoded representation of this JavaScript object:
{
find: "pizza",
zipcode: 02134,
radius: "1km"
}
Form encoding is so widely used on the Web, and so well supported in all server-side
programming languages, that form-encoding your nonform data is often the easiest
thing to do. Example 18-4 demonstrates how to form-encode the properties of an
object.
Example 18-4. Encoding an object for an HTTP request
/**
* Encode the properties of an object as if they were name/value pairs from
* an HTML form, using application/x-www-form-urlencoded format
*/
function encodeFormData(data) {
if (!data) return "";    // Always return a string
502 | Chapter 18: Scripted HTTP
Documents you may be interested
Documents you may be interested