Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning ASP.NET 2.0 With CSharp (2006) [eng]

.pdf
Скачиваний:
75
Добавлен:
16.08.2013
Размер:
20.33 Mб
Скачать

Chapter 12

2.There are two possible web services here. The format and style of this screen are the same for any .asmx web service file you browse. The link to the web service that gives you the weather forecast is called GetWeather. Click this link, and you’ll arrive at a screen similar to Figure 12-2.

Figure 12-2

3.Supply the name of the city where you live, or closest to where you live, and the name of the country. Scroll down and look at the code (see Figure 12-3).

428

Figure 12-3

Web Services

4.Click Invoke to get the result, shown in Figure 12-4. It will be customized to where you live and is dependent on the weather of the moment.

Figure 12-4

How It Works

You’ve just consumed a web service. The Wrox United application does not have the capability to do weather forecasting, so you looked elsewhere to get this service. By browsing to an .asmx file, you are able to use the web service, and supply input and get an answer tailored to your specifics. When you supplied the city name and country name, you probably noticed that your input was wrapped up in an XML document. This is the document broadcast to the server. Although the data can be wrapped up by three different methods, just look at the first on the page for now:

POST /globalweather.asmx HTTP/1.1

Host: www.webservicex.net

Content-Type: text/xml; charset=utf-16

Content-Length: length

SOAPACTION: “http://www.webserviceX.NET/GetWeather”

<?xml version=”1.0” encoding=”utf-16”?>

<soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>

<soap:Body>

<GetWeather xmlns=”http://www.webserviceX.NET”> <CityName>string</CityName>

<CountryName>string</CountryName>

</GetWeather>

</soap:Body>

</soap:Envelope>

Your input is simply substituted for the words string in the highlighted code:

<GetWeather xmlns=”http://www.webserviceX.NET”> <CityName>Birmingham</CityName> <CountryName>United Kingdom</CountryName>

</GetWeather>

429

Chapter 12

Of course one big drawback is that there isn’t a user interface, so you’re using a normal interface, and also all your code is returned as one large lump of XML. So it’s not exactly something you’d stick into your application as it is, without your users getting confused. Also you’ll see that the weather report is much too detailed for your match reports. Ideally you’d just want to be able to pick out, say, sky conditions and temperature and probably leave it at that. To be honest, a few other pitfalls exist that would make a weather service difficult to integrate into your application. Not least is the fact that the weather service extracts the current weather, and if you were to display this in your match reports, you’d need to make sure you saved the weather in the database alongside the match details, otherwise you’d be reading about Wednesday’s match, and seeing Friday’s weather.

Later in the chapter, you’ll look at creating some web services for the Wrox United application, but for now you only need to understand that web services are freely available for very ordinary chores to all sorts of weird and wonderful things. If there is a URL with an .asmx file available, you can access and use the web service in a standard way. And if you can access and use the web service in this standard way, you can stick it in your application just as easily.

The Life Cycle of a Web Service

It’s time to look at some theory behind what is happening here. This section strips down a web service to its basic essentials, which is a four-stage process. Following that, this section expands upon each stage, and talks a little bit about the technologies and standards used at each step.

The four-stage process of a web service is as follows (as detailed in Figure 12-5):

1.The client calls web service over a protocol.

2.The client sends the method to the server, which contains instructions on what is needed from the web service.

3.The server returns values and/or an acknowledgment that it has received the method.

4.The client gets the results and acts on the received information. This may involve calling the web service again, or a different web service, with the results received.

Client sends method

Client calls

Server returns

web service

values or an acknowledgement

Client acts on information

430

Figure 12-5

Web Services

This can happen as a cyclical process, where information is sent and received, acted upon, and sent out again. In the next several sections, each step of the process is put under the magnifying class because with web services, there are usually quite a few interesting things going on.

Calling the Web Service

When you ran the first example and consumed the simple web service, you did so by typing a URL into a browser. However when you type the URL, you also specify the protocol that you are using (for example, http://). This is important, because web services are able to work over a multitude of protocols from SMTP (Simple Mail Transport Protocol) to HTTP (secure HTTP). However, using anything other than HTTP is beyond the scope of this book, and you can achieve plenty just using the HTTP protocol, but you shouldn’t think that you are restricted in this way.

ASP.NET passes information backward and forward using the HTTP-Request/Response system. Any information is sent to the web service as part of the request, and the server will return anything from the web service as part of the response. Most commonly, you can transmit values to a web service via an HTML form and the standard HTML controls.

The request that is sent to the web service contains the following information:

The web service’s URL

The fact that it is an HTTP request

The amount of information being sent

The type of document you want back from the web service

Information about the client

The date of the request

The parameters you want to send to the web service

The browser collects the information from the form and wraps it up in a document ready for transmission. This process is called serialization.

Transmitting the Web Service

When you transmit the information required by the web service, as you’ve seen already, it is serialized in an XML document. This can be done in three different ways:

HTTP-GET via the querystring

HTTP-POST via the body of the form

SOAP via the body of the form

You already know about the first two methods, so this section focuses on the last one. The phrase “serialized in an XML document” doesn’t tell the whole story with SOAP. SOAP isn’t just any type of XML, but a specific dialect specially created for the exchange of messages. SOAP used to stand for Simple Object Access Protocol, but these days it is commonly regarded as not standing for anything in particular. A message contained in SOAP is nothing more than a well-formed XML document or plain, vanilla text. So what exactly is SOAP’s purpose?

431

Chapter 12

SOAP is a message template for sending requests and receiving responses to web services between the browser and the web service. Because the web relies on the HTTP protocol, it commonly excludes anything other than HTTP; so SOAP (XML) documents have to be sent as part of the HTTP data. SOAP will send a particular instruction such as “Get me a certain bit of information” wrapped in the HTTP, and then this information can be retrieved by the web service at the other end.

In the previous Try It Out, underneath the text boxes into which you entered the name of a city and country, you saw some example code. The example code took the three formats: HTTP-GET, HTTP-POST, and SOAP. The SOAP document looked like this:

POST /globalweather.asmx HTTP/1.1

Host: www.webservicex.net

Content-Type: text/xml; charset=utf-16

Content-Length: length

SOAPACTION: “http://www.webserviceX.NET/GetWeather”

<?xml version=”1.0” encoding=”utf-16”?>

<soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>

<soap:Body>

<GetWeather xmlns=”http://www.webserviceX.NET”> <CityName>string</CityName> <CountryName>string</CountryName>

</GetWeather>

</soap:Body>

</soap:Envelope>

The first thing to note is that the document was split into two sections. The first section is a set of HTTP headers that are used to communicate various aspects about your document. HTTP headers are also sent as a matter of course with HTML page requests so there’s nothing new here. Take a brief look at the HTTP headers to see what they indicate.

The first line indicates that you are sending information via the HTTP-POST method. This might seem to immediately contradict the fact that you are using SOAP, but your SOAP message has to be sent as or in an HTTP request to allow it to get through to most web servers. It also specifies the endpoint of your service, globalweather.asmx. The next three lines of HTTP headers are pretty standard, but the final header, the SOAPACTION header, must be present; otherwise the message will be invalid. It’s there to help the server decide whether it can let through a message’s content.

The XML document is of greater interest. The opening line is the XML document header, standard to all XML documents. Then you have the structure of the document, which in SOAP will always have this structure. You have a SOAP Envelope tag that contains a SOAP Header and a SOAP Body.

The SOAP Header is optional and is missing from the code, but the SOAP Envelope contains some vital information in the attributes to help it make up the document. It contains three attributes that all provide namespace information: xsi, xsd, and soap. xmlns is short for XML namespace. At this level of programming, you really only want to know about the latter attribute, and this is because you use it to specify a prefix to your SOAP tags:

xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”

The prefix specified after the xmlns: attribute is soap, and this prefix is used in front of all the SOAP tags:

432

Web Services

<soap:Envelope>

<soap:Body>

... Web Service content here...

<soap:Body>

<soap:Envelope>

All documents sent by SOAP will need to adhere to this structure. Inside the SOAP:Envelope attribute is the SOAP:Body tag. The SOAP:Body tag is always contained within the envelope and it contains the information that has been gleaned from the parameters and needs to be sent to the web service. Inside the SOAP:Body tags, you find at last the data you want to send:

<GetWeather xmlns=”http://www.webserviceX.NET”> <CityName>Birmingham</CityName> <CountryName>United Kingdom</CountryName>

</GetWeather>

The GetWeather tag is the web service, and the xmlns attribute outlines the location of the web service, which in this case is www.webservicex.net. Inside the GetWeather tag are two tags: CityName and CountryName. These are the two parameters that you originally supplied to the web service when you invoked it. These parameters have been serialized into a SOAP document, which itself is parceled up in the HTTP data and is now transmitted to the web service.

Rather than use the more common terminology call, the term invoke is used with relation to web services. If you check Dictionary.com, you will find the definition of invoke is to call upon a “higher system or power for assistance, support or inspiration.” The higher power in this instance is of course the web service. I suppose it is used because the word call, of course, just doesn’t paint the same picture.

You’re probably wondering why we’re going into some quite esoteric detail about SOAP document structure. The answer is that if you want to supply data to the web service manually, it is going to have to have this structure involved. Also there is another important reason, which you will discover in the next sections.

Returning the Response

A web service doesn’t have to return a response. It will most commonly return a response, but this isn’t essential — it might be just enough to send some information to a database or to change an attribute on the server. Before a response of any sort can be returned, though, a few tasks must be accomplished by the web service.

Because the data has been serialized so that it can be transmitted across the web, it has to be deserialized first. This is just the process of obtaining the data (which in the previous example were the words “Birmingham” and “United Kingdom”) from the XML and then executing the web service with this data. Of course the data isn’t the only thing sent back as part of the response. You also get the following:

A return address for the consumer

The fact that this is an HTTP response and that there is no further action required

A success or failure code

Configuration information

433

Chapter 12

One of two scenarios is possible: either a value needs to be returned, in which case the result has to be serialized once more in an XML document and sent back to the client, or there are no values that need transmitting back, in which case there will only be a success or failure code to indicate what has happened to your web service.

In the example, you might notice that the response isn’t actually returned as a SOAP document, but one large XML string using the HTTP-POST protocol. This is because you sent your original call to the service as a HTTP-POST document, so the web service is just returning in like format. It is also possible to call your web service using HTTP-GET. As you might remember from Chapter 2, a call to the server using HTTP-GET involves adding a querystring to the URL and adding the parameters as querystrings. You can send the same request to the example web service as follows:

http://www.webservicex.net/globalweather.asmx/GetWeather?CityName=Birmingham&Coun

tryName=United%20Kingdom

Doing this will return exactly the same response as you saw in Figure 12-4.

This leaves the SOAP message template. To send and retrieve a document using SOAP requires a little more effort, and isn’t possible via the endpoint without extra code. However, the information contained with a SOAP document retains structure, rather than being sent back as a convoluted jumble bundled in a

<string> element:

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-16

Content-Length: length

<?xml version=”1.0” encoding=”utf-16”?>

<soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>

<soap:Body>

<GetWeatherResponse xmlns=”http://www.webserviceX.NET”> <GetWeatherResult>

<Location>Birmingham / Airport, United Kingdom (EGBB) 52-27N 001-44W 0M</Location>

<Time>Jul 12, 2005 - 05:20 AM EDT / 2005.07.12 0920 UTC</Time> <Wind> from the E (090 degrees) at 5 MPH (4 KT) (direction variable):0</Wind>

<Visibility> greater than 7 mile(s):0</Visibility> <SkyConditions> mostly cloudy</SkyConditions> <Temperature> 64 F (18 C)</Temperature> <DewPoint> 59 F (15 C)</DewPoint> <RelativeHumidity> 82%</RelativeHumidity> <Pressure> 30.47 in. Hg (1032 hPa)</Pressure> <Status>Success</Status>

</GetWeatherResult>

</GetWeatherResponse>

</soap:Body>

</soap:Envelope>

The first three lines are the HTTP header. However, this time the weather report results (which are different than what was shown in Figure 12-4 because it was done on a different day) are placed within the

434

Web Services

<soap:Envelope> and <soap:body> elements. There is no <soap:header> element here — it’s optional and you don’t need one. If you examine the results, you will also see that the <string> element is missing, which leaves your document with its intended structure.

This doesn’t answer one question, though: What happens if you didn’t want to include all of the information that the web service had returned, and just wanted some particular bits and pieces? The weather web service returns all kinds of extraneous information, when all you were interested in were the sky conditions and temperature. It’s certainly possible to extract items from a string, but you are better served by restricting what information the web service returns at source. To do this, you need to invest in the flexibility that a command-line prompt tool like wsdl.exe (a tool that comes as part of the .NET Framework) offers. And that requires a little extra work and is beyond the scope of this book.

Using the Response

After the client has received a response from the web service saying that either the response has succeeded or failed along with any data that was required, the cycle of your web service ends. The client in the test example received pure XML, and therefore displayed it as a normal XML document. Both HTTPPOST and HTTP-GET wrapped the response in a single string, which to be fair isn’t a lot of use to you. This is why it is preferable to use SOAP, because the response would be returned in the same format as the request, and it would enable you to access individual items within the XML document more easily. However, because browsers use HTTP to transfer information, it would require a separate application to create a web service that uses the SOAP message template, and to be able to decipher the response sent via the SOAP message template.

When you consume a web service in the Wrox United application, it will be problematic when you get the whole document returned as one string, rather than individual elements, from which you can pick and choose. However, it is beyond the scope of this chapter to write a separate application to be able to send a web service request in the SOAP message template. We will instead settle for this imperfect state of affairs and try and use the information contained within the string as best we can. In the real world, we suggest that you use SOAP. For more details, look at http://msdn.microsoft.com/webservices/.

The Structure of Your Web Service

A web service has a particular structure that needs to be maintained whenever you create a new web service. This structure is pretty much unchanged between ASP.NET 1.x and ASP.NET 2.0, so if you have experience in the area, it should look familiar. Every web service you create must have basically four items (detailed in the following sections).

Processing Directive

At the head of any web service file, you need a directive, which essentially just lets ASP.NET know that this is a web service. The processing directive must always be the first line and it takes the following syntax:

<%@ WebService Language=”language” Class=”classname” %>

435

Chapter 12

The directive is used to specify particular settings such as which language the web service is written in and where to find the class that defines the particulars of your web service. The class should be a separate file.

Namespaces

As with the rest of ASP.NET, occasionally you will need to specify other namespaces so that you can appropriate other classes and functions within your own web service. These namespaces are defined after the @WebService attribute in the file. In C#, four references are added as default, which are as follows:

using System; using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

These references are required as an absolute minimum, because they contain classes needed for web services to handle network connection issues and other related tasks.

Public Class

The class is simply a container for the web service, and the name of the class signifies the name of the web service:

public class Service : System.Web.Services.WebService { ...

}

The class name needs to correspond with the class attribute that is specified within the processing directive. Then for all other intents and purposes, it is just a normal object, albeit one that is exposed to the web. The trick with this web server, though, is that any calls to the object will look like they came from the same machine, and not via a foreign source.

Web Methods

To signify that a particular method (or property) is callable via the web, you need to add a [WebMethod] declaration. In ASP.NET 1.x, you could only expose methods to the web, but in ASP.NET 2.0, you can also expose properties.

The [WebMethod] declaration is the part that does all of the legwork. You can define one or more web methods, and not only that, you can make sure some web methods are publicly accessible, whereas others can have access to them restricted via the protected keyword. Though the syntax varies slightly between VB.NET and C# (VB.NET uses greater-than and less-than symbols, whereas C# uses square brackets to define the method call), they are both recognizably similar.

The syntax in VB.NET is as follows:

<WebMethod()> _

Public Function Hello (ByVal strName As String) As String

....

End Function

436

Web Services

This defines a web method that accepts a string as a parameter and returns a string as a result, just like a normal function.

The syntax in C# is as follows:

[WebMethod]

public string Hello (string strName)

{

....

}

This also defines a web method that accepts a string as a parameter and returns a string as a result. If you don’t want to expose a particular web method to the public, you simply remove the declaration.

Web methods also take parameters of their own. You can set the different attributes to modify the behavior of the web service. This allows you to customize the web service in several ways. For example, you can use the CacheDuration attribute to specify the number of seconds for which you want the WebMethod declaration to cache its results. When a consumer browses to the web service inside this allotted period, instead of the web service going back to retrieve the result, it gets a cached copy of the results instead.

In VB.NET, you can specify an attribute as follows:

<WebMethod(CacheDuration:=60)> _

Public Function Hello (ByVal strName As String) As String

....

End Function

In C#, you can specify an attribute as follows:

[WebMethod(CacheDuration=60)] public string Hello (string strName)

{

....

}

You can specify multiple attributes by separating them with commas. The Description attribute allows you to specify a little detail about your web method, which can help potential consumers identify whether or not they want to use it.

In VB.NET, you can specify multiple attributes as follows:

<WebMethod(Description:=”A web service that says hello to you”, _ CacheDuration:=60)> _

Public Function Hello (ByVal strName As String) As String

....

End Function

In C#, you can specify multiple attributes as follows:

[WebMethod(Description=”A web service that says hello to you”,CacheDuration=60)]

public string Hello (string strName)

437