I have created an outgoing webhook in MS Teams. At mentioning the name specified in the outgoing webhook, it will successfully cause an API call in my app - all fine and good.
According to the documentation, my app is required to respond to that request with a response message. But I absolutely can't find any documentation of the format that is accepted in this response.
The only reference, I can find is this one:
https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-outgoing-webhook
Unfortunately, it does not go into detail of what such a message can look like. It only gives an example that this would be acceptable:
{
"type": "message",
"text": "This is a reply!"
}
I would however not like to respond with a simple message, but much rather with something more rich formatted like a card or - in some cases a reaction instead of a message.
Is that possible? Is there any documentation, what other responses are acceptable? Are there other types than just "message" that can be returned?
Alright, here's a quick and dirty way to handle things for teams. For some reason this is not documented very clearly, but what teams requires is for the "Card" to be created as an attachment, instead of just getting the response directly.
What I've done is capture the boilerplate required to house the card first:
string TeamsAdaptiveCardBoilerplate =
#"
{
""type"":""message"",
""attachments"":[
{
""contentType"":""application/vnd.microsoft.card.adaptive"",
""contentUrl"":null,
""content"":{
""$schema"":""http://adaptivecards.io/schemas/adaptive-card.json"",
""type"":""AdaptiveCard"",
""version"":""1.2"",
""body"":[
##BODY##
]
}
}
]
}
";
Then, I build the body (usually, this would not be static text, but it serves well as an example)
string AdaptiveCardBody =
#"
{
""type"": ""TextBlock"",
""text"": ""Here is a ninja cat""
},
{
""type"": ""Image"",
""url"": ""http://adaptivecards.io/content/cats/1.png""
}
";
Next I simple swap out the placeholder with the real body:
var jsonPayload1 = TeamsAdaptiveCardBoilerplate.Replace("##BODY##", AdaptiveCardBody);
And finally, return the assembled payload (converted back into an object so the correct response headers get set):
var payload1 = JsonConvert.DeserializeObject(jsonPayload1);
return (ActionResult)new OkObjectResult(payload1);
From there, you should be good to go.
Note:
For convenience, the entirety of the "content" (and not "body") block is what you'd copy/paste into the adaptivecards.io designer. You might refactor the above to reflect that reality if it was important to you.
Could you please try this sample json { "$schema": "adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.2", "body": [ { "type": "Image", "url": "c.s-microsoft.com/en-us/CMSImages/…" }, { "type": "TextBlock", "text": "Sample image for Adaptive Card..", "wrap": true } ] }
Within a release pipeline a new Pull Requested is created using REST API.
How to link a specific (already existing) Work Item to the Pull Request using REST API?
In the current version (DevOps 2019) it is not supported to link Work Items using Pull Request API. (See also related community issue.)
Using PowerShell the following snipped may help.
$requestUri = "$tfsCollectionUri/$teamProject/_apis/wit/workitems/$workItemId" + "?api-version=5.0"
$json = '
[ {
"op": "add", "path": "/relations/-",
"value": {
"rel": "ArtifactLink",
"url": "$pullRequestArtifact",
"attributes": { "name": "pull request" }
}
} ]'
$response = Invoke-RestMethod -Uri $requestUri -UseDefaultCredentials -ContentType "application/json-patch+json" -Method Post -Body $json
Note, $pullRequestArtifact needs to be set. You can get it e.g. from get request.
I am trying to create a service endpoint (aka service connection) in Azure DevOps. I first attempted to use the DevOps CLI but this method hangs. Using az devops as shown below.
az devops service-endpoint azurerm create --name “Azure subscription 1 endpoint” --azure-rm-service-principal-id $serviceprincipleid --azure-rm-subscription-id $subscriptionid --azure-rm-tenant-id $tenantid --azure-rm-subscription-name $serviceprinciplename --organization $organization --project $project
Hangs till i restart PowerShell
I suspect the logged in account doesn't have access?? IDK. And there's no way to specify a personal access token which is what I need anyway.
I then turned my attention towards calling the DevOps REST method using a Personal Access Token (PAT) to authenticate. I'm using the documentation from this sample
Here is the basic code in PowerShell
$body = '{
"data": {
"subscriptionId": "1272a66f-e2e8-4e88-ab43-487409186c3f",
"subscriptionName": "subscriptionName",
"environment": "AzureCloud",
"scopeLevel": "Subscription",
"creationMode": "Manual"
},
"name": "MyNewARMServiceEndpoint",
"type": "AzureRM",
"url": "https://management.azure.com/",
"authorization": {
"parameters": {
"tenantid": "1272a66f-e2e8-4e88-ab43-487409186c3f",
"serviceprincipalid": "1272a66f-e2e8-4e88-ab43-487409186c3f",
"authenticationType": "spnKey",
"serviceprincipalkey": "SomePassword"
},
"scheme": "ServicePrincipal"
},
"isShared": false,
"isReady": true,
"serviceEndpointProjectReferences": [
{
"projectReference": {
"id": "c7e5f0b3-71fa-4429-9fb3-3321963a7c06",
"name": "TestProject"
},
"name": "MyNewARMServiceEndpoint"
}
]
}' | convertto-json | convertfrom-json
$bo = $body | convertfrom-json
$bo.data.subscriptionId = $subscriptionid
$bo.data.subscriptionName = "subscription name"
$bo.name = $serviceprinciplename
$bo.authorization.parameters.tenantid = $tenantid
$bo.authorization.parameters.serviceprincipalid = $serviceprincipalid
$bo.authorization.parameters.serviceprincipalkey = $serviceprincipalkey
$bo.serviceEndpointProjectReferences = #{}
$readybody = $bo | convertto-json -Depth 100
#POST https://dev.azure.com/{organization}/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4
function createazurermserviceendpoint($body, $pat, $org, $project)
{
#POST https://dev.azure.com/{organization}/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4
$requestpath = "/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$pat"))
$uribase = "https://dev.azure.com/" + $org
$uri = $uribase+$requestpath
$authheader = "Authorization=Basic " + $token
$result = az rest --method post --uri $uri --headers "Content-Type=application/json" $authheader --body $body | convertfrom-json
return $result
}
$result = createazurermserviceendpoint $readybody $pat $org $project
The method throws a Bad Request exception as shown below
az : Bad Request({"$id":"1","innerException":null,"message":"TF400898: An Internal Error Occurred. Activity Id:
10a098a9-b4b5-4def-8356-307a5cad0579.","typeName":"Newtonsoft.Json.JsonReaderException,
Newtonsoft.Json","typeKey":"JsonReaderException","errorCode":0,"eventId":0})
So, i went into the UI with fiddler and captured both an automated and manual create service endpoint believing the contract would be the same. I'm not certain it is. The resulting json body from the API is shown below. When I attempt to pass this through the script I get the exact same error as above for both of them. None of the json is like the other; I started with the sample json structure in the article mentioned above. Now I'm not certain what the issue is at all.
#hack a version from fiddler to try it
#fiddler body capture from automated service connection
$readybody = '{"authorization":{"parameters":{"tenantid":"xxxxxxxx-34e9-4306-ac1a-5f28c1d08fb1","serviceprincipalid":"","serviceprincipalkey":"","authenticationType":"spnKey"},"scheme":"ServicePrincipal"},"createdBy":{},"data":{"environment":"AzureCloud","scopeLevel":"Subscription","subscriptionId":"yyyyyyyy-75c4-4dfd-bdd5-c8c42d1a5dd0","subscriptionName":"Azure subscription 1.1","creationMode":"Automatic","appObjectId":"","azureSpnPermissions":"","azureSpnRoleAssignmentId":"","spnObjectId":""},"isShared":false,"name":"Azure sub 1.1 test","owner":"library","type":"azurerm","url":"https://management.azure.com/","administratorsGroup":null,"description":"","groupScopeId":null,"operationStatus":null,"readersGroup":null,"serviceEndpointProjectReferences":[{"description":"","name":"Azure sub 1 test","projectReference":{"id":"zzzzzzzz-fad9-427f-ad6c-21f4ae2d311f","name":"Connected2someone"}}]}'
$result = createazurermserviceendpoint $readybody $pat $org $project
Fails the same way
#fiddler body capture from manual service connection
$readybody = '{"dataSourceDetails":{"dataSourceName":"TestConnection","dataSourceUrl":"","headers":null,"resourceUrl":"","requestContent":null,"requestVerb":null,"parameters":null,"resultSelector":"","initialContextTemplate":""},"resultTransformationDetails":{"callbackContextTemplate":"","callbackRequiredTemplate":"","resultTemplate":""},"serviceEndpointDetails":{"administratorsGroup":null,"authorization":{"scheme":"ServicePrincipal","parameters":{"serviceprincipalid":"xxxxxxxx-65b2-470d-adc7-c811fc993014","authenticationType":"spnKey","serviceprincipalkey":"{a key}","tenantid":"yyyyyyy-34e9-4306-ac1a-5f28c1d08fb1"}},"createdBy":null,"data":{"environment":"AzureCloud","scopeLevel":"Subscription","subscriptionId":"zzzzzzzz-75c4-4dfd-bdd5-c8c42d1a5dd3","subscriptionName":"azure test 2 ","creationMode":"Manual"},"description":"","groupScopeId":null,"name":"azure test 2 connection","operationStatus":null,"readersGroup":null,"serviceEndpointProjectReferences":null,"type":"azurerm","url":"https://management.azure.com/","isShared":false,"owner":"library"}}'
$result = createazurermserviceendpoint $readybody $pat $org $project
Fails the same way.
Can someone confirm the REST API works? what version of the API is specified and does the body json look like what I posted?
I did a test with your PowerShell script and got the same error you did.
Then I switched to another PowerShell script with the same body, and it worked.
Here is my script:
$pat = "{PAT}"
$pat = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$url="https://dev.azure.com/{organization}/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4"
$body = #'
{
body
}
'#
$head = #{ Authorization =" Basic $pat" }
Invoke-RestMethod -Uri $url -Method Post -Headers $head -Body $body -ContentType application/json
So the cause of the error may be your PowerShell script (probably az rest) and not the REST API request body. You can try out the PowerShell script I've provided.
By the way:
You can sign in Azure DevOps CLI with a PAT. Please click this document for detailed information.
I think there might be a bug in the following API endpoint to get calendar events for different meeting rooms: https://graph.microsoft.com/beta/me/calendar/getSchedule.
I know it is still beta and I see some inconsistency in returned data for meetings:
Testing scenario when the returned data changes:
Logged in user: Bogdan C.
Add a meeting
Query the API and see meeting title as subject
Add another meeting
Run again the query and see username as subject for the first meeting.
As a test scenario:
request body:
{
schedules: ['room1'],
//..other params
}
As a part of the response:
{
"scheduleId": "room1",
"scheduleItems": [
{
// first meeting added
...
"subject": "**Bogdan C.**", // bad
"location": "Room 1",
},
{
...
"subject": "**Design meeting**", // good
"location": "Room 1",
}
]
}
Any idea about what might be wrong?
Thanks
The issue here was related to the AddOrganizerToSubject and DeleteSubject calendar processing variables in Outlook, which both default to true.
We fixed them with the following PowerShell commands:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
Get-Mailbox -RecipientTypeDetails RoomMailbox | Set-CalendarProcessing -AddOrganizerToSubject $false -DeleteSubject $false
Now the meeting subjects appear as expected.
I am trying to create a build request and specify new values for custom variables defined in the TFS build definition. I assume I can do this without updating the build definition first. I posted the following JSON to the URL: http://<server-name>/tfs/DefaultCollection/<project-name>/_apis/build/builds?api-version=3.1. The build queued up but the variable value passed in did not override the default value. What am I missing? Do I need to specify the variable name differently?
{
"definition": {
"id": 24,
"variables": {
"IssueNumber": {
"value": "98765"
}
}
}
}
You're providing the wrong JSON structure. It's parameters, not variables, and the way you're specifying the key/value pairs is incorrect.
This PowerShell snippet should point you in the right direction:
$url = 'http://test-tfs-instance:8080/tfs/myCollection'
$body = #{
definition = #{
id = 1435
}
parameters = '{"MyParam":"OverriddenValue","system.debug":"false"}'
}
Invoke-RestMethod -Uri "$($url)/TeamProject/_apis/build/builds?api-version=3.1" -UseDefaultCredentials -Method Post -ContentType 'application/json' -body ($body | convertto-json -Compress -Depth 10)
For what it's worth, this kind of thing is trivial to discover by opening up the developer tools in your browser and looking at the REST call the TFS UI makes. Sometimes the documentation is unclear (as it is in this case), but it's hard to get mixed up when you're copying the same REST calls the application makes.