如何在Retrofit中发送带有请求体的HTTP-delete请求?

40

当我尝试创建一个删除方法时:

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

我遇到了一个错误,基本上可以归结为堆栈跟踪中的这些行:

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.

我如何在删除方法中添加请求体?

我在这里搜索过,但找到了3个无用的答案,而且没有使用retrofit的内容。

8个回答

96
一个更简化的答案。
@HTTP(method = "DELETE", path = "/api/analysis_delete", hasBody = true)
Call<Analysis_Delete_RequestResult_Api10> analysis_delete_api10(@Field("seq") String seq);

这样就可以了。


10
如果需要发送数据主体(Body),则应移除@FormUrlEncoded。 - sunlover3
1
@sunlover3 真是太准确了! - Virat18
完全可行,谢谢。顺便说一句,不需要像sunlover3所说的那样使用@FormUrlEncoded。 - Yucel Bayram
感谢您的帮助,非常感谢! - Hetal
这个解决方法对我来说出现了错误: “retrofit.RetrofitError: UserService.delete: 需要HTTP方法注释(例如,@ GET,@ POST等)。”。 - Donki
对我不起作用。 - Khadija Hameed

20

这是我的版本

@HTTP(method = "DELETE", path = "{login}", hasBody = true)
Call<ResponseBody> getData(@Path("login") String postfix, @Body Map<String, Object> options);

14

这是文档中的一段摘录,它是HTTP注释记录功能的一个文档化特性。

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


7

如果您正在使用不支持@HTTP的旧版本,您还可以添加另一个实现@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();
}

然后使用方式变为:
public interface ImageService {
    @DELETEWITHBODY("api/v1/attachment")
    Call<BaseResponse> delete(@Body DeleteModel deleteModel);
}

2

这对我很有用(Kotlin)

用于删除多个对象(作为键值对)

@HTTP(method = "DELETE", path = "api/v1/attachment", hasBody = true)
fun getData(@Body requestBody: Map<String, DeleteModel>): Callable<ResponseBody>

或者删除一个对象
@HTTP(method = "DELETE", path = "api/v1/attachment", hasBody = true)
fun getData(@Body requestBody: DeleteModel): Callable<ResponseBody>

0

我遇到了同样的问题,希望能帮助其他人

我使用:Kotlin、Retrofit、协程

@FormUrlEncoded
@HTTP(method = "DELETE", path = "your_end_point_path", hasBody = true)
suspend fun delete(
    @Field("id") id: String
): Response<BaseResponse<*>>

0

该服务:

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

并且在服务器控制器中

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());
    }
}

你必须通过某种方式触发条件,并且可能需要对URL/头部/正文进行一些过滤以去除触发器,
除非删除的URL/正文/头部足够独特,不会与POST或GET请求冲突。

0

原始回答在这里:https://dev59.com/OVoT5IYBdhLWcg3w-TZV#62920127

Kotlin 代码:

path 不是必需的,如果您接口方法的第一个参数是使用 @Url 注释的 URL。 例如:

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

如果接口方法的第一个参数不是URL,则使用此选项。
    @HTTP(method = "DELETE", path = "{urlPath}", hasBody = true)
    fun deleteStudentFromDatabase(
        @Body payload: StudentModel,
        @Path("urlPath") url: String
     ): Observable<Any>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接