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

My problem is thatI 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 - receivestatus = true. If not - receivestatus = falseand required parameters which are wrong (e.g. mail is already taken)

So I can receivestatus = trueorstatus = falseand array with max 5 parameters (username, email, password, gender, birthDate).

I tried thisAPI 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 inActivity:

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 optionBody->x-www-form-urlencoded.

How can I create Iregisterquery to this API?Change@Fieldto something else? I have got this error always...

EDIT: Need to changeAPI Interfaceto 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:8400for 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...

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.

The problem was because I try toPUTe.g.longitude\latitude\locationwith no value - emptyString.

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.

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.

What Others Are Reading