I am trying to get the list of users in ADO using .NET clients. I am referring to this git repository:
https://github.com/microsoft/azure-devops-dotnet-samples/blob/master/ClientLibrary/Quickstarts/dotnet/GraphQuickStarts/Samples/EnumerateUsers.cs
I tried same thing but still it shows error that GetUsersAsync needs assembly reference. I have tried all the references. I am getting GetUserAsync but that is for one user. I need to fetch all the users.
Instead of using GetUsersAsync, please use ListUsersAsync:
PagedGraphUsers users = graphClient.ListUsersAsync().Result;
In the following two code samples i'm returning the users' emails. You can use Azure DevOps' userentitlements to return the information you need like the license details.
SDK
//string organization = ...
//string userName = ...
//string pat = ...
List<string> users = new List<string>();
var uri = new Uri($"https://vsaex.dev.azure.com/{organization}");
var credentials = new VssBasicCredential(userName, pat);
using (var connection = new VssConnection(uri, credentials))
using (var client = connection.GetClient<MemberEntitlementManagementHttpClient>())
{
string continuationToken = null;
do
{
var data = await client.SearchUserEntitlementsAsync(continuationToken);
continuationToken = data.ContinuationToken;
foreach (var member in data.Members)
{
string email = member.User.MailAddress.ToLower();
users.Add(email);
}
}
while (continuationToken != null);
}
Rest API
//string organization = ...
// HttpClient client = ...
List<string> users = new List<string>();
string baseUrl = $"https://vsaex.dev.azure.com/{organization}/_apis/userentitlements?api-version=6-preview.3";
string url = baseUrl;
string continuationToken = string.Empty;
do
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
dynamic data = await response.Content.ReadAsAsync<object>();
foreach (var member in data.members)
{
users.Add(member.user.mailAddress.ToString());
}
continuationToken = HttpUtility.UrlEncode(data.continuationToken.ToString());
url = baseUrl + "&continuationToken=" + continuationToken;
}
}
while (!string.IsNullOrWhiteSpace(continuationToken));
Related
Trying to make use of the AndroidPublisherService from Play Developer API Client.
I can list active tracks and the releases in those tracks, but when I try to upload a new build there seems to be no way of attaching the authentication already made previously to read data.
I've authenticated using var googleCredentials = GoogleCredential.FromStream(keyDataStream) .CreateWithUser(serviceUsername); where serviceUsername is the email for my service account.
private static void Execute(string packageName, string aabfile, string credfile, string serviceUsername)
{
var credentialsFilename = credfile;
if (string.IsNullOrWhiteSpace(credentialsFilename))
{
// Check env. var
credentialsFilename =
Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
EnvironmentVariableTarget.Process);
}
Console.WriteLine($"Using credentials {credfile} with package {packageName} for aab file {aabfile}");
var keyDataStream = File.OpenRead(credentialsFilename);
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var service = new AndroidPublisherService();
var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
edit.Credential = credentials;
var activeEditSession = edit.Execute();
Console.WriteLine($"Edits started with id {activeEditSession.Id}");
var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
tracksList.Credential = credentials;
var tracksResponse = tracksList.Execute();
foreach (var track in tracksResponse.Tracks)
{
Console.WriteLine($"Track: {track.TrackValue}");
Console.WriteLine("Releases: ");
foreach (var rel in track.Releases)
Console.WriteLine($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
}
using var fileStream = File.OpenRead(aabfile);
var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
var uploadProgress = upload.Upload();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
Console.WriteLine($"Upload {uploadProgress.Status}");
var tracksUpdate = service.Edits.Tracks.Update(new Track
{
Releases = new List<TrackRelease>(new[]
{
new TrackRelease
{
Name = "Roswell - Grenis Dev Test",
Status = "completed",
VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
}
})
}, packageName, activeEditSession.Id, "internal");
tracksUpdate.Credential = credentials;
var trackResult = tracksUpdate.Execute();
Console.WriteLine($"Track {trackResult?.TrackValue}");
var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
Console.WriteLine($"{commitResult.EditId} has been committed");
}
And as the code points out, all action objects such as tracksList.Credential = credentials; can be given the credentials generated from the service account.
BUT the actual upload action var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream"); does not expose a .Credential object, and it always fails with:
The service androidpublisher has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. [401]
Errors [
Message[Login Required.] Location[Authorization - header] Reason[required] Domain[global]
]
at Google.Apis.Upload.ResumableUpload`1.InitiateSessionAsync(CancellationToken cancellationToken)
at Google.Apis.Upload.ResumableUpload.UploadAsync(CancellationToken cancellationToken)
So, how would I go about providing the actual Upload action with the given credentials here?
Managed to figure this out during the day, I was missing one call to CreateScoped() when creating the GoogleCredential object as well as a call to InitiateSession() on the upload object.
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
Once that was done I could then get a valid oauth token by calling
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
And I can now use that oauth token in the upload request:
upload.OauthToken = oauthToken;
_ = await upload.InitiateSessionAsync();
var uploadProgress = await upload.UploadAsync();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
The full code example for successfully uploading a new aab file to google play store internal test track thus looks something like this:
private async Task UploadGooglePlayRelease(string fileToUpload, string changeLogFile, string serviceUsername, string packageName)
{
var serviceAccountFile = ResolveServiceAccountCertificateInfoFile();
if (!serviceAccountFile.Exists)
throw new ApplicationException($"Failed to find the service account certificate file. {serviceAccountFile.FullName}");
var keyDataStream = File.OpenRead(serviceAccountFile.FullName);
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
var service = new AndroidPublisherService();
var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
edit.Credential = credentials;
var activeEditSession = await edit.ExecuteAsync();
_logger.LogInformation($"Edits started with id {activeEditSession.Id}");
var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
tracksList.Credential = credentials;
var tracksResponse = await tracksList.ExecuteAsync();
foreach (var track in tracksResponse.Tracks)
{
_logger.LogInformation($"Track: {track.TrackValue}");
_logger.LogInformation("Releases: ");
foreach (var rel in track.Releases)
_logger.LogInformation($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
}
var fileStream = File.OpenRead(fileToUpload);
var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
upload.OauthToken = oauthToken;
_ = await upload.InitiateSessionAsync();
var uploadProgress = await upload.UploadAsync();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
_logger.LogInformation($"Upload {uploadProgress.Status}");
var releaseNotes = await File.ReadAllTextAsync(changeLogFile);
var tracksUpdate = service.Edits.Tracks.Update(new Track
{
Releases = new List<TrackRelease>(new[]
{
new TrackRelease
{
Name = $"{upload?.ResponseBody?.VersionCode}",
Status = "completed",
InAppUpdatePriority = 5,
CountryTargeting = new CountryTargeting { IncludeRestOfWorld = true },
ReleaseNotes = new List<LocalizedText>(new []{ new LocalizedText { Language = "en-US", Text = releaseNotes } }),
VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
}
})
}, packageName, activeEditSession.Id, "internal");
tracksUpdate.Credential = credentials;
var trackResult = await tracksUpdate.ExecuteAsync();
_logger.LogInformation($"Track {trackResult?.TrackValue}");
var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
commitResult.Credential = credentials;
await commitResult.ExecuteAsync();
_logger.LogInformation($"{commitResult.EditId} has been committed");
}
I have this piece of code in C# using InstaSharper to return information of a media id from Instagram.
public async Task<UserSessionData> SignIn(string userName, string password)
{
userSessionData = new UserSessionData();
userSessionData.UserName = "username";
userSessionData.Password = "password";
api = InstaApiBuilder.CreateBuilder()
.SetUser(userSessionData)
.Build();
var loginRequest = await api.LoginAsync();
if (loginRequest.Succeeded && api.IsUserAuthenticated)
{
IResult<InstaUser> userSearch = await api.GetUserAsync(userName);
IResult<InstaMediaList> media = await api.GetUserMediaAsync(userName, PaginationParameters.MaxPagesToLoad(1));
IResult<InstaMedia> mediaInfo = await api.GetMediaByIdAsync("1924613027431050955");
return userSessionData;
}
else
{
return null;
}
}
GetMediaByIdAsync method correctly returns data about the requested media but the Likers and Tags collection is empty. Is there any way to include those data?
Had the same issue, I found the solution.
Try using this code:
var posts = await api.GetUserMediaAsync("username", PaginationParameters.MaxPagesToLoad(Int32.MaxValue)); // If you want to load all of the posts. If not, replace the "Int32.MaxValue" with the amount of posts you want to load
foreach (var post in posts.Value)
{
var likers = await api.GetMediaLikersAsync(post.InstaIdentifier);
foreach (var liker in likers.Value)
{
Console.WriteLine(liker.UserName);
}
}
This works fine for me, try it out, Im sure it will work for you as well.
I'm trying to access Azure Cosmos DB using Table API.
The challenge is, despite creating SharedKeyLite, server is still returning Unauthorized - seems like SharedKeyLite is not supported or I'm generating the signature or headers wrong.
Here is the code
static readonly string storageAccountName = "accountName";
static readonly string storageAccountKey = "xxxx";
static readonly string uri = "https://accountName.table.cosmosdb.azure.com/Contacts()";
static readonly string utc_date = DateTime.UtcNow.ToString("r");
static void Main(string[] args)
{
Console.WriteLine(GetResult().Result);
}
static async Task<string> GetResult()
{
// Set this to whatever payload you desire. Ours is null because
// we're not passing anything in.
Byte[] requestPayload = null;
var requestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var requestUri = new Uri(uri);
DateTime now = DateTime.UtcNow;
//Instantiate the request message with a null payload.
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
{ Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
{
ConstructHeaders(httpRequestMessage.Headers, requestDateString);
string authorizationHeader = GenerateSharedKeyLite(storageAccountKey, storageAccountName, uri,requestDateString);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("SharedKeyLite", authorizationHeader);
// Send the request.
using (HttpResponseMessage httpResponseMessage = await new HttpClient().SendAsync(httpRequestMessage))
{
string json = await httpResponseMessage.Content.ReadAsStringAsync();
return json;
}
}
}
These are the headers I"m adding, expansion of ConstructHeaders method.
Refer this link for request parameters
//Construct the headers
static void ConstructHeaders(HttpRequestHeaders headers, string now)
{
headers.Add("x-ms-date", now);
headers.Add("x-ms-version", "2017-04-17");
// If you need any additional headers, add them here before creating
// the authorization header.
headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (headers.Contains("DataServiceVersion"))
headers.Remove("DataServiceVersion");
headers.Add("DataServiceVersion", "3.0;NetFx");
if (headers.Contains("MaxDataServiceVersion"))
headers.Remove("MaxDataServiceVersion");
headers.Add("MaxDataServiceVersion", "3.0;NetFx");
}
And this is the method that creates the SharedKeyLite
//Created Shared Key Lite
static string GenerateSharedKeyLite(string accessKey, string account, string url, string date)
{
var uri = new Uri(url);
var canonicalizedResourceString = uri.PathAndQuery;
var queryStart = canonicalizedResourceString.IndexOf('?');
if (queryStart > -1)
{
if (queryStart < canonicalizedResourceString.Length - 1)
{
var path = canonicalizedResourceString.Substring(0, queryStart);
var parameters = HttpUtility.ParseQueryString(canonicalizedResourceString.Substring(queryStart + 1));
var sb = new StringBuilder();
foreach (var keyOri in parameters.Keys)
{
var value = parameters[keyOri];
var key = keyOri.ToLowerInvariant();
sb.Append("\n");
sb.Append(key);
sb.Append(":");
sb.Append(value);
}
canonicalizedResourceString = canonicalizedResourceString + sb.ToString();
}
else
{
canonicalizedResourceString = canonicalizedResourceString.Substring(0, canonicalizedResourceString.Length - 1);
}
}
canonicalizedResourceString = $"/{account}{canonicalizedResourceString}";
var stringToSign = $"{date}\n{canonicalizedResourceString}";
var signedSignature = string.Empty;
using (var hmac = new HMACSHA256(Convert.FromBase64String(accessKey)))
{
var outputBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
var signature = Convert.ToBase64String(outputBytes);
return $"{account}:{signature}";
}
}
Any Help? Ideally I want to perform the odata query using simple.odata, but first trying to make this work using HttpClient
Just copy your code and it works on my side. If you haven't modified your code, please make sure your storageAccountName and storageAccountKey are correct.
BTW, in method GenerateSharedKeyLite there's no need to add query parameters to canonicalizedResourceString for entity operation. You only need to add comp if you want to operate component info for table or service. See constructing-the-canonicalized-resource-string.
The query string should include the question mark and the comp parameter (for example, ?comp=metadata). No other parameters should be included on the query string.
I'm using the Azure Management Libraries (specifically fluent) to create web request towards their api to get a list of my databases under my subscription. I'm able to get an instance of the sqlserver using fluent but am unable to get a list of all databases under a specific server.
Define and delete work fine it is just the list() function.
I've tried using it for sqlserver.firewallrules and the list function doesn't work there as well.
Here is some code:
The log at some point just pauses then writes "has exited with code 0"
public async Task<List<String>> getSqlDatabaseList()
{
System.Diagnostics.Debug.WriteLine("Starting to get database list");
List<string> dbNameList = new List<string>();
//the var azure is defined earlier in the project and is authenticated.
var sqlServer = await azure.SqlServers.GetByResourceGroupAsync("<resource group name>", "<server Name>");
//The code below successfully writes the server name
System.Diagnostics.Debug.WriteLine(sqlServer.Name);
//The code below here is where everyting stop and "has exited with code 0" happens after a few seconds of delay
var dbList = sqlServer.Databases.List();
//Never reaches this line
System.Diagnostics.Debug.WriteLine("This line never is written");
foreach (ISqlDatabase db in dbList)
{
dbNameList.Add(db.Name);
}
return dbNameList;
}
Clarification:
I'm using ASP.NET MVC
Here is how my controller method accesses the class method. Resource Manager is the name of the class that implements getSQlDatabaseList();
// GET: Home
public async Task<ActionResult> Index()
{
ResourceManager rm = new ResourceManager();
List<string> test = await rm.getSqlDatabaseList();
//Never Gets to this line of code and never calls the for each or anything after
foreach (var item in test)
{
System.Diagnostics.Debug.WriteLine(item);
}
System.Diagnostics.Debug.WriteLine("Is past for each");
//AzureManager azm = await AzureManager.createAzureManager();
//await azm.getResourceGroupList();
return View(new UserLogin());
}
According to your code and description, I guess the reason why your code couldn't create the table is about your async getSqlDatabaseList.
I guess you call this method in console main method or something else.
If your main method is executed completely, your async method getSqlDatabaseList isn't execute the completely and return the list of the string. It will end all async method.
I suggest you could add await or result key keyword when calling the getSqlDatabaseList method to wait the thread execute the method completely.
More details, you could refer to below test demo.
static void Main(string[] args)
{
//use result to wait the mehtod executed completely
List<String> test = getSqlDatabaseList().Result;
foreach (var item in test)
{
Console.WriteLine(item);
}
Console.Read();
}
public static async Task<List<String>> getSqlDatabaseList()
{
//System.Diagnostics.Debug.WriteLine("Starting to get database list");
List<string> dbNameList = new List<string>();
var credentials = SdkContext.AzureCredentialsFactory.FromFile(#"D:\Auth.txt");
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithDefaultSubscription();
var sqlServer = await azure.SqlServers.GetByResourceGroupAsync("groupname", "brandotest");
var dbList = sqlServer.Databases.List();
foreach (ISqlDatabase db in dbList)
{
dbNameList.Add(db.Name);
}
return dbNameList;
}
Update:
According to your description, I have created a test MVC application. As you say I have reproduce your issue.
I think there are something wrong with the azure management fluent SDK.
Here is a workaround, I suggest you could directly send rest api to get the database.
More details, you could refer to below codes:
Send the request to below url:
https://management.azure.com/subscriptions/{subscriptionsid}/resourceGroups/{resourceGroupsname}/providers/Microsoft.Sql/servers/{servername}/databases?api-version={apiversion}
public static List<String> getSqlDatabaseList()
{
//System.Diagnostics.Debug.WriteLine("Starting to get database list");
List<string> dbNameList = new List<string>();
string tenantId = "yourtenantid";
string clientId = "yourclientId";
string clientSecret = "clientSecret";
string subscriptionid = "subscriptionid";
string resourcegroup = "resourcegroupname";
string sqlservername = "brandotest";
string version = "2014-04-01";
string authContextURL = "https://login.windows.net/" + tenantId;
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential(clientId, clientSecret);
var result = authenticationContext.AcquireToken(resource: "https://management.azure.com/", clientCredential: credential);
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Sql/servers/{2}/databases?api-version={3}", subscriptionid, resourcegroup, sqlservername, version));
request.Method = "GET";
request.Headers["Authorization"] = "Bearer " + token;
request.ContentType = "application/json";
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string jsonResponse = streamReader.ReadToEnd();
dynamic json = JsonConvert.DeserializeObject(jsonResponse);
dynamic resultList = json.value.Children();
foreach (var item in resultList)
{
dbNameList.Add(((Newtonsoft.Json.Linq.JValue)item.name).Value.ToString());
}
}
return dbNameList;
}
Result:
Another workaround.
I suggest you could use thread.join to wait the list method execute completely.
Code:
public static async Task<List<String>> getSqlDatabaseList()
{
//System.Diagnostics.Debug.WriteLine("Starting to get database list");
List<string> dbNameList = new List<string>();
var credentials = SdkContext.AzureCredentialsFactory.FromFile(#"D:\Auth.txt");
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithDefaultSubscription();
var sqlServer = await azure.SqlServers.GetByResourceGroupAsync("brandosecondtest", "brandotest");
IReadOnlyList<ISqlDatabase> dbList = null;
Thread thread = new Thread(() => { dbList = sqlServer.Databases.List(); });
thread.Start();
//wait the thread
thread.Join();
foreach (ISqlDatabase db in dbList)
{
dbNameList.Add(db.Name);
}
return dbNameList;
}
Result:
I trying using Google Analytics with C# to get stats information to display in my webiste
Here is my code
public ActionResult Index()
{
string userName = "admin#email.com";
string passWord = "mypass";
string profileId = "ga:xxxxxxxx";
string key = "2d751338cb092ef8da65f716e37a48604386c9sw";
string dataFeedUrl = "https://www.google.com/analytics/feeds/data"+key;
var service = new AnalyticsService("API Project");
service.setUserCredentials(userName, passWord);
var dataQuery = new DataQuery(dataFeedUrl)
{
Ids = profileId,
Metrics = "ga:pageviews",
Sort = "ga:pageviews",
GAStartDate = new DateTime(2010, 3, 1).ToString("yyyy-MM-dd"),
GAEndDate = DateTime.Now.ToString("yyyy-MM-dd")
};
var dataFeed = service.Query(dataQuery);
var totalEntry = dataFeed.Entries[0];
ViewData["Total"] = ((DataEntry)(totalEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var yesterdayEntry = dataFeed.Entries[0];
ViewData["Yesterday"] = ((DataEntry)(yesterdayEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var todayEntry = dataFeed.Entries[0];
ViewData["Today"] = ((DataEntry)(todayEntry)).Metrics[0].Value;
return View(dataFeed.Entries);
}
But when i run the code it always said "{"Invalid credentials"}"
Not sure why i facing this error while i checked many time about the key,username,password and profileId
Anyone facing this problem,can help me?
Many thanks
I think that your url is wrong. try in this way (you are missing ?key=).
string dataFeedUrl = "https://www.google.com/analytics/feeds/data?key="+key;
refer this google example where there is this example that should help you
public DataFeedExample()
{
// Configure GA API.
AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0");
// Client Login Authorization.
asv.setUserCredentials(CLIENT_USERNAME, CLIENT_PASS);
// GA Data Feed query uri.
String baseUrl = "https://www.google.com/analytics/feeds/data";
DataQuery query = new DataQuery(baseUrl);
query.Ids = TABLE_ID;
query.Dimensions = "ga:source,ga:medium";
query.Metrics = "ga:visits,ga:bounces";
query.Segment = "gaid::-11";
query.Filters = "ga:medium==referral";
query.Sort = "-ga:visits";
query.NumberToRetrieve = 5;
query.GAStartDate = "2010-03-01";
query.GAEndDate = "2010-03-15";
Uri url = query.Uri;
Console.WriteLine("URL: " + url.ToString());
// Send our request to the Analytics API and wait for the results to
// come back.
feed = asv.Query(query);
}
refer also this guide to configure your project
Also follow this guide to use OAuth 2.0