2

I'm trying to learn how Android interacts with WCF (C#) service. I have gone through a lot of posts regarding the same, here at SO. However, I couldn't find a definite answer to the problem. Every body has posted their own approach and it is confusing me.

I have created a demo service which just returns the string "Hello World!!".

    public string HelloWorld()
    {
        return ("Hello World!");
    } 

I have defined the service contract as:

    [OperationContract]
    [XmlSerializerFormat(Style = OperationFormatStyle.Document, Use = OperationFormatUse.Literal)]
    [WebGet(BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Xml, 
        ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/GetMessage")]
    string HelloWorld();

The service is working fine on http://localhost:32444/Service1.svc.

Now, from Android I'm trying to consume the service with the following code.

public class MainActivity extends Activity {
    /**
     * Called when the activity is first created.
     */

    private final static String SERVICE_URI = "http://10.0.2.2:32444/Service1.svc";
    TextView textView;
    Button btnShow;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        textView = (TextView) findViewById(R.id.textView);
        btnShow = (Button) findViewById(R.id.btnShow);

        btnShow.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View arg0){

                try {

                    DefaultHttpClient httpClient = new DefaultHttpClient();
                    HttpGet request = new HttpGet(SERVICE_URI + "/GetMessage");

                    request.setHeader("Accept", "application/xml");
                    request.setHeader("Content-type", "application/xml");

                    HttpResponse response = httpClient.execute(request);

                    HttpEntity responseEntity = response.getEntity();
                    String output = EntityUtils.toString(responseEntity);

                    //Toast.makeText(getApplicationContext(), output, Toast.LENGTH_SHORT).show();
                    textView.setText(output);


                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                }
                }
        });
    }
}

The emulator shows no output. I checked using Toast message and the return is null.The error is due to "HTTP1.1/400 Bad Request", which I came across while debugging.

Can somebody please guide me with this? Also, if the approach/concept is wrong please point to me my mistake and provide an explanation.

Thanking all in advance!

From the WCF Service Library: Service1.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfServiceAndroid
{
    /* NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name 
     * "Service1" in both code and config file together.*/
    public class Service1 : IService1
    {
        public string HelloWorld()
        {
            return ("Hello World!");
        }

        //public string[] NumberWorld()
        //{
        //    string[] arr= {"1","2","3","4","5"};
        //    return arr;
        //}

        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

IService1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;

namespace WcfServiceAndroid
{
    /* NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name 
    "IService1" in both code and config file together.*/
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        //[WebGet(UriTemplate = "/GetMessage", BodyStyle = WebMessageBodyStyle.WrappedRequest,
          //      ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        [XmlSerializerFormat(Style = OperationFormatStyle.Document, Use = OperationFormatUse.Literal)]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Xml,
            Method = "GET", ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/GetMessage")]
        string HelloWorld();

        //[OperationContract]
        //string[] NumberWorld();

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: Add your service operations here
    }

    // Use a data contract as illustrated in the sample below to add composite types to service operations
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

App.config:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true"/>
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="NewBindingAndroid"/>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="WcfServiceAndroid.Service1">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration=""
          contract="WcfServiceAndroid.IService1">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://<domain>:<port>/WcfServiceAndroid/Android/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

From the Service application: Web.config:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>      

Service1.svc

<%@ ServiceHost Language="C#" Debug="true" Service="WcfServiceAndroid.Service1"%>
sreyan
  • 21
  • 1
  • 4

3 Answers3

0

Try accessing

http://localhost:32444/Service1.svc/GetMessage 

from browser and check whether it is working.

Eldhose M Babu
  • 14,382
  • 8
  • 39
  • 44
  • No, http://localhost:32444/Service1.svc/GetMessage doesn't work. What can I do about it? – sreyan Nov 26 '13 at 09:52
  • Since its a rest based service, you are supposed to get the result in browser right? Otherwise it might be a problem with your service. – Eldhose M Babu Nov 26 '13 at 11:16
  • Do you think you can help me out with that Eldhose? I updated the original post with the service/interface classes and the config files. Kindly check once. Thanks. – sreyan Nov 26 '13 at 11:30
  • Go through this tutorial in creating a Rest based WCF service. http://www.codeproject.com/Articles/571813/A-Beginners-Tutorial-on-Creating-WCF-REST-Services. It seems like problem with your service. – Eldhose M Babu Nov 26 '13 at 12:35
0

try to grub wsdl information and build client across generated classes. find tools like "svcutils" for java. Addditional you can make an error with connection setting and authentification.

llCorvinuSll
  • 242
  • 3
  • 12
0

instead of localhost you should use 10.0.2.2 . Because localhost is not your computer. It is your android emulator. And if you still can't connect, try to edit your iis config.

in your user Documents > IISExpress > applicationhost.config edit your wcf service projects binding information. it is something like this : bindingInformation=":21422:localhost" and you should delete localhost and should be something like this : bindingInformation=":21422:"

to be clear your connection address is http:// 10.0.2.2:port/svcfile/...

I hope it works

edit: you have to run visual studio with administrator privileges (Run as administrator)

TurKorsaN
  • 53
  • 1
  • 6