I have a simple resftul wcf service. The .svc file looks like this
<%# ServiceHost Service="NameSpace.RestfulService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
The interface method declaration
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "test2", RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
List<MyObj> Test2(MyObj test);
Method implementation
public List<MyObj> Test2(MyObj test)
{
return new List<MyObj>() { new MyObj() { MyObjId = "1", RowVersion = 1 }, new MyObj() { MyObj= "2", RowVersion = 2 } };
}
Method on a wpf client to call the service
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(MyObj));
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, new MyObj() { MyObjId = "A", RowVersion = 1 });
string jason = Encoding.Default.GetString(ms.ToArray());
//get a handle to the request stream to write data to it
WebRequest myRequest = WebRequest.Create("http://localhost/MyService.svc/test2");
myRequest.Method = "POST";
myRequest.ContentType = "application/jason; charset=utf-8";
StreamWriter sw = new StreamWriter(myRequest.GetRequestStream());
sw.Write(jason);
sw.Close();
//get a handle to the response stream from the server to read the response
WebResponse myResponse = myRequest.GetResponse();
DataContractJsonSerializer RecData = new DataContractJsonSerializer(typeof(List<MyObj>));
var result = (List<MyObj>)RecData.ReadObject(myResponse.GetResponseStream());
When I try to get the RequestStream "myRequest.GetRequestStream()" it says bad request error 400.
Any idea what might be causing this error?
Thanks
Your content type is "application/jason; charset=utf-8". JSON's MIME-type is "application/json" (no 'a'). This is my likely why it 400's when you send the initial headers (which is done when you call GetRequestStream) because the WCF service doesn't recognize the content-type and immediately rejects the request.
Related
I'm trying to send some data to wcf server using restsharp and xamarine and get return value.Here's code on server side:
public interface IRestService
{
[OperationContract(Name = "Login")]
[WebInvoke(UriTemplate = "/Login/", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json,RequestFormat = WebMessageFormat.Json)]
Boolean Login(String username);
and implementation of Login:
Boolean IRestService.Login(string username)
{
if (string.IsNullOrEmpty(username))
return false;
else
return true;
}
here is how i'm trying to make connection on client side:
var client = new RestClient("http://192.168.0.187:9226/RestService.svc");
client.AddDefaultHeader("ContentType", "application/json");
var request = new RestRequest(String.Format("/Login/", "198440"));
request.Method = Method.POST;
request.AddParameter("username", "blabla");
request.RequestFormat = DataFormat.Json;
IRestResponse response1 = client.Execute<Boolean>(request);
When I'm tracing my wcf, i keep getting "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'."
Any help?
You should not use AddParamater. This create a form encoded body for the POST
instead:
request.RequestFormat = DataFormat.Json;
request.AddBody(new { "username" = "blabla"}));
I have developed a REST WCF service method as following:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Details")]
DetailData GetDetails(TestData requst);
[DataContract]
public class TestData
{
[DataMember]
public string DetailData { get; set; }
}
Now I am trying to invoke the service using following client code:
ASCIIEncoding encoding = new ASCIIEncoding();
string testXml = "<TestData>" +
"<DetailData>" +
"4000" +
"</DetailData>" +
"</TestData>";
string postData = testXml.ToString();
byte[] data = encoding.GetBytes(postData);
string url = "http://localhost/WCFRestService.svc/bh/Details";
string strResult = string.Empty;
// declare httpwebrequet wrt url defined above
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
// set method as post
webrequest.Method = "POST";
// set content type
webrequest.ContentType = "text/xml";
// set content length
webrequest.ContentLength = data.Length;
// get stream data out of webrequest object
Stream newStream = webrequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
//Gets the response
WebResponse response = webrequest.GetResponse();
//Writes the Response
Stream responseStream = response.GetResponseStream();
StreamReader sr = new StreamReader(responseStream);
string s = sr.ReadToEnd();
I am getting the following error :
"The remote server returned an error: (400) Bad Request"
I could successfully call another service method where "GET" verb is being used. But the above client code for invoking the service using "POST" verb is not working. I think, I am missing something in Client code.
What could be the problem?
Try changing
WebMessageBodyStyle.WrappedRequest
to
WebMessageBodyStyle.Bare
Have created a Restful WCF service with webHTTPBinding
While consuming the service in my client application, am facing with this error
The remote server returned an error: (400) Bad Request. (Have already tried solution like setting maxReceivedMessageSize and others mentioned online)
Scenario :
2 methods in client side
1) Working fine ** GET request**
private static void GenerateGETRequest()
{
HttpWebRequest GETRequest = (HttpWebRequest)WebRequest.Create(url);
GETRequest.Method = "GET";
GETRequest.ContentType = "application/json";
Console.WriteLine("Sending GET Request");
HttpWebResponse GETResponse = (HttpWebResponse)GETRequest.GetResponse();
Stream GETResponseStream = GETResponse.GetResponseStream();
StreamReader sr = new StreamReader(GETResponseStream);
Console.WriteLine("Response from Restful Service");
Console.WriteLine(sr.ReadToEnd());
}
2) Exception ****** (PUT request with response)**
private static void GeneratePUTRequest()
{
byte[] dataByte = CreateJSONObject(Object); //this custom method converts object that I pass to JSON serialized object
HttpWebRequest PUTRequest = (HttpWebRequest)HttpWebRequest.Create(Url);
PUTRequest.Method = "PUT";
**//PUTRequest.ContentType = "application/json"; //error 400 when un-commenting this**
PUTRequest.ContentLength = dataByte.Length;
Stream PUTRequestStream = PUTRequest.GetRequestStream();
PUTRequestStream.Write(dataByte, 0, dataByte.Length);
**HttpWebResponse PUTResponse = (HttpWebResponse)PUTRequest.GetResponse(); // this is where i get the exception when un-commenting above line**
Stream PUTResponseStream = PUTResponse.GetResponseStream();
StreamReader sr = new StreamReader(PUTResponseStream);
Console.WriteLine("Response from Restful Service");
Console.WriteLine(sr.ReadToEnd());
}
2 method throws the xception when i un-comment the line mentioned in the comment (in code). The place where exception is thrown is also mentioned in the comment (in code above).
The second method works fine with desired output (if i comment the mentioned line).
Additional resource
[OperationContract]
[WebInvoke(Method = "PUT",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "Controller")]
In order to send data through a POST or PUT, you need to construct your data correctly according to the WCF service. Here is basically what you need (Just change the POST to PUT for your application)
1) WCF Service Interface
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "GetData",
RequestFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Bare)]
string GetData(DataRequest parameter);
2) WCF Service Implementation
public string GetData(DataRequest parameter)
{
//Do stuff
return "your data here";
}
3) Data Contract in your WCF service (In this case it's DataRequest)
[DataContract(Namespace = "YourNamespaceHere")]
public class DataRequest
{
[DataMember]
public string ID{ get; set; }
[DataMember]
public string Data{ get; set; }
}
4) Client sending the data must have the data constructed properly! (C# console app in this case)
static void Main(string[] args)
{
ASCIIEncoding encoding = new ASCIIEncoding();
string SampleXml = "<DataRequest xmlns=\"YourNamespaceHere\">" +
"<ID>" +
yourIDVariable +
"</ID>" +
"<Data>" +
yourDataVariable +
"</Data>" +
"</DataRequest>";
string postData = SampleXml.ToString();
byte[] data = encoding.GetBytes(postData);
string url = "http://localhost:62810/MyService.svc/GetData";
string strResult = string.Empty;
// declare httpwebrequet wrt url defined above
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
// set method as post
webrequest.Method = "POST";
// set content type
webrequest.ContentType = "application/xml";
// set content length
webrequest.ContentLength = data.Length;
// get stream data out of webrequest object
Stream newStream = webrequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
//Gets the response
WebResponse response = webrequest.GetResponse();
//Writes the Response
Stream responseStream = response.GetResponseStream();
StreamReader sr = new StreamReader(responseStream);
string s = sr.ReadToEnd();
return s;
}
[WebInvoke(Method="POST",UriTemplate="/Users",RequestFormat=WebMessageFormat.Json)]
public string StudentUsers(Student user)
{
return string.Format("Hello {0}", user.Name);
}
Above code is my REST service. And my client code is :
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
Student user =
new Stuent {
Name="Test User",
Email = "test#test.com",
Password = "test"
};
DataContractJsonSerializer ser = new DataContractJsonSerializer(user.GetType());
MemoryStream ms = new MemoryStream();
ser.WriteObject(ms, user);
String json = Encoding.UTF8.GetString(ms.ToArray());
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(json);
writer.Close();
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
My service is hosted and I'm using webHttpBinding. When I debug my REST service I'm receiving null in Student object. I am sure that my post method is sending data as I test it by taking Name, Email and Password as parameters at REST service so my data is posted successfully but the thing is my Json data which is posted is not getting converted to Student object. I read somewhere that RESTfull Service will convert that Json data to object. Is that true or we need to convert it explicitly?
You need to sent the Content-Length for your POST-ed data:
request.ContentLength = ms.Length;
see here for more details:
I have fixed the issue by changing WebInvoke to
[WebInvoke(Method="POST",UriTemplate="/Users",RequestFormat=WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Bare)]
I have a WCF Service declared as follows:
[OperationContract, XmlSerializerFormat]
[WebInvoke(UriTemplate = "ProessUpload",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Xml)]
void ProcessUpload(ProductConfig stream);
I am trying to call this service using WebClient but I am always getting a response 400 (BadRequest) from the server. However if I use HttpWebRequest the WCF consumes my post and correctly responds with 200. I am also able to successfully construct a request using Fiddler to call the WCF Service.
WebClient Code
WebClient webClient = new WebClient();
webClient.Headers.Add("Content-Type", "application/xml");//; charset=utf-8
try
{
string result = webClient.UploadString("http://jeff-laptop/SalesAssist.ImageService/Process", "POST", data2);
}
catch (Exception ex)
{
var e = ex.InnerException;
}
HttpWebRequest code
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://jeff-laptop/SalesAssist.ImageService/Process");
request.ContentType = "application/xml";
request.Method = "POST";
request.KeepAlive = true;
using (Stream requestStream = request.GetRequestStream())
{
var bytes = Encoding.UTF8.GetBytes(data2);
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
}
var response = (HttpWebResponse)request.GetResponse();
var abc = new StreamReader(response.GetResponseStream()).ReadToEnd();
The XML that is being sent
var data2 = #"<Product><Sku>3327</Sku><NameProduct</Name><Category>Bumper</Category><Brand Id='3'><Collection>14</Collection></Brand></Product>";
Why is that HttpWebRequest works and WebClient doesn't? I can't see a real difference in the sent headers via Fiddler.
Try setting the Encoding property on the WebClient before you send the string. Since you aren't specifying it I suspect it defaults to ASCII. Quoting from the UploadString reference page.
Before uploading the string, this
method converts it to a Byte array
using the encoding specified in the
Encoding property. This method blocks
while the string is transmitted. To
send a string and continue executing
while waiting for the server's
response, use one of the
UploadStringAsync methods.
webClient.Encoding = Encoding.UTF8;