views:

86

answers:

2

I'm attempting to use an HttpDelete object to invoke a web service's delete method. The web service's code parses JSON from the message's body. However, I'm failing to understand how to add a body to an HttpDelete object. Is there a way to do this?

With HttpPut and HttpPost, I call the setEntity method and pass in my JSON. There doesn't appear to be any such method for HttpDelete.

If there is no way to set a body for an HttpDelete object, could you please link me to a resource that uses a super class of HttpDelete such that I can set the method (delete) and set a body. I know that isn't ideal, but at this point I can't alter the web service.

+2  A: 

There are different interpretation in the question whether the body is allowed or not in the HTTP DELETE request. See this for example. In the HTTP 1.1 specification it is not explicitly prohibied. In my opinion you should not use body in the HTTP DELETE.

Nevertherless I think that you should use URL like mysite/myobject/objectId (shop.com/order/1234) where the objectId (a part of the url) is the additional information. As an alternative you can use URL parameters: mysite/myobject?objectName=table&color=red to send additipnal information to the server in the HTTP DELETE request. The part starting with '?' is the urlencoded parameters devided dy '&'.

If you want to send more complex information you can convert the data to JSON with respect of DataContractJsonSerializer or JavaScriptSerializer and then send the converted data (a string which I name myJsonData later) also as the parameter: mysite/myobject?objectInfo=myJsonData.

If you need to send too much additionnal data as a part of HTTP DELETE request so that you have problem with the URL length then you should probably better change the design of your application.

UPDATED: Iy you do want send some body per HTTP DELETE you can do this for example like following

// somewhere above add: using System.Net; and using System.IO;

WebClient myWebClient = new WebClient ();

// 1) version: do simple request    
string t= myWebClient.UploadString ("http://www.examples.com/", "DELETE", "bla bla");
// will be send following:
//
// DELETE http://www.examples.com/ HTTP/1.1
// Host: www.examples.com
// Content-Length: 7
// Expect: 100-continue
// Connection: Keep-Alive
//
//bla bla

// 2) version do complex request    
Stream stream = myWebClient.OpenWrite ("http://www.examples.com/", "DELETE");

string postData = "bla bla";
byte[] myDataAsBytes = Encoding.UTF8.GetBytes (postData);
stream.Write (myDataAsBytes, 0, myDataAsBytes.Length);
stream.Close (); // it send the data
// will be send following:
// 
// DELETE http://www.examples.com/ HTTP/1.1
// Host: www.examples.com
// Content-Length: 7
// Expect: 100-continue
// 
// bla bla

// 3) version
// create web request 
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create ("http://www.examples.com/");
webRequest.Method = "DELETE";
webRequest.ServicePoint.Expect100Continue = false;

// post data 
Stream requestStream = webRequest.GetRequestStream ();
StreamWriter requestWriter = new StreamWriter (requestStream);
requestWriter.Write (postData);
requestWriter.Close ();

//wait for server response 
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse ();
// send following:
// DELETE http://www.examples.com/ HTTP/1.1
// Host: www.examples.com
// Content-Length: 7
// Connection: Keep-Alive
// 
// bla bla

the full code could be a little more complex, but this one already will work. Nevertheless I continue to say that Web Service needed data in the body of HTTP DELETE request is bad designed.

Oleg
-1. The questioner said quite clearly that he cannot change the web service, and he probably didn't design it either. Since every recommendation in this post involves changing code not under control of the asker, it's completely unhelpful in the situation at hand.
Walter Mundt
For what it's worth, I don't disagree with your points on principle; a web service requiring DELETE methods with a body is probably poorly designed. Nonetheless, it is legitimate to ask how to interface with a badly-designed and possibly standards-noncompliant web service, and that is how I interpret this question.
Walter Mundt
@Walter Mundt: If one **do** need to send body in the HTTP DELETE I added an example with one of the possible way to do this.
Oleg
Fair enough. Downvote removed.
Walter Mundt
Could I ask why having a body with a delete method isn't a good idea? Is it just because people don't generally do it? It's certainly possible to do; so what's the reasoning for it being a bad idea? (I'm not disagreeing. I'm just inquiring. I'm new to web services)
Andrew
@Andrew: The most implementation of HTTP libraries classes and so on think that DELETE should has no body. In the case one have to have a **VERY GOOD** reason to design an implementation of a wen service which has this. Mostly one use not HTTP DELETE in RESTful services. In REST the url should identify resource, so HTTP DELETE has all information about the object which should be deleted **in the URL**. It is not prohibited to use HTTP GET with parameters to change resources or use HTTP PUT to delete resources, but it would be a bad style (bad design).
Oleg
+2  A: 

Have you tried overriding HttpEntityEnclosingRequestBase as follows:

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import java.net.URI;
import org.apache.http.annotation.NotThreadSafe;

@NotThreadSafe
class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
    public static final String METHOD_NAME = "DELETE";
    public String getMethod() { return METHOD_NAME; }

    public HttpDeleteWithBody(final String uri) {
        super();
        setURI(URI.create(uri));
    }
    public HttpDeleteWithBody(final URI uri) {
        super();
        setURI(uri);
    }
    public HttpDeleteWithBody() { super(); }
}

That will create a HttpDelete-lookalike that has a setEntity method. I think the abstract class does almost everything for you, so that may be all that's needed.

FWIW, the code is based on this source to HttpPost that Google turned up.

Walter Mundt
This worked perfectly
Andrew