Assign a License (Microsoft Graph API) - c#

I'm trying to assign a license in C# via Graph API.
https://learn.microsoft.com/en-us/graph/api/user-assignlicense?view=graph-rest-1.0
Parameters:
addLicenses (AssignedLicense collection)
A collection of assignedLicense objects that specify the licenses to add. You can
disable plans associated with a license by setting the disabledPlans
property on an assignedLicense object.
removeLicenses (Guid collection)
A collection of GUIDs that identify the licenses to remove.
Here is my code ...
var userQuery = await client.Users
.Request()
.Filter("userPrincipalName eq 'xxx#xxx.de'")
.GetAsync();
var user = userQuery.FirstOrDefault();
var skus = await client.SubscribedSkus.Request().GetAsync();
do
{
foreach (var sku in skus)
{
AssignedLicense aLicense = new AssignedLicense { SkuId = sku.SkuId };
IList<AssignedLicense> licensesToAdd = new AssignedLicense[] { aLicense };
IList<Guid> licensesToRemove = new Guid[] { };
try
{
client.Users[user.Id].AssignLicense(licensesToAdd, licensesToRemove);
}
}
}
while (skus.NextPageRequest != null && (skus = await skus.NextPageRequest.GetAsync()).Count > 0);
I don't get an error, but it does not work. The user has no license ...

I think you forgot something here:
client.Users[user.Id].AssignLicense(licensesToAdd, licensesToRemove);
I think it should be:
await client.Users[user.Id].AssignLicense(licensesToAdd, licensesToRemove).Request().PostAsync();
PS:
You can get the user with less code like:
var userQuery = await client.Users["xxx#xxx.de"].Request().GetAsync();

Related

AWS Cost Explorer API doesn't return Resource ID

I'm testing the AWS Cost Explorer API (I'm using the .NET SDK), in particular the GetCostAndUsageWithResources method to get the costs split by resource.
This is the code I'm testing with:
string nextPageToken = null;
do
{
var costRequest = new GetCostAndUsageWithResourcesRequest()
{
Granularity = Granularity.HOURLY,
GroupBy = {
new GroupDefinition() {
Key = "RESOURCE_ID",
Type = GroupDefinitionType.DIMENSION
}
},
Metrics = { "BlendedCost" },
NextPageToken = nextPageToken
};
var costResponse = await client.GetCostAndUsageWithResourcesAsync(costRequest);
nextPageToken = costResponse.NextPageToken;
foreach (var resultByTime in costResponse.ResultsByTime)
{
foreach (var instanceGroup in resultByTime.Groups)
{
var instanceId = instanceGroup.Keys.First();
if(g.Keys.First() != "NoResourceId" && !g.Keys.First().StartsWith("i-"))
{
Debugger.Break(); //NEVER gets hit
}
}
}
} while (!string.IsNullOrEmpty(nextPageToken));
However, as you can see from the comment in the code, I have an issue: the resource ID (which is the dimension I'm grouping by) seems to only be retrieved correctly for EC2 machine instances (IDs that start with i-). Otherwise, all other results have the ID key set to NoResourceId
What am I doing wrong here? Why does the Cost Explorer API only populate the Resource ID of EC2 instances, and all others are not identified? What if I want to know the costs of all other AWS services, how do I identify to which service the result belongs?
Am I doing something wrong here in the way I invoke the API? What am I missing?

Downloading attachments with in sub folders using graph api and C#

I'm creating a solution to download attachments from an outlook365 account. The inbox of this account has subfolders and folders within the subfolders. The structure looks like below.
I've been trying to download the attachments but I'm only able to get the attachment from the messages in the main inbox.
But I want to look into the subfolders. So by studying the Microsoft graph document (https://learn.microsoft.com/en-us/graph/api/attachment-get?view=graph-rest-1.0&tabs=http#http-request) I found the below HTTP URL request.
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}/$value
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}/$value
I'm pretty new to C# I'm having a hard time converting above mentioned URL method to C#. Below is the current code I use to grab the messages and expand the attachments.
public static async Task<IMailFolderMessagesCollectionPage> GetAttachmentToday()
{
var DateToDay = DateTime.Now.ToString("dd.MM.yyyy");
var SearchOption = new List<QueryOption>
{
new QueryOption("search", $"%22received:{DateToDay}%22")
};
try
{
var attachments = await graphClient.Me.MailFolders.Inbox.Messages
.Request(SearchOption)
.Top(5)
.Select(a => new
{
a.Subject,
a.HasAttachments
})
.Expand("attachments")
.GetAsync();
return attachments;
}
catch(ServiceException ex)
{
Console.WriteLine($"Error getting events: {ex.Message}");
return null;
}
}
I can't figure out how to implement the Microsoft document URL suggestion to work with var attachments = await graphClient.Me.MailFolders.Inbox.Messages. Hope someone can point me down the right path.
I figure this out and used the example HTML code given by Microsoft documents. Which is below.
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}/$value
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}/$value
So based on the above code I came up with the below C# code.
//To get the first supfolder and it's ID.
var FirstSubFolderIDs = await graphClient.Me.MailFolders["Inbox"].ChildFolders
.Request()
.Select(fid => new
{
fid.Id,
fid.DisplayName
})
.GetAsync();
foreach(var FirstSubFolderID in FirstSubFolderIDs)
{
if(FirstSubFolderID.Id != null)
{ //Using the above ID to get the second folder and it's ID.
var SecondSubFolderIDs = await graphClient.Me.MailFolders["Inbox"]
.ChildFolders[$"{FirstSubFolderID.Id}"]
.ChildFolders
.Request()
.Select(sid => new
{
sid.Id,
sid.DisplayName
})
.GetAsync();
foreach (var SecondSubFolderID in SecondSubFolderIDs)
{
if(SecondSubFolderID.Id != null)
{ //Continuing on using the first 2 ID's to get the 3rd folder and it's ID.
var ThirdSubFolderIDs = await graphClient.Me.MailFolders["Inbox"]
.ChildFolders[$"{FirstSubFolderID.Id}"]
.ChildFolders[$"{SecondSubFolderID.Id}"]
.ChildFolders
.Request()
.Select(tid => new
{
tid.Id,
tid.DisplayName,
})
.GetAsync();
foreach (var ThirdSubFolderID in ThirdSubFolderIDs)
{
if(ThirdSubFolderID.DisplayName == "New")
{ //Now you're at the last folder where the emails are at.
var GetMessageAttachments = await graphClient.Me.MailFolders["Inbox"]
.ChildFolders[$"{FirstSubFolderID.Id}"]
.ChildFolders[$"{SecondSubFolderID.Id}"]
.ChildFolders[$"{ThirdSubFolderID.Id}"]
.Messages
//.Request(SearchOption)
.Request()
.Expand("attachments")
.Select(gma => new
{
gma.Id,
gma.Subject,
gma.HasAttachments,
gma.Attachments
})
.GetAsync();
//Get Message count that includes attachments
var MessageCount = GetMessageAttachments.Count;
if (MessageCount != 0)
{
//Do what you want here
}
Decided to answer my question so someone else might find this helpful.

Stripe; how to get subscriptionId when creating a customer with a new subscription

I'm creating a new customer and adding them to a subscription in one call like so:
StripeConfiguration.SetApiKey(StripeData.ApiKey);
var customerService = new CustomerService();
var myCustomer = new CustomerCreateOptions
{
Email = stripeEmail,
Source = stripeToken,
Plan = StripeData.MonthlySubscriptionPlanId
};
Customer stripeCustomer = customerService.Create(myCustomer);
Then I used to be able to do this:
myLocalUser.StripeCustomerId = stripeCustomer.Id;
myLocalUser.StripeSubscriptionId = stripeCustomer.Subscriptions.Data[0]?.Id;
But now the API isn't returning the customer's subscriptions so the second line fails
I'm now having to call the API again with this ugly code to get the customer's subscriptionId:
if (stripeCustomer.Subscriptions != null)
{
user.StripeSubscriptionId = stripeCustomer.Subscriptions.Data[0]?.Id;
}
else
{
//get subscriptionId
var cust = customerService.Get(stripeCustomer.Id, new CustomerGetOptions
{
Expand = new System.Collections.Generic.List<string> { "subscriptions" }
});
if (cust.Subscriptions.Any())
{
stripeSubscriptionId = cust.Subscriptions.First().Id;
}
}
CustomerService.Create() doesn't have the same Expand parameter option that the Get() method does...
This is expected, as subscriptions are no longer included by default on a customer object unless you expand them since API version 2020-08-27.
Creating a customer with a source and plan is still possible (although not the recommended integration path anymore since you might run into problems with 3DS and tax rates), although since you are on a newer API version you won't get the subscriptions list back. If you can you should update to creating subscriptions via their own API.
If you however still want to use this old integration path, you can still get the subscriptions back in the customer create call, you just need to expand the subscriptions on creation:
var customerService = new CustomerService();
var myCustomer = new CustomerCreateOptions
{
Email = stripeEmail,
Source = stripeToken,
Plan = StripeData.MonthlySubscriptionPlanId
};
myCustomer.AddExpand("subscriptions");
Customer stripeCustomer = customerService.Create(myCustomer);

How to notify user when programatically adding them to a group

I am adding members to a group with the code below.
My question is very simple :
When adding members with this code, the invited person does not get an email notifying them. However when doing the same from the UI there is an option to notify the user. How can I do that from the code?
public void UpdateGoupMembers(string groupName, List<string> loginNames)
{
using (var clientContext = new ClientContext(baseUrl))
{
clientContext.Credentials = credentials;
var web = clientContext.Web;
var group = web.SiteGroups.GetByName(groupName);
if (group != null)
{
foreach (var loginName in loginNames)
{
var user = web.EnsureUser(loginName);
if (user != null)
{
group.Users.AddUser(user);
}
}
var existingUsers = group.Users;
clientContext.Load(existingUsers, includes => includes.Include(
f => f.LoginName,
f => f.UserId,
f => f.PrincipalType,
f => f.Email,
f => f.Id));
clientContext.ExecuteQuery();
foreach (var existingUser in existingUsers)
{
var userName = existingUser.LoginName.Split('|')[2];
if (!loginNames.Contains(userName))
{
group.Users.RemoveByLoginName(existingUser.LoginName);
}
}
}
clientContext.ExecuteQuery();
}
}
I do not believe it is possible to send a Welcome Email when users are added to a group programatically based off of the method documentation.
However, you can use the CSOM library to send an email programatically to the specific user after adding them to the group. Send Emails via SharePoint CSOM will be a great reference on how to do this.

How to recover a database to a different page?

I created a database with SQLite-net so:
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "Database.db"), true);
await conn.CreateTableAsync<Musei>();
Musei musPref;
if (muss.NumeroTel != null && muss.Descrizione!=null && muss.indirizzoEmail!= null && muss.Immagine!= null)
{
musPref = new Musei
{
DidascaliaLista=muss.DidascaliaLista,
NomeMuseo = muss.NomeMuseo,
Luogopreciso = muss.Luogopreciso,
Descrizione = muss.Descrizione,
NumeroTel = muss.NumeroTel,
IndirizzoEmail = muss.IndirizzoEmail,
Immagine= muss.Immagine,
};
}
await conn.InsertAsync(musPref);
In another project I need to recover the database created and insert objects inside a ListView, But I do not know how to proceed ..
try
{
StorageFile data = await ApplicationData.Current.LocalFolder.GetFileAsync("Database.db");
}
catch(Exception)
{
}
And now??
I would like to retrieve the database created above and use it, inserting objects "Musei" that are in it and display it in a ListView
If you want to read from the database you created earlier, you can do the following:
// Get a connection to the database that is in the local folder.
var dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "Database.db");
var con = new SQLiteAsyncConnection(dbPath, true);
// Get all "Musei" in the database stored in the "Musei" table.
var results = await con.QueryAsync<Musei>("SELECT * FROM Musei");
If you only want the Musei that match a certain field value, for example: you only want to read those in the specific location "Rome", you can do that like this:
var searchLocation = "Rome"; // for example entered by the user in your UI.
// Get only the "Musei" in `searchLocation`.
var results = await con.QueryAsync<Musei>("SELECT * FROM Musei WHERE Luogopreciso ='?'", searchLocation);
An alternative, if you are only querying a single table, is to do it like this, using LINQ:
var query = con.Table<Musei>();
// or, if looking for `searchLocation`:
var query = con.Table<Musei>().Where(m => m.Luogopreciso == "Rome");
you can then get this as a list using:
var result = await query.ToListAsync();
To find out which tables are actually present in your opened database files, you can do this:
var nTables = 0;
System.Diagnostics.Debug.WriteLine("Tables in the database");
foreach (var mapping in con.TableMappings)
{
System.Diagnostics.Debug.WriteLine(mapping.TableName);
nTables++;
}
System.Diagnostics.Debug.WriteLine("{0} tables in total", nTables);
and look at the debug output.

Categories