How pass multiple body parameters in wcf rest using webinvoke method(Post or PUT) - wcf

I have written a REST Service in WCF in which I have created a method(PUT) to update a user. for this method I need to pass multiple body parameters
[WebInvoke(Method = "PUT", UriTemplate = "users/user",BodyStyle=WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
public bool UpdateUserAccount(User user,int friendUserID)
{
//do something
return restult;
}
Although I can pass an XML entity of user class if there is only one parameter. as following:
var myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
myRequest.Method = "PUT";
myRequest.ContentType = "application/xml";
byte[] data = Encoding.UTF8.GetBytes(postData);
myRequest.ContentLength = data.Length;
//add the data to be posted in the request stream
var requestStream = myRequest.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();
but how to pass another parameter(friendUserID) value?
Can anyone help me?

For all method types except GET only one parameter can be sent as the data item. So either move the parameter to querystring
[WebInvoke(Method = "PUT", UriTemplate = "users/user/{friendUserID}",BodyStyle=WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
public bool UpdateUserAccount(User user, int friendUserID)
{
//do something
return restult;
}
or add the parameter as node in the request data
<UpdateUserAccount xmlns="http://tempuri.org/">
<User>
...
</User>
<friendUserID>12345</friendUserID>
</UUpdateUserAccount>

Related

WCF client restsharp sending raw format

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

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

RestSharp post object to WCF

I am having an issue posting an object to my WCF REST Web Service.
On the WCF side I have the following:
[WebInvoke(UriTemplate = "", Method = "POST")]
public void Create(myObject object)
{
//save some stuff to the db
}
When I am debugging, the break point is never hit.However, the break point is hit when I remove the parameter.So, I am guessing I have done something wrong on the RestSharp side of things.
Here's my code for that part:
var client = new RestClient(ApiBaseUri);
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Xml;
request.AddBody(myObject);
var response = client.Execute(request);
Am I doing this wrong? How can the WCF side see my object? What way should I be making the request? Or should I be handling it differently on the WCF side?
Things that I have tried:
request.AddObject(myObject);
and
request.AddBody(request.XmlSerialise.serialise(myObject));
Any help and understanding in what could possibly be wrong would be much appreciated. Thanks.
I have been struggling with the same problem. Once you try to add the object to pass, it becomes a "Bad request". I tried a variety of things based on various sites I found and got nothing. Then I changed the format from Xml to Json, and it just started working. Must be some glitch with XML passing. Might need to setup a 2nd PC and try to sniff the actual http with something like wireshark or fiddler. (Or maybe I'll just stick to json)
Below is the function from my experimental WCF interface
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "manualselect", ResponseFormat = WebMessageFormat.Json)]
void PostManualSelect(ManualUpdateRequest S);
then my test RestSharp client
var client = new RestClient();
client.BaseUrl = "http://127.0.0.1:8000";
/* Initialization of ManualUpdateRequest instance "DR" here */
var request = new RestRequest(Method.POST);
request.Resource = "manualselect";
request.RequestFormat = DataFormat.Json;
request.AddBody(DR);
RestResponse response = client.Execute(request);
Perhaps someone can shed some more light on the matter. I am also new to REST services. I'd thought I'd add my findings to steer towards a better answer.
(--EDIT--)
I did some more digging and found this tidbit
So I added the [XmlSerializerFormat] attribute to ServiceContract interface like so
[ServiceContract]
[XmlSerializerFormat]
public interface IMyRestService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "manualselect", ResponseFormat = WebMessageFormat.Xml)]
void PostManualSelect(ManualUpdateRequest S);
}
and then this finally worked and I got an object in my service
var client = new RestClient();
client.BaseUrl = "http://127.0.0.1:8000";
/* Initialization of ManualUpdateRequest instance "DR" here */
var request = new RestRequest(Method.POST);
request.Resource = "manualselect";
request.RequestFormat = DataFormat.Xml;
request.AddBody(DR);
RestResponse response = client.Execute(request);
(--EDIT 2--) I have encountered some more XML serializing weirdness that lead me to make this extension (borrowing from here). Might help if you still have trouble. There is also an answer here that implies you need to use public properties to serialize correctly, which I have not tried yet.
public static class RestSharpExtensions
{
public static T GetXmlObject<T>(this IRestResponse response)
{
if (string.IsNullOrEmpty(response.Content))
{
return default(T);
}
XmlSerializer serializer = new XmlSerializer(typeof(T));
XmlReaderSettings settings = new XmlReaderSettings();
// No settings need modifying here
using (StringReader textReader = new StringReader(response.Content))
{
using (XmlReader xmlReader = XmlReader.Create(textReader, settings))
{
return (T)serializer.Deserialize(xmlReader);
}
}
}
public static void UseDotNetXml(this IRestRequest request)
{
request.RequestFormat = DataFormat.Xml;
request.XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer();
}
}
So my RestSharp calls start looking more like this
public SimpleSignUpdateDataSet GetSimpleDataset()
{
var client = new RestClient(SerivceURL);
var request = new RestRequest("simpledataset", Method.GET);
request.UseDotNetXml();
var resp = client.Execute(request);
return resp.GetXmlObject<SimpleSignUpdateDataSet>();
}
This answer is getting long, but I hope it is of some help to someone.
you can use fiddler on the same pc .... no need for a second one. If you install it, solving these types of problems gets really much easier, you see what you do!
Specify proxy like this:
using system.net; // for the WebProxy
RestClient rc = new RestClient(aUrl);
rc.Proxy = new WebProxy("http://127.0.0.1:8888");

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.