0

I've created a wcf webservice that has a login method. this is my code: IService1.cs

[ServiceContract]
    public interface IService1
    {
        [OperationContract]

        [WebInvoke( BodyStyle = WebMessageBodyStyle.Wrapped,ResponseFormat =WebMessageFormat.Xml, Method ="POST")]
        bool LoginUserDetails(string name, string pass);
    }

Service1.svc.cs

public class Service1 : IService1
    {
        public bool LoginUserDetails(string name, string pass)
        {
           
            SqlConnection con = new SqlConnection("server=DESKTOP-CPOJ94O\\MSSQLSERVER1;database=users;integrated security=true");
            con.Open();
            SqlCommand cmd = new SqlCommand("SELECT username, password FROM hjk where CONVERT(VARCHAR, username)=@username and CONVERT(VARCHAR, password)=@password", con);
            cmd.Parameters.AddWithValue("@username", name);
            cmd.Parameters.AddWithValue("@password", pass);
            bool result = false;
            SqlDataReader dr = cmd.ExecuteReader();
            if (dr.HasRows)
            {
                result = true;
                return result;
            }
            else
            {
                result = false;

            }
            return result;
        }
    }

web.config

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

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WcfService4.Service1" behaviorConfiguration="ServiceBehavior">
        <endpoint address="" binding="webHttpBinding" contract="WcfService4.IService1" behaviorConfiguration="web">
          
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="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="true"/>
        </behavior>
      </serviceBehaviors>
    <endpointBehaviors >
      <behavior name="web">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="webHttpBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

then I tried to consume this service in Xamarin.android app. in my main activity I wrote the following:

 EditText editText1 = FindViewById<EditText>(Resource.Id.editText1);
            EditText editText2 = FindViewById<EditText>(Resource.Id.editText2);
            TextView txtview = FindViewById<TextView>(Resource.Id.textView1);
            //System.IO.StreamWriter myWriter = null;
            string txt1 = editText1.Text;
            string txt2 = editText2.Text;
            Button btn = FindViewById<Button>(Resource.Id.button1);
           
            btn.Click += delegate { 
string myRequest = "name=rana&pass=ranahd";
                string myResponse = "";
                string myUrl = "http://192.168.0.104/wcf1/Service1.svc/LoginUserDetails";
                System.IO.StreamWriter myWriter = null;// it will open a http connection with provided url
                System.Net.HttpWebRequest objRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(myUrl);//send data using objxmlhttp object
                objRequest.Method = "PUT";
                //objRequest.ContentLength = TranRequest.Length;
                objRequest.ContentType = "text/xml";//to set content type
                myWriter = new System.IO.StreamWriter(objRequest.GetRequestStream());
                myWriter.Write(myRequest);//send data
                myWriter.Close();//closed the myWriter object
                try
                {
                    System.Net.HttpWebResponse objResponse = (System.Net.HttpWebResponse)objRequest.GetResponse();//receive the responce from objxmlhttp object 
                    using (System.IO.StreamReader sr = new System.IO.StreamReader(objResponse.GetResponseStream()))
                    {
                        myResponse = sr.ReadToEnd();
                    }

                    txtview.Text = myResponse;
                }
                catch(Exception exp)
                {
                    System.Net.WebException exception = new System.Net.WebException();
                    Toast.MakeText(this,exception.Message,ToastLength.Long).Show();
                }
            };

        }

I got the exception: system.net.webexception:error on the remote server: (400) bad request. and when I read the message in the toast it said: operation is not valid due to current state of the object. I did my research but I couldn't find what the problem was. what did I do wrong? thanks in advance.

rana hd
  • 355
  • 3
  • 18
  • Hi,has the problem been solved? – Ding Peng Aug 12 '20 at 07:45
  • @Dingpeng thanks a lot sir for being so helpful. the problem is that i'm working on multiple projects and i'm having a very hard time. i'm gonna try the code that you've updated. I would be grateful if you could bear with me. – rana hd Aug 12 '20 at 14:48

1 Answers1

0

Since the XML format has only one root and the JSON format has only one object, only one parameter can be passed to the method. In fact, if you changed a service contract to something like:

  [OperationContract]
  [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, Method = "POST")]
  bool LoginUserDetails(string name, string pass);

a service would throw a exception:

enter image description here

Changing WebMessageBodyStyle to wrapped is not the best way to solve this exception.

We should encapsulate username and password into a class:

[DataContract]
public class User {
    [DataMember]
    public string username { get; set; }
    [DataMember]
    public string pass { get; set; }
}

This is interface:

 [OperationContract]
 [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, Method = "POST")]
 bool LoginUserDetails(User user);

I suggest you enable the help document in WCF:

<webHttp helpEnabled="true"/>

enter image description here

Results

enter image description here

enter image description here

Feel free to let me know if the problem persists.

UPDATE

This is my demo:

 [OperationContract]

 [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, Method = "POST")]
 bool LoginUserDetails(User user);

This is the interface of the service.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8763/TEST/LoginUserDetails");
            request.Method = "POST";
            request.ContentType = "application/json;charset=UTF-8";
            string Json = "{\"pass\":\"123\",\"username\":\"sdd\"}";
            request.ContentLength = Encoding.UTF8.GetByteCount(Json);
            Stream myRequestStream = request.GetRequestStream();
            StreamWriter myStreamWriter = new StreamWriter(myRequestStream, Encoding.GetEncoding("gb2312"));
            myStreamWriter.Write(Json);
            myStreamWriter.Close();

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            Console.WriteLine(retString);
            Console.ReadKey();

This is the client's request.

enter image description here

Ding Peng
  • 3,702
  • 1
  • 5
  • 8
  • thanks a lot sir for your help. i edited my codes as you mentioned, but i don't know how is my request in Xamarin app supposed to be. the one that i'm supposed to put in my "mywriter.write". string myRequest = "name=rana&pass=ranahd" doesn't work anymore and i can't figure out what to write instead. – rana hd Aug 11 '20 at 12:26