37

When I try to create a delete method:

public interface ImageService {
    @DELETE("api/v1/attachment")
    Call<BaseResponse> delete(@Body DeleteModel deleteModel);
}

I get the error which basically boils down to these lines from the stacktrace:

E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Failure delivering result
java.lang.IllegalArgumentException: Non-body HTTP method cannot contain @Body.
Caused by: java.lang.IllegalArgumentException: Non-body HTTP method cannot contain @Body.

How can I add a body to a delete method ?

I have searched here but found 3 not answers and nothing using retrofit.

HopefullyHelpful
  • 1,592
  • 3
  • 18
  • 36

6 Answers6

90

A more simplified answer.

@HTTP(method = "DELETE", path = "/api/analysis_delete", hasBody = true)
Call<Analysis_Delete_RequestResult_Api10> analysis_delete_api10(@Field("seq") String seq);

This will do the trick.

murgupluoglu
  • 5,167
  • 4
  • 28
  • 35
March3April4
  • 1,902
  • 15
  • 33
15

Here is my version

@HTTP(method = "DELETE", path = "{login}", hasBody = true)
Call<ResponseBody> getData(@Path("login") String postfix, @Body Map<String, Object> options);
Jens Borrisholt
  • 5,893
  • 1
  • 27
  • 61
Sharanjeet Kaur
  • 706
  • 12
  • 18
11

Here's an excerpt from the docs, it's a documented feature of the HTTP annotation.

This annotation can also used for sending DELETE with a request body:

 interface Service {
   @HTTP(method = "DELETE", path = "remove/", hasBody = true)
   Call<ResponseBody> deleteObject(@Body RequestBody object);
 }

https://square.github.io/retrofit/2.x/retrofit/retrofit2/http/HTTP.html

headsvk
  • 2,576
  • 1
  • 16
  • 22
6

In case you are you are using an old version that doesn't support @HTTP, you can also add another interface that implements the @RestMethod

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import retrofit.http.RestMethod;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/** Make a DELETE request to a REST path relative to base URL with body. */
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "DELETE", hasBody = true)
public @interface DELETEWITHBODY {
  String value();
}

And then the usage becomes:

public interface ImageService {
    @DELETEWITHBODY("api/v1/attachment")
    Call<BaseResponse> delete(@Body DeleteModel deleteModel);
}
Yftach
  • 702
  • 5
  • 15
0

the service:

public interface ImageService {
    @Post("api/v1/attachment")
    Call<BaseResponse> delete(@Body DeleteModel deleteModel);
}

and in the servercontroller

import okhttp3.Request;

private final class ApiInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request oldRequest = chain.request();
        Request.Builder builder = oldRequest.newBuilder();
        if(condition) {
            return chain.proceed(builder.build().newBuilder().delete(builder.build().body()).build());
        }
        return chain.proceed(builder.build());
    }
}

you have to trigger condition, via something and potentially have to do some filtering for the url/header/body to remove the trigger,

unless the delete url/body/header is unique enough to not collide with post or get requests.

HopefullyHelpful
  • 1,592
  • 3
  • 18
  • 36
0

Originally answered here : https://stackoverflow.com/a/62920127/8956093

Kotlin Code :

path is not required if your first argument to interface method is a url annotated with @Url Example :

@HTTP(method = "DELETE", hasBody = true)
fun deleteStudentFromDatabase(
    @Url url: String,
    @Body payload: StudentModel
 ): Observable<Any>

If first argument to interface method is not a url then use this

    @HTTP(method = "DELETE", path = "{urlPath}", hasBody = true)
    fun deleteStudentFromDatabase(
        @Body payload: StudentModel,
        @Path("urlPath") url: String
     ): Observable<Any>
Ramakrishna Joshi
  • 1,036
  • 12
  • 18