Retrofit 2.0 throwing "IllegalArgumentException: @Field parameters can only be used with form encoding". How to do right API query and fix it?

61,510

Solution 1

The problem was because I try to PUT e.g. longitude \ latitude \ location with no value - empty String.

I mean - there was a problem on API side. So to avoid that I changed method to this:

@FormUrlEncoded
@PUT(ApiConstants.REGISTER_URL_PART)
Call<RegisterModel> registerUser(
        @Field("username") String username,
        @Field("email") String email,
        @Field("password") String password,
        @Field("fbID") String fbID,
        @Field("gmailID") String gmailID,
        @Field("twitID") String twitID,
        @Field("gender") String gender,
        @Field("birthDate") String birthDate,
        @Nullable @Field("location") String location,
        @Nullable @Field("longitude") String longitude,
        @Nullable @Field("latitude") String latitude,
        @Field("profileImage") String profileImage
);

Now, when I go no value for one of them, I simply don't enclose this field.

Solution 2

you just missed @FormUrlEncoded above your Rest method call.

Solution 3

Your request is not encoded right, but are postman, so do change that :

@FormUrlEncoded
@PUT("/api/register")
    Call<AuthRegisterUserModel> getStatus(
            @Field("username") String username,
            @Field("email") String email,
            @Field("password") String password,
            @Field("fbID") String fbID,
            @Field("gmailID") String gmailID,
            @Field("twitID") String twitID,
            @Field("gender") String gender,
            @Field("birthDate") String birthDate,
            @Field("location") String location,
            @Field("longitude") String longitude,
            @Field("latitude") String latitude,
            @Field("profileImage") String profileImage);

Tell me if it's ok.

Solution 4

I got a similar error message and I noticed that in my interface definition I missed the @ForUrlEncoded annotation - on top of the rest call that will use the form part, which seems to be the same thing you did at the first posted code block. Take a look at it.

Hope this helps.

Share:
61,510
y07k2
Author by

y07k2

BY DAY: Java Developer at work. Android Developer at home. BY NIGHT: I'm interested in sport (especially football), new technologies and mobile phones. FOR FUN: Playing FIFA 17 with friends, watching football matches (EPL, UCL and Polish Ekstraklasa) and play football with mates.

Updated on August 01, 2022

Comments

  • y07k2
    y07k2 over 1 year

    My problem is that I don't know how to start using Retrofit 2.0 with received API - mentioned below...

    Firstly, I need to username, password, fbID (optional), gmailID (optional), twitID (optional), gender, birthDate, location (not required - if long and lat has values), longitude (optional), latitude (optional), profileImage (optional).

    When all parameters are good - receive status = true. If not - receive status = false and required parameters which are wrong (e.g. mail is already taken)

    So I can receive status = true or status = false and array with max 5 parameters (username, email, password, gender, birthDate).

    I tried this API Interface:

    public interface AuthRegisterUserApi {
        @PUT()
        Call<AuthRegisterUserModel> getStatus(
                @Field("username") String username,
                @Field("email") String email,
                @Field("password") String password,
                @Field("fbID") String fbID,
                @Field("gmailID") String gmailID,
                @Field("twitID") String twitID,
                @Field("gender") String gender,
                @Field("birthDate") String birthDate,
                @Field("location") String location,
                @Field("longitude") String longitude,
                @Field("latitude") String latitude,
                @Field("profileImage") String profileImage
                );
    
        class Factory {
            private static AuthRegisterUserApi service;
    
            public static AuthRegisterUserApi getInstance() {
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(ApiConstants.REGISTER_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
    
                service = retrofit.create(AuthRegisterUserApi.class);
    
                return service;
            }
        }
    }
    

    with this API models (Pastebin.com)

    and this code in Activity:

    AuthRegisterUserApi.Factory.getInstance()
            .getStatus(
                    usernameEditText.getText().toString(),
                    emailEditText.getText().toString(),
                    passwordEditText.getText().toString(),
                    "", "", "",
                    (maleRadioButton.isChecked() ? "male" : "female"),
                    mYear + "-" + mMonth+1 + "-" + mDay,
                    (geoLocationToggleButton.isChecked() ? geoLocationEditText.getText().toString() : ""),
                    (!geoLocationToggleButton.isChecked() ? "50" : ""),
                    (!geoLocationToggleButton.isChecked() ? "50" : ""),
                    "")
            .enqueue(new Callback<AuthRegisterUserModel>() {
        @Override
        public void onResponse(Call<AuthRegisterUserModel> call, Response<AuthRegisterUserModel> response) {
            if(response.isSuccessful()) {
                if (response.body().isStatus()) {
                    showToast(getApplicationContext(), "Registration ok.");
                } else {
                    response.body().getInfo().getUsername();
                }
            }
        }
    
        @Override
        public void onFailure(Call<AuthRegisterUserModel> call, Throwable t) {
    
        }
    });
    

    I have error: java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding. (parameter #1) for method AuthRegisterUserApi.getStatus

    I tried to register user using Postman and it works when I used option Body -> x-www-form-urlencoded.

    How can I create I register query to this API? Change @Field to something else? I have got this error always...

    EDIT: Need to change API Interface to this:

    public interface AuthRegisterUserApi {
        @FormUrlEncoded
        @PUT("/api/register")
        Call<AuthRegisterUserModel> getStatus(
                @Field("username") String username,
                @Field("email") String email,
                @Field("password") String password,
                @Field("fbID") String fbID,
                @Field("gmailID") String gmailID,
                @Field("twitID") String twitID,
                @Field("gender") String gender,
                @Field("birthDate") String birthDate,
                @Field("location") String location,
                @Field("longitude") String longitude,
                @Field("latitude") String latitude,
                @Field("profileImage") String profileImage
                );
    
        class Factory {
            private static AuthRegisterUserApi service;
    
            public static AuthRegisterUserApi getInstance() {
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(ApiConstants.BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
    
                service = retrofit.create(AuthRegisterUserApi.class);
    
                return service;
            }
        }
    }
    

    BASE_URL = http://ip_address:8400 for me...

    But still got error: Response.rawResponse = Response{protocol=http/1.1, code=400, message=Bad Request, url=http://ip_address:8400/api/register}. Using Postman with the same data I received code=201 Created. Don't know why...

  • y07k2
    y07k2 almost 8 years
    Response.rawResponse = Response{protocol=http/1.1, code=400, message=Bad Request, url=http://ip_address:8400/api/register}. Co this is not working.
  • Raphael Teyssandier
    Raphael Teyssandier almost 8 years
    You are sure, that your request is a put and not a post ?
  • Raphael Teyssandier
    Raphael Teyssandier almost 8 years
    Have try with a different arguments ? Because since you put him in the database you can't reput him ?
  • y07k2
    y07k2 almost 8 years
    Trying with different params on app first - response null; on Postman - response status = true. Mindblow...
  • Raphael Teyssandier
    Raphael Teyssandier almost 8 years
    Okay, that's weird, on postman the endpoint is register/ or register ?
  • y07k2
    y07k2 almost 8 years
    register, without slash "/"
  • y07k2
    y07k2 almost 8 years
    POST method is working. But PUT method is working when I removed response.isStatus() from onResponse() method... Trying to change status to String, still response null when using response.isStatus()...
  • Arhat Baid
    Arhat Baid about 7 years
    You saved me, man!!! Thanks a ton.By mistake, I deleted this line and was facing this error.