How to append my url in Post request using retrofit interface in android - retrofit2

I want to add or append my url in interface of retrofit. Code of interface is given below.
public interface PostInterface {
#POST("api/v1/app/user/resetpassword/token")
#Headers({
"Content-Type: application/json"
})
Call<JsonObject> getResult(#Body JsonObject body);
}
In the given url #POST("api/v1/wallet/user/resetpassword/token") i want to append token value.Which is value of a variable of an activity.
and my activity code is given below from where i am call the method.
try {
JsonObject params = new JsonObject();
params.addProperty("email", email);
params.addProperty("signup_mode", "mobile");
PostInterface apiService =TestApiClient.getClient(this).create(PostInterface.class);
Call call = apiService.getResult(params);
call.enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) {

I'm not entirely sure I understood if this should be part of the path or part of the query parameters, so here's both ways.
Part of the path
The way to do this with retrofit is to make it a "variable" in the path and pass it as arguments to the function.
#POST("api/v1/app/user/resetpassword/{token}")
#Headers({
"Content-Type: application/json"
})
Call<JsonObject> getResult(
#Path("token") String token,
#Body JsonObject body);
Notice the curly braces in {token} in the url. This tells retrofit that it should format an argument of your method into the url. To know which argument you use the annotation Path with the same name as the one being formatted. This results in urls like api/v1/app/user/resetpassword/09df7seh98ghs (09df7seh98ghs is my poor representation of a token).
(this assumes your token is a String. Retrofit supports more than that.)
Part of the query parameters
Similar to the way you do this with the #Path annotation you can use the #Query annotation:
#POST("api/v1/app/user/resetpassword/token")
#Headers({
"Content-Type: application/json"
})
Call<JsonObject> getResult(
#Query("token") String token,
#Body JsonObject body);
The difference here is that retrofit will add the given token as a query parameter resulting in urls like api/v1/app/user/resetpassword/token?token=...

Hey i got the answer of my question. Hope if any body is having such problem it can help in future.
Modification in interface:
#POST
#Headers({"Content-Type: application/json"})
Call<JsonObject> getResult(#Url String url, #Body JsonObject body);
Now inside your activity call back please do the following changes
try {
JsonObject params = new JsonObject();
params.addProperty("email", email);
params.addProperty("signup_mode", "mobile");
String url= Constants.BASE_URL+"api/v1/wallet/user/changepassword/"+userIdStr;
PostInterface apiService = TestApiClient.getClient(this).create(PostInterface.class);
Call call = apiService.getChangePassword(url,params);
call.enqueue(new Callback() {
Its working fine.

Related

Accept x-www-form-urlencoded in Web API .NET Core

I have a .NET Core Web API that is returning a 415 Unsupported Media Error when I try to post some data to it that includes some json. Here's part of what is returned in the Chrome Debugger:
Request URL:http://localhost:51608/api/trackAllInOne/set
Request Method:POST
Status Code:415 Unsupported Media Type
Accept:text/javascript, text/html, application/xml, text/xml, */*
Content-Type:application/x-www-form-urlencoded
action:finish
currentSco:CSharp-SSLA:__How_It_Works_SCO
data:{"status":"incomplete","score":""}
activityId:13
studentId:1
timestamp:1519864867900
I think this has to do with my controller not accepting application/x-www-form-urlencoded data - but I'm not sure. I've tried decorating my controler with Consumes but that does not seem to work.
[HttpPost]
[Route("api/trackAllInOne/set")]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Post([FromBody] PlayerPackage playerPackage)
{ etc..}
Any help greatly appreciated.
The following code worked fine in .NET 4.6.1 and I am able to capture and process the posts shown above.
[ResponseType(typeof(PlayerPackage))]
public async Task<IHttpActionResult> PostLearningRecord(PlayerPackage playerPackage)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var id = Convert.ToInt32(playerPackage.ActivityId);
var learningRecord = await _context.LearningRecords.FindAsync(id);
if (learningRecord == null)
return NotFound();
etc...
Try using [FromForm] instead of [FromBody].
public IActionResult Post([FromForm] PlayerPackage playerPackage)
FromBody > Bind from JSON
FromForm > Bind from Form parameters
You can also remove [FromBody] altogether and trial it then. Because you are expecting form-urlencoded should tell it to bind to object.
For PlayerPackage, the request should send a PlayerPackage Json Object, based on your description, you could not control the request which is posted from other place.
For the request, its type is application/x-www-form-urlencoded, it will send data with {"status":"incomplete","score":""} in string Format instead of Json object. If you want to accept {"status":"incomplete","score":""}, I suggest you change the method like below, and then convert the string to Object by Newtonsoft.Json
[HttpPost]
[Route("~/api/trackAllInOne/set")]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Post([FromForm] string data)
{
PlayerPackage playerPackage = JsonConvert.DeserializeObject<PlayerPackage>(data);
return Json(data);
}
This did the trick for me:
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Post([FromForm]IFormCollection value)
I had the same problem. FormDataCollection has no default constructors which is required by Formatters. Use IFormCollection instead.
Can make setting like as
[HttpPost()]/[HttpGet()]
[Consumes("application/x-www-form-urlencoded")]
public async Task<IActionResult> MethodName([FromForm] IFormCollection value)
don't forget to add [FromForm]

post parameter that passed in as #Field does not being added into RequestBody in Retrofit2?

base on Retrofit #Field doc, when making a post request
a combination of using #FormUrlEncoded and #Field will yields a request body of: paramName=paramValue&paramName=paramValue.
but what I am not getting field paramemters included in RequestBody.
my interface definition as below:
(I have no endpoint, and jake Wharton says use ./ as explicit intent that you want to use the path of the base URL and add nothing to it, but I tried #POST("./") it's not work, i got 404 not found error, so I add full url address to bypass this error temporarily)
public interface BannerService {
#FormUrlEncoded
#POST("http://10.10.20.190:6020/router")
Flowable<List<BannerBeanList.BannerBean>> getBannerData(#Field("method") String method, #Field("adspaceId") String adspaceId);
}
and this is how I make calls to interface service:
public class RemoteListDataSource implements RemoteDataSource {
#Override
public Flowable<List<BannerBeanList.BannerBean>> getBannerListData(ADFilterType adFilterType) {
BannerService bannerService = RetrofitHttpManger.getInstance().create(BannerService.class);
return bannerService.getBannerData("mz.app.ad.list", String.valueOf(adFilterType.getValue()));
}
}
below is retrofit instance in it's private constructor
retrofit = new Retrofit.Builder()
.client(httpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//TODO baseurl tempororily hard code for test purpose
.baseUrl("http://10.10.20.190:6020/router/")
.build();
this is the result I got:
the current request body that I am logging is the common parameters that I added from FromBody in interceptor, only except the parameters that I passed in from #Field annoation, and server side info tells the same thing.
I have solved this issue, thanks to #iagreen's comment.
the request body was replaced by FormBody.Builder().add().build() which passed into chain.request().newBuilder().post().build() in my interceptor.
then the question turns out to be how to append paramemters in RequestBody, and the solution can refers to Retrofit2: Modifying request body in OkHttp Interceptor

Can't send volley post request from android phone

I'm using Volley to send an http post request with parameters from my android app to my local server running in http://192.168.1.4:3000/battery_signal_report
I'm pretty sure the server is running properly (I checked it with Postman successfully).
also, I successfully sent the request through Android Studio's Emulator using ip 10.0.2.2
Trying to make it work, i used various request implementations including JsonObjectRequest, StringRequest and the custom request described here: Volley JsonObjectRequest Post request not working
Also, I've read somewhere that Volley post requests have some problems with the request header, so i tried to override it in different ways.
Nothing works. onErrorResponse is called every time with an empty VolleyError input.
I've fairly new to android development, so any insights would be much appreciated.
Thanks in advance.
For anyone else coming across this, you need to forget about the header override and setup your own getBodyContentType() and getBody() methods. Follow this pattern:
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, successListener, errorListener) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";//set here instead
}
#Override
public byte[] getBody() {
try {
Map<String, String> params = yourObject.getMappedParams();
JSONObject json = new JSONObject(params);
String requestBody = json.toString();
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
return null;
}
}
};

Need Working Example of Nest REST API without using Firebase API

I'm struggling trying to find a working example of writing data to the Nest Thermostat API using plain rest. Attempting to write a C# app and cannot use Firebase. The multiple Curl examples posted so far do not work. I have a valid auth_token and can read data without issues. Finding the correct post url is elusive. Can anyone assist?
Examples like
curl -v -X PUT "https://developer-api.nest.com/structures/g-9y-2xkHpBh1MGkVaqXOGJiKOB9MkoW1hhYyQk2vAunCK8a731jbg?auth=<AUTH_TOKEN>" -H "Content-Type: application/json" -d '{"away":"away"}'
don't change any data.
Two things. First, follow redirects with -L. Second, put directly to the away data location, like
curl -v -L -X PUT "https://developer-api.nest.com/structures/g-9y-2xkHpBh1MGkVaqXOGJiKOB9MkoW1hhYyQk2vAunCK8a731jbg/away?auth=<AUTH_TOKEN>" -H "Content-Type: application/json" -d '"away"'
The PUT overwrites all data at a location. The previous command would logically be setting the structure's data to just {"away":"away"}.
user3791884,
Any luck with your C# PUT? Here is C# code that works:
using System.Net.Http;
private async void changeAway()
{
using (HttpClient http = new HttpClient())
{
string url = "https://developer-api.nest.com/structures/" + structure.structure_id + "/?auth=" + AccessToken;
StringContent content = new StringContent("{\"away\":\"home\"}"); // derived from HttpContent
HttpResponseMessage rep = await http.PutAsync(new Uri(url), content);
if (null != rep)
{
Debug.WriteLine("http.PutAsync2=" + rep.ToString());
}
}
}
Debug.WriteLine writes this to the Output window:
"http.PutAsync2=StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Access-Control-Allow-Origin: *
Cache-Control: no-cache, max-age=0, private
Content-Length: 15
Content-Type: application/json; charset=UTF-8
}"
These two methods return a valid structure of my data.
1/ command line
curl -v -k -L -X GET "https://developer-api.nest.com/structures/Za6hCZpmt4g6mBTaaA96yuY87lzLtsucYjbxW_b_thAuJJ7oUOelKA/?auth=c.om2...AeiE"
2/ C#
private bool getStructureInfo()
{
bool success = false;
try
{
// Create a new HttpWebRequest Object to the devices URL.
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("https://developer-api.nest.com/structures/?auth=" + AccessToken);
// Define the request access method.
myHttpWebRequest.Method = "GET";
myHttpWebRequest.MaximumAutomaticRedirections=3;
myHttpWebRequest.AllowAutoRedirect=true;
myHttpWebRequest.Credentials = CredentialCache.DefaultCredentials;
using(HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse())
{
if (null != myHttpWebResponse)
{
// Store the response.
Stream sData = myHttpWebResponse.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader (sData, Encoding.UTF8);
Debug.WriteLine("Response Structure stream received.");
string data = readStream.ReadToEnd();
Debug.WriteLine(data);
readStream.Close();
success = deserializeStructure(data);
}
}
}
catch (Exception ex)
{
Debug.WriteLine("getStructure Exception=" + ex.ToString());
}
return success;
}

how to pass in paramters to a post request using the servicestack json client

I'm having trouble getting my servicestack json client to format a REST Post request.
I'm trying to post to my login service with a raw json body of
{"Uname":"joe", "Password":"test"}
but the post methods is actually mistakenly sending this
{"login":""}
Here's the code I'm using.
JsonServiceClient.HttpWebRequestFilter = filter =>
{
filter.Headers.Add(string.Format("X-API-Key: {0}", "test"));
};
var client = new JsonServiceClient(url);
var url = "/login";
var login = new LoginModel { Uname = uname, Password = pwd };
return client.Post<UserCredentials>(url, login);
How should I structure the parameter object so that it serializes to the correctly to the intended raw value in the post request? Additionally, can I just pass in a dictionary or a more generic object so that I don't have to create a LoginModel class or struct?
It turns out the issue was that I was using public fields instead of public properties in my LoginModel. Changing it to properties fixed it.

Resources