Web service (asmx) POST test fails on specific load balanced servers - asp.net

I have a ASP.NET WebApp that contains some ASMX webservices. We recently migrated to load balanced Windows 2008 servers from a Windows 2003 server. The new servers sit behind some F5 appliance for the load balancing (that's all I know about it!).
We can reach the built in ASP.NET POST test (example: http://webapp.company.com/webservices/Person.asmx?op=GetPerson) but invoking it from that test page fails (page not available). A new tab in the browser opens with the same url, but with a port number appended on the end: http://webapp.company.com:50831/webservices/Person.asmx?op=GetPerson. When I put that URL(with port) into my browser, it fails as well. Heck, http://webapp.company.com:50831 isn't reachable at all.
We didn't get that on our previous server. I setup my own personal webserver on a personal Windows 2012 server and tested the same code on there and it worked. So I'm thinking it has to do with the load balancing.
Unfortunately, I have no control over the web servers our company offers for hosting internal applications. I don't get to touch the IIS either. All I get is a file path to publish my files to. The hosting organization is telling me my ASP.NET WebApp code is appending the port number, but I don't think that's right. It only occurs on those load balanced servers!
Has anyone else ran into this before when invoking ASMX or WCF that's hosted behind a F5 appliance?

The IT group that maintains those servers didn't have any answers for us, but we were able to verify those odd ports were in fact being assigned by the F5 appliances. We ended up using a port rewriter as a workaround until the group that maintains the web servers can alter the configuration. The code we used is below which is taken straight from the URL below where they were discussing the same problem behind the same F5 appliance (BigIP).
http://www.justskins.com/forums/port-mapping-a-web-51075.html
public class WSDLAddress : SoapExtensionReflector
{
bool bFirstTime = true;
public override void ReflectMethod()
{
if (!bFirstTime) return;
bFirstTime = false;
SoapAddressBinding sabAddress = ReflectionContext.Port.Extensions.Find(typeof(SoapAddressBinding)) as SoapAddressBinding;
string sPort = ConfigurationSettings.AppSettings["myPort"];
UriBuilder uriLocation = new UriBuilder(sabAddress.Location);
uriLocation.Port = Int32.Parse(sPort);
sabAddress.Location = uriLocation.Uri.AbsoluteUri;
}
}

Related

Unable to use WebService specifing the URI through code

I have two PCs conected with a LAN. Firewall ports are opened.
I'm running a WebService on A machine, using IIS. Of course, I can access the WebService (on A) through the Web Browser on the B machine, so I'm sure the WebService can be accessed remotely.
Now, I'm running a console app on B machine, developed in vb.net, which will access the WebService of A machine.
Both, the console app and the WebService, has been developed on VS2010.
Creating the reference on the project, I can see and use the WebService. But I need to specify on code the URI due to the WebService may change its location.
The code indicating the URI manually:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13:8080")
This line throw an exception with the message that did not find any element with the name indicated. I have tried too, without success, the following lines:
This one:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13")
And this one:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13:8080/ServicioWeb.asmx")
But the result is always the same.
Some user (raja) wrote an answer a few days ago indicating that this should work, but I don't know the reason why does not work in my case.
As I said before, if I create the reference on the project, and I use the following line of code:
Dim myService As New MiServicioWeb.WebServiceSoapClient()
It works!, but what I need is to set the URI manually...
Some help will be thankful.
if not already present, you need to modify the proxy class to have a constructor that can take a Uri and set it. This Uri needs to be supplied to the proxy.
Dim uriFromConfig as String;
// read uriFromConfig from config or set it accordingly.
Dim myService As New MiServicioWeb.ServicioWebSoapClient(uriFromConfig);
this way, any ASMX can be called, as long as the right Uri is provided.
in summary to call a webservice hosted on machine with IP a.b.c.d from another machine:
Give the Proxy Uri with the IP Address. a.b.c.d
Open the port (50594) you're using in the machine hosting the web service from the Firewall settings.
Verify if the asmx is accesible by typing http://a.b.c.d:50594/ServicioWeb.asmx from the browser of the client machine. (not the machine hosting the web service)
if #3 is successful, then you'll see a nice page on the browser.
your client app should also be able to connect now.

Is it possible to set IP restrictions for Windows Azure Web sites?

We are using Windows Azure Web Sites, so we don't create Web roles. Now we need to temporarily set IP restrictions for the site, and I am not sure this is possible for Web Sites.
What is usually done is adding ipSecurity element to system.webServer section in web.config. But the ipSecurity section is locked by default, so it must be first unlocked by running a script command. But running Startup script is not possible for Azure Web sites, is it?
Does this mean that for Azure Web Sites (that don't have Web roles) it's simply not possible to configure IP range restriction?
Nir Mashkowski explains in a blog post on how you can enable IP Restriction in Windows Azure Web Sites.
AFAIK ipSecurity is not active on Azure Web Sites.
Workaround: you can write a small piece of code in global.asax Application_BeginRequest and check the client ip address on your allowed IP addresses list. You can load the list on Application_Start.
protected void Application_BeginRequest(...)
{
string clientIP = request.UserHostAddress;
if (!Check(clientIP, myOKList))
{
Response.Write("<html><body>You are not authorized!</body></html>");
Response.End();
}
}

Web Garden and Static Objects difficult to understand

I am in the process of investigating to convert our web application to the web farm. So I started with web garden, by converting the 'Maximum Worker Process = 3'. Following is the simplified version of my problem.
Following is my Static Object class.
public static class MyStaticObject
{
public static string MyProperty {get;set;}
}
Then on Page Load I initialized the Static Objects as follows -
MyStaticObject.MyProperty = "My Static Property";
Then using asp.net ajax [WebMethod] create the ajax method on my web page
[WebMethod()]
public static string getStaticProperty()
{
return MyStaticObject.MyProperty;
}
// Then I call this Ajax method using Javascript and set the return to the text box.
This test is not working as expected. Following are my assumptions and wrong outcome from the test.
I thought when we set virtual directory to be web garden, then each request to the virtual directory is handled by different process in web garden, so my next few request to the server, should return null as I have initialized the static objects for one working process. But even if I click the ajax button for 20 times in row (means 20 requests) even then the static objects return me value.
Am i right in assuming on restarting the IIS should kill all the static objects.
Static objects are not shared in web gardens/web farms.
I am surprised by the behaviour of IIS, static objects and web garden.
Is I am assuming wrong or my way of testing is wrong.
Thanks.
Your assumptions about the way static objects are managed in AppPools / web gardens is correct.
However, your assumption about the way that web requests are distributed is not. HTTP requests are round-robined by the http.sys driver to IIS worker processes only when a new TCP connection is established, not when a new request arrives. Since keepalives are enabled by default, even though you made 20 requests in a row, they probably were all served by the same IIS worker process.
You can have IIS disable keepalives for testing purposes from the HTTP Response Headers section in IIS Manager, under Set Common Headers. That should cause your browser to open a new connection for each request.
To test with keepalives enabled, you can use the Web Capacity Analysis Tool (WCAT), available with the IIS 6 Resource Kit, to generate a multi-threaded load that accesses both IIS processes in your web garden.

Webservices help

We have a web service running on the server. We want to use the service in local machine. Could some one kindly give all the steps to get the methods availble in the client.
We have created web methods in the server. And trying to access the same thing on the client. I can literally access those methods using the refernce variable of the server. but when I try to run it , it comes up with run time exception unable to connect to remote server.
I have added the web reference to my client class. What else I am missing. Do I need to do any kind of registration of service with client from command prompt.
I am assuming the client is unable to connect to server because the server is not running when I try to access the methods.
Any one with guidance will be helpful.
Thank you
Hari Gillala
I have added web refernce to this below client class using http://ipaddressofwerver/decisionclass/decisionclass.svc
The code:
try
{
DecisionClass ds = new DecisionClass();
string s = ds.Url;
Label1.Text = s;
string [] a = ds.GetList();
foreach (string i in a)
{
Response.Write(i);
}
}
catch (Exception Ex)
{
Response.Write(Ex.Message);
}
I am assuming the client is unable to connect to server because the server is not running when I try to access the methods.
If it's not running, it won't generate a WSDL either. However, it may have been running while you created the web reference, and then stopped.
Here are some things you can try to track down the problem:
Open the web service's URL, as specified in the web reference, in a regular web browser. This should bring up the web service's documentation page, and if you're running locally and haven't changed the web service's web.config, you can even call some simple methods using the provided test forms
See if you can access the web service with SoapUI or a similar tool.
Also, make sure you're running the web service in IIS, not in the Visual Studio development server - IIS will keep running when you close the project or even Visual Studio, but the development server might not.

How do I get the host domain name in ASP .NET without using HttpContext.Current.Request?

I've got an ASP .Net application running on IIS7. I'm using the current url that the site is running under to set some static properties on a class in my application. To do this, I'm getting the domain name using this (insde the class's static constructor):
var host = HttpContext.Current.Request.Url.Host;
And it works fine on my dev machine (windows XP / Cassini). However, when I deploy to IIS7, I get an exception: "Request is not available in this context".
I'm guessing this is because I'm using this code in the static constructor of an object, which is getting executed in IIS before any requests come in; and Cassini doesn't trigger the static constructor until a request happens. Now, I didn't originally like the idea of pulling the domain name from the Request for this very reason, but it was the only place I found it =)
So, does anyone know of another place that I can get the host domain name? I'm assuming that ASP .Net has got to be aware of it at some level independent of HttpRequests, I just don't know how to access it.
The reason that the domain is in the request is...that's what's being asked for. For example these are a few stackexchange sites from http://www.stackexchangesites.com/:
http://community.ecoanswers.com
http://www.appqanda.com
http://www.irosetta.com/
If you ping them, you'll see they all point to the same IP/Web Server and be served by the same app (or multiple apps in this case, but the example holds if it was one big one)...but the application doesn't know which one until a host header comes in with the request asking the server for that site. Each request may be to a different domain...so the application doesn't know it.
If however it doesn't change, you could store it as an appSetting in the web.config.
Use global.asax or write a HttpModule and subscribe to start request events. You will have the request passed into your event handler.
Use this instead:
HttpRuntime.AppDomainAppVirtualPath
Or if you want the physical path:
HttpRuntime.AppDomainAppPath
For further reading:
http://weblogs.asp.net/reganschroder/archive/2008/07/25/iis7-integrated-mode-request-is-not-available-in-this-context-exception-in-application-start.aspx

Resources