Retrofit - @Body parameters cannot be used with form or multi-part encoding

73,841

Solution 1

This post pointed me to the right direction https://stackoverflow.com/a/21423093/1446856. I attached everything in the body and send it as a TypedInput.
So the interface looks something like this

@POST("/api/register")
@Headers({ "Content-Type: application/json;charset=UTF-8"})
Observable<RegisterResponse> register(
    @Header("Authorization") String authorization,
    @Body TypedInput body
);

and the body looks something like this

String bodyString = jsonBody + "?grant_type=" + 
    grantType + "&scope=" + scope;
TypedInput requestBody = new TypedByteArray(
    "application/json", bodyString.getBytes(Charset.forName("UTF-8")));

Solution 2

maybe this could help some people, if you have this trouble, you should remove @FormUrlEncoded of your interface. Hope this helps.

Solution 3

Adding to Julien's answer, also remove the @Multipart annotation. Here's how I have used it:

@POST("/app/oauth/token")
Call<AuthResponse> getAuthToken(@Body RequestBody body);

And, here is how I have constructed the RequestBody:

RequestBody requestBody = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("grant_type", "password")
                        .addFormDataPart("username", username)
                        .addFormDataPart("password", password)
                        .build();

Solution 4

I solved this problem by adding the field into

@POST("/api/register") 

like this:

@POST("/api/register?grantType=value")

it's not a good solution, but may be useful.

Share:
73,841
Chris
Author by

Chris

Updated on July 05, 2022

Comments

  • Chris
    Chris almost 2 years

    I m trying to make a request in which I want to include a Header , a form-urlencoded field and a json body. My Retrofit interface is as follows

    @FormUrlEncoded
    @POST("/api/register")
    Observable<RegisterResponse> register(
        @Header("Authorization") String authorization, 
        @Field("grant_type") String grantType, 
        @Body RegisterBody body
    );
    

    When I make this request I get back exception @Body parameters cannot be used with form or multi-part encoding.
    I have also tried with the @Multipart annotation:

    @Multipart
    @FormUrlEncoded
    @POST("/api/register")
    Observable<RegisterResponse> register(
        @Header("Authorization") String authorization, 
        @Part("grant_type") TypedString grantType, 
        @Body RegisterBody body
    );
    

    and I get an IllegalArgumentException and only one encoding annotation is allowed.

  • ViksaaSkool
    ViksaaSkool almost 9 years
    what's the value for 'jsonBody'?
  • Chris
    Chris over 8 years
    @ViksaaSkool it can be any json string. for instance {"currency":"GBP", "customerId":2, "country":"GB", "lang":"en-GB", "sizeSchema":"UK", "store":"1"}
  • LOG_TAG
    LOG_TAG almost 8 years
    This one not works in Retrofit 2 , we should use RequestBody !!
  • Dhiren
    Dhiren almost 7 years
    what is the value for the bodyString ? or how to achieve this in retrofit 2 ?
  • Alireza Noorali
    Alireza Noorali over 5 years
    @Multipart would cause the same problem, too!
  • Dantalian
    Dantalian over 3 years
    Cleaner and easier than the accepted answer, works like a charm.