system.net.webexception:error on the remote server: (400) bad request

457 Views Asked by At

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.

1

There are 1 best solutions below

1
Ding Peng On BEST ANSWER

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