If I define a GET operation as follows:
[OperationContract]
[WebInvoke(UriTemplate = "/findcategories", Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
FindCategoriesResponse FindCategories(FindCategoriesRequest request);
but when I try this I get the exception:
Operation 'FindCategories' in contract 'IComplaintService' uses GET, but also has body parameter 'request'. GET operations cannot have a body. Either make the parameter 'request' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute.
Is there no way of accepting a JSON object as a parameter when doing GET request?
Thanks
Is there no way of accepting a JSON object as a parameter when doing GET request?
Nope. With a GET request you use query string parameters. If you want to send an entire JSON object you should use POST.
Related
i did search before posting this question and none of the answers helped me
i am hosting a WCF web service on IIS and using GET and POST in it successfully. the error is only showing when calling a POST web method with multiple param
Example:
**//this fails**
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "test", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
String test(String p, String credential);
**//this works**
[OperationContract]
[WebInvoke(Method = "POST",UriTemplate = "test")]
String test(String p);
the code behind simply returns a string for testing
I am receiving the following error:
The server encountered an error processing the request. The exception
message is 'Error in deserializing body of request message for
operation 'test'. The OperationFormatter could not deserialize any
information from the Message because the Message is empty (IsEmpty =
true)
i am testing the following web methods on POSTMAN
Parameters passed are random string:
p: tt
credetial: ghdhdj
WCF doesn’t support form-data by default, we merely pass the parameter by using the Wrapper element when we use Http_Post request.
As you mentioned, we should use the below code to wrap the multiple parameters.
[OperationContract]
[WebInvoke(BodyStyle =WebMessageBodyStyle.Wrapped)]
string GetData(string value,string value2);
And then we can pass the parameters with JSON format.
{"value":"ab","value2":"cd"}
Screenshot.
Feel free to let me know if the problem still exists.
I have a WCF Rest Service and an OperationContract defined in the following way:
[ServiceContract]
public interface IMyService {
[OperationContract]
[WebInvoke( Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "get/{filename}" )]
MyFileStructure GetFile( string filename );
}
The Server stores some files and the GetFile() retrieves some information from the specified file in the GET request and put them in a MyFileStructure instance which is then JSON parsed and returned back to the client.
E.g. the user can get data from the file named myfile.xml, just typing the following on the browser: http://localhost:[port]/MyService.svc/get/myfile
(the file extension is always ".xml").
This works fine.
The question:
I now need to customize this request a bit more, passing some parameters to my file request. Basically, each stored XML file contains a set of attributes, which can be different (in attribute names and size) from file to file. Please notice that a domain of these attributes does not exist. Each parameter in the request should refer to a specific attribute of the specified file, but since the attributes defined in the file are not known, I cannot use the following:
[OperationContract]
[WebInvoke( Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "get/{filename}?param1={param1}" )]
MyFileStructure GetFile( string filename );
I would like to be able to pass my parameter list in a standard GET request, e.g.:
http://localhost:[port]/MyService.svc/get/myfile?myparam1=value1&myparam2_value2&...
but, at the same time being able to receive that as a single string/whatever object on the server side, in order to process the parameters based on the selected file. Is that possible? How?
You can receive a json object with any parameters you want or a key value pair object, like a dictionary, as it follows:
MyFileStructure GetFile( string filename, [FromBody]IDictionary<string, string> params);
And in javascript:
var parms = {};
parms['param1'] = "one";
parms['param2'] = "two";
$.ajax({
url: '/api/GetFile?filename=' + filename,
data: JSON.stringify(parms),
contentType: 'application/json'
type: 'POST',
dataType: 'json'
});
Hope it helps.
From the question I didn't understand if it is critical to use only GET requests or not.
But if it is, one more options could be usage of http headers. You can pass any header you want from the client, do then a GET request and then access these header in your service using weboperationcontext.current.incomingrequest.headers.
You can check here if some header specified and run some specific code for it, otherwise check another header and so on.
And yes WebAPI, is a kind of symbiosis of WCF and ASP.NET which is preferably now for RESTful API development. But you can use headers there as well.
I think it is not a good idea to use GET Http verb for method which takes a multiple parameters as input data. In this case I would recommend to use POST Http Verb. Something like that:
[OperationContract]
[WebInvoke( Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = **WebMessageBodyStyle.WrappedRequest**,
UriTemplate = "/getFiles" )]
MyFileStructure GetFile( List<string> filenames );
It will be a little bit comfortable to use and it also has a serious advantages over sending data via Get request such as safety. If you will have a lot of parameters you may lost some of them because of max length of url (which equal to 2000 characters). Using post request you can avoid this problem
My best bet is use a post request to do it. You can use Stream as parameter in method and which will gain you to read and save file stream and other data also.
I created a new REST API which is a PUT method.
[OperationContract]
[WebInvoke(UriTemplate = "/Place/Info", Method = "PUT",
BodyStyle = WebMessageBodyStyle.Bare)]
Info SavePlaceInfo(Info inf);
I'm passing {} I'm expecting some error but getting 0 response.
What could be the reason.
I'm able to resolve the issue.
The issue was: Json serializer cannot serialize .Net DateTime.MinValue as its kind is of unsepecified.
I'm trying to consume my WCF webservice via an MVC Web Application. I add a service reference via the Add service reference dialogue in VS. Now when I try to call my proxy.LoginUser I get the error message:
Operation 'GetAlertNotification' of contract 'IService1' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped.
The only problem is there is no body parameters in GetAlertNotification?? If I understand correctly if I pass all parameters via the query string this should not be an issue? Here is the signature of GetAlertNotification in IService:
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/GetAlertNotification?project={project}¤tversion={currentversion}&EncryptData={EncryptData}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
AlertNotification GetAlertNotification(string project, string currentversion, bool EncryptData = false);
Edit:
I replaced WebInvoke by WebGet and still get the error message above. How can it say it has multiple request body parameters with everything specified in the UriTemplate? I'm I not understanding what the error is saying? Anynone?
Following up from the solution to the previous question I asked here. It seems I now have a problem where if I use a custom binding in my .NET4 web service, then my methods that implement the web service WebInvoke contracts are no longer getting called when they contain the argument of the request body Stream.
So here's code that runs the webservice as found from the the link above:
webserviceHost = new WebServiceHost(typeof(Service1), new Uri("http://localhost:8080));
webserviceHost.AddServiceEndpoint(typeof(IService), getBinding(), "webservice").Behaviors.Add(new WebHttpBehavior());
webserviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
webserviceHost.Open();
Here's the WebInvoke service contract defined:
[WebInvoke(UriTemplate = "import_data?param={value}", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
WebResult importOrder(string value, Stream httpRequestPostBody);
And here's the method implementing the above contract:
public WebResult importOrder(String value, Stream httpRequestPostBody)
{
doSomething(value, httpRequestPostBody);
}
So if I try making a HTTP request through Fiddler to the webservice endpoint contract it will return a connection reset HTTP error response. If I remove the Stream httpRequestPostBody argument then it will run the method, but I have no way to get access to the raw JSON data in the request body (I can get the body but its in an XML form). So I can only gather that I'm missing something in my custom binding to ensure that the body stream of the request can be passed. Anybody got any clues?
So the only answer I've been able to come up with is to remove the stream from the contract and then use .NET's DataContractJsonSerializer to convert the HTTP request body message from XML back to JSON. As shown below
Contract:
[WebInvoke(UriTemplate = "import_data?param={value}", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
WebResult importOrder(string value);
Implementation:
public WebResult importOrder(String value){
MyObject myObject = (MyObject)new DataContractJsonSerializer(typeof(MyObject)).ReadObject(OperationContext.Current.RequestContext.RequestMessage.GetReaderAtBodyContents());
doSomething(value, myObject);
}
This solution is not ideal since the message is being converted from RAW to JSON to XML to MyObject, and additionally does not allow me to easily use a better 3rd party JSON parser and control how my objects are being initialised from the incoming data.
If anyone has got a better solution I'm all ears.