views:

41

answers:

1

I am new to Web services and .NET. I have to authenticate a web service that is being accessed using http post.

I tried putting a custom soap header and sending it to the service and checking the header in service but the header object is always null in the service.

also if i put the user and password options in http headers how can i validate them on the server ?

Thanks in advance

Client code:

 private void button1_Click(object sender, EventArgs e)
        {
           HttpWebRequest request;

           string strSOAPRequestBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
           "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt;"+
           "<soap:Header>"+
           "<AuthHeader xmlns=\"http://tempuri.org/\"&gt;" +
           "<Username>apple</Username>"+
           "<Password>apple</Password>"+
           "</AuthHeader>"+
           "</soap:Header>"+
           "<soap:Body xmlns=\"http://tempuri.org/\"&gt;"+
           "<HelloWorld>"+
           "</soap:Body>"+
           "</soap:Envelope>";

           request = (HttpWebRequest)WebRequest.Create("http://localhost:1494/Service1.asmx/HelloWorld");
           request.Accept = "text/xml";
           request.Method = "POST";
           request.ContentType = "application/soap+xml; charset=utf-8";
           request.ContentLength = strSOAPRequestBody.Length;


           using (Stream stream = request.GetRequestStream())
           {
               using (StreamWriter sw = new StreamWriter(stream))
               {
                   sw.Write(strSOAPRequestBody);
                   sw.Flush();
               }
           }
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
           {
               using (StreamReader responseStream = new StreamReader(response.GetResponseStream()))
               {
                  txtResponse.Text = System.Web.HttpUtility.HtmlDecode(responseStream.ReadToEnd());
               }
           }
        } 

Service

public class Service1 : System.Web.Services.WebService
    {


        public AuthHeader Authentication;

        [WebMethod]
        [SoapHeader("Authentication", Direction = SoapHeaderDirection.In)]
         public XmlDocument HelloWorld()
        {
            XmlDocument response = new XmlDocument();
            try
            {

                //Boolean validateUser = Membership.ValidateUser(Authentication.Username, Authentication.Password);
                if (Authentication != null)
                {
                    response.LoadXml(String.Format("{0}{1}{2}", "<BOM>", "Hurray", "</BOM>"));
                }

            }
            catch( Exception ex)
            {
                response.LoadXml(String.Format("{0}{1}{2}", "<Error>", ex.Message, "</Error>"));
            }
                return response;
        }
    }
A: 

The problem is with the client code:

  • Set the URI to the service URI (i.e. the asmx file)
  • Add the soap action as a header (i.e. HelloWorld)
  • Set the content type as text/xml
  • Change the soap request to include the namespace on the soap method and not the body element

Try this:

HttpWebRequest request;

string strSOAPRequestBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt;" +
"  <soap:Header>" +
"    <AuthHeader xmlns=\"http://tempuri.org/\"&gt;" +
"      <Username>string</Username>" +
"      <Password>string</Password>" +
"    </AuthHeader>" +
"  </soap:Header>" +
"  <soap:Body>" +
"    <HelloWorld xmlns=\"http://tempuri.org/\" />" +
"  </soap:Body>" +
"</soap:Envelope>";

request = (HttpWebRequest)WebRequest.Create("http://localhost:1494/Service1.asmx");
request.Accept = "text/xml";
request.Method = "POST";
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Headers.Add("SOAPAction", "\"http://tempuri.org/HelloWorld\"");    
request.ContentLength = strSOAPRequestBody.Length;

using (Stream stream = request.GetRequestStream())
{
    using (StreamWriter sw = new StreamWriter(stream))
    {
        sw.Write(strSOAPRequestBody);
        sw.Flush();
    }
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
    using (StreamReader responseStream = new StreamReader(response.GetResponseStream()))
    {
        Console.WriteLine((responseStream.ReadToEnd()));
    }
}

If you do that you should receive the response:

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3
.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;&lt;soap:Body&gt;&lt;HelloWorldResponse xmlns="http://tempuri.org/
"><HelloWorldResult><BOM xmlns="">Hurray</BOM></HelloWorldResult></HelloWorldResponse></soap:Body></soap:Envelope>

To validate the username and password would depend on your implementation -- if you have asp.net membership then you should be able to use the ValidateUser method. Also note that if you are not using SSL then the username and password will be visible when sent over the wire.

Tuzo
Andreas Paulsson
@Andreas Paulsson, good article. I agree. Hand crafting XML is not the way to go for a production implementation -- at the very least use the XML framework classes.
Tuzo
Thank you all I will avoid XML in string. Thanks Tuzo.
akash