Wse Problems thru firewalls.

I have been working on web services using WSE2, and today while doing a test deployment to the outside world, I encountered a huge show-stopper problem.

Steps to reproduce the issue: (WSE 2.0 SP1 installed)
 
1. Create a simple web service ("Hello World").
2. Create a simple client, add a reference to the Hello World web service.
3. Enable WSE2 on both client and server side. (Rt-click on project-->WSE 2.0 settings)
4. Update web reference on client (rt-click on web reference-->Update Reference)
5. Add a button and label to the client. In the click event of the button:
 

private void btnbutton1_Click(object sender, System.EventArgs e)
{
    
WSETest.TestWse proxy = new WSETest.TestWse();
    this.lbllabel1.Text = proxy.HelloWorld();
}

Make sure you are referring to the Wse version of the web service proxy class.
 
6. Set the "URL Behaviour" of the web reference to Dynamic. (click on web reference in Solution Explorer, see Properties window).
7. Run the app. Click the button. You should see "Hello world'" in the label.
 
 
To see the problem:
 
1. Deploy the web service to another server, on the other side of a firewall/ISA. In our environment, we have the test web service available by the internal name: http://irc-devserver1/testing/WSETest/test.asmx. We also have an ISA forwarding rule that forwards web requests to http://yaddayadda.imaginets.com/testing to http://irc-devserver1/testing/
2. Deploy the client to somewhere in the outside world where it will have to access the web service via the external address.
3. Update the .config file for the app, changing the appSettings section to update the URL for the web service.
 

<appSettings>
    <!
--
    <add key="WSETestClient.WSETest.Test" value="http://irc-devserver1/testing/WSEtest/test.asmx"/>
    --
>
   
<add key="WSETestClient.WSETest.Test" value="http://yaddayadda.imaginets.com/testing/WSEtest/test.asmx"/>
</appSettings>

4. Run the app. Click the button. You will get an exception as follows:
 
System.Web.Services.Protocols.SoapHeaderException: Destination Unreachable --> WSE816: The <To> header must match the value of an incoming message's HTTP Request Url if the soap receiver does not have an actor name. The <To> header received contained http://yaddayadda.imaginets.com/testing/WSEtest/test.asmx while the HTTP Request Url was http://irc-devserver1.imaginets.net/testing/WSEtest/test.asmx.
 
This appears to be a method to prevent spoofing of SOAP messages that is implemented by WSE2. I can add the Actor name to the web service using the SoapActor attribute decoration:
 

[Microsoft.Web.Services2.Messaging.SoapActor("soap://imaginets.com/WSETest")]
public class WSETest: System.Web.Services.WebService

When I do that, the next exception is as follows:

Microsoft.Web.Services2.Addressing.AddressingFault: Destination Unreachable ---> System.Exception: WSE817: The <To> header must match the Actor attribute on this receiver. The <To> header contained "http://yaddayadda.imaginets.com/testing/WSEtest/test.asmx" whereas the Actor attribute was "soap://imaginets.com/WSETest".

Here is the question:

What is the easiest way to change the SOAPheader <To> to use the Actor attribute above, by configuring the client proxy?

The WSE documentation says that you can create a different proxy class using the WseWsdl2.exe tool.

C:\Program Files\Microsoft WSE\v2.0\Tools\Wsdl>wsewsdl2 http://localhost/wsetest/test.asmx?wsdl -name "soap://imaginets.com/WSETest" WSeTestsoap.cs

There are some problems with the resulting proxy class (WSeTestsoap.cs):

1. You have to also add a reference to System.Web (minor)
2. The proxy class is much different
than the auto-generated classes when you add a web reference via the VS.IDE. Very much unlike the proxy classes created in the IDE, where there is a WSETest proxy and a WSETestWse proxy that are very similar in nature.
3. The URL for the endpoint is set in the constructor, so I suspect it will be difficult to change after.

I would prefer to use the proxy class generated by the VS.IDE and not the wsewsdl2.exe tool. Is it possible?

I think the answer lies in the WSETestWse.RequestSoapContext class and its sub-classes, but I'm unsure of how to do that.

(Aside: the root of this problem is that the SoapActor attribute is not described anywhere in the WSDL, so the wsdl proxy generators, neither the VS.IDE nor the WseWsdl2.exe, cannot determine that the proxy classes must set the appropriate Actor. They have added a command line switch for it to WseWsdl2.exe, but the resulting proxy classes are not similar enough to the IDE's proxies to be immediately useful.)

Anyone got any suggestions for me?

Mike

2 Comments

  • There seem to be two approaches to handling this situation:



    1. Use the Destination property instead of the Url property and also include a Via to set the next hop for the message. The following code should do the trick for you:



    this.Destination = new EndpointReference(

    &quot;http://localhost/service.asmx&quot;,

    &quot;<a target="_new" href="http://localhost:7777/service.asmx&quot;">http://localhost:7777/service.asmx&quot;);





    2. Use a logical name for the service with a combination of the Destination property and the SoapActor attribute on the WebService itself. SoapActor(&quot;urn:MyService&quot;) on the WebService class in conjunction with the following at the client should do the trick:



    this.Destination = new EndpointReference(

    &quot;urn:MyService&quot;,

    &quot;<a target="_new" href="http://localhost:7777/service.asmx&quot;">http://localhost:7777/service.asmx&quot;);

  • Sorry, the URIs got crapped...

Comments have been disabled for this content.