I working on a REST service based on the 'WCF REST Service template' in VS2010. Out-of-the-box, you can have a service return XML or JSON, based on the Accept type specified in the request, but how do I add my own format....
I found an example:
http://msdn.microsoft.com/en-us/library/ee476510.aspx
where you test the Accept header in the method, and return Message based on that type, however I don't really like to implement this in all my service methods.
What I'd really like is a way where I could annotate (attribute) my DataContract with a formatter/serializer for each kind of Content-Type that I want to support, and then framework call my formatter/serialiser when asked for a Content-Type not supported out-of-the-box.
Are there already some extensionpoints, in the WCF REST Service framework, for doing this??
Any help would be greatly appreciated
TIA
Søren
WcfRestContrib should be able to do this via Formatters. It provides set of build in formatters for XML, JSON, URL encoded form posts and it also allows creating custom formatters.
Built in webHttpBinding in WCF doesn't have this functionality at the moment - it allows only appliation/json and text/xml negotiation and other content types can be mapped to these two via custom content type mapper.
"Attributes" for response formatting are only available for syndication where it works little bit differently. Service must always return SyndicationFeedFormatter and known types allow defining multiple derived formatters for Atom or Rss.
Related
My users enter a few information fields in an iOS app.
This information must be validated on my server, which has a RESTful API.
After validation the UI of the iOS app changes to indicate the result.
Neither GET, PUT, or POST seem to be appropriate, because I'm not getting a resource, and neither is a resource created or updated.
What is the best fitting REST operation to implement this validation?
I use the same scenario as you and use PUT for it. You have to ask yourself: "when I send the same request twice, does this make a different state on server?" If yes, use POST, if no use PUT.
My users enter a few information fields in a iOS app. This information
must be validated on my server, which has a RESTful API. After
validation the UI of the iOS app changes to indicate the result....I'm
not getting a resource, and neither is a resource created or updated.
Since you aren't saving anything (not modifying any resource), I'd think this is technically more RPC than RESTful to me.
The following is my opinion, so don't take it as gospel:
If the information is simply being submitted and you're saying yes or no, and you're not saving it, I'd say POST is fine..
If information were actually being saved / updated, then choosing the proper HTTP method would be a lot more relevant.
POST = CREATE / SUBMIT (in an RPC context)
PUT = UPDATE (or CREATE if there is nothing to UPDATE)
I recommend using a ValidationResource and two requests. Each instance of this resource represents the validation of a set of data. The workflow:
1. Create new ValidationResource
Request: POST /path/to/validations
data to validate as the body
Response: 201 Created
Location: /path/to/validations/<unique-id-of-this-validation>
2. Look up result
Request: GET /path/to/validations/<unique-id-of-this-validation>
Respons: 200 OK
body: {'valid': true} or {'valid': false}
This is a RESTful approach in which the Validation is a Resource with server state.
Google proposes use of Custom Methods for REST API
For custom methods, they should use the following generic HTTP
mapping:
https://service.name/v1/some/resource/name:customVerb
The reason to use : instead of / to separate the custom verb from the
resource name is to support arbitrary paths. For example, undelete a
file can map to POST /files/a/long/file/name:undelete
Source: https://cloud.google.com/apis/design/custom_methods
So for validation the URL should be POST /resource:validate
I believe it is similar to GET entity but since we need to send data to validate and sending confidential data in URL is wrong habit as only payload data is ciphered by TLS, the only way left is POST or PUT.
However you may save or update the data in validate(eg. "verified":false). Based on requirement, you can go for POST or PUT (recommended POST if no update)
POST /user/validate-something
It seems like you're not doing it the correct way, if the validation is at the server-side then it should happen while submitting the data using a POST method. Then you'll validate that data, if validation fails then you can raise a 400 BAD REQUEST error, else you can create the resource.
This approach is more RESTful, as the POST method is properly used to create a resource or to raise 400 if validation fails
I am writing a client for OpenTox webservices, but several services they provide have optional support for certain MIME types with only a few obligatory, e.g. this Dataset service. So I need to discover which of those content types are supported by a particular running service dynamically...
Now, for GET services I can use the "Accepts" HTTP header and when I POST content I can use "Content-type" to set what format I am sending in. But I rather not default into trial-and-error, as these data sets can be large. Therefore, I like to know up front the best MIME type I can use.
How do I perform content negotiation with POST services? I am using the Apache HttpClient, but that is not important for the answer.
POSTed Content negotiation is not enshrined in the HTTP specification; instead what is advisable is to use the OPTIONS method. This is exactly the case in the OpenTox framework: OPTIONS has to be implemented by all web services. The service returns an RDF document (according to the Accept Header you specify) and a WADL-like content, i.e. it returns machine-readable documentation specifying the available MIME types, the possible HTTP status codes etc. Unfortunately so far there's only one implementation of OPTIONS in OpenTox, namely JAQPOT3. Check out this wiki entry.
I am confused on one thing. As I have read web services use SOAP protocol for communication and it is an XML based protocol; I was expecting the classical HelloWorld method on an asp.net web service to return an xml based data.
But when I checked with Fiddler i see that the Response Textview has a JSON string instead of an XML structure like:
{"d":"Hello World"}
Does this mean that asp.net web-service implementation returns 'string' types embedded as a value of a property called 'd' ?
Web services don't have to use SOAP as the protocol. The WCF lets you use all sorts of protocols for your web services. SOAP and JSON are just 2 of the options.
ASMX services return JSON if you request them via POST, with a content-type containing application/json. More info here: http://encosia.com/2010/03/03/asmx-and-json-common-mistakes-and-misconceptions/
Their return value isn't limited to just strings either. If you return a collection type, you'll get a JSON array. If you return a server-side class, that will be serialized into the correct JSON key/value pairs to represent that object.
The .d is sort of an orthogonal issue. It's a security feature to thwart a particular attack against JavaScript's Array constructor. More here: http://encosia.com/2009/02/10/a-breaking-change-between-versions-of-aspnet-ajax/
Ok. I have found my answer, here:
"ASP.NET AJAX sends JSON messages to Web Services as opposed to the standard Simple Object Access Protocol (SOAP) calls typically associated with Web Services. This results in smaller request and response messages overall. It also allows for more efficient client-side processing of data since the ASP.NET AJAX JavaScript library is optimized to work with JSON objects. "
More details in :
http://www.asp.net/ajax/tutorials/understanding-asp-net-ajax-web-services
As you can see here JSON responses are supported by recent releases of the .NET Framework.
If a clients sends data in an unsupported media type to a HTTP server, the server answers with status "415 unsupported media type". But how to tell the client what media types are supported? Is there a standard or at least a recommended way to do so? Or would it just be written to the response body as text?
There is no specification at all for what to do in this case, so expect implementations to be all over the place. (What would be sensible would be if the server's response included something like an Accept: header since that has pretty much the right semantics, if currently in the wrong direction.)
I believe you can do this with the OPTIONS Http verb.
Also the status code of 300 Multiple Choices could be used if your scenario fits a certain use case. If they send a request with an Accept header of application/xml and you only support text/plain and that representation lives at a distinct URL then you can respond with a 300 and in the Location header the URL of that representation. I realize this might not exactly fit your question, but it's another possible option.
And from the HTTP Spec:
10.4.7 406 Not Acceptable
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.
Unless it was a HEAD request, the response SHOULD include an entity containing a list of available entity characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. Depending upon the format and the capabilities of the user agent, selection of the most appropriate choice MAY be performed automatically. However, this specification does not define any standard for such automatic selection.
Note: HTTP/1.1 servers are allowed to return responses which are
not acceptable according to the accept headers sent in the
request. In some cases, this may even be preferable to sending a
406 response. User agents are encouraged to inspect the headers of
an incoming response to determine if it is acceptable.
tl;dr;
Edited the generated proxy class to inherit from Microsoft.Web.Services3.WebServicesClientProtocol**.
I came across this question when troubleshooting this error, so I thought I would help the next person who might come through here, although not sure if it answers the question as stated. I ran into this error when at some point I had to take over an existing solution which was utilizing WSE and MTOM encoding. It was a windows client calling a web service.
To the point, the client was calling the web service where it would throw that error.
Something that contributed to resolving that error for me was to check the web service proxy class that apparently is generated by default to inherit from System.Web.Services.Protocols.SoapHttpClientProtocol.
Essentially that meant that it didn't actually use WSE3.
Anyhow I manually edited the proxy and changed it to inherit from Microsoft.Web.Services3.WebServicesClientProtocol.
BTW, to see the generated proxy class in VS click on the web reference and then click the 'Show All Files' toolbar button. The reference.cs is da place of joy!
Hope it helps.
In his book "HTTP Developer's Handbook" on page 81 Chris Shiflett explains what a 415 means, and then he says, "The media type used in the content of the HTTP response should be indicated in the Content-Type entity header."
1) So is Content-Type a possible answer? It would presumably be a comma-separated list of accepted content types. The obvious problem with this possibility is that Content-Type is an entity header not a response header.
2) Or is this a typo in the book? Did he really mean to say "the HTTP request"?
Is it allowable to pass parameters to a web page through the URL (after the question mark) when using the POST method? I know that it works (most of the time, anyways) because my company's webapp does it often, but I don't know if it's actually supported in the standard or if I can rely on this behavior. I'm considering implementing a SOAP request handler that uses a parameter after the question mark to indicate that it is a SOAP request and not a normal HTTP request. The reason for this that the webapp is an IIS extension, so everything is accessed via the same URL (ex: example.com/myisapi.dll?command), so to get the SOAP request to be processed, I need to specify that "command" parameter. There would be one generic command for SOAP, not a specific command for each SOAP action -- those would be specified in the SOAP request itself.
Basically, I'm trying to integrate the Apache Axis2/C library into my webapp by letting the webapp handle the HTTP request and then pass off the incoming SOAP XML to Axis2 for handling if it's a SOAP request. Intuitively, I can't see any reason why this wouldn't work, since the URL you're posting to is just an arbitrary URL, as far as all the various components are concerned... it's the server that gives special meaning to the parts after the question mark.
Thanks for any help/insight you can provide.
Lets start with the simple stuff. HTTP GET request variables come from the URI. The URI is a requested resource, and so any webserver should (and apache does) have the entire URI stored in some variable available to the modules or appserver components running within the webserver.
An http POST which is different from an http GET is a separate logical call to the webserver, but it still defines a URI that should process the post. A good webserver (apache being one) will again make the URI available to whatever module or appserver is running within it, then will additionally make available the variables which were sent in the POST headers.
At the point where your application takes control from apache during a POST you should have access to both the GET and POST variables and be able to do whatever control logic you wish, including replying with a SOAP protocol instead of HTML.
If you are asking whether it is possible to send parameters via both GET and POST in a single HTTP request, then the answer is "YES". This is standard functionality that can be used reliably AFAIK.
One such example is sending authentication credentials in two pieces, one over GET and the other through POST so that any attempt to hijack a session would require hijacking both the GET and POST variables.
So in your case, you can use POST to contain the actual SOAP request but test for whether it is a SOAP request based on the parameter passed in GET (or in other words through the URL).
I believe that no standard actually defines the concept of "HTTP parameters" or "request variables". RFC 1738 defines that an URL may have a "search part", which is the substring after the question mark. HTML specifies in the form submission protocol how a browser processing a FORM element should submit it. In either case, how the server-side processes both the search part and the HTTP body is entirely up to the server - discarding both would be conforming to these two specs (but fairly useless).
In order to determine whether you can post a search part to a specific service, you need to study this service's protocol specification. If the service is practically defined by means of a HTML form, then you cannot use a mix - you can't even use POST if the FORM specifies GET (and vice versa). If you post to a web service, you need to look at the web service's WSDL - which will typically mandate POST; with all data in a SOAP message. Etc.
Specific web frameworks may have the notion of "request variables" - whether they will draw these variables both from a search part and a request body, you need to find out in the product documentation.
I deployed a web application with 3 (a mobile network operator) in the UK. It originally used POST parameters, but the 3 gateway stripped them (and X-headers as well!). So beware...
allowable? sure, it's doable, but i'm leaning towards the spec suggesting dual methods isn't necessarily supposed to happen, or be supported. RFC2616 defines HTTP/1.1, and i would argue suggests only one method per request. if you think about your typical HTTP transaction from the client side, you can see the limitation as well:
$ telnet localhost 80
POST /page.html?id=5 HTTP/1.1
host: localhost
as you can see, you can only use one method (POST/GET, etc...), however due to the nature of how various languages operate, they may pick up the query string, and assign it to the GET variable. ultimately though, this is a POST request, and not a GET.
so basically, yes this functionality exists, is it intended? i would say no.