Multiple Parameter in REST-PUT with both #Path and #Body - android

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

Sending a JSONObject with retrofit using Kotlin

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

Retrofit gives null response while calling Post request from android

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.

How to upload photo in android retrofit 2?

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

Retrofit: what is different between #Field and #Body

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

Using #Path and #Url paramers together with retrofit2

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.

Categories

Resources