WCF client restsharp sending raw format - wcf

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"}));

Related

Webhook Subscription for Teams Conversation not working with WCF Relay

Can someone please help me to fix this Issue. I am not able to debug from where it is going wrong. Basically I have created a WCF Rest API WebService using WCF Relay in Azure to have hybrid connection between on-premise and Azure. Also if I am ignoring any certificate validation, that endpoint is for on-premise as it is self-signed certificate but when making API call, I am using the base64 encoded public key provided by WCF Relay when publishing it in Azure.
WCF Contract And Implementation:
Contract Interface
Implementation
I am successfully able to get the "validationToken" in the WCF service and also returning the same validationToken immediately below 5 seconds. After returning, it always error out showing this message.
Postman Client For Sending HTTP Request
Error Response and no subscription created
EDIT
WCF Contract
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "webhookForConservation?validationToken={validationToken}",
BodyStyle = WebMessageBodyStyle.Bare)]
string webhookForConservation(WebhookPayload data, string validationToken);
WCF Implementation:
1st approach to return 200 OK status code:
public string webhookForConservation(WebhookPayload data, string validationToken = "")
{
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "text/plain");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
HttpResponseMessage response = null;
WebOperationContext ctx = WebOperationContext.Current;
if (validationToken != null && validationToken != "")
{
response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription?validationToken=" + validationToken, null).Result;
var apiContent = response.Content.ReadAsStringAsync().Result;
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
ctx.OutgoingResponse.ContentType = "text/plain";
return apiContent;
}
else
{
StringContent strContent = new StringContent(DataContractJsonSerializerHelper.SerializeJson(data));
strContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription", strContent).Result;
}
var result = (response != null) ? response.Content.ReadAsStringAsync().Result : "";
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
return result;
}
2nd Approach to return 200 status code:
public WebFaultException<string> webhookForConservation(WebhookPayload data, string validationToken="")
{
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "text/plain");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
HttpResponseMessage response = null;
if (validationToken != null && validationToken != "")
{
response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription?validationToken=" + validationToken, null).Result;
var apiContent = response.Content.ReadAsStringAsync().Result;
return new WebFaultException<string>(apiContent, HttpStatusCode.OK);
}
else
{
StringContent strContent = new StringContent(DataContractJsonSerializerHelper.SerializeJson(data));
strContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription", strContent).Result;
}
var result = (response != null) ? response.Content.ReadAsStringAsync().Result : "";
return new WebFaultException<string>(result, HttpStatusCode.OK); ;
}
Same error seen after returning 200 OK response code from WCF Service
Calling Relay WCF API directly with Postman:
Headers:
Thank you in advance for all the help.
Two problems were preventing the WCF relay to work properly:
The relay wasn't setting the response content type to text/plain, this was fixed with ctx.OutgoingResponse.ContentType = "text/plain"
The relay was adding an XML wrapper to the required response body, this was addressed by changing the return value to Stream

POST request in REST WCF

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

Restful WCF with PUT operation when using JSON (server error 400)

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;
}

Call DELETE method of wcf restful service from client applicaiton

Here is how I try to call the DELETE method from my WCF service:
string tmpUrl1 = "http://localhost:1234/MyService.svc/EndPoint/MyMethod";
WebRequest request1 = WebRequest.Create(tmpUrl1);
request1.Method = "DELETE";
byte[] byteArray1 = Encoding.UTF8.GetBytes("{\"idName\":" + newIdName + "}");
request1.ContentType = "application/json";
request1.ContentLength = byteArray1.Length;
Stream dataStream1 = request1.GetRequestStream();
dataStream1.Write(byteArray1, 0, byteArray1.Length);
dataStream1.Close();
WebResponse response1 = request1.GetResponse();
But I get error 400.
Here is the method's name in the wcf:
[OperationContract]
[WebInvoke(
Method = "DELETE",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/MyMethod/{deleteRP}/",
BodyStyle = WebMessageBodyStyle.Bare
)]
MyClass MyMethod(string deleteRP);
Where am I making a mistake?
Try enabling Tracing on your service and inspect the trace log for the actual error. Also your url address should have something like
"http://localhost:1234/MyService.svc/EndPoint/MyMethod/55"
rather than
"http://localhost:1234/MyService.svc/EndPoint/MyMethod"
UPDATE:
private static byte[] ToByteArrayUsingDataContractSer<T>(T requestBody)
{
byte[] bytes = null;
var serializer1 = new DataContractSerializer(typeof(T));
var ms1 = new MemoryStream();
serializer1.WriteObject(ms1, requestBody);
ms1.Position = 0;
var reader = new StreamReader(ms1);
bytes = ms1.ToArray();
return bytes;
}
Now replace the following line
byte[] byteArray1 = Encoding.UTF8.GetBytes("{\"idName\":" + newIdName + "}");
with
byte[] array = ToByteArrayUsingDataContractSer<string>("{\"idName\":" + newIdName + "}");

Restful WCF bad request error

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.