Help me! How do I connect to an ASMX web service?

With the rise of mobile applications (Windows Store and Windows Phone Store apps), the need for remote processing and storage has never been greater. The necessarily-small footprint of these apps, the limited storage capacity of the hardware, and the sometimes need to do really processor-intensive operations makes offloading jobs to remote servers critical to the usefulness of mobile apps. There are multiple ways to connect to remote servers - sockets come in many forms – but services running over HTTP have become one of the most ubiquitous and useful for high-level applications.

As a moderator in the MSDN forums, I’ve had many requests for instructions on how to instantiate, call, and authenticate to web service methods from within Windows Store apps, and with the recent joining of Windows Phone development to the Windows Store Solutions team, from Windows Phone 8 applications. This blog posts covers how to use an ASMX web service from within your mobile app.

ASMX Web Services

ASMX web services have been around a long time and are widely used. They rely on SOAP structures (an XML-based series of messages) to pass information back and forth between client and server over HTTP.  The creation of these SOAP structures and the method calls which make them can be complex to write manually, but luckily for us, every version of Visual Studio since .NET was released supports automatic creation of the class proxies necessary to make a call to the methods within the Web Service as easy as making a call to a method created within our own project.  It’s a simple few steps to create a reference to an ASMX web service.  This procedure is the same for both Store projects and Phone projects:

 

1) From within your Solution Explorer of your project, right-click on “Service References”, then click on “Add Service Reference”:

 

image

2) The dialog box which appears allows you to put in the URL of your web service.   Enter it, then press the “Go” Button”:

 

image

3) You can see that the name of the web service appears in the Services pane.  Give your webservice a namespace (anything you like) that will be used to refer to it from within your project.  Press the OK button.  That namespace will now appear in the list of Service References.  As you can see from the list below, I have two namespaces for my project, for each of the two separate ASMX web services I will be demonstrating in this post.

 

image

 

 

Consuming an ASMX Web Service using Anonymous Authentication from a Windows Store Application

A web service is considered to have anonymous authentication if no specific permission is required to access it. The server is allowed to fulfill every request without regard to the entity who is requesting the information.  This is the case for many web services on the internet. 

For reference, this is the source code for the method which I will be calling from my Store application:

  1: [WebMethod]
  2: public List<string> GetStrings(int StartNumber, int EndNumber)
  3: {
  4:      List<string> MyList = new List<string>();
  5:      for (int i = StartNumber; i <= EndNumber; i++)
  6:      {
  7:           MyList.Add("AuthASMXService String #" + i.ToString());
  8:      }
  9:      return MyList;
  10: }

… and here’s the code that will call the method in the web service instantiated above:

  1: private async void ASMXWebServiceInvoke_Click_1(object sender, RoutedEventArgs e)
  2: {
  3:     ASMXWebServiceReference.WebService1SoapClient MyASMXWebServiceClient 
          = new ASMXWebServiceReference.WebService1SoapClient();
  4:     ASMXWebServiceReference.GetStringsResponse MyStringsResponse = await 
           MyASMXWebServiceClient.GetStringsAsync(10, 20);
  5:     ASMXWebServiceReference.ArrayOfString MyStrings = 
          MyStringsResponse.Body.GetStringsResult;
  6:     ASMXGridView.ItemsSource = MyStrings;
  7: }

 

 

Let’s break this down, line-by-line (lines 3 through 6):

  • First, we must instantiate an object from the webservice namespace

  • From the instantiated webservice object, we call the GetStrings method asynchronously, passing the parameters that our webservice expects.  We receive a response, but it is not the return type from the webservice.  It is composed of all of he information that would be available from a network call, as well as our expected response.

  • We instantiate an object (MyStrings) to hold the expected response, and then assign that to the actual response.

  • Finally, we can use the response in our gridview.  This is what my populated gridview looks like:

    image

 

 

Consuming an ASMX Web Service using Windows Authentication from a Windows Store Application

Many webservices, particularly those part of Line-Of-Business applications, require security for their web services.  To access these web services, it requires that we pass credentials to the web service.  Here’s the code for this process:

 1:  private async void AuthASMXWebServiceInvoke_Click_1(object sender, RoutedEventArgs e)
  2:         {
  3:             bool ShowError = false;
  4:             System.Exception MyException = new Exception();
  5:             try
  6:             {
  7:  
  8:                 System.ServiceModel.BasicHttpBinding MyHttpBinding = 
                      new System.ServiceModel.BasicHttpBinding(
                       System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly);
  9:                 MyHttpBinding.Security.Transport.ClientCredentialType = 
                      System.ServiceModel.HttpClientCredentialType.Windows;
  10:  
  11:                 System.ServiceModel.EndpointAddress MyAuthASMXWebServiceAddress = 
                       new System.ServiceModel.EndpointAddress(new Uri(
                       "https://localhost/AuthWebService2.asmx"));
  12:                 AuthASMXWebServiceReference2.AuthWebService2SoapClient 
                       MyAuthWebServiceClient = new AuthASMXWebServiceReference2.
                       AuthWebService2SoapClient(MyHttpBinding, MyAuthASMXWebServiceAddress);
  13:                 MyAuthWebServiceClient.ClientCredentials.Windows.ClientCredential.Domain 
                       = "localhost";
  14:                 MyAuthWebServiceClient.ClientCredentials.Windows.ClientCredential.UserName
                       = "SpecialUser";
  15:                 MyAuthWebServiceClient.ClientCredentials.Windows.ClientCredential.Password
                       = "Password123";
  16:  
  17:                 AuthASMXWebServiceReference2.GetStringsResponse MyStringsResponse = 
                       await MyAuthWebServiceClient.GetStringsAsync(20, 30);
  18:                 AuthASMXWebServiceReference2.ArrayOfString MyStrings = 
                       MyStringsResponse.Body.GetStringsResult;
  19:                 AuthASMXGridView.ItemsSource = MyStrings;
  20:  
  21:             }
  22:             catch (Exception ex)
  23:             {
  24:                 ShowError = true;
  25:                 MyException = ex;
  26:             }
  27:             if (ShowError)
  28:             {
  29:                 var MyMessageBox = new Windows.UI.Popups.MessageDialog(MyException.Message);
  30:                 await MyMessageBox.ShowAsync();
  31:             }
  32:         }

 

  1:  private async void AuthASMXWebServiceInvoke_Click_1(object sender, RoutedEventArgs e)
  2:         {
  3:             bool ShowError = false;
  4:             System.Exception MyException = new Exception();
  5:             try
  6:             {
  7:  
  8:                 System.ServiceModel.BasicHttpBinding MyHttpBinding = new 
                      System.ServiceModel.BasicHttpBinding
                      (System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly);
  9:                 MyHttpBinding.Security.Transport.ClientCredentialType = 
                      System.ServiceModel.HttpClientCredentialType.Windows;
  10:  
  11:                 System.ServiceModel.EndpointAddress MyAuthASMXWebServiceAddress = new 
                       System.ServiceModel.EndpointAddress(new Uri(
                       "https://localhost/AuthWebService2.asmx"));
  12:                 AuthASMXWebServiceReference2.AuthWebService2SoapClient
                       MyAuthWebServiceClient = new AuthASMXWebServiceReference2.
                       AuthWebService2SoapClient(MyHttpBinding, MyAuthASMXWebServiceAddress);
  13:                 MyAuthWebServiceClient.ClientCredentials.Windows.ClientCredential.Domain 
                       = "localhost";
  14:                 MyAuthWebServiceClient.ClientCredentials.Windows.ClientCredential.UserName 
                        = "SpecialUser";
  15:                 MyAuthWebServiceClient.ClientCredentials.Windows.ClientCredential.Password 
                       = "Password123";
  16:  
  17:                 AuthASMXWebServiceReference2.GetStringsResponse MyStringsResponse 
                       = await MyAuthWebServiceClient.GetStringsAsync(20, 30);
  18:                 AuthASMXWebServiceReference2.ArrayOfString MyStrings
                       = MyStringsResponse.Body.GetStringsResult;
  19:                 AuthASMXGridView.ItemsSource = MyStrings;
  20:  
  21:             }
  22:             catch (Exception ex)
  23:             {
  24:                 ShowError = true;
  25:                 MyException = ex;
  26:             }
  27:             if (ShowError)
  28:             {
  29:                 var MyMessageBox = new Windows.UI.Popups.MessageDialog(MyException.Message);
  30:                 await MyMessageBox.ShowAsync();
  31:             }
  32:         }

 

This method contains an exception handling routine which will capture any failures while communicating with the web service.  For example, if I change the password to an incorrect value and attempt to authenticate, I will see this on my screen:

image

 

 

The main difference between this code and the anonymous code is that we have to give the credentials to the calling code.

  • Line 8 instantiates an HTTP binding object which will allow us to specify the type of authentication method which will be used.  Also, the constructor takes a parameter which tells the binding that it’s ok to not use SSL, but to send the credentials unsecured.  It is possible to change this so that SSL is required for the passing of this credential.
  • Line 9 sets the authentication type to Windows, also known as Negotiate.  Other valid types include Basic, NTLM, Client Certificates, and Digest.
  • When passing credentials, it’s important to know where they are going – after all, these are resources which can be used to gain access to secured information.  Line 11 lets us set the endpoint destination to our web service URL.
  • When instantiating the web service object this time, we will pass in the HTTPBinding object and the Endpoint.  This changes the object so it knows to use Windows Authentication when communicating with the web service itself.
  • Finally, lines 13, 14 and 15 are where we set the domain, username and password necessary to gain access to the web service.

The rest of the web service call is the same as an anonymous call.  This is my working web service call:

image

 

Conclusion
Accessing web services is an incredibly important part of programming mobile services. I hope that the code presented is useful to you and helps you when designing your application. Please feel free to leave questions in the comments below. 

Also, please follow us on Twitter @WSDevSol!