I have a route in my web service that receives POST request with Json body and returns simple array in Json format. I'm using PostMan for testing route and it works perfectly. but when I'm using RestSharp it doesn't get any content (or data in deserialization case).
Here is my C# code :
public static async Task<string> UpdateProfile(Profile user, string serviceUrl)
{
string bodyraw = JsonConvert.SerializeObject(user)
var client = new RestClient(serviceUrl);
var request = new RestRequest();
request.Method = Method.POST;
request.Parameters.Clear();
request.AddParameter("application/json", bodyraw, ParameterType.RequestBody);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var response = await client.ExecuteTaskAsync<Profile>(request);
return response.Data.Address;
}
And here is the Profile Class:
public class Profile
{
public string Name { get; set; }
public string Family { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
public string Postal_code { get; set; }
public string Education { get; set; }
public string Gender { get; set; }
public string Age { get; set; }
public string Default_contact { get; set; }
public override string ToString()
{
return string.Concat(Name," " ,Family, " ", Address);
}
}
And this is PostMan OutPut:
{
"Name": "Holma",
"Family": "Kool",
"Email": "dr#gmail.com",
"Mobile": "09063094744",
"Address": "some city- basic av. sq 60",
"Postal_code": "10246666",
"Education": "1",
"Gender": "male",
"Age": "35"
}
And the PHP code that I used is:
function silverum_update_user_profile($request ){
$parameters = $request->get_json_params();// this is a WordPress method and works just fine
$name=sanitize_text_field($parameters['name']);
$family=sanitize_text_field($parameters['family']);
$email=sanitize_text_field($parameters['email']);
$mobile=sanitize_text_field($parameters['mobile']);
$address=sanitize_text_field($parameters['address']);
$postal_code=sanitize_text_field($parameters['postal_code']);
$education=sanitize_text_field($parameters['education']);
$gender=sanitize_text_field($parameters['gender']);
$age=sanitize_text_field($parameters['age']);
$extdp = [
"Name"=>$name,
"Family"=>$family,
"Email"=>$email,
"Mobile"=>$mobile,
"Address"=>$address,
"Postal_code"=>$postal_code,
"Education"=>$education,
"Gender"=>$gender,
"Age"=>$age
];
return $extdp;
}
When PHP method returns "Parameter" its OK and both PostMan and RestSharp can see output content but when method Returns new Array only PostMan is able to recive returnd object. I spent a couple of hour on the issue but didn't get anywhere. help please.
Try using the AddJsonBody() method within the RestRequest object as opposed to adding the parameter manually.
public static async Task<string> UpdateProfile(Profile user, string serviceUrl)
{
var client = new RestClient(serviceUrl);
var request = new RestRequest();
request.Method = Method.POST;
request.AddJsonBody(user);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var response = await client.ExecuteAsync<Profile>(request);
return response.Data.Address;
}
Related
I try to do some CRUD operations on a sharepoint list, unfortunately I cannot update an item in the list. Since I can create and also delete items from the list, I think everything is fine with authentication and rights, but maybe I am not aware of some specific for the update process.
I have extracted the code from my libs to thrill it down to the most relevant lines, in an async method I first read the list and get the item to update
async Task Main()
{
var BaseUrl = "https://my_site/";
var credentials = new NetworkCredential("user", "pass", "domain");
string RequestDigest = null;
HttpClientHandler handler = new HttpClientHandler { Credentials = credentials };
var SpClient = new HttpClient(handler)
{
BaseAddress = new Uri(BaseUrl)
};
SpClient.DefaultRequestHeaders.Accept.Clear();
SpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var url = BaseUrl + $"_api/lists/getbytitle('Test')/items";
var response = await SpClient.GetAsync(url);
var data = await response.Content.ReadAsStringAsync();
if (response.StatusCode != HttpStatusCode.OK) throw new Exception(response.StatusCode.ToString() + " - " + response.RequestMessage.RequestUri);
SharepointListItems listEntries = JsonSerializer.Deserialize<SharepointListItems>(data);
var existing = listEntries.ListItems.FirstOrDefault(p => p.Title == "Eins");
This works fine, existing now contains the item from the list.
Now I tried to update this item:
// This will not work: StatusCode: 403, ReasonPhrase: 'FORBIDDEN', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
existing.Title = "Changed";
string jsonString = JsonSerializer.Serialize<SharepointListItem>(existing);
So I tried to set up the sting for the item "by Hand" for testing purpose:
// This will also not work : StatusCode: 403, ReasonPhrase: 'FORBIDDEN', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
// Prepare body string for testing
string jsonString = "{\"__metadata\": { \"type\": \"SP.Data.TestListItem\" }, \"Title\": \"Changed\"}";
Finally this is the code, that writes the item back to the list:
// write item back to list
if (RequestDigest == null || DateTime.Now > Convert.ToDateTime(RequestDigest.Split(',')[1]).AddSeconds(1800))
{
url = BaseUrl + "_api/contextinfo";
response = await SpClient.PostAsync(url, null);
data = response.Content.ReadAsStringAsync().Result;
var result = JsonSerializer.Deserialize<SharepointContext>(data);
RequestDigest = result.FormDigestValue;
SpClient.DefaultRequestHeaders.Remove("X-RequestDigest");
SpClient.DefaultRequestHeaders.Add("X-RequestDigest", RequestDigest);
SpClient.DefaultRequestHeaders.Add("X-HTTP-Method", "MERGE");
SpClient.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
}
if (existing.odataetag != null)
{
SpClient.DefaultRequestHeaders.Remove("If-Match");
SpClient.DefaultRequestHeaders.Add("If-Match", $"*");
}
var content = new StringContent(jsonString);
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/json");
content.Headers.Add("X-RequestDigest", RequestDigest);
content.Headers.Add("X-HTTP-Method", "MERGE");
url = BaseUrl + $#"_api/lists/getbytitle('Test')/items({existing.Id})";
response = await SpClient.PostAsync(url, content);
Console.WriteLine(response.StatusCode);
response.Dump();
}
This sample I have extracted from my code and written in LinqPad. Here are the classes required for the full sample to run:
public class SharepointListItems
{
[JsonPropertyName("odata.metadata")]
public string odatametadata { get; set; }
[JsonPropertyName("value")]
public List<SharepointListItem> ListItems { get; set; }
}
public class SharepointListItem
{
public SharepointListItem() { }
[JsonPropertyName("odata.type")]
public string odatatype { get; set; }
[JsonPropertyName("odata.id")]
public string odataid { get; set; }
[JsonPropertyName("odata.etag")]
public string odataetag { get; set; }
[JsonPropertyName("odata.editLink")]
public string odataeditLink { get; set; }
public string Title { get; set; }
public int Id { get; set; }
}
public class SharepointContext
{
public string odatametadata { get; set; }
public int FormDigestTimeoutSeconds { get; set; }
public string FormDigestValue { get; set; }
public string LibraryVersion { get; set; }
public string SiteFullUrl { get; set; }
public string[] SupportedSchemaVersions { get; set; }
public string WebFullUrl { get; set; }
}
May anyone give any tips what I am doing wrong here?
As stated above the code runs fine on creating a new item. The only difference is that the body in this case only contains the item as Json without metadata and the etag header is not set.
Thank's for any hint.
I have been working on using a Rest Api for authentication (https://api.vorexlogin.com/)
So far I have added the RestSharp library to dismiss errors to RestClient and RestRequest.
So far when I run the code that I have in the textbox I get this:
RestSharp.Response
The Response that is needed should be something like:
"success": true,
"result": {
"accessToken": "eyJhbGtccccc.xxxx.yyyyzzzzz",
"refreshToken": "67ZYfdsJFDKLS879337937DKJSDLGFSDFRDEMO=",
"accessTokenExpireOn": "2021-07-03T22:19:23.8330686Z",
"refreshTokenExpireOn": "2021-08-02T21:49:23.8330686Z"
}
Even if it failed it should still be a json file of some sort. I will provide my code below.
private async void button1_Click(object sender, EventArgs e)
{
var client = new RestClient("https://api.vorexlogin.com/v2/security/authenticate");
var request = new RestRequest("resources", Method.Post);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("accept", "application/json");
request.AddParameter("application/x-www-form-urlencoded",
"grantType=password&userName=+"+ usernametbx + "&password=" + passwordtbx + "&tenant=" + tenanttbx, ParameterType.RequestBody);
var response = await client.PostAsync<IRestResponse>(request);
textBox1.Text = response.ToString();
}
public class IRestRepsonseList
{
public string accessToken { get; set; }
public string refreshToken { get; set; }
public string accessTokenExpireOn { get; set; }
public string refreshTokenExpireOn { get; set; }
}
public class IRestResponse
{
public bool success { get; set; }
public List<IRestRepsonseList> result { get; set; }
}
By using PostAsync<T> you tell RestSharp to deserialize the response to T. Your IRestResponse class doesn't implement ToString(), so the default object.ToString is used by your code, which just returns the instance class name.
I cloud also suggest you read the documentation, as you wrote lots of unnecessary code.
Here is an example of what you should be doing:
var client = new RestClient("https://api.vorexlogin.com/v2/security/authenticate");
var request = new RestRequest("resources", Method.Post)
.AddParameter("grantType", "password")
.AddParameter("userName", usernametbx)
.AddParameter("password", passwordtbx)
.AddParameter("tenant", tenanttbx);
var response = await client.PostAsync(request);
textBox1.Text = response.Content;
I'm integrating Outlook Calendar with a custom calendar with client credential flow and I'm trying to make my own api and not use MAPI all to much.
I would like to make a Post to https://outlook.office.com/api/v2.0/TenantDomain/users/useremail#domain/events
I am following this guide Create Events and have made the helper classes:
public class ToOutlookCalendar
{
[JsonProperty("Subject")]
public string Subject { get; set; }
[JsonProperty("Body")]
public Body Body { get; set; }
[JsonProperty("Start")]
public End Start { get; set; }
[JsonProperty("End")]
public End End { get; set; }
[JsonProperty("Attendees")]
public List<Attendee> Attendees { get; set; }
}
public class Attendee
{
[JsonProperty("EmailAddress")]
public EmailAddress EmailAddress { get; set; }
[JsonProperty("Type")]
public string Type { get; set; }
}
public class EmailAddress
{
[JsonProperty("Address")]
public string Address { get; set; }
[JsonProperty("Name")]
public string Name { get; set; }
}
public class Body
{
[JsonProperty("ContentType")]
public string ContentType { get; set; }
[JsonProperty("Content")]
public string Content { get; set; }
}
public class End
{
[JsonProperty("DateTime")]
public DateTimeOffset DateTime { get; set; }
[JsonProperty("TimeZone")]
public string TimeZone { get; set; }
}
my json object looks like this:
List<ToOutlookCalendar> toOutlook = new List<ToOutlookCalendar>();
toOutlook.Add(new ToOutlookCalendar
{
Start = new End
{
DateTime = DateTimeOffset.UtcNow,
TimeZone = "Pacific Standard Time"
},
End = new End
{
DateTime = DateTimeOffset.UtcNow,
TimeZone = "Pacific Standard Time"
},
Body = new Body
{
ContentType = "HTML",
Content = "testar for att se skit"
},
Subject = "testin",
Attendees = new List<Attendee>
{
new Attendee
{
EmailAddress = new EmailAddress
{
Address = "some email",
Name = "name"
}
},
new Attendee
{
EmailAddress = new EmailAddress
{
Address = "some email",
Name = "name"
}
}
}
});
return new JsonResult
{
Data = toOutlook,
ContentType = "application/json",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
what i want to do is to make a PostAsync method like so:
var res = await ToOutlookKalendrar();
var stringPayload = await Task.Run(() => JsonConvert.SerializeObject(res));
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
var responsse = await client.PostAsync($"https://outlook.office.com/api/v2.0/{tenantDomain}/users/{userEmail}/events", stringPayload );
However this gives me 401 unauthorized, Have I missed something? do I need to include the accessToken in the Httpclient?
Update
I have added the token in the request headers but still get 401 unauthorized:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + tokenn);
Update 2
I get this error now after having included the accessToken in the header:
reason="The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.";error_category="invalid_token"
Now I'm lost, does the accesstoken need to be in the header or in the body of the json object?
Update 3
apperently I need to udate how i get the accessToken, I'll post the answer if I manage to do it right this time
Any help is appreciated!!
This question has been answered in another post, follow this link for the answer. I was using the the wrong requestURL here, everytnig is explained in the other post :)
I can't work this one out. If I use NewtonSoft to serialize the object to JSON before a HTTP Post, I receive a 400 from the REST Service. If I just post the JSON as a string, in the below code as "jsonx" it works. However, if I compare the strings "json" and "jsonx" they're the same.
public async Task<String> TransferAsync(String fromAddress, Int64 amount, String toAddress, String assetId)
{
Models.CoinPrism.TransferRequest request = new CoinPrism.TransferRequest()
{
fees = 1000,
from = fromAddress,
};
request.to[0] = new CoinPrism.Transfer()
{
address = toAddress,
amount = amount,
asset_id = assetId
};
String json = Newtonsoft.Json.JsonConvert.SerializeObject(request);
String jsonX = "{ \"fees\": 1000, \"from\": \"1zLkEoZF7Zdoso57h9si5fKxrKopnGSDn\", \"to\": [ { \"address\": \"akSjSW57xhGp86K6JFXXroACfRCw7SPv637\", \"amount\": \"10\", \"asset_id\": \"AHthB6AQHaSS9VffkfMqTKTxVV43Dgst36\" } ]}";
Uri baseAddress = new Uri("https://api.coinprism.com/");
using (var httpClient = new HttpClient { BaseAddress = baseAddress })
{
using (var content = new StringContent(jsonX, System.Text.Encoding.Default, "application/json"))
{
using (var response = await httpClient.PostAsync("v1/sendasset?format=json", content))
{
string responseData = await response.Content.ReadAsStringAsync();
return responseData;
}
}
}
}
Models
public class TransferRequest
{
public Int64 fees { get; set; }
public String from { get; set; }
public Transfer[] to { get; set; }
public TransferRequest(Int32 n = 1)
{
this.to = new Transfer[n];
}
public TransferRequest(Transfer transfer)
{
this.to = new Transfer[1];
this.to[0] = transfer;
}
}
public class Transfer
{
public String address { get; set; }
public Int64 amount { get; set; }
public String asset_id { get; set; }
}
The reason of the error is that they are identical strings but with different encoding.
You are sending the wrong encoding for the string.
1- After serializing, convert the string to ANSI encoding (for example)
2- using (var content = new StringContent(jsonX, System.Text.Encoding.ANSI, "application/json)
I'm trying to do a very simple example of using RestSharp's Execute method of querying a rest endpoint and serializing to a POCO. However, everything I try results in a response.Data object that has all properties with a NULL value.
Here is the JSON response:
{
"Result":
{
"Location":
{
"BusinessUnit": "BTA",
"BusinessUnitName": "CASINO",
"LocationId": "4070",
"LocationCode": "ZBTA",
"LocationName": "Name of Casino"
}
}
}
Here is my test code
[TestMethod]
public void TestLocationsGetById()
{
//given
var request = new RestRequest();
request.Resource = serviceEndpoint + "/{singleItemTestId}";
request.Method = Method.GET;
request.AddHeader("accept", Configuration.JSONContentType);
request.RootElement = "Location";
request.AddParameter("singleItemTestId", singleItemTestId, ParameterType.UrlSegment);
request.RequestFormat = DataFormat.Json;
//when
Location location = api.Execute<Location>(request);
//then
Assert.IsNotNull(location.LocationId); //fails - all properties are returned null
}
And here is my API code
public T Execute<T>(RestRequest request) where T : new()
{
var client = new RestClient();
client.BaseUrl = Configuration.ESBRestBaseURL;
//request.OnBeforeDeserialization = resp => { resp.ContentLength = 761; };
var response = client.Execute<T>(request);
return response.Data;
}
And finally, here is my POCO
public class Location
{
public string BusinessUnit { get; set; }
public string BusinessUnitName { get; set; }
public string LocationId { get; set; }
public string LocationCode { get; set; }
public string LocationName { get; set; }
}
Additionally, the ErrorException and ErrorResponse properties on the response are NULL.
This seems like a very simple case, but I've been running around in circles all day! Thanks.
What is the Content-Type in the response? If not a standard content type like "application/json", etc. then RestSharp won't understand which deserializer to use. If it is in fact a content type not "understood" by RestSharp (you can verify by inspecting the Accept sent in the request), then you can solve this by doing:
client.AddHandler("my_custom_type", new JsonDeserializer());
EDIT:
Ok, sorry, looking at the JSON again, you need something like:
public class LocationResponse
public LocationResult Result { get; set; }
}
public class LocationResult {
public Location Location { get; set; }
}
And then do:
client.Execute<LocationResponse>(request);