y07k2 y07k2 - 1 month ago 20
Java Question

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 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...

Answer

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.