JSON Formatting issue in C# - c#

I understand this might be an easy thing or C# Experts but I'm kinda struggling to get values out of a Http Response using Azure Rest API.
What I trying to do: I have a requirement to get Azure TrafficManager ProfileName, EndpointName and TargetName from Azure Rest API using C#. I managed to get to the ProfileName but unable fetch the Endpoint Name and Target Name from the response.
Each Subscription has more than one Traffic Manager Profiles and each Profile has multiple Endpoints. So, I looped the initial ProfileName Response (1st Rest API Call) in FOR Loop which is working fine and trying to get to Endpoints and Targets out (2nd Rest API Call) in below code.
Please help me fetch Endpoints and Targets from 2nd Rest API Call.
I pasted the HTTP Response that I'm getting from 2nd Rest API Call.
2nd Http Response which has Endpoint Name and Target Name
{
"id":"\/subscriptions\/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\/resourceGroups\/MyResourceGroupName\/providers\/Microsoft.Network\/trafficManagerProfiles\/MyTrafficManagerProfileName",
"name":"MyTrafficManagerProfileName",
"type":"Microsoft.Network\/trafficManagerProfiles",
"location":"global",
"tags":{},
"properties":
{
"profileStatus":"Enabled",
"trafficRoutingMethod":"Weighted",
"dnsConfig":
{
"relativeName":"MyTrafficManagerProfileName",
"fqdn":"yTafficManagerProfileName.trafficmanager.net",
"ttl":60
},
"monitorConfig":
{
"profileMonitorStatus":"Online",
"protocol":"HTTPS",
"port":443,
"path":"\/vip",
"intervalInSeconds":30,
"toleratedNumberOfFailures":3,
"timeoutInSeconds":10
},
"endpoints":
[
{
"id":"\/subscriptions\/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\/resourceGroups\/MyResourceGroupName\/providers\/Microsoft.Network\/trafficManagerProfiles\/MyTrafficManagerProfileName\/azureEndpoints\/MyEndPointName1",
"name":"MyEndPointName1",
"type":"Microsoft.Network\/trafficManagerProfiles\/azureEndpoints",
"properties":
{
"endpointStatus":"Enabled",
"endpointMonitorStatus":"Online",
"targetResourceId":"\/subscriptions\/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\/resourceGroups\/MyResourceGroupName\/providers\/Microsoft.Web\/sites\/MyTrafficManagerProfileName",
"target":"MyTargetName1",
"weight":1000,
"priority":1,
"endpointLocation":"North Central US"
}
},
{
"id":"\/subscriptions\/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\/resourceGroups\/MyResourceGroupName\/providers\/Microsoft.Network\/trafficManagerProfiles\/MyTrafficManagerProfileName\/externalEndpoints\/MyEndPointName2",
"name":"MyEndPointName2",
"type":"Microsoft.Network\/trafficManagerProfiles\/externalEndpoints",
"properties":
{
"endpointStatus":"Disabled",
"endpointMonitorStatus":"Disabled",
"target":"MyTargetName2",
"weight":1,
"priority":2,
"endpointLocation":null
}
}
]
,"trafficViewEnrollmentStatus":"Disabled"
}
}
C# Method to fetch Values from Azure Rest API
private static async Task GetTMPDetailsAsync(string token, string TeamGroupsName, string ServiceName, string SubscriptionName, string SubscriptionGUID, string SQLServerName, string SQLServerAdmin, string SQLServerAdminPasword, string DatabaseName)
{
string ResourceType = "Microsoft.Network/trafficmanagerprofiles";
var httpClient = new HttpClient
{
BaseAddress = new Uri("https://management.azure.com/subscriptions/")
};
// Get Network Profile Name and ResourceGroupName
string URI = $"/subscriptions/{SubscriptionGUID}/resources?$filter=resourceType%20EQ%20'{ResourceType}'&api-version=2019-05-10";
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false);
var HttpsResponse = await response.Content.ReadAsStringAsync();
dynamic ResourcesList = JsonConvert.DeserializeObject<object>(HttpsResponse);
if (ResourcesList.value != null && !ResourcesList.value.Contains("SubscriptionNotFound"))
{
foreach (dynamic ResourceName in ResourcesList["value"])
{
string ResourceID = ResourceName.id;
string ProfileName = ResourceName.name;
string Region = ResourceName.location;
string ResourceGroupName = ResourceID.Remove(0, 67);
int CharsToRemove = 52 + ProfileName.Length;
ResourceGroupName = ResourceGroupName.Remove(ResourceGroupName.Length - CharsToRemove);
var TMPhttpClient = new HttpClient
{
BaseAddress = new Uri("https://management.azure.com/subscriptions/")
};
// Get EndPoints and Targets
string TMPURI = $"/subscriptions/{SubscriptionGUID}/resourceGroups/{ResourceGroupName}/providers/{ResourceType}/{ProfileName}?api-version=2018-04-01";
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
HttpResponseMessage EndPointResponse = await httpClient.GetAsync(TMPURI).ConfigureAwait(false);
var EndPointsResponse = await EndPointResponse.Content.ReadAsStringAsync();
dynamic ProfileList = JsonConvert.DeserializeObject<object>(EndPointsResponse);
foreach (dynamic ProfileDetailed in ProfileList)
{
string EndPointName = ProfileDetailed.properties.endpoints.name;
string Target = ProfileDetailed.properties.endpoints.properties.target;
DateTime RawDate = DateTime.Now;
string RefreshedAt = RawDate.ToString("yyyy-MM-dd HH:mm:ss.fff");
Console.WriteLine($"'{TeamGroupsName}', '{ServiceName}', '{SubscriptionName}', '{SubscriptionGUID}', '','', '{ProfileName}', '{Region}',' {EndPointName}', {Target}, '{RefreshedAt}'");
//string SQLStatement = ($"INSERT INTO AzureCapacityUsage..TMPDetailed_New" +
// $" Select '{TeamGroupsName}', '{ServiceName}', '{SubscriptionName}', '{SubscriptionGUID}', '','', '{ProfileName}', '{Region}',' {EndPointName}', {Target}, '{RefreshedAt}'");
//SQLConnectionHelper.ExecuteTSQL(SQLServerName, SQLServerAdmin, SQLServerAdminPasword, DatabaseName, SQLStatement);
}
}
}
}

private static async Task GetTMPDetailsAsync(string token, string TeamGroupsName, string ServiceName, string SubscriptionName, string SubscriptionGUID, string SQLServerName, string SQLServerAdmin, string SQLServerAdminPasword, string DatabaseName)
{
string ResourceType = "Microsoft.Network/trafficmanagerprofiles";
var httpClient = new HttpClient
{
BaseAddress = new Uri("https://management.azure.com/subscriptions/")
};
// Get Network Profile Name and ResourceGroupName
string URI = $"/subscriptions/{SubscriptionGUID}/resources?$filter=resourceType%20EQ%20'{ResourceType}'&api-version=2019-05-10";
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false);
var HttpsResponse = await response.Content.ReadAsStringAsync();
dynamic ResourcesList = JsonConvert.DeserializeObject<object>(HttpsResponse);
if (ResourcesList.value != null && !ResourcesList.value.Contains("SubscriptionNotFound"))
{
foreach (dynamic ResourceName in ResourcesList["value"])
{
string ResourceID = ResourceName.id;
string ProfileName = ResourceName.name;
string Region = ResourceName.location;
string ResourceGroupName = ResourceID.Remove(0, 67);
int CharsToRemove = 52 + ProfileName.Length;
ResourceGroupName = ResourceGroupName.Remove(ResourceGroupName.Length - CharsToRemove);
var TMPhttpClient = new HttpClient
{
BaseAddress = new Uri("https://management.azure.com/subscriptions/")
};
// Get EndPoints and Targets
string TMPURI = $"/subscriptions/{SubscriptionGUID}/resourceGroups/{ResourceGroupName}/providers/{ResourceType}/{ProfileName}?api-version=2018-04-01";
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
HttpResponseMessage EndPointResponse = await httpClient.GetAsync(TMPURI).ConfigureAwait(false);
var endPointsResponse = await EndPointResponse.Content.ReadAsStringAsync();
ProfileDetailed profiles = JsonConvert.DeserializeObject<ProfileDetailed>(endPointsResponse);
foreach (var endpoint in profiles.Properties.Endpoints)
{
Console.WriteLine($"{endpoint}");
string endpointName = endpoint.Name;
string target = endpoint.EndPointProperties.Target;
DateTime RawDate = DateTime.Now;
string RefreshedAt = RawDate.ToString("yyyy-MM-dd HH:mm:ss.fff");
Console.WriteLine($"'{TeamGroupsName}', '{ServiceName}', '{SubscriptionName}', '{SubscriptionGUID}', '','', '{ProfileName}', '{endpointName}', {target}, '{RefreshedAt}'");
string SQLStatement = ($"INSERT INTO AzureCapacityUsage..TMPDetailed_New" +
$" Select '{TeamGroupsName}', '{ServiceName}', '{SubscriptionName}', '{SubscriptionGUID}', '','', '{ProfileName}', '{endpointName}', '{target}', '{RefreshedAt}'");
SQLConnectionHelper.ExecuteTSQL(SQLServerName, SQLServerAdmin, SQLServerAdminPasword, DatabaseName, SQLStatement);
}
}
}
}

Related

How to use an information sent on httpResponse?

I am learning about making requests to an api using my backend and when i make this i receive a response with some informations i want to use but i don't know how to use this.
Let me clarify this for you.
I HAVE THIS CODE TO MAKE THE REQUEST
try
{
//Set Basic Auth
var userPagarme = test_key;
var password = "";
var base64String = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{userPagarme}:{password}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64String);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var clienteToAdd = new PagarmeCliente()
{
Name = registerUser.Name,
Code = registerUser.Code,
Document = registerUser.Document,
Type = registerUser.Type,
Document_Type = registerUser.Document_Type,
Birthdate = registerUser.Birthdate,
Email = registerUser.Email,
Gender = registerUser.Gender,
Address = new PagarmeClienteEndereco()
{
city = registerUser.City,
country = registerUser.Country,
line_1 = registerUser.Line_1,
line_2 = registerUser.Line_2,
state = registerUser.State,
zip_code = registerUser.Zip_Code
},
Phones = new PagarmeClienteTelefone()
{
mobile_phone = new PagarmeClienteTelefoneMobile()
{
area_code = registerUser.Mobile_phone_area_code,
country_code = registerUser.Mobile_phone_country_code,
number = registerUser.Mobile_phone_number
},
}
};
var jsonString = JsonConvert.SerializeObject(clienteToAdd);
HttpResponseMessage response = await client.PostAsJsonAsync(urlPagarme + "customers", clienteToAdd);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
this.responseBodyJSON = JsonConvert.DeserializeObject(responseBody); // I have created this prop as an OBJ to receive the obj that was sent. I don't know if it is correct
}
catch (HttpRequestException e)
{
return BadRequest("\nException Caught - Message :{0} " + e.Message);
}
That is what i have in this responseBodyJSON and i want to use this property ID to insert on my database but if i make something like this below it doesn't work:
string idThatIWant = responseBodyJSON.id... or something like that.
var jsonString = JsonConvert.SerializeObject(clienteToAdd);
HttpResponseMessage response = await client.PostAsJsonAsync(urlPagarme + "customers", clienteToAdd);
You converted your model to JSON but you didn't use that jsonString. This could be the cause of the problem.
var respBody = JsonConvert.DeserializeObject<PagarmeCliente>(responseBody);
respBody.ID should be available if the class PagarmeCliente has the ID field you wanted populated.

SEndGrid not replacing Dynamics Data

My one template is not replacing dynamics data in the email
My Code is given below
public static System.Net.HttpStatusCode SendEmailV2(DynamicsModel dynamicsmodel, string templateId, TraceWriter log)
{
log.Info("Executing SendEmailV2");
var SendGridApiCode = System.Environment.GetEnvironmentVariable("SendGridApiCode", EnvironmentVariableTarget.Process);
var fromEmail = System.Environment.GetEnvironmentVariable("FromEmail", EnvironmentVariableTarget.Process);
var fromName = System.Environment.GetEnvironmentVariable("FromName", EnvironmentVariableTarget.Process);
var dynamicTemplateData = new DynamicData
{
Name = dynamicsmodel.FullName
};
string output = JsonConvert.SerializeObject(dynamicTemplateData);
log.Info("json:" + output);
EmailAddress from = new EmailAddress(fromEmail, "test name");
EmailAddress to = new EmailAddress(dynamicsmodel.Email, dynamicsmodel.FullName);
var sendGridClient = new SendGridClient(SendGridApiCode);
var sendGridMessage = CreateSingleTemplateEmail(from, to, templateId, dynamicTemplateData);
var response = sendGridClient.SendEmailAsync(sendGridMessage).Result;
if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
{
log.Info("Emails Sent from SendGrid");
}
else
{
log.Info("response.StatusCode:" + response.StatusCode.ToString());
}
return response.StatusCode;
}
My JSON which is being passed is given below
{"name":"Test User"}
This happens to one template only. Any help will be much appreciated

send value from Angular service App to C# backend controller

I'm getting absolutely insane with this, I've tried almost everything and can't find a way to pass a string value from a service to backend to return Json result based on that string.
Here's the problem, I have a backend that cooks all the JSON with meta-info that
frontend provides, and then return them to the frontend to display, on this case I have to get a JSON that's based on a filter that is made by a string inserted in frontend but can't find a way to pass the string to the backend, and I don't want to pass it through the URL.
Here's my code:
angular typescript service: I want to pass the "whr"
getAdvancedFilterResult(concept: string, whr: string): Promise<any> {
const headers: Headers = new Headers({
'Content-Type': 'application/json'
});
this.authService.getAuthorizationHeader(headers);
headers.append('IdLng', this.config.idLanguage);
const options: RequestOptions = new RequestOptions();
options.headers = headers;
return this.http.get(this.config.apiDomain + this.config.apiEndpointEntities + '/' + concept + '/' + "filtered",
options
)
.toPromise()
.then(
response => response.json() as any[]
)
.catch((error) => this.customHandleError(error, this.toastrService));
}
Backend controller:
[Route("api/Entities/{entity}/filtered/")]
public HttpResponseMessage GetFilter(string entity) {
HttpResponseMessage response = new HttpResponseMessage();
string action = "READ";
//Check Authorization
AuthorizationResponse authResponse = AuthProvider.CheckAuthorization(new AuthorizationRequest() {
SCode = UserUtils.GetUserSCode(User),
ConceptString = entity,
ActionString = action,
UserId = UserUtils.GetUserID(User),
ExtraParameters = new AuthorizationRequest.ExtraParamaters() {
IdsOnly = false, Where = "!!!!!WHR HERE!!!!"
}
});
if (authResponse.IsAuthorized) {
//code
response = Request.CreateResponse(HttpStatusCode.OK, json);
} else {
response = Request.CreateResponse(HttpStatusCode.Unauthorized);
}
return response;
}
Should I pass it through the header, with headers.append('whr', whr);, that goes into the options on http.get or into body with options.body = whr;?
Also, how can I get it on the backend side to use?
You should pass the Headers like this:
getAdvancedFilterResult(concept: string, whr: string): Promise<any> {
this.authService.getAuthorizationHeader(headers);
let headers: HttpHeaders = new HttpHeaders();
headers = headers.append('Content-Type', 'application/json');
headers = headers.append('x-corralation-id', '12345');
headers = headers.append('IdLng', this.config.idLanguage);
headers = headers.append('whr', whr);
const options: RequestOptions = new RequestOptions();
options.headers = headers;
return this.http.get(this.config.apiDomain + this.config.apiEndpointEntities + '/' + concept + '/' + "filtered",
options
)
.toPromise()
.then(
response => response.json() as any[]
)
.catch((error) => this.customHandleError(error, this.toastrService));
}
To get the headers on the Server Side try this:
[Route("api/Entities/{entity}/filtered/")]
public HttpResponseMessage GetFilter(string entity) {
var request = Request;
var headers = response.Headers;
HttpResponseMessage response = new HttpResponseMessage();
string action = "READ";
var whrHeader = headers.Contains("whr") ? request.Headers.GetValues("whr").First() : ""
AuthorizationResponse authResponse = AuthProvider.CheckAuthorization(new AuthorizationRequest() {
SCode = UserUtils.GetUserSCode(User),
ConceptString = entity,
ActionString = action,
UserId = UserUtils.GetUserID(User),
ExtraParameters = new AuthorizationRequest.ExtraParamaters() {
IdsOnly = false,
Where = whrHeader
}
});
if (authResponse.IsAuthorized) {
//code
response = Request.CreateResponse(HttpStatusCode.OK, json);
} else {
response = Request.CreateResponse(HttpStatusCode.Unauthorized);
}
return response;
}
I got the solution, thanks to SiddAjmera!!
At frontend service:
getAdvancedFilterResult(concept: string, whr: string): Promise<any> {
let headers: Headers = new Headers();
this.authService.getAuthorizationHeader(headers);
headers.append('Content-Type', 'application/json');
headers.append('IdLng', this.config.idLanguage);
headers.append('whr', whr);
const options: RequestOptions = new RequestOptions();
options.headers = headers;
return this.http.get(
this.config.apiDomain + this.config.apiEndpointEntities + '/' + concept + '/' + "filtered",
options
)
.toPromise()
.then(
response => response.json() as any[]
)
.catch((error) => this.customHandleError(error, this.toastrService));
}
And then on the backend, just used the UserUtils already made to get the header which has the value 'whr' and pass it through a function.
UserUtilis.cs:
public static string Where(HttpRequestMessage re) {
string whereCLause = "";
var headers = re.Headers;
if (headers.Contains("whr")) {
whereCLause = headers.GetValues("whr").First();
} else {
whereCLause = " ";
}
return whereCLause;
}
And Controller.cs
...
var re = Request;
HttpResponseMessage response = new HttpResponseMessage();
string action = "READ";
//Check Authorization
AuthorizationResponse authResponse = AuthProvider.CheckAuthorization(new AuthorizationRequest() {
SCode = UserUtils.GetUserSCode(User),
ConceptString = entity,
ActionString = action,
UserId = UserUtils.GetUserID(User),
ExtraParameters = new AuthorizationRequest.ExtraParamaters() {
IdsOnly = false, Where = UserUtils.Where(re)
}
});
...

Instagram Api (https://api.instagram.com/oauth/access_token" , "post" , parameters) returns 400 Bad Request

I am developing an app using instagram api to bring feed to my website. I have following code but when i try to access the access_token using the code provided by Instagram it's giving me `400 Bad request error. I would be much obliged if someone could help me to overcome this problem. Many Thanks
string code="";
public ActionResult Index()
{
if (!String.IsNullOrEmpty(Request["code"]))
{
code = Request["code"].ToString();
GetDataInstagramToken();
}
return View();
}
public ActionResult Instagram()
{
var client_id = ConfigurationManager.AppSettings["instagram.clientid"].ToString();
var redirect_uri = ConfigurationManager.AppSettings["instagram.redirecturi"].ToString();
string url = "https://api.instagram.com/oauth/authorize/?client_id=" + client_id + "&redirect_uri=" + redirect_uri + "&response_type=code";
Response.Redirect(url);
return View();
}
public void GetDataInstagramToken()
{
var json = "";
var page = HttpContext.CurrentHandler as Page;
try
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("client_id", ConfigurationManager.AppSettings["instagram.clientid"].ToString());
parameters.Add("client_secret", ConfigurationManager.AppSettings["instagram.clientsecret"].ToString());
parameters.Add("grant_type", "authorization_code");
parameters.Add("redirect_uri", ConfigurationManager.AppSettings["instagram.redirecturi"].ToString());
parameters.Add("code", code);
WebClient client = new WebClient();
var result = client.UploadValues("https://api.instagram.com/oauth/access_token", "post", parameters);
var response = System.Text.Encoding.Default.GetString(result);
// deserializing nested JSON string to object
var jsResult = (JObject)JsonConvert.DeserializeObject(response);
string accessToken = (string)jsResult["access_token"];
int id = (int)jsResult["user"]["id"];
//This code register id and access token to get on client side
page.ClientScript.RegisterStartupScript(this.GetType(), "GetToken", "<script> var instagramaccessid=\"" + #"" + id + "" + "\"; var instagramaccesstoken=\"" + #"" + accessToken + "" + "\";</script>");
}
catch (Exception ex)
{
throw;
}
}
I am getting exception at
var result = client.UploadValues("https://api.instagram.com/oauth/access_token", "post", parameters);
In this line
client.UploadValues("https://api.instagram.com/oauth/access_token", "post", parameters);
You don't send any value to Instagram. If you check your parameter you can see your key but you cant see any value.
Try this:
public async void GetTokenFromCode()
{
var values = new Dictionary<string, string> {
{ "client_id","Your ChatId" },
{ "client_secret", "Your Client Secret" },
{ "grant_type", "authorization_code" },
{ "redirect_uri", "Your Redirect url"},
{ "code", "code" } };
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://api.instagram.com/oauth/access_token", content);
var responseString = await response.Content.ReadAsStringAsync();
}

How to use cursors to iterate through the result set of GET followers/list in Twitter API using c#?

I have been trying a way to get the data in the next page of the result set of GET followers/list API call. I can get the default data set with the data of first 20 followers and not the others. To get the data of other followers i have to access the next page using the next_cursor but it's not working. I tried using the pseudo-code mentioned in this link. https://dev.twitter.com/docs/misc/cursoring
Is it a must to use this(this is mentioned in the dev. site):
var api-path = "https://api.twitter.com/1.1/endpoint.json?screen_name=targetUser"
Because I have been using the resource URL as,
var resource_url = "https://api.twitter.com/1.1/followers/list.json";
and I tried appending the next_cursor to the same resource URL.
var url_with_cursor = resource_url + "&cursor=" + 1463101490306580067;
and then created the request.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url_with_cursor);
but I'm getting an exception in this line when getting the response.
WebResponse response = request.GetResponse();
The error I'm getting is
The Remote Server returned an Error 401 Unauthorized
Can someone tell the exact way to do cursor-ing, or the exact way to include the cursor in the request. I'm using a asp.net C# web application.
Here's my code, The oauth_token, oauth_token_secret, oauth_consumer_key, oauth_consumer_secret, oauth_version and oauth_signature_method are defined in my application
var resource_url = "https://api.twitter.com/1.1/followers/list.json";
var cursor = "-1";
do
{
var url_with_cursor = resource_url + "&cursor=" + cursor;
// unique request details
var oauth_nonce = Convert.ToBase64String(
new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
var timeSpan = DateTime.UtcNow
- new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
// create oauth signature
var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
"&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}";
var baseString = string.Format(baseFormat,
oauth_consumer_key,
oauth_nonce,
oauth_signature_method,
oauth_timestamp,
oauth_token,
oauth_version
//,Uri.EscapeDataString(status)
);
baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));
var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
"&", Uri.EscapeDataString(oauth_token_secret));
string oauth_signature;
using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
{
oauth_signature = Convert.ToBase64String(
hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
}
// create the request header
var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
"oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
"oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
"oauth_version=\"{6}\"";
var authHeader = string.Format(headerFormat,
Uri.EscapeDataString(oauth_nonce),
Uri.EscapeDataString(oauth_signature_method),
Uri.EscapeDataString(oauth_timestamp),
Uri.EscapeDataString(oauth_consumer_key),
Uri.EscapeDataString(oauth_token),
Uri.EscapeDataString(oauth_signature),
Uri.EscapeDataString(oauth_version)
);
// make the request
ServicePointManager.Expect100Continue = false;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url_with_cursor);
request.Headers.Add("Authorization", authHeader);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
WebResponse response = request.GetResponse();
string result = new StreamReader(response.GetResponseStream()).ReadToEnd();
JObject j = JObject.Parse(result);
JArray data = (JArray)j["users"];
cursor = (String)j["next_cursor_str"];
} while (!cursor.Equals("0"));
Thanks.
Tweetinvi would make it somewhat easier for you.
Please visit https://github.com/linvi/tweetinvi/wiki/Get-All-Followers-Code to have an idea on how to do it including RateLimit handling.
Without considering the RateLimits, you could simply use the following code.
long nextCursor = -1;
do
{
var query = string.Format("https://api.twitter.com/1.1/followers/ids.json?screen_name={0}", username);
var results = TwitterAccessor.ExecuteCursorGETCursorQueryResult<IIdsCursorQueryResultDTO>(query, cursor: cursor).ToArray();
if (results.Any())
{
nextCursor = results.Last().NextCursor;
}
else
{
nextCursor = -1;
}
}
while (nextCursor != -1 && nextCursor != 0);
you should make a different call to authenticate, by an authorization request. Once that has been granted, you can call the webresponse with the cursor. See my sample code below (Take special note to the StartCreateCall method, where the authentication is done. The data from Twitter is then retrieved by the CallData method):
public partial class twitter_followers : System.Web.UI.Page
{
public string strTwiterFollowers { get; set; }
private List<TwiterFollowers> listFollowers = new List<TwiterFollowers>();
private string screen_name = string.Empty;
// oauth application keys
private string oauth_consumer_key = string.Empty;
private string oauth_consumer_secret = string.Empty;
// oauth implementation details
private string resource_urlFormat = "https://api.twitter.com/1.1/followers/list.json?screen_name={0}&cursor={1}";
// unique request details
private string oauth_nonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
protected void Page_Load(object sender, EventArgs e)
{
//just get your request parameters from the config file.
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[GetVariableName(() => screen_name)])) {
screen_name = ConfigurationManager.AppSettings[GetVariableName(() => screen_name)];
}
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_key)]))
{
oauth_consumer_key = ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_key)];
}
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_secret)]))
{
oauth_consumer_secret = ConfigurationManager.AppSettings[GetVariableName(() => oauth_consumer_secret)];
}
StartCreateCall();
}
// Do the authenticate by an authorization request
private void StartCreateCall() {
// You need to set your own keys and screen name
var oAuthUrl = "https://api.twitter.com/oauth2/token";
// Do the Authenticate
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oauth_consumer_key) + ":" +
Uri.EscapeDataString((oauth_consumer_secret)))
));
var postBody = "grant_type=client_credentials";
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
authRequest.Headers.Add("Authorization", authHeader);
authRequest.Method = "POST";
authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream stream = authRequest.GetRequestStream())
{
byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
stream.Write(content, 0, content.Length);
}
authRequest.Headers.Add("Accept-Encoding", "gzip");
WebResponse authResponse = authRequest.GetResponse();
// deserialize into an object
TwitAuthenticateResponse twitAuthResponse;
using (authResponse)
{
using (var reader = new StreamReader(authResponse.GetResponseStream()))
{
JavaScriptSerializer js = new JavaScriptSerializer();
var objectText = reader.ReadToEnd();
twitAuthResponse = JsonConvert.DeserializeObject<TwitAuthenticateResponse>(objectText);
}
}
//now we have been granted access and got a token type with authorization token from Twitter
//in the form of a TwitAuthenticateResponse object, we can retrieve the data recursively with a cursor
CallData(twitAuthResponse, authHeader, cursor);
int totalFollowers = listFollowers.Count;
lblTotalFollowers.Text = screen_name + " has " + listFollowers.Count + " Followers";
Random objRnd = new Random();
List<TwiterFollowers> randomFollowers = listFollowers.OrderBy(item => objRnd.Next()).ToList<TwiterFollowers>();
foreach (TwiterFollowers tw in randomFollowers)
{
strTwiterFollowers = strTwiterFollowers + "<li><a target='_blank' title='" + tw.ScreenName + "' href=https://twitter.com/" + tw.ScreenName + "><img src='" + tw.ProfileImage + "'/><span>" + tw.ScreenName + "</span></a></li>";
}
}
//Retrieve the data from Twitter recursively with a cursor
private void CallData(TwitAuthenticateResponse twitAuthResponse, string authHeader, string cursor)
{
try {
JObject j = GetJSonObject(twitAuthResponse, authHeader, cursor);
JArray data = (JArray)j["users"];
if (data != null)
{
foreach (var item in data)
{
TwiterFollowers objTwiterFollowers = new TwiterFollowers();
objTwiterFollowers.ScreenName = item["screen_name"].ToString().Replace("\"", "");
objTwiterFollowers.ProfileImage = item["profile_image_url"].ToString().Replace("\"", "");
objTwiterFollowers.UserId = item["id"].ToString().Replace("\"", "");
listFollowers.Add(objTwiterFollowers);
}
JValue next_cursor = (JValue)j["next_cursor"];
if (long.Parse(next_cursor.Value.ToString()) > 0)
{
//Get the following data from Twitter with the next cursor
CallData(twitAuthResponse, authHeader, next_cursor.Value.ToString());
}
}
} catch (Exception ex)
{
//do nothing
}
}
private JObject GetJSonObject(TwitAuthenticateResponse twitAuthResponse, string authHeader, string cursor)
{
string resource_url = string.Format(resource_urlFormat, screen_name, cursor);
if (string.IsNullOrEmpty(cursor))
{
resource_url = resource_url.Substring(0, resource_url.IndexOf("&cursor"));
}
HttpWebRequest fRequest = (HttpWebRequest)WebRequest.Create(resource_url);
var timelineHeaderFormat = "{0} {1}";
fRequest.Headers.Add("Authorization", string.Format(timelineHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token));
fRequest.Method = "Get";
WebResponse response = fRequest.GetResponse();
string result = new StreamReader(response.GetResponseStream()).ReadToEnd();
return JObject.Parse(result);
}
private string GetVariableName<T>(Expression<Func<T>> expr)
{
var body = (MemberExpression)expr.Body;
return body.Member.Name;
}
private class TwitAuthenticateResponse
{
public string token_type { get; set; }
public string access_token { get; set; }
}
private class TwiterFollowers
{
public string ScreenName { get; set; }
public string ProfileImage { get; set; }
public string UserId { get; set; }
}
}
You are getting "401 Unauthorized"
Did you check you are setting everything right?
Credentials? Check both queries on fiddler.

Categories