Showing posts with label Web Services. Show all posts
Showing posts with label Web Services. Show all posts

Enabling HTTP POST for an ASP.NET Web Service


Tuesday, January 8, 2008

If you have been working with ASP.NET web services, you might have noticed that on your local or development server, the web service exposes its methods via several ways (HTTP SOAP, HTTP Get, HTTP Post). Moreover, for those methods that accept parameters, the page displays HTTP Post form, which allows you to quickly test the web service.

However, when you deploy the web service, the only available methods for calling it is HTTP Soap. What if you need to allow HTTP Get and Post calls?

It turns out to be quite easy. Moreover, you can enable/disable protocols for a whole machine or for specific webservices. However, please keep in mind that enabling GET and POST protocols adds security risks. At least that's what Microsoft says. Technically, I don't think there is a considerable risk associated with enabling Post calls. Anyway, if you don't really need POST calls, then it's better to keep it disabled.

So, how do we do that anyway? Glad you asked. Look at the configurations below.

To enable HTTP GET and HTTP POST protocols for the whole machine:

Open the Machine.config file in a text editor. This file as rule lives in the \Config subdirectory of the installation root.

Add the following configuration between and tags.


<webServices>
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/>
<add name="HttpGet"/>
<add name="Documentation"/>
<add name="HttpPostLocalhost"/>
</protocols>
</webServices>
Save Machine.config.

This configuration change takes effect on the next request to a Web service hosted on that machine.


To enable support for a protocol for an individual Web application:

Open the Web.config file in the root directory of the Web application in a text editor.

Add the following configuration between and tags.

<webServices>
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/>
<add name="HttpGet"/>
<add name="Documentation"/>
<add name="HttpPostLocalhost"/>
</protocols>
</webServices>
Save Web.config.

This configuration change takes effect on the next request to a Web service hosted by the Web application.




Simultaneously Calling Several Asynchronous Web Service Methods


Saturday, November 10, 2007

It's no more a secret that web services have become extremely popular past couple of years. Many distributed applications contain web services as a part of the solution. Even if your solution does not need a web service, you may need to consume a third party web service at some point.

C#/.NET makes it easy both creating your own web service and consuming either your own or a third party web service. As you may already know, you can call web service methods either synchronously or asynchronously. Frequently, asynchronous method of calling web service methods is a preferred way. Generally, when possible, I do use asynchronous calls.

Currently, I'm working on a project that heavily uses web services. At one point I ran in a situation where I needed to call multiple web service methods simulatenously. Development of the web service and the consumer application goes in parallel. Naturally, before consuming a web service method, we do test the web service. Suddenly, a strange exception started occurring when we were asynchronously calling two web service methods at the same time. The exception message is given below and you can see it in the screen shot.


Exception has been thrown by the target of an invocation.

InnerException

"There was an error during asynchronous processing. Unique state object is required for multiple asynchronous simultaneous operations to be outstanding."

When I checked the web service methods, they both worked without any problems.

It looks like that when we call several web service methods asynchronously, we need to somehow differentiate the calls. If you provide unique UserState objects to the calls, then this exception does not occur. But what shall we do if we do not need to use UserState objects at all? I have simply solved this by supplying a dummy user state object.

Look at the code fragment below. m_WSController is the instance of the web service class. Here I call two methods asynchronously:

GetPaymentMethodsAsync and GetUserPaymentDetailsAsync. Notice that adding a simple new object() dummy user state object solves the problem.

// THIS DOES NOT WORK

m_WSController = new MyApp.WebService.Controller();

m_WSController.GetUserPaymentDetailsCompleted += new MyApp.WebService.GetUserPaymentDetailsCompletedEventHandler(m_WSController_GetUserPaymentDetailsCompleted);
m_WSController.GetPaymentMethodsCompleted += new MyApp.WebService.GetPaymentMethodsCompletedEventHandler(m_WSController_GetPaymentMethodsCompleted);

m_WSController.GetPaymentMethodsAsync();
m_WSController.GetUserPaymentDetailsAsync(m_SessionId);

// THIS WORKS!


m_WSController = new MyApp.WebService.Controller();

m_WSController.GetUserPaymentDetailsCompleted += new MyApp.WebService.GetUserPaymentDetailsCompletedEventHandler(m_WSController_GetUserPaymentDetailsCompleted);
m_WSController.GetPaymentMethodsCompleted += new MyApp.WebService.GetPaymentMethodsCompletedEventHandler(m_WSController_GetPaymentMethodsCompleted);

m_WSController.GetPaymentMethodsAsync(new object());
m_WSController.GetUserPaymentDetailsAsync(m_SessionId);


Hopefully, this saves you time when getting the above described exception.