REST-API PUT with both #Path and #Body as input parameters
I am trying to create an API PUT method which should use both #Path and #Body as input parameters but cannot find the exact example(sample code) to achieve that.
This is a sample for your requirement.
#PUT("/api/{username}")
void putAPICall(#Path("username") String username, #Body RequestBody params);
Related
I'm having trouble finding how to do a Retrofit #POST with a JSONObject.
interface AuthApi {
#Multipart
#POST("auth/login")
suspend fun userLogin(
#Body authResponse: JSONObject?
): Response<AuthResponse>
}
When sending I am getting an error:
E/UncaughtException: java.lang.IllegalArgumentException: #Body
parameters cannot be used with form or multi-part encoding.
I'm pretty sure I am not sending the JSONObject the right way, but I can't find a good guide to help me with this implementation in Kotlin.
I have tried to add the:
#Headers("Content-Type: application/json; charset=urf-8")
Directly after the #Multipart, to no avail. I would like to know how to correctly send my JSONObject.
User #Part instead of #Body
Since your using the Multi Part encoding, it doesn't take in just one Body object. It takes in multiple Part parameters
Current response
Response{protocol=http/1.0, code=404, message=Not Found,
url=http://testapp*****/api/dev/myapp**/subscription%2F2be110}
But url which i'm passing is
url=http://testapp*****/api/dev/myapp**/subscription/2be110
"subscription/2be110" which is passing as string to api service which receives at following function
#Headers("Content-Type: application/json;charset=UTF-8","Accept: application/json")
#POST("{urlEndString}")
fun getResponse(
#Path ("urlEndString") urlEndString : String, #Body `object`: JsonObject
):Call<JsonObject>
How back slash changed to "%2F" format ? Any solution to resolve this issue?
Nb: using retrofit2
#Path parameters are URLEncoded. Therefore slash will be URLEncoded as well. You can use 2 path parameters like
#POST("{urlEndString1}/{urlEndString2}")
fun getResponse(
#Path ("urlEndString1") urlEndString1 : String, #Path ("urlEndString2") urlEndString2 : String, #Body `object`: JsonObject):Call<JsonObject>
And pass 2 parts of your URL ending split by slash.
As alternative, you can use #Path(value="urlEndString", encoded=true) to show that the parameter is already encoded, and Retrofit does not need to encode it.
I can't upload photo to server. java.lang.IllegalArgumentException: #Field parameters can only be used with form encoding. (parameter #1). Please help me, how to solve or any other suggestions. postman
#FormUrlEncoded
#Multipart
#POST("qq/api/xxxx")
Call<Custom> postCustom(#Field("Id") String Id,
#Part MultipartBody.Part file,
#Field("Status") String Status);
Change your request interface like this
#Multipart
#POST("qq/api/xxxx")
Call<Custom> postCustom(
#Part("Id") String Id,
#Part MultipartBody.Part file,
#Part("Status") String Status);
You cannot use both #FormUrlEncoded and #Multipart on a single method since an HTTP request can only have one Content-Type. #FormUrlEncoded and #Multipart are both content types.
From Jake Wharton
You can have to use FormUrlEncodedTypedOutput as a #Part argument for the form encoded part and build it up yourself. The annotation on the method is for the outermost encoding which in this case is multipart.
References
I have added also these issue reference which is really helpful for you to understanding what you are about to change in your http request method
https://github.com/square/retrofit/issues/662
https://github.com/square/retrofit/issues/1210
In some post request, I don't know when to use #Field, when to use #Body.
Like whats the difference between:
#POST("users/register")
Call<String> register(#Body RequestBody registerRequest);
and:
#POST("users/register")
Call<String> register(#Field String id, #Field String pass);
Can I use #Body instead of #Field, and reverse ? If not, why ? And how to know this case use #Body, other case use #Field ?
Can you please give me some case and explain, thank you.
#Body – Sends Java objects as request body.
#Field – send data as form-urlencoded. This requires a #FormUrlEncoded annotation attached with the method.
The #Field parameter works only with a POST. #Field requires a mandatory parameter. In cases when #Field is optional, we can use #Query instead and pass a null value.
Both are used for posting data only, but they have following difference -
The #Body annotation defines a single request body.
interface Foo {
#POST("/jayson")
FooResponse postJson(#Body FooRequest body);
}
That means if you are using #Body, it should be only parameter. It is helpful when you have already a JsonObject and you want to send it as it with you api call.
Another way is, you can send data using #Field and send the Place object as a JSON string.
#POST("/post/addphoto/")
public void addImage(#Field("image_url") String url, #Field("caption") String caption, #Field("google_place_id") String placeId, #Field("facebook_place") String place, Callback<UploadCallBack> response);
Hope it will help... :-)
I'm using retrofit2 to comunicate with a webapi.
I need to set the URL of the webapi dynamically beacuase the user can change it, so i use the #Url annotation to specify it like this:
#POST
Call<LoginResponse> login(#Url String url, #Body LoginRequest user);
In one of the operations, i need to send some path parameters to the server, so i do this:
#GET
Call<DataResponse> getOrder(#Url String url,
#Header(WEBAPI_EMAIL_HEDER) String email,
#Header(WEBAPI_TOKEN_ID_HEDER) String token,
#Path("id") int id);
When i call the operation getOrder(...), an exception is rised by retrofit because i am not suppoused to use #Url and #Path parameters in the same operation.
This is the exception:
java.lang.IllegalArgumentException: #Path parameters may not be used with #Url. (parameter #4)
One solution is to replace the id parameter on the url and use only the #Url parameter in the invokation. But i think this is not the best way, beacuase i will be doing this with all the operations with #Path parameters.
Is there any other cleaner solution? Maybe using another retrofit2 annotation?
Thanks in advance.
As described in the post Retrofit 2 - Dynamic URL, the #Url notation assumes that the String is a fully defined URL and does not check whether it contains #Path variables.
To use the #Path annotation, you have to configure an endpoint URL and include the #Path variable inside the #GET() annotation.
There is a workaround. Incase of a dynamic Url with some variable path, we can define a string format with paths denoted by %s arguments.
E.g:
Suppose the dynamic url with path is : https://www.example.com/users/{id}/whoami
Here we can just replace {id} with %s. So now it becomes,
val formatString = https://www.example.com/users/%s/whoami
Now we can use it as a format string and replace it with required id.
val url = formatString.format(id)
and in the retrofit interface, use #Url parameter in the function.
interface AnyService {
fun whoAmI(#Url url:String): Call<ResponseBody>
}
Incase you are using MVVM architecture, you can call the formatting code in the concerned repository.