Using the Microsoft Teams Portal, I created a Group that came with Assignments and the Notebook tab. I want to create a similar Group programmatically.
I am using the Nuget Microsoft.Graph.Beta 4.0.1-preview to create Team for a School Classroom programmatically on Microsoft Teams.
However I noticed that the team created does not have the Assignments tab nor the Notebook.
Then I compared with a Team I created on the teams portal and found that the Team created manually on the Teams portal have this creationOptions on the class Group
"creationOptions": ["classAssignments", "ExchangeProvisioningFlags:2509"]
But on the group created by API it does not contain that.
The API also does not have the field creationOptions
How to add that information when creating it using the API?
Or
How can I add those options after the Team is created?
I also tried this:
var grupo = await graphClient.Groups.Request().AddAsync(new Group()
{
DisplayName = "Turma Dialética 2021",
Description = "Grupo da Turma Dialética 2021",
MailNickname = "f958e37c-f093-4177-8de4-2f86bfaba624",
MailEnabled = false,
SecurityEnabled = false,
GroupTypes = new string[] { "Unified" },
Visibility = "HiddenMembership",//
AdditionalData = new Dictionary<string, object>()
{
{"creationOptions", new List<string> { "classAssignments", "ExchangeProvisioningFlags:2509" } }
}
}
);
Which sends this JSON payload
{
"description": "Grupo da Turma Dialética 2021",
"displayName": "Turma Dialética 2021",
"groupTypes": [
"Unified"
],
"mailEnabled": false,
"mailNickname": "f958e37c-f093-4177-8de4-2f86bfaba624",
"securityEnabled": false,
"visibility": "HiddenMembership",
"#odata.type": "microsoft.graph.group",
"creationOptions": [
"classAssignments",
"ExchangeProvisioningFlags:2509"
]
}
But when I add this AdditionalData, then this Exception happens:
Microsoft.Graph.ServiceException: 'Code: Request_BadRequest Message: A value without a type name was found and no expected type is available. When the model is specified, each value in the payload must have a type which can be either specified in the payload, explicitly by the caller or implicitly inferred from the parent value. Inner error: AdditionalData: date: 2021-04-08T21:14:22 request-id: d3a0b0d3-5940-46d8-8188-56a1eaf5d350 client-request-id: d3a0b0d3-5940-46d8-8188-56a1eaf5d350`
If I add an # symbol in front of the word creationOptions. e.g. "#creationOptions" then no error when creating the Group, but then when I try to create the Team from this Group:
var team = new Microsoft.Graph.Team()
{
MemberSettings = new TeamMemberSettings()
{
AllowCreateUpdateChannels = false
},
MessagingSettings = new TeamMessagingSettings()
{
AllowUserEditMessages = false,
AllowUserDeleteMessages = false
},
FunSettings = new TeamFunSettings()
{
AllowGiphy = false
}
,
AdditionalData = new Dictionary<string, object>()
{
{"template#odata.bind", "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"},
{"group#odata.bind", "https://graph.microsoft.com/v1.0/groups('" + grupo.Id + "')"}
}
};
graphClient.Teams.Request().AddAsync(team);
This error occurs:
Microsoft.Graph.ServiceException: 'Code: NotFound
Message: Failed to execute Templates backend request CreateTeamFromGroupWithTemplateRequest. Request Url: https://teams.microsoft.com/fabric/amer/templates/api/groups/9ee04411-993b-45f9-8d72-63343f703105/team, Request Method: PUT, Response Status Code: NotFound, Response Headers: Strict-Transport-Security: max-age=2592000
x-operationid: e922312859272d4ea8573cef70e37163
x-telemetryid: 00-e922312859272d4ea8573cef70e37163-0b5da564c6209441-00
X-MSEdge-Ref: Ref A: 34D331F1C0454DA7AE8CD7497D0558A7 Ref B: DM2EDGE1008 Ref C: 2021-04-09T15:16:22Z
Date: Fri, 09 Apr 2021 15:16:23 GMT
, ErrorMessage : {"errors":[{"message":"Failed to execute GetGroupAsync.","errorCode":"Unknown"}],"operationId":"e922312859272d4ea8573cef70e37163"}
Inner error:
AdditionalData:
date: 2021-04-09T15:16:24
request-id: d5ef1a33-d6d9-4d30-b9c5-83a7a477a1b5
client-request-id: d5ef1a33-d6d9-4d30-b9c5-83a7a477a1b5
ClientRequestId: d5ef1a33-d6d9-4d30-b9c5-83a7a477a1b5
'
You need to bind the correct template when POSTing to the /teams endpoint.
The educationClass template should create the right primitives in Teams and also set up the correct options under the hood in the Group.
From the POST /teams doc page:
POST https://graph.microsoft.com/beta/teams
Content-Type: application/json
{
"template#odata.bind": "https://graph.microsoft.com/beta/teamsTemplates('educationClass')",
"displayName": "My Class Team",
"description": "My Class Team’s Description"
}
The property doesn't appear to be defined in the metadata hence why it's not available in the SDK.
However, if you look at the definition for entity which group inherits from (via directory object), you'll find the additionalData property.
Setting the information there with something like the code snippet below should allow you to pass the desired information to the service.
AdditionalData = new Dictionary<string, object>()
{
{"#creationOptions", new List<string> { "classAssignments", "ExchangeProvisioningFlags:2509" } }
}
The # sign in front of the key is because this property is an instance annotation.
Related
We are creating a team group (with the beta Graph API) and we want the emailaddress to contain another value than the value that's based on what's provided in displayName.
While searching through the documentation it seems that this is possible by providing a value for mailNickname in AdditionalData (https://learn.microsoft.com/en-us/graph/teams-create-group-and-team).
So I implemented that. Unfortunately the mailaddress and the alias were still like TestGroup#domain.nl instead of TestMailNickname#domain.nl.
var graphApiServiceClient = new GraphServiceClient(this.authenticationProvider)
{
BaseUrl = "https://graph.microsoft.com/beta"
};
var owner = "valueForOwner";
var teamTemplate = teamTemplateType == TeamTemplateType.Staff
? "educationStaff"
: "educationClass";
var team = new Team
{
AdditionalData = new Dictionary<string, object>
{
{ "template#odata.bind", $"https://graph.microsoft.com/beta/teamsTemplates('{teamTemplate}')" },
{ "owners#odata.bind", new[]{$"https://graph.microsoft.com/beta/users('{owner}')"}},
{ "displayName", "TestGroup" },
{ "description", "This is a testgroup" },
{ "mailNickname", "TestMailNickname" }
}
};
await graphApiServiceClient.Teams.Request().AddAsync(team);
The MailNickname does change when I update the MailNickname property afterwards with an update request like await graphApiServiceClient.Groups[objectId].Request().UpdateAsync(new Group { MailNickname = mailNickname});.
This is confirmed with a graphApiServiceClient.Groups[objectId].Request().GetAsync()
Unfortunately it still shows TestGroup#domain.nl as the alias in the admin at https://admin.microsoft.com/AdminPortal/Home#/groups.
But, updating the value like this doesn't work for the Mail property because it states it's readonly in the update request.
Does anyone know what I am doing wrong in my original create/add request?
Plus does anyone know why the old alias value is still shown instead of the updated alias at https://admin.microsoft.com/AdminPortal/Home#/groups?
This is possible by creating a group via the Graph api first and then using the group ID to create a team for this group.
Create the group via "https://graph.microsoft.com/v1.0/groups".
{
"displayName": "TestGroup",
"mailNickname": "TestMailNickname",
"mailEnabled": true,
"securityEnabled": false,
"description": "This is a testgroup",
"groupTypes": [
"Unified"
],
"owners#odata.bind": [
"https://graph.microsoft.com/v1.0/users/OWNEDID"
]
}
Once the group has been made it'll output an ID which you'll then use to create a team via "https://graph.microsoft.com/v1.0/groups/YOURIDHERE/team"
Body would look something like;
{
"memberSettings": {
"allowCreateUpdateChannels": false,
"allowAddRemoveApps": false,
"allowCreateUpdateRemoveTabs": false,
"allowCreateUpdateRemoveConnectors": false
}
}
It looks like you are using an EDU tenant, since you are referencing the particular templates.
I have tested this previously, and the method suggested above will not work with the "EducationClass" template.
The way I got it to work was:
Create the Team with the template
$Teamdata =
'{
"displayName":"' + $newteamName + '",
"description":"' + $newteamName + '",
"template#odata.bind": "https://graph.microsoft.com/v1.0/teamsTemplates(\u0027educationClass\u0027)",
"hideFromOutlookClients": "true",
"hideFromAddressLists": "true",
"members":[
{
"#odata.type":"#microsoft.graph.aadUserConversationMember",
"roles":[
"owner"
],
"user#odata.bind":"'+ $DefaultOwnerURL + '"
}
]
}'
Wait for the group to be created (usually about 20 seconds)
patch the group mailnickname
$Body_SetGroupSDSSettings =
'{
"mailNickname": "' + $newteamMailNickname + '"
}'
It isn't perfect, but it is the best way I could find to do this.
POST: https://graph.microsoft.com/beta/teams/teamsId/channels/channelId
Request body
{
"displayName": "Task management",
"teamsApp#odata.bind"
"https://graph.microsoft.com/beta/appCatalogs/teamsApps/com.microsoft.teamspace.tab.planner",
"configuration": {
"entityId": "",
"contentUrl": "",
"websiteUrl": "",
"removeUrl": ""
}
}
entityId = plan id
contentUrl = websiteUrl = removeUrl = https://tasks.office.com/{tenantName}/Home/PlannerFrame?page=7&planId={planId}
Graph API's docs referred
https://learn.microsoft.com/en-us/graph/teams-configuring-builtin-tabs
https://learn.microsoft.com/en-us/graph/api/teamstab-add?view=graph-rest-beta
But works fine if created using teams app or even update the same tab using settings.
Looking at the logs, the URL you are specifying for the contentUrl seems to be missing the "page=7" query parameter, which looks like the reason the page doesn't load.
I'm trying to add a SharePoint Library tab to a Microsoft Team Channel programmatically through the Microsoft Graph.
Here is the payload I'm sending through the Graph Explorer POST
{
"teamsAppId": "com.microsoft.teamspace.tab.files.sharepoint",
"name": "Documents3",
"sortOrderIndex": "10300",
"configuration": {
"siteUrl": "https://baywet.sharepoint.com/sites/customerhub",
"libraryServerRelativeUrl": "/sites/customerhub/Shared Documents",
"selectedDocumentLibraryTitle": "Documents",
"selectedSiteTitle": "customerhub",
"dateAdded": "2018-10-05T16:56:59.169Z"
}
}
I get a 201 status response, my tab is added to the channel. However whenever somebody tries to upload a file from the Teams UI, they get the following error message The File {filename} is missing. If they click on Open in SharePoint and then upload the file, it works.
If I compare with a tab created through the UI (which works properly) here is the description I get.
{
"id": "a68e34db-9d43-4821-953b-2dec938ce785",
"name": "Document%20Library",
"teamsAppId": "com.microsoft.teamspace.tab.files.sharepoint",
"sortOrderIndex": "10200",
"webUrl": "https://teams.microsoft.com/l/channel/19%3ab2e05a0aae42487485b13e088d5d2f0f%40thread.skype/tab%3a%3aa63916e6-f252-477d-9696-7934980e7e47?label=Document%2520Library&groupId=71ed6a2e-67ca-4930-a3c2-abb25ca29fbf&tenantId=bd4c6c31-c49c-4ab6-a0aa-742e07c20232",
"configuration": {
"entityId": null,
"contentUrl": null,
"removeUrl": null,
"websiteUrl": null,
"siteUrl": "https://baywet.sharepoint.com/sites/customerhub",
"libraryServerRelativeUrl": "/sites/customerhub/Shared Documents",
"libraryId": "706FAD5678484E7B93B0855E52A0BCD9",
"selectedDocumentLibraryTitle": "Documents",
"selectedSiteImageUrl": "https://baywet.sharepoint.com/sites/customerhub/_api/GroupService/GetGroupImage?id='f9d430ca-4de3-42f1-9474-1427bfdb16b0'&hash=636743460492415245",
"selectedSiteTitle": "customerhub",
"dateAdded": "2018-10-05T16:56:59.169Z"
}
}
The only difference being the libraryId configuration value. (you're not supposed to send in the webUrl and id).
This library id doesn't match the library id in SharePoint, or the drive item id in the Graph so my question is: what value am I supposed to set for the libraryId? Is there anything else I am missing?
The following code Creates the team for a known Group ID (365 that When created, created a team site) and adds 3 tabs on the existing channel.
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(GraphClientId)
.WithTenantId(GraphTenantId)
.WithClientSecret(GraphClientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var team = new Team
{
MemberSettings = new TeamMemberSettings
{
AllowCreateUpdateChannels = true
},
MessagingSettings = new TeamMessagingSettings
{
AllowUserEditMessages = true,
AllowUserDeleteMessages = true
},
FunSettings = new TeamFunSettings
{
AllowGiphy = true,
GiphyContentRating = GiphyRatingType.Moderate
}
};
Team addedTeam = await graphClient.Groups[GroupID].Team
.Request()
.PutAsync(team);
ECGTeam ecgTeam = new ECGTeam {ProjectNumber= ProjectNumber ,GroupID = GroupID, TeamID = addedTeam.Id };
string channelID = string.Empty;
var channels = await graphClient.Teams[addedTeam.Id].Channels.Request().GetAsync();
channelID = channels[0].Id;
ecgTeam.ChannelID = channelID;
TeamsTab newTab = addTab(targetWebUrl, "WorkingPapers", "Working Papers");
var addedTab = await graphClient.Teams[addedTeam.Id].Channels[channelID].Tabs.Request().AddAsync(newTab);
ecgTeam.TabWorkingPapersID = addedTab.Id;
//DPC documents
newTab = addTab(targetWebUrl, "DPCdocuments", "DPC documents");
addedTab = await graphClient.Teams[addedTeam.Id].Channels[channelID].Tabs.Request().AddAsync(newTab);
ecgTeam.TabDPCdocumentsID=addedTab.Id;
//ContractDocuments //
newTab = addTab(targetWebUrl, "ContractDocuments", "Contract Documents");
addedTab = await graphClient.Teams[addedTeam.Id].Channels[channelID].Tabs.Request().AddAsync(newTab);
ecgTeam.TabContractDocumentsID = addedTab.Id;
//log.LogInformation(addedTab.Id);
Now, If you can help me create a Library for the said site that uses a custom content type, I will buy you coffee :-)
The wealth of good documentation for MS Graph in .NET Core makes me want to cry :-(
I found the solution a while after, sorry for not posting here earlier.
POST https://graph.microsoft.com/beta/teams/{groupId}/channels/{channelId}/tabs
{
"teamsApp#odata.bind": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/com.microsoft.teamspace.tab.files.sharepoint",
"name": "test",
"sortOrderIndex": "10400",
"configuration": {
"contentUrl": "https://baywet.sharepoint.com/sites/NYC/test"
}
}
Where contentUrl is the URL of the document library
I am wondering if the /v1.0/me/sendMail has the ability to delay sending an email. In the Outlook client, you can specify that you want your email sent at a later date and time. I've snooped around to see if there is a property that can be set on the message object to indicate this.
Did anyone find a way to get this working? Of course, I could implement something in my software to handle the delayed sending, but why re-create something if it is already there.
You can achieve delayed sending of emails using extended properties. These can be set on the Graph API request payload using the "singleValueExtendedProperties" attribute.
The property to use is PidTagDeferredSendTime which has the ID 0x3FEF and type SystemTime.
The id attribute of "singleValueExtendedProperties" takes different formats depending on the property you are setting.
For the deferred send time you would use SystemTime 0x3FEF.
Example using a HTTP JSON POST Payload:
{
"message": {
"subject": "Meet for lunch?",
"body": {
"contentType": "Text",
"content": "The new cafeteria is open."
},
"toRecipients": [
{
"emailAddress": {
"address": "bob#contoso.com"
}
}
],
"singleValueExtendedProperties":
[
{
"id":"SystemTime 0x3FEF",
"value":"2019-01-29T20:00:00"
}
]
}
}
Example using the Microsoft Graph API client library:
var client = /* Create and configure GraphServiceClient */;
var msg = new Message();
msg.ToRecipients = List<Recipient>();
msg.ToRecipients.Add(new Recipient() {
EmailAddress = new EmailAddress() { Address ="bob#contoso.com" }
};
msg.Subject = "Meet for lunch?";
msg.Body = new ItemBody()
{
Content = "The new cafeteria is open.",
ContentType = BodyType.Text,
};
msg.SingleValueExtendedProperties = new MessageSingleValueExtendedPropertiesCollectionPage();
msg.SingleValueExtendedProperties.Add(new SingleValueLegacyExtendedProperty()
{
Id = "SystemTime 0x3FEF",
Value = DateTime.UtcNow.AddMinutes(5).ToString("o")
});
await client.Me.SendMail(msg, true).Request().PostAsync();
https://gallery.technet.microsoft.com/office/Send-Emails-until-a-9cee20cf
You set the deferred send time extended prop when creating the item.
This question is related to Microsoft Dynamics CRM 2015, that I'm calling through API.
I create contact entity:
POST [organization URI]/api/data/contacts
Content-Type: application/json; charset=utf-8
Accept: application/json
{
"emailaddress1": "myemail#example.com",
}
It works, I see new record, after I log into the panel.
And I can call it through the API:
[organization URI]/api/data/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)
{
"#odata.context":"[organization URI]/api/data/$metadata#contacts/$entity",
"#odata.etag":"W/\"460199\"",
...
"contactid":"f76e4e7c-ea61-e511-80fd-3863bb342b00",
"emailaddress1":"myemail#example.com",
....
}
Next thing I want to do, is to add annotation record associated with that contact.
Following the guide I call:
POST [organization URI]/api/data/annotations
Content-Type: application/json; charset=utf-8
Accept: application/json
{
"notetext": "TEST",
'contact#odata.bind': 'contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'
}
But it returns 400 error:
An undeclared property 'contact' which only has property annotations in the payload but no property value was found in the payload. In OData, only declared navigation properties and declared named streams can be represented as properties without values.
When I call:
POST [organization URI]/api/data/annotations
Content-Type: application/json; charset=utf-8
Accept: application/json
{
"notetext": "TEST",
}
New entity is created, but without a relation to contact.
How to properly compose this POST request? What am I missing here?
I suspect, that contact#odata.bind should be presented somehow different, I've tried contactid#odata.bind, object#odata.bind, objectid#odata.bind - but no effects.
Any ideas?
Instead of using objectid#odata.bind, you have to use objectid_contact#odata.bind. This results are in:
"objectid_contact#odata.bind": "/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)"
To get the list of properties, look under the single-valued navigation properties in the documentation.
Part 1:
MS Docs Reference: Deep Insert
You can create entities related to each other by defining them as navigation properties values. This is known as deep insert.
As with a basic create, the response OData-EntityId header contains the Uri of the created entity. The URIs for the related entities created aren’t returned.
Below code is to create Account (1), create + associate Primary contact (2), create & Associate Opportunity (3) and create + associate Task (4)
POST [Organization URI]/api/data/v8.2/accounts HTTP/1.1
Content-Type: application/json; charset=utf-8
OData-MaxVersion: 4.0
OData-Version: 4.0
Accept: application/json
{
"name": "Sample Account",
"primarycontactid":
{
"firstname": "John",
"lastname": "Smith"
},
"opportunity_customer_accounts":
[
{
"name": "Opportunity associated to Sample Account",
"Opportunity_Tasks":
[
{ "subject": "Task associated to opportunity" }
]
}
]
}
Part 2:
Associating annotation to contact uses the below syntax.
note["objectid_contact#odata.bind"] = "/contacts(C5DDA727-B375-E611-80C8-00155D00083F)";
Refer SO link & blog
Part 3:
Answer to your comment on another answer about annotation_id_from_first_request:
To get the created record Id in response from last request, you can parse like below:
//get Response from Created Record
entityIdWithLink = XMLHttpRequest.getResponseHeader("OData-EntityId");
//get EntityId from ResponseHeader of Created Record
getEntityId = entityIdWithLink.split(/[()]/);
getEntityId = getEntityId[1];
You can read more
You can compose your POST request so that data from the created record will be returned with a status of 201 (Created).
To get this result, you must use the return=representation preference in the request headers.
To control which properties are returned, append the $select query option to the URL to the entity set.
The $expand query option will be ignored if used.
When an entity is created in this way the OData-EntityId header containing the URI to the created record is not returned
Note: This capability was added with December 2016 update for Dynamics 365
MS Docs Reference: Create with data returned
Update:
If anyone looking for working payload sample to deep insert a record + annotation, the below is from my project:
data = {
"new_attribute1": "test attribute 1",
"new_attribute2": "test attribute 2",
"new_comments": "test comments",
"new_recordurl": recordURL,
"new_feedback_Annotations":
[
{
"notetext": "Screenshot attached",
"subject": "Attachment",
"filename": file.name,
"mimetype": file.type,
"documentbody": base64str,
}
]
};
I've found this working, but in two requests:
POST [organization URI]/api/data/annotations
Content-Type: application/json; charset=utf-8
Accept: application/json
{
"notetext": "TEST"
}
POST [organization URI]/api/data/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)/Contact_Annotation/$ref
Content-Type: application/json; charset=utf-8
Accept: application/json
{
"#odata.id": "[organization URI]/annotations(annotation_id_from_first_request)"
}
Edit:
annotation_id_from_first_request value is taken form first request's response.
This answer applies for web api usage:
If the references property has been defined using uppercase letters, you have to use uppercase letters in the property on update and insert. Look at the Schema name in the property list of the primary entity.
Lets say you have an entity called myprefix_entity with a reference to the account entity, and you named it Account, and the schema name became myprefix_AccountId, you would have to refer it as:
"myprefix_AccountId#odata.bind":"/accounts(f76e4e7c-ea61-e511-80fd-000000000000)"
The uppercase A and the uppercase I in myprefix_AccountId matters, if that is how the schema name has been defined.
I'm using this C# Code for creating and linking (the Task.Await stuff is not very clever, so... be careful):
dynamic testAno = new ExpandoObject();
testAno.NoteText = "Hello World!";
testAno.Subject = "Note Subject";
dynamic refAccount = new ExpandoObject();
refAccount.LogicalName = "account";
refAccount.Id = "003CCFC2-4012-DE11-9654-001F2964595C";
testAno.ObjectId = refAccount;
testAno.ObjectTypeCode = refAccount.LogicalName;
var demo = JsonConvert.SerializeObject(testAno);
HttpContent content = new StringContent(demo, Encoding.UTF8, "application/json");
var handler = new HttpClientHandler { UseDefaultCredentials = true };
HttpClient client = new HttpClient(handler);
var test = client.PostAsync(new Uri("http://crm/.../XRMServices/2011/OrganizationData.svc/AnnotationSet"), content).Result;
The JSON is looking like this:
{"NoteText":"Hello World!",
"Subject":"Note Subject",
"ObjectId": {"LogicalName":"account",
"Id":"003CCFC2-4012-DE11-9654-001F2964595C"}
,"ObjectTypeCode":"account"}
You can use following.
'contactid_contact#odata.bind': '/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'
In most of the record you will get _contactid_value as a parameter name. So you have to pass like contactid_entityname#odata.bind as a parameter and in the value you have to pass 'EntitySetName' which would be contacts and GUID. '/EntitysetName(GUID)'
So the value will be '/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'
might be a bit late for this, but the answer in the following link explains how the binding works really well.
basically, you need to use the field schema name with the suffix #odata.bind and the value being "/entityschemaname(recordGUID)" good to remember that the entityschemaname needs to have an 's' and the recordGUID should not have the curly brackets.
for more information follow this link below where i got this information from
'An undeclared property' when trying to create record via Web API
If you use OData, then you can do it this way...
In your Annotation data model:
[DataContract(Name = "annotations")]
public record Annotation
{
[DataMember(Name = "objectid_rd_servicerequestsession")]
public ServiceRequestSession ObjectId { get; set; } = default!;
[DataMember(Name = "objecttypecode")]
public string ObjectTypeCode { get; set; } = default!;
Where the rd_servicerequestsession is your entity name. Then you just need to create a new object Annotation object
var annotation = new Annotation
{
ObjectId = serviceRequestSession,
ObjectTypeCode = "rd_servicerequestsession",
And simply invoke InsertEntry method.