Thursday, May 12, 2005

.NET Web Services FAQs #1

Does ASP.NET support server-side includes?

Yes. Server-side includes work the same in ASP.NET as they do in ASP.



What platforms do .NET XML Web Services run on?

Currently, they're supported on Windows 2000 and Windows XP. ASP.NET integrates with Internet Information Server (IIS) and thus requires that IIS be installed. It runs on server and non-server editions of Windows 2000 and XP as long as IIS is installed.


Can two different programming languages be mixed in a single ASMX file?

No.

What is code-behind?

Code-behind allows you to associate Web Service source code written in a CLR compliant language (such as C# or VB.NET) as compiled in a separate file (typically *.asmx.cs or *.asmx.vb). You would otherwise typically find the executable code directly inserted into the .asmx file.


What event handlers can I include in Global.asax?

* Application_Start
* Application_End
* Application_AcquireRequestState
* Application_AuthenticateRequest
* Application_AuthorizeRequest
* Application_BeginRequest
* Application_Disposed
* Application_EndRequest
* Application_Error
* Application_PostRequestHandlerExecute
* Application_PreRequestHandlerExecute
* Application_PreSendRequestContent
* Application_PreSendRequestHeaders
* Application_ReleaseRequestState
* Application_ResolveRequestCache
* Application_UpdateRequestCache
* Session_Start
* Session_End

You can optionally include "On" in any of method names. For example, you can name a BeginRequest event handler Application_BeginRequest or Application_OnBeginRequest.

You can also include event handlers in Global.asax for events fired by custom HTTP modules.

Note that not all of the event handlers make sense for Web Services (they're designed for ASP.NET applications in general, whereas .NET XML Web Services are specialized instances of an ASP.NET app). For example, the Application_AuthenticateRequest and Application_AuthorizeRequest events are designed to be used with ASP.NET Forms authentication.



What namespaces are imported by default in ASMX files?

The following namespaces are imported by default. Other namespaces must be imported manually.

* System
* System.Collections
* System.ComponentModel
* System.Data
* System.Diagnostics
* System.Web
* System.Web.Services


What are ASHX files?

ASHX files contain HTTP handlers-software modules that handle raw HTTP requests received by ASP.NET. The following code institutes a simple ASP.NET HTTP handler:

<%@ WebHandler Language="C#" Class="Hello" %>

using System.Web;

public class Hello : IHttpHandler
{

public void ProcessRequest (HttpContext context)
{
string name = context.Request["Name"];
context.Response.Write ("Hello, " name);
{

public bool IsReusable
{
get { return true; }
}
}


If this code is placed in an ASHX file named Hello.ashx and requested using the URL http://.../hello.ashx?Name=Cindy, it returns "Hello, Cindy" in the HTTP response. ASHX files provide developers with a convenient way to deploy HTTP handlers without customizing Machine.config or Web.config. ASHX files can also employ code-behind just like ASPX and ASMX files.



If I want to charge for a Web service, how do I know who's calling it?

While there are probably many possible use models, the three most likely are service agreement, subscription, and per-use.

With a service agreement, you and your clients sign agreements indicating the terms of the service. These terms vary widely, as you might imagine.

Subscriptions allow your clients to access the Web Service for a given period of time or for a set number of invocations. Assuming their account remains in good standing, you continue to allow them to access your Web Service.

Per-use, of course, is billed each time the client uses the Web Service.

The key to all of these use models is authentication. You simply must know with whom it is you're dealing (or in the case of per-use, you'll want to authenticate their payment method, such as validating a credit card number with the account holder's name). Therefore, it isn't uncommon for you to require the client authenticate prior to the use of billable Web Services. That is, you provide a "login" method, or you require the client provide login-style information with the use of each Web Service. The login method would return some sort of authentication token (akin to a session token with traditional ASP.NET), and the client would then return that token to you when a billable Web Service was accessed. Conversely, they could provide their authentication information with each use (username and password, for example).

One design facet to consider is where this information is located within your SOAP packet. Using the login method and authentication token as an example, the token might be passed into a protected Web Service through either a SOAP Header or as an input parameter to the Web Service method itself. Both have benefits and drawbacks.

The benefit of placing an authentication token as a method parameter is that the client doesn't need to deal with SOAP Headers. They simply pass the token into the method, typically as a Base64-encoded string of opaque bytes. The drawback is that the authentication token isn't really a necessary input parameter if it weren't for the requirement the client authenticate. That is, the authentication token is "out of band" information to the method, or "orthogonal." For example, if you provided a Web Service that calculated the sin of a given angle, the authentication token as an input string has no significance to the sin function. This leads to oddly-factored methods that could possibly look and feel like spaghetti.

You can counter this by requiring the client to place the authentication token in a SOAP Header. SOAP Headers were specifically designed to convey such orthogonal information (this token, a transactional ID, and so forth), and they're the perfect place to stuff this ugly, Base64-encoded string. The drawback is you then require the client to deal with the creation and use of the SOAP Header, thereby increasing the code they need to write to use your Web Service as well as increasing the "pain in the...typing hand" factor.


How do I require a SOAP Header when designing my Web Service?

.NET is rich with classes and Web Service support, and SOAP Headers are but another example. Following up with the authentication theme... The first thing to do is create a class that will represent the header:

public class AuthToken : SoapHeader
{
protected string m_strAuthToken;
public AuthToken ()
{
m_strAuthToken = "";
}

public string Token
{
get { return m_strAuthToken; }
set { m_strAuthToken = value; }
}
}


As it happens, SOAP Headers within the .NET Framework are actually implemented as attributes of the Web Method. Therefore, within your Web Service class you'll create an instance of the header class that may be referenced by each interested Web Method:

public class Service1 : System.Web.Services.WebService
{
public AuthToken m_authToken;

...

[WebMethod]
[SoapHeader("m_authToken",Direction=SoapHeaderDirection.In)]
public string MyBillableWebMethod()
{
m_authToken.DidUnderstand = true; // else SoapFault!
if ( !Authenticate(m_authToken.Token) )
{
return "";
}
// Continue processing...
...
}

}


Note that we needed to inform .NET that we, in fact, did understand the SOAP header or .NET will throw the requisite SOAP Fault (if we didn't do this, to .NET's way of thinking SOAP's mustUnderstand constraint wasn't met). You will also need to provide an implementation for Authenticate() to actually validate the authentication token.


How do I provide information to the Web Service when the information is required as a SOAP Header?

The key here is the Web Service proxy you created using wsdl.exe or through Visual Studio .NET's Add Web Reference menu option. If you happen to download a WSDL file for a Web Service that requires a SOAP header, .NET will create a SoapHeader class in the proxy source file. Using the previous example:

public class Service1 : System.Web.Services.Protocols.SoapHttpClientProtocol {
public AuthToken AuthTokenValue;

...

[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/", IsNullable=false)]
public class AuthToken : SoapHeader {
public string Token;
}
}


In this case, when you create an instance of the proxy in your main application file, you'll also create an instance of the AuthToken class and assign the string:

Service1 objSvc = new Service1();

// Create the header itself. This header will go to the
// Web Service for processing
objSvc.AuthTokenValue = new AuthToken();
objSvc.AuthTokenValue.Token = ;

// Call the Web Service

string strResult = objSvc.MyBillableWebMethod();


.NET will make sure the SOAP Header is created and filled with the authentication token's value (for this example).

0 Comments:

Post a Comment

<< Home