WCF XmlSerialization Attribute(POST) - c#

I currently have a WCF service to consume a remote REST service with the following:
[ServiceContract]
[XmlSerializerFormat]
public interface IMyApi
{
[OperationContract]
[WebGet(
ResponseFormat = WebMessage.Xml,
UriTemplate = "RemoteServicePage.jsp")]
MyNewClass Send();
}
The nice part about this is the XmlSerializerFormat attribute. Automatically deserializes a response into the return type of the method(ie, POX response => MyNewClass).
I've been unsuccessful, however, in finding any samples of the reverse. I'd like to post a POX request to a given service. I'm curious if there's a similar way to pass an object to a WCF service which in turn makes the post request to the target.
Any thoughts are greatly appreciated.
UPDATE
Just a clarification of the question:
Is it possible to post an object to a web service via WCF(which handles the serialization)?
UPDATE
I believe Steve touched on what I believe is the right direction below with using the WebInvoke method and attribute RequestFormat to achieve what I'm looking for. I guess I want to point out I'm not hosting a web service that allows for posting, but rather trying to post to an external web service(ie, a remote *.jsp) using WCF.
WCF allows for easy consumption and access of external web services and this is something I'm familiar with. I've never attempted to post a stream or object to an external source however(posting via UriTemplate is straightforward).

I don't understand. Why not just use HttpWebRequest? One of the benefits of doing REST over HTTP is that you get to use standard HTTP libraries. Doing a POST with HttpWebRequest is relatively trivial. Why do you need WCF? If you want to serialize an object into your POST body, then you can do that with either the DataContractSerializer or with the XmlSerializer.
If you really don't like that option, then look at the new Microsoft.Http.HttpClient class that is in the WCF Rest Starter Kit Preview 2. It is a very nice client library and despite its name and packaging, it does not even have a dependency on WCF!
This answer is based on your second update. I only say this because your initial statement of "I currently have a WCF service to consume a remote REST service" makes no sense. You cannot declaratively define a remote interface that you want to consume. The term WebInvoke is not what you are thinking, it is simply a catch all attribute for handing non GET requests. WebGet and WebInvoke both handing incoming requests.
If you want to consume a remote "REST" interface then you need to use HttpWebRequest or the new HttpClient class.

I don't think you understand the meaning of XmlSerializerFormat. It means that the XML Serializer should be used instead of the Data Contract Serializer. Both will serialize to XML.

Use the RequestFormat attribute. For JSON, this would be
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
Good luck

Related

Webservice expecting JSON, sending multipart-form data

I am trying to make the upload of files in a asyncronous way. I am currently using jquery.form plugin and using the ajaxSubmit method. Backend consists of getting this uploaded document and insert it into a document library. No problems in that part. Now when I try to do an upload, I get a 404 bad request error. The webservice expects JSON from a request. I noticed that this isn't the case, as in the request payload I get something like the following.
Content-Disposition: form-data; name="file"; filename="Json45r11 (1).zip"
Whic isn't a JSON, so I think this is why I get a bad request.
Webservice definition of backend method is like this:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest , ResponseFormat = WebMessageFormat.Json)]
SuccessUpload uploadDoc(string id);
Front end submit looks like this:
$('#form').ajaxSubmit({url: 'backend Method', type: 'post',data: JSON.stringify({id:1})});
Is there a workaround all this? Any help is appreciated, sorry if bad english not native language.
The jQuery.form plugin uses multipart/form-data encoded request when uploading a file which a classic ASMX web service cannot understand. You could replace your web service with a generic ASHX handler (IHttpHandler) which would allow you to handle any request format. Or even better if you don't want to get as low-level as handlers you could use some of the new frameworks such as ASP.NET MVC, ASP.NET WEB API, WCF, ServiceStack, ... which all will happily handle multipart/form-data encoded requests.
Since the webservice expects a JSON, in the declaration of your method just put that it receives an object of type STREAM.
this should work:
[OperationContract]
SuccessUpload uploadDoc2(Stream data);

WCF Client does not follow contract UriTemplates

I have defined a function in the ServiceContract of my WCF service as followed:
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "/test")]
CommandResponse Test();
And on the other end, at the client app I added the WCF service via "Add service reference" in visual studio. When calling the service test function using:
var test = m_ServiceClient.Test();
I am getting an error saying:
Operation 'GetUser' of contract... specifies multiple request body parameters to be serialized ...
The GetUser() is an other function I have in the service contract (also a GET function but with parameters in the UriTemplate).
My guess is that the client is calling the function with it's parameters as it should but the request is going to the wrong UriTemplate (or with no template at all and it just jumps to some kind of default).
Any special instructions I have to follow to let the client know about the functions UriTemplates ?
I've search all over and could not find a single page that helps with this issue...
The WebInvoke/WebGet attributes are used when you expose your service via WebHttpBinding which is for consuming your WCF service in REST style. In order to access the method via SOAP add [OperationContract] attribute and expose a endpoint via basicHttpBinding.
If you would want to access the service in a REST style then you should use the HttpWebRequest class to create your request rather than adding a Add Service Reference.
For achieving both i.e accessing the service via SOAP and REST just add [OperationContract] along with the WebInvoke attribute and expose another endpoint element with basicHttpBinding
For the client to recognize the UriTemplates and pass each method to it's own Url in the format defined by the template I copied the ServiceContract Interface to the client and then created a channel to the service base url
WebChannelFactory<IServiceContract> cf = new WebChannelFactory<IServiceContract>(new Uri("http://...."));
var service = cf.CreateChannel();
The resulting 'service' is a usable interface that works directly with the web service.

How to POST JSON HTTP Request to RESTful API made by WCF

I am trying to make Android consume a simple WCF webservice made by my self. Here is my WCF Service definition:
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/UploadCallLog2")]
[OperationContract]
String UploadCallLog2(String number, String cached_name, String duration, String date, String line_number);
I have two questions:
1. And what should my HTTP Request Look Like? What kind of Content type should I choose when add the request header?
2. Is there the correct way to put input param in body as JSON and the webservice can auto detect the value of input parameters?
Fred
I would suggest using an MVC project for this over a WCF service.
The controller can return a JsonResult, the MVC library contains Json helper methods to serialize and deserialize the json objects into c# objects if the properties match.
Also this then allows the MVC based service to be called from any client that has support for XmlHttpRequest using ContentType as "application/json". You can use either HttpGet or HttpPost depending on your request type and security of data under SSL as well. You can also take advantage of the authentication model to secure your methods.
This just makes for a really clean implementation that doesn't have any complex server and client configurations. More information regarding similar approaches is the new Web API in MVC 4.

how to send an object from RESTful client to WCF RESTful server using C#

I am trying to send data from my RESTful client to my RESTful server. How do I pass an object which contains string, int, byte[], etc. using c# web/desktop client. I need help for client side implementation. Please guide me.
My server code like:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "")]
void GetObject(Object obj);
You may have to use KnownTypeAttribute to specify what types that obj may be, so that the WCF DataContractSerializer can work.

Make a single WCF service support both SOAP, REST and WSDL

I'm trying to build a C# service in .NET 3.5 that supports both SOAP - and shows the WSDL - and REST.
The SOAP service and WSDL generation was easy enough to do using the ServiceHost and a BasicHttpBinding classes. Got that working and the client was happy.
Because the SOAP calls all used simple parameters, the client developers requested a REST interface for some of the commands. So I changed the ServiceHost class to a WebServiceHost, added necessary WebInvoke and WebGet attributes, added a WebHttpBinding class, and bingo - REST and SOAP were both working out of one service. Way cool, change one interface and both REST and SOAP got the new stuff.
But one problem - the WSDL no longer gets generated. I couldn't browse to http://server/service?wsdl and get the WSDL file. Checking the MSDN docs, that appears to be behavior for a default WebServiceHost.
Question: can I override this behavior so that the WSDL could be obtained? Doesn't have to the same URL as before - it can change - but I just need to have some URL into service to get the WSDL for those SOAP developers.
When you say "added a WebHttpBinding class", it sounds like you are doing a lot of the configuration in code as opposed to in configuration files.
If this is the case, you could try moving the configuration to the configuration file. Then create 2 endpoints for the contract one REST and one SOAP, with 2 different addresses and bindings.
But one problem - the WSDL no longer
gets generated. I couldn't browse to
http://server/service?wsdl and get the
WSDL file. Checking the MSDN docs,
that appears to be behavior for a
default WebServiceHost.
Yes - that's one of the drawbacks of REST - no more WSDL, no more machine-readable service description. You need to hope the service provider gives you a usable and up to date documentation on what you can do.
There's no WSDL for REST - period. Can't be turned on or anything - it just doesn't exist.
There are some efforts under way to provide something similar - called WADL (Web Application Description Language), but as far as I know, it's still far from an established standard by any means. Also see: Do we need WADL?
Circa, 2007, WSDL v2.0 is supposed to be able to describe RESTful services. I have found that with WCF in .Net v4.0, that the WDSL generated from a purely RESTful service is invalid (WSDL v1.0?).
I created a similar project that exposes both SOAP and RESTful endpoints, and enabled this by, as you did, modifying the interface as such:
// Get all Categories - complex object response
[OperationContract] // categories
[WebGet(BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "GetAllCategories")]
CategoryCollection GetAllCategories(); // SubSonic object
[OperationContract] // categories - respond with a JSON object
[WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "GetAllCategories.JSON")]
CategoryCollection GetAllCategoriesJSON(); // SubSonic object
One caveat to this is that all input parameters now must be of type string for all SOAP requests.
Any way of getting around this?

Categories