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"%>