Retrieving cookies from httprequest in Xamarin.forms - web-services

help me, i couldn't get the cookies from an httprequest, i tried the plugins.settings, i tried the pcl share too, am in this problem for a month
public async Task<bool> PostAsync(AuthUser user)
{
var CookieContainer = new CookieContainer();
var handler = new HttpClientHandler() { CookieContainer =
CookieContainer };
var _client = new HttpClient(handler);
IEnumerable<string> cookieStrings = null;
//var httpClient = new HttpClient();
_client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
var json = JsonConvert.SerializeObject(user);
HttpContent httpContent = new StringContent(json);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
try
{
string url = WebServiceUrl + "j_spring_security_check?j_username=" + user.j_username +"&j_password=" + user.j_password + "&ajax=true";
HttpResponseMessage result = await _client.PostAsync(url, httpContent);
IEnumerable<string> cookies;
if (result.Headers.TryGetValues("set-cookie", out cookies))
{
foreach (var c in cookies)
{
await App.Current.MainPage.DisplayAlert("Cookie", c , "OK");
}
}
if (result.IsSuccessStatusCode)
{
using (var responsecontent = result.Content)
{
string resultString = responsecontent.ReadAsStringAsync().Result;
var response = JsonConvert.DeserializeObject<AuthUser>(resultString);
if (response.error != null)
{
await App.Current.MainPage.DisplayAlert("Error", response.result.error, "OK");
return false;
}
else if (response.result.success.Equals("1"))
{
App.Current.MainPage = new NavigationPage(new TimelineMenuPage(response.result.user_id.ToString(), response.result.token));
return true;
}
}
}
return result.IsSuccessStatusCode;
}
catch (Exception e)
{
await App.Current.MainPage.DisplayAlert("Alert", e.ToString(), "OK");
throw;
}
}
when debugging it skips this part :
if (result.Headers.TryGetValues("set-cookie", out cookies))
{
foreach (var c in cookies)
{
await App.Current.MainPage.DisplayAlert("Cookie", c , "OK");
}
}
**and then i get in CookieContainer count=0 **

Since you are already using a CookieContainer, and you will know the Uri you are getting them from, why don't you just get the Cookies directly from the Container, instead of a set-cookie command, that you will then have to parse.
cookieContainer.GetCookies(new Uri("mydomain.com"));
After your HttpRequest, it will automatically put them into the CookieContainer.

Related

Use Aws4RequestSigner to sign PAAPI 5 Request

I'm trying to use Aws4RequestSigner in a VS2015 form to sign a search request to Amazon PAAPI.
https://www.nuget.org/packages/Aws4RequestSigner/
I get this response from the API:
{"__type":"com.amazon.paapi5#IncompleteSignatureException","Errors":[{"Code":"IncompleteSignature","Message":"The request signature did not include all of the required components. If you are using an AWS SDK, requests are signed for you automatically; otherwise, go to https://webservices.amazon.com/paapi5/documentation/sending-request.html#signing."}]}
private async void Form1_Load(object sender, EventArgs e)
{
_accessKey = "x";
_secretKey = "x";
_service = "ProductAdvertisingAPIv1";
_region = "us-east-1";
_requestUri = new Uri("https://webservices.amazon.com/paapi5/searchitems");
var payload = new
{
Keywords = "Harry",
Marketplace = "www.amazon.com",
PartnerTag = "x0d-20",
PartnerType = "Associates",
Resources = new string[] { "Images.Primary.Small", "ItemInfo.Title", "Offers.Listings.Price" },
SearchIndex = "All"
};
string jsonString = JsonConvert.SerializeObject(payload);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var xAmzDate = GetTimeStamp();
content.Headers.Add("content-encoding", "amz-1.0");
content.Headers.Add("x-amz-date", xAmzDate);
content.Headers.Add("x-amz-target", "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems");
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = _requestUri,
Content = content
};
request.Headers.Host = "webservices.amazon.com";
var contentType = new MediaTypeHeaderValue("application/json");
contentType.CharSet = "utf-8";
request.Content.Headers.ContentType = contentType;
var signer = new AWS4RequestSigner(_accessKey, _secretKey);
request = await signer.Sign(request, _service, _region);
try
{
var client = new HttpClient();
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
}
// response.EnsureSuccessStatusCode();
txtDisplay.Text = await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
string error = ex.Message;
txtDisplay.Text = error;
}
}
private string GetTimeStamp()
{
return DateTime.UtcNow.ToString("yyyyMMdd\\THHmmss\\Z");
}
It could be that the headers are being added incorrectly or Aws4RequestSigner is simply outdated.

PowerBI Embedded: DeleteUserAsAdminAsync returns unauthorized

Receiving an unauthorized response when trying to remove a user from a workspace (group). I'm using the .Net SDK method DeleteUserAsAdminAsync. I tried the DeleteUserInGroupAsync method with the same result. I've had no trouble retrieving groups, reports, even adding users to groups using the same authentication code shown below. I'm quite stumped.
public async Task<ResultObject> RemoveUsersFromWorkspaces(List<PowerBIWorkspace> powerBIWorkspaces)
{
// Authenticate using created credentials
AuthenticationResult authenticationResult = null;
authenticationResult = await DoAuthentication("CustomerAppRegistration");
var tokenCredentials =
new TokenCredentials(authenticationResult.AccessToken, "Bearer");
using (var client = new PowerBIClient(
new Uri("https://api.powerbi.com/"), tokenCredentials))
{
try
{
foreach (var wksp in powerBIWorkspaces)
{
// Remove the user to the workspace.
await client.Groups.DeleteUserAsAdminAsync(new Guid(wksp.WorkspaceId), wksp.UserEmail);
}
}
catch (Exception ex)
{
var errorObject = new ResultObject();
errorObject.Success = false;
errorObject.ErrorMessage = ex.Message;
return errorObject;
}
}
var resultObject = new ResultObject();
resultObject.Success = true;
resultObject.ErrorMessage = "";
return resultObject;
}
private const string AuthorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
private const string MSGraphScope = "https://analysis.windows.net/powerbi/api/.default";
private async Task<AuthenticationResult> DoAuthentication(string appRegistrationSection)
{
var config = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json").Build();
//var section = config.GetSection(nameof(AppRegistration));
var section = config.GetSection(appRegistrationSection);
var appRegistration = section.Get<AppRegistration>();
TenantID = appRegistration.TenantId;
ClientID = appRegistration.ClientId;
ClientSecret = appRegistration.ClientSecret;
IConfidentialClientApplication daemonClient;
daemonClient = ConfidentialClientApplicationBuilder.Create(ClientID)
.WithAuthority(string.Format(AuthorityFormat, TenantID))
.WithClientSecret(ClientSecret)
.Build();
AuthenticationResult authResult =
await daemonClient.AcquireTokenForClient(new[] { MSGraphScope }).ExecuteAsync();
return authResult;
}

Api Response as a List / fetching all the data from api response

I am new to .netcore mvc architecture. I am trying to consume the api data response, So far I have successfully fetched the data, but the problem I am facing is when the api response/result is more than one. Forexample if the actuall api response is the following
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"title:\"A\""}},
"response":{"numFound":3,"start":0,"docs":[
{
"date":"1970-01-01T00:00:00Z",
"tstamp":"2019-11-22T12:22:31.698Z",
"digest":"e23d679991d80d832504e7395d139fe4",
"contentLength":"25476",
"boost":0.0,
"title":["emb- A1]
"url":"https://www.example.com/a/b/c0/"},
{
"date":"1970-01-01T00:00:00Z",
"tstamp":"2019-11-22T12:22:31.698Z",
"digest":"e23d679991d80d832504e7395d139fe4",
"contentLength":"25476",
"boost":0.0,
"title":["emb - A2]
"url":"https://www.example.com/a/b/c1/"
},
{
"date":"1970-01-01T00:00:00Z",
"tstamp":"2019-11-22T12:22:31.698Z",
"digest":"e23d679991d80d832504e7395d139fe4",
"contentLength":"25476",
"boost":0.0,
"title":["emb - A3]
"url":"https://www.example.com/a/b/c2/"
}
I am only getting
{"title":"[\r\n \"emb- A1","source":"https://www.example.com/a/b/c0/"}
instead of having all the response data.
My Code is below.
Model
SearchModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace searchEngineTesting.Models
{
public class SearchModel
{
public string Title;
public string Source;
}
}
Controller
EngineController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using searchEngineTesting.Models;
namespace searchEngineTesting.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EngineController : ControllerBase {
[HttpGet("[action]/{query}")]
public async Task<IActionResult> Product(string query)
{
var model = new SearchModel();
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var root = (JObject)JsonConvert.DeserializeObject(stringResult);
//var details = JsonConvert.DeserializeObject<SearchModel>(stringResult);
var items = root.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var item in items)
{
if (item.Key == "response")
{
var key = item.Value.SelectToken("").OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var k in key)
{
if(k.Key == "docs")
{
var tests = JsonConvert.DeserializeObject<JArray>(k.Value.ToString());
var data = k.Value.SelectToken("").Children().First();
var test = data.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value).ToList();
foreach (var t in test)
{
if (t.Key =="url")
{
model.Source = t.Value.ToString();
}
else if (t.Key == "title")
{
model.Title = t.Value.ToString(); }
}
}
}
}
}
return new JsonResult(model);
}
catch (InvalidOperationException httpreq) {
return BadRequest("Sorry: There are no results for your query");
}
}
}
}
}
How can I retrieve whole of the response I am getting from actual API.
Please help..!
How can I retrieve whole of the response I am getting from actual API.
If you want to return all the actual api response,then just use below code:
[HttpGet("[action]/{query}")]
public async Task<IActionResult> Product(string query)
{
var model = new SearchModel();
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var root = (JObject)JsonConvert.DeserializeObject(stringResult);
return new JsonResult(root);
}
catch (InvalidOperationException httpreq)
{
}
}
return Ok()
}
If you would like to just return List<SearchModel> from the actual response,you should not use var data = k.Value.SelectToken("").Children().First(); which will only retrieve the first element of docs array.
Try to foreach k.Value.SelectToken("").Children() and return List<SearchModel> instead of a SearchModel,refer to
[HttpGet("[action]/{query}")]
public async Task<IActionResult> Product(string query)
{
//initialize a list SearchModel
var modelList = new List<SearchModel>();
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var root = (JObject)JsonConvert.DeserializeObject(stringResult);
var items = root.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var item in items)
{
if (item.Key == "response")
{
var key = item.Value.SelectToken("").OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var k in key)
{
if (k.Key == "docs")
{
//remove .First()
var arrayData = k.Value.SelectToken("").Children();
foreach(var data in arrayData)
{
var model = new SearchModel();
var test = data.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value).ToList();
foreach (var t in test)
{
if (t.Key == "url")
{
model.Source = t.Value.ToString();
}
else if (t.Key == "title")
{
model.Title = t.Value.ToString();
}
}
modelList.Add(model);
}
}
}
}
}
return new JsonResult(modelList);
}
catch (InvalidOperationException httpreq)
{
}
}
return Ok();
}
Your model is not a list, but only a single object which you would overwrite continuously in your loop so that only one element remains.
Then you will need to iterate over all docs, not just use the first (e.g. k.Value.SelectToken("").Children().First()).
So you should be able to resolve your issue by changing your model to a List of SearchModels, and ensuring to iterate through all documents (it helps to inspect the variables in a debugger to see what happens).
An easier approach would be using JsonConvert, where you just would need to mirror the relevant structure of the JSON using C# classes, e.g.:
public class Document
{
public string Title;
public string Url;
}
public class Result
{
public Response response;
}
public class Response
{
public List<Document> docs;
}
then deserialize the json simple as:
var result = JsonConvert.DeserializeObject<Result>(stringResult);
and finally converting the result to your SearchModel:
var searchModels = result.response.docs.Select(x => new SearchModel {Source = x.Url, Title = x.Title}).ToList();

How to share post in facebook by using Xamarin Forms

I'm currently working on Xamarin and I'm confused with the facebook sharing option in xamarin forms particularly in Xamarin Android the IOS code is
public void ShareOnFacebook(IFacebookDelegate pDele)
{
string[] perm = {"publish_actions"};
if (AccessToken.CurrentAccessToken == null || !AccessToken.CurrentAccessToken.HasGranted("publish_actions"))
{
UIViewController mainController = UIApplication.SharedApplication.KeyWindow.RootViewController;
_manager.LogInWithPublishPermissions(perm, mainController, (result, error) =>
{
if (error != null || result.IsCancelled)
{
}
else {
ShareNow();
}
});
} else {
ShareNow();
}
}
The only thing which stops me is Xamarin Android facebook post sharing.
Can anyone modify this code according to Xamarin Android Or share his/her own code .
I have implemented share for twitter and fb .
iOS version
you can share using native social services from ios and if not available use
OAuth2Authenticator to get access token then post using FB graph
public void ShareViaSocial(string serviceType, string urlToShare)
{
socialKind = serviceType == "Twitter" ? SLServiceKind.Twitter : SLServiceKind.Facebook;
if (SLComposeViewController.IsAvailable(socialKind))
{
_socialComposer = serviceType == "Twitter" ? SLComposeViewController.FromService(SLServiceType.Twitter) : SLComposeViewController.FromService(SLServiceType.Facebook);
_socialComposer.AddUrl(new Uri(urlToShare));
viewController.PresentViewController(_socialComposer, true, () =>
{
_socialComposer.CompletionHandler += (result) =>
{
Device.BeginInvokeOnMainThread(() =>
{
viewController.DismissViewController(true, null);
if (result == SLComposeViewControllerResult.Done)
{ OnShare(this, ShareStatus.Successful); }
else
{ OnShare(this, ShareStatus.NotSuccessful); }
});
};
});
}
//If user doest have fb app and no credential for social services we use fb graph
else if (socialKind == SLServiceKind.Facebook)
{
var auth = new OAuth2Authenticator(
clientId: SharedConstants.FacebookLiveClientId,
scope: SharedConstants.FacebookScopes,
authorizeUrl: new Uri(SharedConstants.FacebookAuthorizeUrl),
redirectUrl: new Uri(SharedConstants.FacebookRedirectUrl));
viewController.PresentViewController((UIViewController)auth.GetUI(), true, null);
auth.AllowCancel = true;
auth.Completed += (s, e) =>
{
//hide the webpage after completed login
viewController.DismissViewController(true, null);
// We presented the UI, so it's up to us to dimiss it on iOS.
if (e.IsAuthenticated)
{
Account fbAccount = e.Account;
Dictionary<string, string> dictionaryParameters = new Dictionary<string, string>() { { "link", urlToShare } };
var requestUrl = new Uri("https://graph.facebook.com/me/feed");
var request = new OAuth2Request(SharedConstants.requestMethodPOST, requestUrl, dictionaryParameters, fbAccount);
request.GetResponseAsync().ContinueWith(this.requestResult);
}
else { OnShare(this, ShareStatus.NotSuccessful); }
};
auth.Error += Auth_Error;
}
//If user doest have twitter app and no credential for social services we use xanarub auth for token and call twitter api for sending tweets
else
{
var auth = new OAuth1Authenticator(
SharedConstants.TwitterConsumerKey,
SharedConstants.TwitterConsumerSecret,
new Uri(SharedConstants.TwitterRequestUrl),
new Uri(SharedConstants.TwitterAuth),
new Uri(SharedConstants.TwitterAccessToken),
new Uri(SharedConstants.TwitterCallBackUrl));
auth.AllowCancel = true;
// auth.ShowUIErrors = false;
// If authorization succeeds or is canceled, .Completed will be fired.
auth.Completed += (s, e) =>
{
// We presented the UI, so it's up to us to dismiss it.
viewController.DismissViewController(true, null);
if (e.IsAuthenticated)
{
Account twitterAccount = e.Account;
Dictionary<string, string> dictionaryParameters = new Dictionary<string, string>() { { "status", urlToShare } };
var request = new OAuth1Request(SharedConstants.requestMethodPOST, new Uri("https://api.twitter.com/1.1/statuses/update.json"), dictionaryParameters, twitterAccount);
//for testing var request = new OAuth1Request("GET",new Uri("https://api.twitter.com/1.1/account/verify_credentials.json "),null, twitterAccount);
request.GetResponseAsync().ContinueWith(this.requestResult);
}
else { OnShare(this, ShareStatus.NotSuccessful); }
};
auth.Error += Auth_Error;
//auth.IsUsingNativeUI = true;
viewController.PresentViewController((UIViewController)auth.GetUI(), true, null);
}
}
Android version
You can use native facebook ShareDialog and if isn't available use OAuth2Authenticator to get access token then post using FB graph
and using OAuth1Authenticator for posing on twitter
public void ShareViaSocial(string serviceType, string urlToShare)
{
ShareDialog di = new ShareDialog(MainActivity.Instance);
var facebookShareContent = new ShareLinkContent.Builder();
facebookShareContent.SetContentUrl(Android.Net.Uri.Parse(urlToShare));
if (serviceType == "Facebook")
{
if (di.CanShow(facebookShareContent.Build(), ShareDialog.Mode.Automatic))
{
di.Show(facebookShareContent.Build());
}
else
{
var auth = new OAuth2Authenticator(
clientId: 'ClientId',
scope: "public_profile,publish_actions",
authorizeUrl: new Uri("https://m.facebook.com/dialog/oauth/"),
redirectUrl: new Uri( "http://www.facebook.com/connect/login_success.html"));
MainActivity.Instance.StartActivity(auth.GetUI(MainActivity.Instance.ApplicationContext));
auth.AllowCancel = true;
auth.Completed += (s, e) =>
{
if (e.IsAuthenticated)
{
Account fbAccount = e.Account;
Dictionary<string, string> dictionaryParameters = new Dictionary<string, string>() { { "link", urlToShare } };
var requestUrl = new Uri("https://graph.facebook.com/me/feed");
var request = new OAuth2Request(SharedConstants.requestMethodPOST, requestUrl, dictionaryParameters, fbAccount);
request.GetResponseAsync().ContinueWith(this.requestResult);
}
else { OnShare(this, ShareStatus.NotSuccessful); }
};
auth.Error += Auth_Error;
}
}
else
{
var auth = new OAuth1Authenticator(
'TwitterConsumerKey',
'TwitterConsumerSecret',
new Uri("https://api.twitter.com/oauth/request_token"),
new Uri("https://api.twitter.com/oauth/authorize"),
new Uri("https://api.twitter.com/oauth/access_token"),
new Uri('TwitterCallBackUrl'));
auth.AllowCancel = true;
// auth.ShowUIErrors = false;
// If authorization succeeds or is canceled, .Completed will be fired.
auth.Completed += (s, e) =>
{
// We presented the UI, so it's up to us to dismiss it.
if (e.IsAuthenticated)
{
Account twitterAccount = e.Account;
Dictionary<string, string> dictionaryParameters = new Dictionary<string, string>() { { "status", urlToShare } };
var request = new OAuth1Request(SharedConstants.requestMethodPOST, new Uri("https://api.twitter.com/1.1/statuses/update.json"), dictionaryParameters, twitterAccount);
//for testing var request = new OAuth1Request("GET",new Uri("https://api.twitter.com/1.1/account/verify_credentials.json "),null, twitterAccount);
request.GetResponseAsync().ContinueWith(this.requestResult);
}
else { OnShare(this, ShareStatus.NotSuccessful); }
};
auth.Error += Auth_Error;
//auth.IsUsingNativeUI = true;
MainActivity.Instance.StartActivity(auth.GetUI(MainActivity.Instance.ApplicationContext));
}
}

Get the AccessToken of Facebook without login using HttpWebRequest for WP8

I am trying to get the accesstoken like this,
string uri = "https://graph.facebook.com/oauth/access_token?client_id=" +
APP_ID +
"&redirect_uri=&client_secret=" + APP_SECRET + "&grant_type=client_credentials";
var access_token = GetMyData(uri);
public async Task<string> GetMyData(string urlToCall)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToCall);
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
using (var sr = new StreamReader(response.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}
It gets stuck in the var taskComplete = new TaskCompletionSource(); and takes a lot of time and does not get the accesstoken also.what is wrong?
You can probably achieve this with the following code
public void GetMyData(string urlToCall)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(urlToCall);
request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallback), request);
}
private static void ReadWebRequestCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse myResponse = (HttpWebResponse)myRequest.EndGetResponse(callbackResult);
using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
{
// Here you get the result
string results = httpwebStreamReader.ReadToEnd();
}
myResponse.Close();
}