WP8 HttpClient.PostAsync never returns result - c#

I have a Windows Phone 8 app where I am calling await HttpClient.PostAsync and it never returns a result. It just sits there and hangs. If I run the exact same code from a console app, it returns the result almost immediately. All of the code doing the work resides in a portable class library. I would appreciate any help you may be able to give. All of the other issues I have found on this state to use await client.PostAsync, which I am already doing.
The code in my class library is as such:
public class Authenticator
{
private const string ApiBaseUrl = "http://api.fitbit.com";
private const string Callback = "http://myCallbackUrlHere";
private const string SignatureMethod = "HMAC-SHA1";
private const string OauthVersion = "1.0";
private const string ConsumerKey = "myConsumerKey";
private const string ConsumerSecret = "myConsumerSecret";
private const string RequestTokenUrl = "http://api.fitbit.com/oauth/request_token";
private const string AccessTokenUrl = "http://api.fitbit.com/oauth/access_token";
private const string AuthorizeUrl = "http://www.fitbit.com/oauth/authorize";
private string requestToken;
private string requestTokenSecret;
public string GetAuthUrlToken()
{
return GenerateAuthUrlToken().Result;
}
private async Task<string> GenerateAuthUrlToken()
{
var httpClient = new HttpClient { BaseAddress = new Uri(ApiBaseUrl) };
var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
var oauthTimestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);
var oauthNonce = DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture);
var authHeaderValue = string.Format(
"oauth_callback=\"{0}\",oauth_consumer_key=\"{1}\",oauth_nonce=\"{2}\"," +
"oauth_signature=\"{3}\",oauth_signature_method=\"{4}\"," +
"oauth_timestamp=\"{5}\",oauth_version=\"{6}\"",
Uri.EscapeDataString(Callback),
Uri.EscapeDataString(ConsumerKey),
Uri.EscapeDataString(oauthNonce),
Uri.EscapeDataString(this.CreateSignature(RequestTokenUrl, oauthNonce, oauthTimestamp, Callback)),
Uri.EscapeDataString(SignatureMethod),
Uri.EscapeDataString(oauthTimestamp),
Uri.EscapeDataString(OauthVersion));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"OAuth",
authHeaderValue);
var content = new StringContent(string.Empty);
var response = await httpClient.PostAsync(RequestTokenUrl, content);
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception("Request Token Step Failed");
}
var responseContent = await response.Content.ReadAsStringAsync();
var responseItems = responseContent.Split(new[] { '&' });
this.requestToken = responseItems[0];
this.requestTokenSecret = responseItems[1];
var url = string.Format("{0}?{1}&display=touch", AuthorizeUrl, this.requestToken);
return url;
}
public string CreateSignature(string url, string nonce, string timestamp, string callback)
{
// code removed
return signatureString;
}
private static byte[] StringToAscii(string s)
{
// code removed
return retval;
}
}
I have a console app that calls this library and it works with no problem:
public class Program
{
public static void Main(string[] args)
{
var o = new Program();
o.LinkToFitbit();
}
public void LinkToFitbit()
{
var authenticator = new Authenticator();
// this works and returns the url immediately
var url = authenticator.GetAuthUrlToken();
// code removed
}
}
When I run from my WP8 app, it just hangs when it gets to this line in the library:
var response = await httpClient.PostAsync(RequestTokenUrl, content);
Here is my WP8 code:
public partial class FitbitConnector : PhoneApplicationPage
{
public FitbitConnector()
{
InitializeComponent();
this.AuthenticateUser();
}
private void AuthenticateUser()
{
var authenticator = new Authenticator();
var url = authenticator.GetAuthUrlToken();
// code removed
}
}

This line is blocking the UI thread:
public string GetAuthUrlToken()
{
return GenerateAuthUrlToken().Result;
}
The code after the await httpClient.PostAsync() needs to be executed in the UI thread, but it can't be executed because is is blocked.
So, replace this:
private void AuthenticateUser()
{
var authenticator = new Authenticator();
var url = authenticator.GetAuthUrlToken();
// code removed
}
With this:
private async void AuthenticateUser()
{
var authenticator = new Authenticator();
var url = await authenticator.GenerateAuthUrlToken();
// code removed
}
Notice I am using async and await. You will need to make GenerateAuthUrlToken() public. You can erase GetAuthUrlToken().
In few words, Task<T>.Result is not asynchronous.

Can you post CreateSignature and StringToAscii code ? I am stuck at basic oAuth.
I can get Request token but get "Invalid OAuth Signature" while performing a request for Access Token.

Nexus, here you go. I created an OauthHelper class that I use to build the pieces I need. Have a look below. I hope this helps.
public static class OauthHelper
{
public const string ConsumerKey = "MyKey";
public const string ConsumerSecret = "MySecret";
public const string UriScheme = "https";
public const string HostName = "api.somePlace.com";
public const string RequestPath = "/services/api/json/1.3.0";
public const string OauthSignatureMethod = "HMAC-SHA1";
public const string OauthVersion = "1.0";
public static string BuildRequestUri(Dictionary<string, string> requestParameters)
{
var url = GetNormalizedUrl(UriScheme, HostName, RequestPath);
var allParameters = new List<QueryParameter>(requestParameters.Select(entry => new QueryParameter(entry.Key, entry.Value)));
var normalizedParameters = NormalizeParameters(allParameters);
var requestUri = string.Format("{0}?{1}", url, normalizedParameters);
return requestUri;
}
public static AuthenticationHeaderValue CreateAuthorizationHeader(
string oauthToken,
string oauthNonce,
string oauthTimestamp,
string oauthSignature)
{
var normalizedUrl = GetNormalizedUrl(UriScheme, HostName, RequestPath);
return CreateAuthorizationHeader(oauthToken, oauthNonce, oauthTimestamp, oauthSignature, normalizedUrl);
}
public static AuthenticationHeaderValue CreateAuthorizationHeader(
string oauthToken,
string oauthNonce,
string oauthTimestamp,
string oauthSignature,
string realm)
{
if (string.IsNullOrWhiteSpace(oauthToken))
{
oauthToken = string.Empty;
}
if (string.IsNullOrWhiteSpace(oauthTimestamp))
{
throw new ArgumentNullException("oauthTimestamp");
}
if (string.IsNullOrWhiteSpace(oauthNonce))
{
throw new ArgumentNullException("oauthNonce");
}
if (string.IsNullOrWhiteSpace(oauthSignature))
{
throw new ArgumentNullException("oauthSignature");
}
var authHeaderValue = string.Format(
"realm=\"{0}\"," +
"oauth_consumer_key=\"{1}\"," +
"oauth_token=\"{2}\"," +
"oauth_nonce=\"{3}\"," +
"oauth_timestamp=\"{4}\"," +
"oauth_signature_method=\"{5}\"," +
"oauth_version=\"{6}\"," +
"oauth_signature=\"{7}\"",
realm,
Uri.EscapeDataString(ConsumerKey),
Uri.EscapeDataString(oauthToken),
Uri.EscapeDataString(oauthNonce),
Uri.EscapeDataString(oauthTimestamp),
Uri.EscapeDataString(OauthSignatureMethod),
Uri.EscapeDataString(OauthVersion),
Uri.EscapeDataString(oauthSignature));
var authHeader = new AuthenticationHeaderValue("OAuth", authHeaderValue);
return authHeader;
}
public static string CreateSignature(
string httpMethod,
string oauthToken,
string oauthTokenSecret,
string oauthTimestamp,
string oauthNonce,
Dictionary<string, string> requestParameters)
{
// get normalized url
var normalizedUrl = GetNormalizedUrl(UriScheme, HostName, RequestPath);
return CreateSignature(
httpMethod,
oauthToken,
oauthTokenSecret,
oauthTimestamp,
oauthNonce,
requestParameters,
normalizedUrl);
}
public static string CreateSignature(
string httpMethod,
string oauthToken,
string oauthTokenSecret,
string oauthTimestamp,
string oauthNonce,
Dictionary<string, string> requestParameters,
string realm)
{
if (string.IsNullOrWhiteSpace(httpMethod))
{
throw new ArgumentNullException("httpMethod");
}
if (string.IsNullOrWhiteSpace(oauthToken))
{
oauthToken = string.Empty;
}
if (string.IsNullOrWhiteSpace(oauthTokenSecret))
{
oauthTokenSecret = string.Empty;
}
if (string.IsNullOrWhiteSpace(oauthTimestamp))
{
throw new ArgumentNullException("oauthTimestamp");
}
if (string.IsNullOrWhiteSpace(oauthNonce))
{
throw new ArgumentNullException("oauthNonce");
}
var allParameters = new List<QueryParameter>
{
new QueryParameter("oauth_consumer_key", ConsumerKey),
new QueryParameter("oauth_token", oauthToken),
new QueryParameter("oauth_nonce", oauthNonce),
new QueryParameter("oauth_timestamp", oauthTimestamp),
new QueryParameter("oauth_signature_method", OauthSignatureMethod),
new QueryParameter("oauth_version", OauthVersion)
};
allParameters.AddRange(requestParameters.Select(entry => new QueryParameter(entry.Key, entry.Value)));
// sort params
allParameters.Sort(new QueryParameterComparer());
// concat all params
var normalizedRequestParameters = NormalizeParameters(allParameters);
// create base string
var signatureBase = string.Format(
"{0}&{1}&{2}",
UrlEncode(httpMethod.ToUpperInvariant()),
UrlEncode(realm),
UrlEncode(normalizedRequestParameters));
var signatureKey = string.Format(
"{0}&{1}",
UrlEncode(ConsumerSecret),
UrlEncode(oauthTokenSecret));
// hash the base string
var hmacsha1 = new HMACSHA1(StringToAscii(signatureKey));
var signatureString = Convert.ToBase64String(hmacsha1.ComputeHash(StringToAscii(signatureBase)));
return signatureString;
}
public static string GenerateNonce()
{
var ts = new TimeSpan(DateTime.Now.Ticks);
var ms = ts.TotalMilliseconds.ToString().Replace(".", string.Empty);
var nonce = ms;
return nonce;
}
public static string GenerateTimeStamp()
{
var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
var timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);
return timestamp;
}
private static string GetNormalizedUrl(string uriScheme, string hostName, string requestPath)
{
var normalizedUrl = string.Format(
"{0}://{1}{2}",
uriScheme.ToLowerInvariant(),
hostName.ToLowerInvariant(),
requestPath);
return normalizedUrl;
}
private static string NormalizeParameters(IList<QueryParameter> parameters)
{
var result = new StringBuilder();
for (var i = 0; i < parameters.Count; i++)
{
var p = parameters[i];
result.AppendFormat("{0}={1}", p.Name, p.Value);
if (i < parameters.Count - 1)
{
result.Append("&");
}
}
return result.ToString();
}
private static byte[] StringToAscii(string s)
{
var retval = new byte[s.Length];
for (var ix = 0; ix < s.Length; ++ix)
{
var ch = s[ix];
if (ch <= 0x7f)
{
retval[ix] = (byte)ch;
}
else
{
retval[ix] = (byte)'?';
}
}
return retval;
}
private static string UrlEncode(string value)
{
const string Unreserved = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
var result = new StringBuilder();
foreach (char symbol in value)
{
if (Unreserved.IndexOf(symbol) != -1)
{
result.Append(symbol);
}
else
{
result.Append('%' + string.Format("{0:X2}", (int)symbol));
}
}
return result.ToString();
}
}
public class QueryParameter
{
public QueryParameter(string name, string value)
{
this.Name = name;
this.Value = value;
}
public string Name { get; private set; }
public string Value { get; private set; }
}
public class QueryParameterComparer : IComparer<QueryParameter>
{
public int Compare(QueryParameter x, QueryParameter y)
{
return x.Name == y.Name
? string.Compare(x.Value, y.Value)
: string.Compare(x.Name, y.Name);
}
}

Since you are using .Result or .Wait or await this will end up causing a deadlock in your code.
you can use ConfigureAwait(false) in async methods for preventing deadlock
like this:
var response = await httpClient.PostAsync(RequestTokenUrl, content).ConfigureAwait(false);
you can use ConfigureAwait(false) wherever possible for Don't Block Async Code .

Related

Objective-c (c#): calling (void) method while -init

I'm trying to rewrite C# code to equivalent objective-c code and get some kind of trouble with called void function inside of -init method.
There are two constructors in C# code, one of them calls void method with different params. I've no idea how to deal with it in objective-c (feels like a novice). I will gladly accept any advice!
C# class:
namespace Translation
{
public class Adapter
{
private readonly int dirId;
private readonly string serviceUrl;
private readonly string clientName;
private readonly string clientSecret;
private static Ticket _ticket = null;
private static object _ticketSync = new object();
public Adapter(int dirId, string configUrl)
{
this.dirId = dirId;
string[] directions;
//method i'm trying to call
GetConfigInfo(configUrl, out serviceUrl, out clientName, out clientSecret, out directions);
}
public Adapter(int dirId, string serviceUrl, string clientName, string clientSecret)
{
this.dirId = dirId;
this.serviceUrl = serviceUrl;
this.clientName = clientName;
this.clientSecret = clientSecret;
}
public static void GetConfigInfo(string configUrl,
out string serviceUrl, out string clientName, out string clientSecret, out string[] directions)
{
var configXml = new XmlDocument();
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("tests", "test");
var xml = client.DownloadString(configUrl);
configXml.LoadXml(xml);
}
serviceUrl = configXml.DocumentElement.SelectSingleNode("Url").InnerText.Trim();
clientName = configXml.DocumentElement.SelectSingleNode("Client").InnerText.Trim();
clientSecret = configXml.DocumentElement.SelectSingleNode("Secret").InnerText.Trim();
directions = configXml.DocumentElement.SelectSingleNode("Directions").InnerText.Trim().
Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
public static KeyValuePair<string, string>[] ParseTopicsInfo(string xml)
{
var topicsXml = new XmlDocument();
topicsXml.LoadXml(xml);
var result = topicsXml.SelectNodes("templates/template").OfType<XmlNode>().
Select(node =>
{
var topicId = node.SelectSingleNode("id").InnerText;
var topicName = node.SelectSingleNode("name").InnerText;
return new KeyValuePair<string, string>(topicId, topicName);
}).ToArray();
return result;
}
private Ticket CreateTicket(ServiceSoap serviceSoap)
{
if (_ticket == null || _ticket.UtcExpiredAt < DateTime.UtcNow.AddSeconds(30))
lock (_ticketSync)
if (_ticket == null || _ticket.UtcExpiredAt < DateTime.UtcNow.AddSeconds(30))
_ticket = serviceSoap.CreateTicket(clientName, clientSecret);
return _ticket;
}
public void Translate(IRanges inRanges, IRanges outRanges)
{
string text = inRanges.Text;
outRanges.OriginText = text;
bool showVariants = inRanges.Properties.GetValue(RangePropertyName.LONG_VARIANTS) != null;
bool translitUnknown = inRanges.Properties.GetValue(RangePropertyName.TRANSLIT_UNKNOWN) != null;
var topicId = (string)inRanges.Properties.GetValue(RangePropertyName.PROFILE);
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
outRanges.Text = soap.TranslateText(ticket.Token,
dirId.ToPrefix(), topicId, text, showVariants, translitUnknown);
}
}
public FindSamplesResult FindSamples(string topic, string text, int page, int pageSize, string contains, int flags)
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return soap.FindSamples(ticket.Token,
dirId.ToPrefix(), topic, text, page, pageSize, contains, flags, System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName);
}
}
public KeyValuePairSOfStringInt32[] GetSampleStats(string text)
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return soap.GetSampleStats(ticket.Token,
dirId.ToPrefix(), text);
}
}
public string GetTranslateSiteUrl(string url, string topic)
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return soap.GetTranslateSiteUrl(ticket.Token,
dirId.ToPrefix(), topic, url, System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName);
}
}
public string GetDirections()
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return soap.GetDirectionsFor(ticket.Token, "text");
}
}
public string DetectLanguage(string text)
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return soap.AutoDetectLang(ticket.Token, text);
}
}
public GetEdInfoOrTranslateTextResult GetEdInfoOrTranslateText(string topic, string text)
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return soap.GetEdInfoOrTranslateText(ticket.Token,
dirId.ToPrefix(), topic, text, System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName);
}
}
public KeyValuePair<string, string>[] GetTopics()
{
using (var soap = new ServiceSoap())
{
soap.Url = serviceUrl;
var ticket = CreateTicket(soap);
return ParseTopicsInfo(soap.GetTopics(ticket.Token, System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName));
}
}
#region Not implemented
public void Initialize(string dirsPath, string k8Path, string mainClsid, int mainDirId, string mainPrefix, Data.IDictionaries dicts, object lms)
{
throw new NotImplementedException();
}
public string TranslateWord(string text, object flags)
{
throw new NotImplementedException();
}
public void Parse(IRanges inRanges, IRanges outRanges)
{
throw new NotImplementedException();
}
public void ParseToRangesMorphologizator(IRanges inRanges, IRanges outRanges)
{
throw new NotImplementedException();
}
public void ParseToRangesMorphologizatorAfterHR(IRanges inRanges, IRanges outRanges)
{
throw new NotImplementedException();
}
#endregion
[WebServiceBindingAttribute(Name = "test1", Namespace = "http://api.test.test/")]
public class ServiceSoap : SoapHttpClientProtocol
{
public new string Url
{
get
{
return base.Url;
}
set
{
base.Url = value;
base.UseDefaultCredentials = IsLocalFileSystemWebService(value);
}
}
[SoapDocumentMethodAttribute("http://api.test.test/CreateTicket")]
public Ticket CreateTicket(string ClientName, string ClientSecret)
{
var results = this.Invoke("CreateTicket", new object[]
{
ClientName,
ClientSecret
});
return (Ticket)results[0];
}
[SoapDocumentMethodAttribute("http://api.test.test/GetDirectionsFor")]
public string GetDirectionsFor(string Token, string For)
{
var results = this.Invoke("GetDirectionsFor", new object[]
{
Token,
For
});
return (string)results[0];
}
[SoapDocumentMethodAttribute("http://api.test.test/GetTopics")]
public string GetTopics(string Token, string Lang)
{
var results = this.Invoke("GetTopics", new object[]
{
Token,
Lang
});
return (string)results[0];
}
[SoapDocumentMethodAttribute("http://api.test.test/TranslateText")]
public string TranslateText(string Token, string DirCode, string TplId, string Text, bool ShowVariants, bool TranslitUnknown)
{
var results = this.Invoke("TranslateText", new object[]
{
Token,
DirCode,
TplId,
Text,
ShowVariants,
TranslitUnknown
});
return (string)results[0];
}
[SoapDocumentMethodAttribute("http://api.test.test/GetEdInfoOrTranslateText")]
public GetEdInfoOrTranslateTextResult GetEdInfoOrTranslateText(string Token, string DirCode, string TplId, string Text, string Lang)
{
var results = this.Invoke("GetEdInfoOrTranslateText", new object[]
{
Token,
DirCode,
TplId,
Text,
Lang
});
return (GetEdInfoOrTranslateTextResult)results[0];
}
[SoapDocumentMethodAttribute("http://api.test.test/AutoDetectLang")]
public string AutoDetectLang(string Token, string Text)
{
var results = this.Invoke("AutoDetectLang", new object[]
{
Token,
Text
});
return (string)results[0];
}
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://api.test.test/FindSamples", RequestNamespace = "http://api.test.test/", ResponseNamespace = "http://api.test.test/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public FindSamplesResult FindSamples(string Token, string DirCode, string Topic, string Text, int Page, int PageSize, string Contains, int Flags, string Lang)
{
object[] results = this.Invoke("FindSamples", new object[] {
Token,
DirCode,
Topic,
Text,
Page,
PageSize,
Contains,
Flags,
Lang});
return ((FindSamplesResult)(results[0]));
}
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://api.test.test/GetSampleStats", RequestNamespace = "http://api.test.test/", ResponseNamespace = "http://api.test.test/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public KeyValuePairSOfStringInt32[] GetSampleStats(string Token, string DirCode, string Text)
{
object[] results = this.Invoke("GetSampleStats", new object[] {
Token,
DirCode,
Text
});
return ((KeyValuePairSOfStringInt32[])(results[0]));
}
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://api.test.test/GetTranslateSiteUrl", RequestNamespace = "http://api.test.test/", ResponseNamespace = "http://api.test.test/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string GetTranslateSiteUrl(string Token, string DirCode, string TopicId, string URL, string Lang)
{
object[] results = this.Invoke("GetTranslateSiteUrl", new object[] {
Token,
DirCode,
TopicId,
URL,
Lang
});
return (string)results[0];
}
private static bool IsLocalFileSystemWebService(string url)
{
if (string.IsNullOrEmpty(url))
return false;
var wsUri = new Uri(url);
if (wsUri.Port >= 1024 && string.Equals(wsUri.Host, "localhost", StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
}
[XmlTypeAttribute(Namespace = "http://api.test.test/")]
public class Ticket
{
public string Token;
public DateTime UtcExpiredAt;
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://api.test.test/")]
public partial class SampleRun
{
private int positionField;
private int lengthField;
/// <remarks/>
public int Position
{
get
{
return this.positionField;
}
set
{
this.positionField = value;
}
}
/// <remarks/>
public int Length
{
get
{
return this.lengthField;
}
set
{
this.lengthField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://api.test.test/")]
public partial class Sample
{
private string corpusIdField;
private string sourceField;
private string translationField;
private SampleRun[] sourceRunsField;
private SampleRun[] translationRunsField;
/// <remarks/>
public string CorpusId
{
get
{
return this.corpusIdField;
}
set
{
this.corpusIdField = value;
}
}
/// <remarks/>
public string Source
{
get
{
return this.sourceField;
}
set
{
this.sourceField = value;
}
}
/// <remarks/>
public string Translation
{
get
{
return this.translationField;
}
set
{
this.translationField = value;
}
}
/// <remarks/>
public SampleRun[] SourceRuns
{
get
{
return this.sourceRunsField;
}
set
{
this.sourceRunsField = value;
}
}
/// <remarks/>
public SampleRun[] TranslationRuns
{
get
{
return this.translationRunsField;
}
set
{
this.translationRunsField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://api.test.test/")]
public partial class KeyValuePairSOfStringInt32
{
private string keyField;
private int valueField;
/// <remarks/>
public string Key
{
get
{
return this.keyField;
}
set
{
this.keyField = value;
}
}
/// <remarks/>
public int Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
#region Samples
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://api.test.test/")]
public partial class GetSampleStatsResult
{
private KeyValuePairSOfStringInt32[] translationsField;
public KeyValuePairSOfStringInt32[] Translations
{
get
{
return this.translationsField;
}
set
{
this.translationsField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://api.test.test/")]
public partial class FindSamplesResult
{
private int totalsField;
private Sample[] samplesField;
private KeyValuePairSOfStringInt32[] corpusesField;
/// <remarks/>
public int Totals
{
get
{
return this.totalsField;
}
set
{
this.totalsField = value;
}
}
/// <remarks/>
public Sample[] Samples
{
get
{
return this.samplesField;
}
set
{
this.samplesField = value;
}
}
/// <remarks/>
public KeyValuePairSOfStringInt32[] Corpuses
{
get
{
return this.corpusesField;
}
set
{
this.corpusesField = value;
}
}
}
#endregion
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://api.test.test/")]
public partial class GetEdInfoOrTranslateTextResult
{
public string ResultType { get; set; }
public string ResultText { get; set; }
}
}
}
Objective-c .h:
#interface Ticket : NSObject
{
NSString* token;
NSDate* dateTimeUtcExpiredAt;
}
#end
#interface SampleRun : NSObject
#property int* position;
#property int* length;
#end
#interface Sample : NSObject
#property NSString* corpusId;
#property NSString* source;
#property NSString* translation;
#property SampleRun* SourceRuns;
#property SampleRun* TranslationRuns;
#end
#interface KeyValuePairsOfStringInt32
#property int* totals;
#property Sample* samples;
#property KeyValuePairsOfStringInt32* corpuses;
#end
#interface GetEdInfoOrTranslateTextResult
#property NSString* resultType;
#property NSString* resultText;
#end
#interface Adapter : NSObject
{
Ticket* _ticket;
NSObject* _ticketSync;
}
#property int* dirId;
#property NSString* serviceUrl;
#property NSString* clientName;
#property NSString* clientSecret;
-(void)getConfigInfoWithConfigUrl: (NSString*) _configUrl AndServiceUrl: (NSString*) _servireUrl AndClientName: (NSString*) _clientName AndClientSecret: (NSString*) _clinetSecret AndDirections: (NSArray*) directions;
#end
Objective-c .mm:
#implementation Adapter
- (id) initWithDirId: (int*) _dirId AndConfigUrl: (NSString*) _configUrl;
{
self = [super init];
if (self) {
self.dirId = _dirId;
NSString* directions;
//here is calling (there are more params ofc)
// but i can't figure it out how to do it in the right way
[self getConfigInfoWithConfigUrl: _configUrl
AndServiceUrl: _servireUrl AndClientName: _clientName
AndClientSecret: _clinetSecret AndDirections: directions];
}
return self;
}
- (id) initBase:(int*) _dirId AndServiceUrl: (NSString*) _serviceUrl AndClientName: (NSString*) _clientName AndClientSecret: (NSString*) _clientSecret;
{
self = [super init];
if (self) {
self.dirId = _dirId;
self.serviceUrl = _serviceUrl;
self.clientName = _clientName;
self.clientSecret = _clientSecret;
}
return self;
}
#end
When I change '-(void)' to '+(void)' in .h file ("+" is like static in c#, so I've tried it first), I get:
No visible #interface for 'OnlineAdapter' declares the selector
'getConfigInfoWithConfigUrl:AndServiceUrl:AndClientName:AndClientSecret:AndDirections:'
When I call with '-(void)', I get errors:
Use of undeclared identifier '_clinetSecret';
did you mean '_clientSecret'? //etc. for other args
I guess it happens because of 'out' attr in C# code, but I'm not sure if there an analogue in obj-c.
Objective-c crashes my brain. Any help would be appreciated!
You didn't show your code for your Objective-C method getConfigInfoWithConfigUrl:AndServiceUrl:AndClientName:AndClientSecret:AndDirections:. Since your C# method GetConfigInfo was a static method, you probably want to make your Objective-C method getConfigInfoWithConfigUrl:AndServiceUrl:AndClientName:AndClientSecret:AndDirections: a class method, declared with a +: +(void) getConfigInfoWithConfigUrl: ...
Class methods will need to be called on a class object, not on an ordinary instance: [Adapter getConfigInfoWithConfigUrl: ...]
out and ref parameters in C# denote that the parameter is passed by reference. In C, we usually accomplish the equivalent thing by passing a pointer to the variable.
So it should be declared something like this:
+ (void)getConfigInfoWithConfigUrl:(NSString *)_configUrl
AndServiceUrl:(NSString **)_servireUrl
AndClientName:(NSString **)_clientName
AndClientSecret:(NSString **)_clientSecret
AndDirections:(NSArray**)directions;
And inside the method it will assign to the variables like this:
*serviceUrl = ...
*clientName = ...
*clientSecret = ...
*directions = ...
And you call it something like this:
[Adapter getConfigInfoWithConfigUrl:_configUrl
AndServiceUrl:&_servireUrl
AndClientName:&_clientName
AndClientSecret:&_clientSecret
AndDirections:&directions];
self in Objective-C is only implicit for accessing instance variables (ivars), not for method calls. So you always need to use the following syntax:
[self getConfigInfoWithConfigUrl: _configUrl];
Note that the method name has a typo in its declaration in the .h file.
The fact that you're doing this from an init… vs any other method makes no difference.

Power Bi: Embedding Report into MVC Site

I have created a power bi report. I want to embed this report to my MVC site. Here is my code:-
private static readonly string ClientID = ConfigurationManager.AppSettings["ClientID"];
private static readonly string ClientSecret = ConfigurationManager.AppSettings["ClientSecret"];
private static readonly string RedirectUrl = ConfigurationManager.AppSettings["RedirectUrl"];
private static readonly string AADAuthorityUri = ConfigurationManager.AppSettings["AADAuthorityUri"];
private static readonly string PowerBiAPI = ConfigurationManager.AppSettings["PowerBiAPI"];
private static readonly string PowerBiDataset = ConfigurationManager.AppSettings["PowerBiDataset"];
private static readonly string baseUri = PowerBiDataset;
private static string accessToken = string.Empty;
public class PBIReports
{
public PBIReport[] value { get; set; }
}
public class PBIReport
{
public string id { get; set; }
public string name { get; set; }
public string webUrl { get; set; }
public string embedUrl { get; set; }
}
public ReportController()
{
try
{
if (Request.Params.Get("code") != null)
{
Session["AccessToken"] = GetAccessToken(
HttpContext.Request["code"],
ClientID,
ClientSecret,
RedirectUrl);
}
if (Session["AccessToken"] != null)
{
accessToken = Session["AccessToken"].ToString();
GetReport(0);
}
}
catch(Exception ex)
{
}
}
public string GetAccessToken(string authorizationCode, string clientID, string clientSecret, string redirectUri)
{
TokenCache TC = new TokenCache();
string authority = AADAuthorityUri;
AuthenticationContext AC = new AuthenticationContext(authority, TC);
ClientCredential cc = new ClientCredential(clientID, clientSecret);
return AC.AcquireTokenByAuthorizationCodeAsync(
authorizationCode,
new Uri(redirectUri), cc).Result.AccessToken;
}
protected void GetReport(int index)
{
System.Net.WebRequest request = System.Net.WebRequest.Create(
String.Format("{0}/Reports",
baseUri)) as System.Net.HttpWebRequest;
request.Method = "GET";
request.ContentLength = 0;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));
using (var response = request.GetResponse() as System.Net.HttpWebResponse)
{
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
{
PBIReports Reports = JsonConvert.DeserializeObject<PBIReports>(reader.ReadToEnd());
if (Reports.value.Length > 0)
{
var report = Reports.value[index];
ViewBag["ReportId"] = report.id;
ViewBag["EmbedUrl"] = report.embedUrl;
ViewBag["ReportName"] = report.name;
ViewBag["WebUrl"] = report.webUrl;
}
}
}
}
public void GetAuthorizationCode()
{
var #params = new NameValueCollection
{
{"response_type", "code"},
{"client_id", ClientID},
{"resource", PowerBiAPI},
{ "redirect_uri", RedirectUrl}
};
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString.Add(#params);
Response.Redirect(String.Format(AADAuthorityUri + "?{0}", queryString));
}
public ActionResult Index()
{
GetAuthorizationCode();
return View();
}
On Redirecting to "Report Page", it goes for power bi login page and after I sign in it redirects back to this page (as homepage and redirect url are same). But Request.Params.Get("code") != null is null. HttpContext.Request is also null. Why? Is there anything wrong in the code?
In the constructor of a controller you don't have the this.HttpContext object to your disposal yet. You might have HttpContext.Current, but I am not sure of that.
What you should do is move that code to an action (for example your GetReport action), where you can make your checks.

Accessing Facebook API using C# await and stuck forever

I'm trying to implement Facebook login and get data in c# project.
what I'm trying to do is that user press his firstname and password then he press on the login button and login then it return his data.
the when I press on the button the program is freeze.
that's my project implementation
Account.cs
public class Account
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Birthday { get; set; }
}
Facebook.client
public interface IFacebookClient
{
Task<T> GetAsync<T>(string accessToken, string endpoint, string args = null);
Task PostAsync(string accessToken, string endpoint, object data, string args = null);
}
public class FacebookClient : IFacebookClient
{
private readonly HttpClient _httpClient;
public FacebookClient()
{
_httpClient = new HttpClient
{
BaseAddress = new Uri("https://graph.facebook.com/v2.8/")
};
_httpClient.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<T> GetAsync<T>(string accessToken, string endpoint, string args = null)
{
var response = await _httpClient.GetAsync($"{endpoint}?access_token={accessToken}&{args}");
if (!response.IsSuccessStatusCode)
return default(T);
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
public async Task PostAsync(string accessToken, string endpoint, object data, string args = null)
{
var payload = GetPayload(data);
await _httpClient.PostAsync($"{endpoint}?access_token={accessToken}&{args}", payload);
}
private static StringContent GetPayload(object data)
{
var json = JsonConvert.SerializeObject(data);
return new StringContent(json, Encoding.UTF8, "application/json");
}
}
FacebookService.cs
public interface IFacebookService
{
Task<Account> GetAccountAsync(string accessToken);
Task PostOnWallAsync(string accessToken, string message);
}
public class FacebookService : IFacebookService
{
private readonly IFacebookClient _facebookClient;
public FacebookService(IFacebookClient facebookClient)
{
_facebookClient = facebookClient;
}
public async Task<Account> GetAccountAsync(string accessToken)
{
var result = await _facebookClient.GetAsync<dynamic>(
accessToken, "me", "fields=id,name,birthday,email");
if (result == null)
{
return new Account();
}
var account = new Account
{
Id = result.id,
Email = result.email,
Name = result.name,
Birthday = result.Birthday
};
return account;
}
public async Task PostOnWallAsync(string accessToken, string message)
=> await _facebookClient.PostAsync(accessToken, "me/feed", new {message});
}
FacebookSettings.cs
var facebookClient = new FacebookClient();
var facebookService = new FacebookService(facebookClient);
var getAccountTask = facebookService.GetAccountAsync(FacebookSettings.AccessToken);
Task.WaitAll(getAccountTask);
var account = getAccountTask.Result;
Console.WriteLine($"{account.Id} {account.Name}");
Login form button
private void btn_facebook_Click(object sender, EventArgs e)
{
var facebookClient = new FacebookClient();
var facebookService = new FacebookService(facebookClient);
var getAccountTask = facebookService.GetAccountAsync(FacebookSettings.AccessToken);
Task.WaitAll(getAccountTask);
var account = getAccountTask.Result;
//Console.WriteLine($"{account.Id} {account.Name}");
}
it stuck on this line on the await
public async Task<Account> GetAccountAsync(string accessToken)
{
var result = await _facebookClient.GetAsync<dynamic>(accessToken, "me", "fields=id,name,birthday,email");
if (result == null)
{
return new Account();
}
var account = new Account
{
Id = result.id,
Email = result.email,
Name = result.name,
Birthday = result.Birthday
};
return account;
}
in this line
var result = await _facebookClient.GetAsync<dynamic>(accessToken, "me", "fields=id,name,birthday,email");
Here's your problem:
Task.WaitAll(getAccountTask);
Don't block on async code. Use await instead:
private async void btn_facebook_Click(object sender, EventArgs e)
{
var facebookClient = new FacebookClient();
var facebookService = new FacebookService(facebookClient);
var account = await facebookService.GetAccountAsync(FacebookSettings.AccessToken);
}

C# object as JavaScript function param

I have next C# code:
public class Login
{
public string UserName { get; set; }
public string Password { get; set; }
public Login(string UserName, string Password)
{
this.UserName = UserName;
this.Password = Password;
}
}
protected const string JsonFunctionFormat = "function {0}(){{ {1}; }}";
protected const string JsonReturnFunctionFormat = "function {0}(){{return {1};}}";
public static void Fill(HtmlDocument Document, string FillerFunctionCode, Login LoginData)
{
if (Document != null)
{
HtmlElement dataElement = Document.CreateElement(OrganizationCardFiller.ScriptHtmlElementName);
IHTMLScriptElement domDataElement = (IHTMLScriptElement)dataElement.DomElement;
domDataElement.text = string.Format(LoginFiller.JsonReturnFunctionFormat, LoginFiller.GetLoginInfoFunctionName, LoginFiller.ConvertToJSon(LoginData));
//domDataElement.text += string.Format(LoginFiller.JsonFunctionFormat, LoginFiller.FillerFunctionName, FillerFunctionCode);
domDataElement.text += FillerFunctionCode;
HtmlElement headElement = Document.GetElementsByTagName(LoginFiller.BodyHtmlElementName)[0];
headElement.AppendChild(dataElement);
//Document.InvokeScript(LoginFiller.FillerFunctionName);
//Document.InvokeScript("FillLoginForm", new object[]{LoginFiller.ConvertToJSon(LoginData)});
//object[] args = { LoginFiller.ConvertToJSon(LoginData) };
//Document.InvokeScript("FillLoginForm", args);
Document.InvokeScript("FillLoginForm", new object[] { "{UserName:'user',Password:'pass'}" });
}
}
private static string ConvertToJSon(object ConvertingObject)
{
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return serializer.Serialize(ConvertingObject);
}
And next JavaScript function:
function objToString (obj) {
var str = '';
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str += p + '::' + obj[p] + '\n';
}
}
return str;
}
function FillLoginForm(login)
{
var userName = document.getElementById('ctl00_ctplhMain_Login1_UserName');
var password = document.getElementById('ctl00_ctplhMain_Login1_Password');
alert(objToString({test: 123, test2: '12345'}));
alert(objToString({""UserName"":""username"",""Password"":""veryHardPassword""}));
alert(typeof(login));
alert(login);
alert(objToString(login));
if(userName!=null)
{
userName.value = login.UserName;
}
if(password!=null)
{
password.value=login.Password;
}
}
Alerts with "{test: 123, test2: '12345'}" and "{""UserName"":""username"",""Password"":""veryHardPassword""}" works great, but typeof(login) return "unknown" and "login" with "objToString(login)" return Empty. As you can see, I tryed different variant, but all of them returns Empty. What's I make wrong, why login param don't pass to JavaScript function by correct format?

Facebook Graph API ASP.NET Post image

I'm trying to post a photo to Facebook using Graph API. I have managed to post a message to my timeline, but not a photo. The Facebook-debugger gives no errors and the object properties are correct.
public class oAuthFacebook
{
public enum Method { GET, POST };
public const string AUTHORIZE = "https://graph.facebook.com/oauth/authorize";
public const string ACCESS_TOKEN = "https://graph.facebook.com/oauth/access_token";
public const string CALLBACK_URL ="http://test.com/FbCallback.aspx";
private string _consumerKey = "";
private string _consumerSecret = "";
private string _token = "";
public string ConsumerKey
{
get
{
if (_consumerKey.Length == 0)
{
_consumerKey = "";
}
return _consumerKey;
}
set { _consumerKey = value; }
}
public string ConsumerSecret
{
get
{
if (_consumerSecret.Length == 0)
{
_consumerSecret = "";
}
return _consumerSecret;
}
set { _consumerSecret = value; }
}
public string Token { get { return _token; } set { _token = value; } }
public string AuthorizationLinkGet()
{
return string.Format("{0}?client_id={1}&redirect_uri={2}&,publish_actions",
AUTHORIZE, this.ConsumerKey, CALLBACK_URL);
}
public void AccessTokenGet(string authToken)
{
this.Token = authToken;
string accessTokenUrl = string.Format("{0}?client_id={1}&redirect_uri=
{2}&client_secret={3}&code={4}",
ACCESS_TOKEN, this.ConsumerKey, CALLBACK_URL, this.ConsumerSecret, authToken);
string response = WebRequest(Method.GET, accessTokenUrl, String.Empty);
if (response.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs["access_token"] != null)
{
this.Token = qs["access_token"];
}
}
}
public string WebRequest(Method method, string url, string postData)
{
HttpWebRequest webRequest = null;
StreamWriter requestWriter = null;
string responseData = "";
webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
webRequest.Method = method.ToString();
webRequest.ServicePoint.Expect100Continue = false;
webRequest.UserAgent = "http://test.com";
webRequest.Timeout = 40000;
if (method == Method.POST)
{
webRequest.ContentType = "application/x-www-form-urlencoded";
requestWriter = new StreamWriter(webRequest.GetRequestStream());
try
{
requestWriter.Write(postData);
}
catch
{
throw;
}
finally
{
requestWriter.Close();
requestWriter = null;
}
}
responseData = WebResponseGet(webRequest);
webRequest = null;
return responseData;
}
public string WebResponseGet(HttpWebRequest webRequest)
{
StreamReader responseReader = null;
string responseData = "";
try
{
responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
responseData = responseReader.ReadToEnd();
}
catch
{
throw;
}
finally
{
webRequest.GetResponse().GetResponseStream().Close();
responseReader.Close();
responseReader = null;
}
return responseData;
}
And this is how I sent a testmessage, it works fine:
var json = oAuth.WebRequest(oAuthFacebook.Method.POST, url, "message=" +
HttpUtility.UrlEncode("Testmessage"));
I've tried for days to get it to work with a photo instead, any ideas of what I'm doing wrong?
I can suggest to look at FB C# SDK (available here or in NuGet) instead of sending raw requests. Here is my function I use to upload images to FB album (you should either know album ID or you can create it as well, or you can enumerate all the albums and get the one you need):
public static string UploadPhoto(string imageName, string albumID, string accesstoken, string photoComment = null, bool doNotPostStory = false)
{
var fbAPI = new FacebookApp(accesstoken);
var p = new FacebookMediaObject {FileName = path};
p.SetValue( <<YOUR IMAGE GOES HERE AS byte[]>>);
p.ContentType = "multipart/form-data";
var param = new Dictionary<string, object> { {"attachment", p} };
if (!string.IsNullOrEmpty(photoComment))
param.Add("message", photoComment);
// http://stackoverflow.com/questions/7340949/is-it-possible-to-upload-a-photo-to-fanpage-album-without-publishing-it
// http://developers.facebook.com/blog/post/482/
if (doNotPostStory == true)
{
param.Add("no_story", "1");
}
var result = fbAPI.Post(string.Format("http://graph.facebook.com/{0}/photos", albumID), param);
return result.ToString();
}

Categories

Resources