diff --git a/.github/fabricbot.json b/.github/fabricbot.json new file mode 100644 index 000000000..6dcaf2f39 --- /dev/null +++ b/.github/fabricbot.json @@ -0,0 +1,1149 @@ +{ + "version": "1.0", + "tasks": [ + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isEvent", + "parameters": { + "eventName": "issues" + } + }, + { + "name": "isAction", + "parameters": { + "action": "opened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isAssignedToSomeone", + "parameters": {} + } + ] + } + ] + }, + "taskName": "Auto-label incoming issues as Needs Triage", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible." + } + }, + { + "name": "addLabels", + "parameters": { + "labels": [ + "Needs: Triage :mag:" + ] + } + } + ] + }, + "id": "DhSdUvTfU" + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": "msft-github-bot" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + }, + { + "name": "hasLabel", + "parameters": { + "label": "no-recent-activity" + } + } + ] + }, + "taskName": "Remove no recent activity label", + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "no-recent-activity" + } + } + ] + }, + "id": "EuTNKsOAX" + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isEvent", + "parameters": { + "eventName": "issue_comment" + } + }, + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isActivitySender", + "parameters": { + "user": { + "type": "author" + } + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "Needs: Author Feedback" + } + } + ] + }, + "taskName": "Add needs attention label to issues", + "actions": [ + { + "name": "addLabels", + "parameters": { + "labels": [ + "Needs: Attention :wave:" + ] + } + } + ] + }, + "id": "4g_ssp7c7" + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": { + "type": "author" + } + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + }, + { + "name": "hasLabel", + "parameters": { + "label": "Needs: Author Feedback" + } + } + ] + }, + "taskName": "Remove needs author feedback label from issues and pull requests", + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "Needs: Author Feedback" + } + } + ] + }, + "id": "LSpcATOkS" + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "id": "R2LaDi6Kz", + "config": { + "taskName": "Closed answered issues in 3 days", + "frequency": [ + { + "weekDay": 0, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + }, + { + "weekDay": 1, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + }, + { + "weekDay": 2, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + }, + { + "weekDay": 3, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + }, + { + "weekDay": 4, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + }, + { + "weekDay": 5, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + }, + { + "weekDay": 6, + "hours": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + } + ], + "searchTerms": [ + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "status:answered" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 3 + } + } + ], + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Closing this issue as \"answered\". If you encounter a similar issue(s), please open up a new issue. See our wiki for more details: [Issue-List: Our approach to closed issues](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#our-approach-to-closed-issues)" + } + }, + { + "name": "closeIssue", + "parameters": {} + }, + { + "name": "lockIssue", + "parameters": { + "reason": "resolved" + } + } + ] + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "id": "ejaaeLe6G", + "config": { + "frequency": [ + { + "weekDay": 0, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + }, + { + "weekDay": 1, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + }, + { + "weekDay": 2, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + }, + { + "weekDay": 3, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + }, + { + "weekDay": 4, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + }, + { + "weekDay": 5, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + }, + { + "weekDay": 6, + "hours": [ + 1, + 5, + 9, + 13, + 17, + 21 + ], + "timezoneOffset": -5 + } + ], + "searchTerms": [ + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "Needs: Author Feedback" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "no-recent-activity" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + } + ], + "taskName": "Close stale issues", + "actions": [ + { + "name": "closeIssue", + "parameters": {} + }, + { + "name": "addReply", + "parameters": { + "comment": "Closing issue due to no response from the original author. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: [No response from the original issue author](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#no-response-from-the-original-issue-author)" + } + }, + { + "name": "lockIssue", + "parameters": {} + } + ] + }, + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "JN4EianUp", + "config": { + "conditions": { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "type:invalid-not-dev-issue" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "type:invalid" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "Reply & close issues tagged \"type:invalid-not-dev-issue\"", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Thank you for your submission. As explained in our wiki ([Issue List: What doesn't belong in the issue list](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#what-doesnt-belong-in-the-issue-list)), this issue list is for SharePoint developer/development issues. All capability question/discussion questions, or topics related to SharePoint administration & end-user topics should be reported through the support user interface available in the tenant admin settings. You can also have a discussion and ask questions at the [SharePoint TechCommunity](https://techcommunity.microsoft.com/t5/SharePoint/ct-p/SharePoint) forum. You can learn more about this in our wiki: [type:invalid-not-dev-issue](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List-Labels#typeinvalid-not-dev-issue)" + } + }, + { + "name": "closeIssue", + "parameters": {} + }, + { + "name": "lockIssue", + "parameters": { + "reason": "off-topic" + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "dTcNyMD5a", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "type:uservoice-request" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Thank you for your submission. As explained in our wiki ([Issue List: What doesn't belong in the issue list](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#what-doesnt-belong-in-the-issue-list)), all new feature requests and change requests to existing features should be posted to the [SP Dev UserVoice](https://aka.ms/sp-dev-uservoice) site. You can learn more about this in our wiki: [type:uservoice-request](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List-Labels#typeuservoice-request)" + } + }, + { + "name": "closeIssue", + "parameters": {} + } + ], + "taskName": "Reply & close issues tagged \"type:uservoice-request\"" + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "TXAA0OOon", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "Needs: Context Detail :question:" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "Reply issues tagged \"Needs: Context Detail\"", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "The more context details you can provide, the easier it is to help assist on issues. Any code you can provide and/or screenshots of the issue also help. The easier you can make it to reproduce the issue, the easier and quicker it is for someone to help you. Please refer to [How to Create Good Issues](https://github.com/SharePoint/sp-dev-docs/wiki/How-to-Create-Good-Issues), specifically [How to Create Good Issues: Include context](https://github.com/SharePoint/sp-dev-docs/wiki/How-to-Create-Good-Issues#include-context), in our wiki for more details." + } + }, + { + "name": "addLabel", + "parameters": { + "label": "Needs: Author Feedback" + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "vAHQpj0AT", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "status:duplicate" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "Close issues tagged \"status:duplicate\"", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Closing this issue as a dupe. Please refer to our wiki for more details: [Issue List Labels: status:duplicate](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List-Labels#statusduplicate)" + } + }, + { + "name": "closeIssue", + "parameters": {} + }, + { + "name": "lockIssue", + "parameters": { + "reason": "resolved" + } + } + ] + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "id": "Lzyb5Csy_", + "config": { + "frequency": [ + { + "weekDay": 0, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 1, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 2, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 3, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 4, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 5, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 6, + "hours": [ + 0, + 6, + 12, + 18 + ] + } + ], + "searchTerms": [ + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isClosed", + "parameters": {} + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + }, + { + "name": "isUnlocked", + "parameters": {} + } + ], + "taskName": "Lock issues if inactive 7d after closing", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: [Issue List: Our approach to locked issues](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#our-approach-to-locked-issues)" + } + }, + { + "name": "lockIssue", + "parameters": { + "reason": "resolved" + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "k84udcNf_", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "bodyContains", + "parameters": { + "bodyPattern": "Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking." + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "actions": [ + { + "name": "addLabel", + "parameters": { + "label": "area:docs-comment" + } + } + ], + "taskName": "Label new issues created as comment on docs with \"area:docs-comment\"" + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "NbeJ2zWgh", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "type:incomplete-submission" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "Reply & tag issues tagged with type:incomplete-submission", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Thank you for your submission, but there isn't enough detail in the issue for us to review & move forward. The new issue template includes sections for you to fill out. Please resubmit your issue and complete the provided sections in the new item template so we can move forward on it refer to our wiki for more information: [How to Create Good Issues](https://github.com/SharePoint/sp-dev-docs/wiki/How-to-Create-Good-Issues)" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "Needs: Triage :mag:" + } + }, + { + "name": "closeIssue", + "parameters": {} + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "id": "SgmbtMnlk", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "type:incomplete-submission" + } + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "Reply & tag PRs tagged with type:incomplete-submission", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Thank you for your submission, but there isn't enough detail in the pull request for us to review & move forward. The new PR template includes sections for you to fill out. Please resubmit your PR and complete the provided sections in the new item template so we can move forward on it refer to our wiki for more information: [How to Create Good Pull Requests]https://github.com/SharePoint/sp-dev-docs/wiki/How-to-Create-Good-Pull-Requests)" + } + }, + { + "name": "closeIssue", + "parameters": {} + } + ] + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "id": "ECBdzA7w3Y7R-jcBx0icn", + "config": { + "frequency": [ + { + "weekDay": 0, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 1, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 2, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 3, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 4, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 5, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 6, + "hours": [ + 0, + 6, + 12, + 18 + ] + } + ], + "searchTerms": [ + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "Needs: Author Feedback" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + } + ], + "actions": [ + { + "name": "addLabel", + "parameters": { + "label": "no-recent-activity" + } + }, + { + "name": "addReply", + "parameters": { + "comment": "This issue has been automatically marked as stale because it has marked as requiring author feedback but has not had any activity for **7 days**. It will be closed if no further activity occurs **within the next 7 days of this comment**. Please see our wiki for more information: [Issue List Labels: Needs Author Feedback](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List-Labels#needs-author-feedback) & [Issue List: No response from the original issue author](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#no-response-from-the-original-issue-author)" + } + } + ], + "taskName": "Mark issue with no-recent-activity label if there's no actions in 7 days" + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "MdPj2K40N73yDGFnu9REz", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "listmaintenance-oldissues" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "This issue is being closed as part of an issue list cleanup project. Issues with no activity in the past 6 months that aren't tracked by engineering as bugs were closed as part of this inititive. If this is still an issue, please [follow the steps outlined to re-open or submit a new issue](https://github.com/sharepoint/sp-dev-docs/wiki/Issue-List#our-approach-to-closed-issues)." + } + }, + { + "name": "closeIssue", + "parameters": {} + } + ], + "taskName": "Close inactive issues based on list maintenance label" + } + } + ], + "userGroups": [] +} diff --git a/.github/label-actions.yml b/.github/label-actions.yml new file mode 100644 index 000000000..80a5bf7aa --- /dev/null +++ b/.github/label-actions.yml @@ -0,0 +1,14 @@ +# Configuration for Label Actions - https://github.com/dessant/label-actions + +# Actions taken when the `type:archive-old-issue` label is added to issues that are being archived. +type:archive-old-issue: + # Post a comment + comment: |+ + Thank you for taking the time to file an issue. We periodically **archive** older or inactive issues as part of our issue management process, which automatically closes them once they are archived. + + If you’d like to understand more about why and how we handle archived (closed) issues, please see [Our approach to closed issues](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#our-approach-to-closed-issues). + + We appreciate your contribution and if this is still an active issue with the latest SPFx versions, please do resubmit the details. We needed to perform a cleanup, so that we can start with a **clean table** with a new process. We apologize for the inconvenience this might cause. + + # Close the issue + close: true diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml new file mode 100644 index 000000000..43263aa44 --- /dev/null +++ b/.github/policies/resourceManagement.yml @@ -0,0 +1,115 @@ +id: bot-issue-management +name: Issue Management +description: Enable tracking & monitoring of issues +resource: repository +disabled: false +configuration: + resourceManagementConfiguration: + scheduledSearches: + - description: Close answered issues after 3 days of inactivity + frequencies: + - hourly: { hour: 0 } + filters: + - isIssue + - isOpen + - hasLabel: { label: status:answered } + - noActivitySince: { days: 3 } + actions: + - addReply: + reply: > + Closing this issue as "answered". If you encounter a similar issue(s), please open up a new issue. See our wiki for more details: [Issue-List: Our approach to closed issues](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#our-approach-to-closed-issues) + - closeIssue + - lockIssue: + reason: resolved + + - description: Close stale issues with no recent author activity after 7 days + frequencies: + - hourly: { hour: 6 } + filters: + - isIssue + - isOpen + - hasLabel: { label: 'Needs: Author Feedback' } + - hasLabel: { label: no-recent-activity } + - noActivitySince: { days: 7 } + actions: + - addReply: + reply: > + Closing issue due to no response from the original author. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: [No response from the original issue author](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#no-response-from-the-original-issue-author) + - closeIssue + - lockIssue + + - description: Mark issues as no recent activity after 7 days + frequencies: + - hourly: { hour: 6 } + filters: + - isIssue + - isOpen + - hasLabel: { label: 'Needs: Author Feedback' } + - noActivitySince: { days: 7 } + actions: + - addLabel: { label: no-recent-activity } + - addReply: + reply: > + This issue has been automatically marked as stale because it has marked as requiring author feedback but has not had any activity for **7 days**. It will be closed if no further activity occurs **within the next 7 days of this comment**. Please see our wiki for more information: [Issue List Labels: Needs Author Feedback](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List-Labels#needs-author-feedback) & [Issue List: No response from the original issue author](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#no-response-from-the-original-issue-author) + + - description: Lock issues inactive 7 days after closing + frequencies: + - hourly: { hour: 6 } + filters: + - isIssue + - isClosed + - noActivitySince: { days: 7 } + - isUnlocked + actions: + - addReply: + reply: > + Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: [Issue List: Our approach to locked issues](https://github.com/SharePoint/sp-dev-docs/wiki/Issue-List#our-approach-to-locked-issues) + - lockIssue: + reason: resolved + + eventResponderTasks: + - if: + - payloadType: Issues + - isAction: { action: opened } + - not: + isAssignedToSomeone: true + then: + - addReply: + reply: > + Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible. + - addLabel: + label: 'Needs: Triage :mag:' + + - if: + - payloadType: Issue_Comment + - isActivitySender: { issueAuthor: true } + - hasLabel: { label: 'Needs: Author Feedback' } + - isOpen + then: + - addLabel: + label: 'Needs: Attention :wave:' + + - if: + - payloadType: Issues + - isActivitySender: { issueAuthor: true } + - not: + isAction: { action: closed } + - hasLabel: { label: 'Needs: Author Feedback' } + then: + - removeLabel: { label: 'Needs: Author Feedback' } + + - if: + - payloadType: Issues + - not: + isActivitySender: { user: microsoft-github-policy-service } + - not: + isAction: { action: closed } + - hasLabel: { label: no-recent-activity } + then: + - removeLabel: { label: no-recent-activity } + + - if: + - payloadType: Issue_Comment + - hasLabel: { label: no-recent-activity } + then: + - removeLabel: { label: no-recent-activity } diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml new file mode 100644 index 000000000..d2dd0ff59 --- /dev/null +++ b/.github/workflows/label-actions.yml @@ -0,0 +1,18 @@ +name: 'Check for Incomplete Issues' + +on: + issues: + types: [labeled, unlabeled] + +permissions: + issues: write + pull-requests: write + +jobs: + reaction: + runs-on: ubuntu-latest + steps: + - uses: dessant/label-actions@v2 + with: + github-token: ${{ github.token }} + process-only: 'issues' diff --git a/.openpublishing.build.ps1 b/.openpublishing.build.ps1 deleted file mode 100644 index aadef7620..000000000 --- a/.openpublishing.build.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -param( - [string]$buildCorePowershellUrl = "https://opbuildstorageprod.blob.core.windows.net/opps1container/.openpublishing.buildcore.ps1", - [string]$parameters -) -# Main -$errorActionPreference = 'Stop' - -# Step-1: Download buildcore script to local -echo "download build core script to local with source url: $buildCorePowershellUrl" -$repositoryRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition -$buildCorePowershellDestination = "$repositoryRoot\.openpublishing.buildcore.ps1" -Invoke-WebRequest $buildCorePowershellUrl -OutFile "$buildCorePowershellDestination" - -# Step-2: Run build core -echo "run build core script with parameters: $parameters" -& "$buildCorePowershellDestination" "$parameters" -exit $LASTEXITCODE diff --git a/.openpublishing.publish.config.json b/.openpublishing.publish.config.json index b7e0be39b..f3522487f 100644 --- a/.openpublishing.publish.config.json +++ b/.openpublishing.publish.config.json @@ -24,8 +24,7 @@ ], "notification_subscribers": [ "vesaj@microsoft.com", - "bjansen@microsoft.com", - "v-licapu@microsoft.com" + "bjansen@microsoft.com" ], "sync_notification_subscribers": null, "branches_to_filter": [], @@ -81,4 +80,4 @@ "nuget_feed": "https://www.myget.org/F/op/api/v2" } ] -} \ No newline at end of file +} diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 90761bfbb..78222f726 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1,99 +1,274 @@ { - "redirections": [ - { - "source_path": "docs/apis/rest/complete-basic-operations-using-sharepoint-rest-endpoints.md", - "redirect_url": "docs/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/determine-sharepoint-rest-service-endpoint-uris.md", - "redirect_url": "docs/sp-add-ins/determine-sharepoint-rest-service-endpoint-uris", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/get-to-know-the-sharepoint-rest-service.md", - "redirect_url": "docs/sp-add-ins/get-to-know-the-sharepoint-rest-service.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/make-batch-requests-with-the-rest-apis.md", - "redirect_url": "docs/sp-add-ins/make-batch-requests-with-the-rest-apis.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/navigate-the-sharepoint-data-structure-represented-in-the-rest-service.md", - "redirect_url": "docs/sp-add-ins/navigate-the-sharepoint-data-structure-represented-in-the-rest-service.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/set-custom-permissions-on-a-list-by-using-the-rest-interface.md", - "redirect_url": "docs/sp-add-ins/set-custom-permissions-on-a-list-by-using-the-rest-interface.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/synchronize-sharepoint-items-using-the-rest-service.md", - "redirect_url": "docs/sp-add-ins/synchronize-sharepoint-items-using-the-rest-service.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/upload-a-file-by-using-the-rest-api-and-jquery.md", - "redirect_url": "docs/sp-add-ins/upload-a-file-by-using-the-rest-api-and-jquery.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/use-odata-query-operations-in-sharepoint-rest-requests.md", - "redirect_url": "docs/sp-add-ins/use-odata-query-operations-in-sharepoint-rest-requests.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/working-with-folders-and-files-with-rest.md", - "redirect_url": "docs/sp-add-ins/working-with-folders-and-files-with-rest.md", - "redirect_document_id": false - }, - { - "source_path": "docs/apis/rest/working-with-lists-and-list-items-with-rest.md", - "redirect_url": "docs/sp-add-ins/working-with-lists-and-list-items-with-rest.md", - "redirect_document_id": false - }, - { - "source_path": "docs/schema/index.md", - "redirect_url": "docs/schema/upgrade-definition-schema.md", - "redirect_document_id": false - }, - { - "source_path": "docs/sp-add-ins/add-a-custom-content-type-to-a-sharepoint-hostedsharepoint-add-in.md", - "redirect_url": "docs/sp-add-ins/add-a-custom-content-type-to-a-sharepoint-hosted-sharepoint-add-in.md", - "redirect_document_id": false - }, - { - "source_path": "docs/sp-add-ins/add-custom-columns-to-a-sharepoint-hostedsharepoint-add-in.md", - "redirect_url": "docs/sp-add-ins/add-custom-columns-to-a-sharepoint-hosted-sharepoint-add-in.md", - "redirect_document_id": false - }, - { - "source_path": "docs/spfx/web-parts/guidance/creating-team-manifest-manually-for-webpart.md", - "redirect_url": "docs/spfx/deployment-spfx-teams-solutions.md", - "redirect_document_id": false - }, - { - "source_path": "docs/general-development/office-365-cdn.md", - "redirect_url": "/office365/enterprise/use-office-365-cdn-with-spo", - "redirect_document_id": false - }, - { - "source_path": "docs/spfx/toolchain/scaffolding-projects-using-yeoman-sharepoint-generator.md", - "redirect_url": "docs/spfx/yeoman-generator-for-spfx-intro.md", - "redirect_document_id": false - }, - { - "source_path": "docs/spfx/office-addins-create.md", - "redirect_url": "docs/spfx/release-1.14.md", - "redirect_document_id": false - }, - { - "source_path": "docs/spfx/web-parts/get-started/office-addins-tutorial.md", - "redirect_url": "docs/spfx/release-1.14.md", - "redirect_document_id": false - } - ] + "redirections": [ + { + "source_path": "docs/apis/rest/complete-basic-operations-using-sharepoint-rest-endpoints.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/determine-sharepoint-rest-service-endpoint-uris.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/determine-sharepoint-rest-service-endpoint-uris", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/get-to-know-the-sharepoint-rest-service.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/make-batch-requests-with-the-rest-apis.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/make-batch-requests-with-the-rest-apis", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/navigate-the-sharepoint-data-structure-represented-in-the-rest-service.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/navigate-the-sharepoint-data-structure-represented-in-the-rest-service", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/set-custom-permissions-on-a-list-by-using-the-rest-interface.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/set-custom-permissions-on-a-list-by-using-the-rest-interface", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/synchronize-sharepoint-items-using-the-rest-service.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/synchronize-sharepoint-items-using-the-rest-service", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/upload-a-file-by-using-the-rest-api-and-jquery.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/upload-a-file-by-using-the-rest-api-and-jquery", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/use-odata-query-operations-in-sharepoint-rest-requests.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/use-odata-query-operations-in-sharepoint-rest-requests", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/working-with-folders-and-files-with-rest.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest", + "redirect_document_id": false + }, + { + "source_path": "docs/apis/rest/working-with-lists-and-list-items-with-rest.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest", + "redirect_document_id": false + }, + { + "source_path": "docs/schema/index.md", + "redirect_url": "/sharepoint/dev/schema/upgrade-definition-schema", + "redirect_document_id": false + }, + { + "source_path": "docs/sp-add-ins/add-a-custom-content-type-to-a-sharepoint-hostedsharepoint-add-in.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/add-a-custom-content-type-to-a-sharepoint-hosted-sharepoint-add-in", + "redirect_document_id": false + }, + { + "source_path": "docs/sp-add-ins/add-custom-columns-to-a-sharepoint-hostedsharepoint-add-in.md", + "redirect_url": "/sharepoint/dev/sp-add-ins/add-custom-columns-to-a-sharepoint-hosted-sharepoint-add-in", + "redirect_document_id": false + }, + { + "source_path": "docs/spfx/web-parts/guidance/creating-team-manifest-manually-for-webpart.md", + "redirect_url": "/sharepoint/dev/spfx/deployment-spfx-teams-solutions", + "redirect_document_id": false + }, + { + "source_path": "docs/general-development/office-365-cdn.md", + "redirect_url": "/sharepoint/dev/office365/enterprise/use-office-365-cdn-with-spo", + "redirect_document_id": false + }, + { + "source_path": "docs/spfx/toolchain/scaffolding-projects-using-yeoman-sharepoint-generator.md", + "redirect_url": "/sharepoint/dev/spfx/yeoman-generator-for-spfx-intro", + "redirect_document_id": false + }, + { + "source_path": "docs/spfx/office-addins-create.md", + "redirect_url": "/sharepoint/dev/spfx/release-1.14", + "redirect_document_id": false + }, + { + "source_path": "docs/spfx/web-parts/get-started/office-addins-tutorial.md", + "redirect_url": "/sharepoint/dev/spfx/release-1.14", + "redirect_document_id": false + }, + { + "source_path": "docs/spfx/sharepoint-2019-support.md", + "redirect_url": "/sharepoint/dev/spfx/sharepoint-2019-and-subscription-edition-support", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/mslearn/m01-01-intro.md", + "redirect_url": "/training/modules/sharepoint-embedded-setup/", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/mslearn/m02-01-intro.md", + "redirect_url": "/training/modules/sharepoint-embedded-create-app/", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/adoptions-and-use.md", + "redirect_url": "/sharepoint/dev/embedded/scenarios-and-use-cases", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/billing.md", + "redirect_url": "/sharepoint/dev/embedded/concepts/admin-exp/billing/billing", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/cta.md", + "redirect_url": "/sharepoint/dev/embedded/concepts/admin-exp/consuming-tenant-admin/cta", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/dev-admin.md", + "redirect_url": "/sharepoint/dev/embedded/concepts/admin-exp/developer-admin/dev-admin", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/terms-and-def.md", + "redirect_url": "/sharepoint/dev/embedded/overview", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/getting-started/enable-sharepoint-embedded.md", + "redirect_url": "/sharepoint/dev/embedded/overview", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/terms-of-service.md", + "redirect_url": "/sharepoint/dev/embedded/overview", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/adminrole.md", + "redirect_url": "/sharepoint/dev/embedded/administration/adminrole", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/billing/billing.md", + "redirect_url": "/sharepoint/dev/embedded/administration/billing/billing", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/billing/billingmanagement.md", + "redirect_url": "/sharepoint/dev/embedded/administration/billing/billingmanagement", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/billing/meters.md", + "redirect_url": "/sharepoint/dev/embedded/administration/billing/meters", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/consuming-tenant-admin/cta.md", + "redirect_url": "/sharepoint/dev/embedded/administration/consuming-tenant-admin/cta", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/consuming-tenant-admin/ctaUX.md", + "redirect_url": "/sharepoint/dev/embedded/administration/consuming-tenant-admin/ctaUX", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/consuming-tenant-admin/ctapowershell.md ", + "redirect_url": "/sharepoint/dev/embedded/administration/consuming-tenant-admin/ctapowershell", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/admin-exp/developer-admin/dev-admin.md", + "redirect_url": "/sharepoint/dev/embedded/administration/developer-admin/dev-admin", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/security-and-compliance.md", + "redirect_url": "/sharepoint/dev/embedded/compliance/security-and-compliance", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/app-architecture.md", + "redirect_url": "/sharepoint/dev/embedded/development/app-architecture", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/auth.md", + "redirect_url": "/sharepoint/dev/embedded/development/auth", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/content-experiences/office-experience.md", + "redirect_url": "/sharepoint/dev/embedded/development/content-experiences/office-experience", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/content-experiences/search-content.md", + "redirect_url": "/sharepoint/dev/embedded/development/content-experiences/search-content", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/content-experiences/user-experiences-overview.md", + "redirect_url": "/sharepoint/dev/embedded/development/content-experiences/user-experiences-overview", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/fluid.md", + "redirect_url": "/sharepoint/dev/embedded/development/fluid", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/limits-calling.md", + "redirect_url": "/sharepoint/dev/embedded/development/limits-calling", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/sharing-and-perm.md", + "redirect_url": "/sharepoint/dev/embedded/development/sharing-and-perm", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/tutorials/doc-processing-acs.md", + "redirect_url": "/sharepoint/dev/embedded/development/tutorials/doc-processing-acs", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/tutorials/launch-experience.md", + "redirect_url": "/sharepoint/dev/embedded/development/tutorials/launch-experience", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/tutorials/metadata.md", + "redirect_url": "/sharepoint/dev/embedded/development/tutorials/metadata", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/tutorials/migrate-abs-to-spe.md", + "redirect_url": "/sharepoint/dev/embedded/development/tutorials/migrate-abs-to-spe", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/tutorials/using-file-preview.md", + "redirect_url": "/sharepoint/dev/embedded/development/tutorials/using-file-preview", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/tutorials/using-webhooks.md", + "redirect_url": "/sharepoint/dev/embedded/development/tutorials/using-webhooks", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/containertypes.md", + "redirect_url": "/sharepoint/dev/embedded/getting-started/containertypes", + "redirect_document_id": false + }, + { + "source_path": "docs/embedded/concepts/app-concepts/register-api-documentation.md", + "redirect_url": "/sharepoint/dev/embedded/getting-started/register-api-documentation", + "redirect_document_id": false + } + ] } diff --git a/README.md b/README.md index 8d22cc941..4e77f8fcb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Welcome to the SharePoint Framework! +# Welcome to the SharePoint Framework! The SharePoint Framework (SPFx) is a page and part model that enables client-side development for building SharePoint experiences. It facilitates easy integration with the SharePoint data, and provides support for open source tooling development. @@ -22,7 +22,6 @@ Review all the SPFx releases here from the [initial GA release in February 2017] * [Setup your Machine](https://learn.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment) * [Go build your first web part](https://learn.microsoft.com/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part) - ## Learn More * [Background and Philosophy](https://learn.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview) diff --git a/assets/ace/URL.txt b/assets/ace/URL.txt new file mode 100644 index 000000000..7d3d66ec3 --- /dev/null +++ b/assets/ace/URL.txt @@ -0,0 +1 @@ +me/events?$select=subject,body,bodyPreview,organizer,attendees,start,end,location \ No newline at end of file diff --git a/assets/ace/calendar-top.png b/assets/ace/calendar-top.png new file mode 100644 index 000000000..d8cb719da Binary files /dev/null and b/assets/ace/calendar-top.png differ diff --git a/assets/ace/email-top.png b/assets/ace/email-top.png new file mode 100644 index 000000000..d9170e95a Binary files /dev/null and b/assets/ace/email-top.png differ diff --git a/assets/ace/events-quick-view.json b/assets/ace/events-quick-view.json new file mode 100644 index 000000000..fb16cb82b --- /dev/null +++ b/assets/ace/events-quick-view.json @@ -0,0 +1,85 @@ +{ + "type": "AdaptiveCard", + "version": "1.5", + "@odata.type": "#microsoft.graph.message", + "body": [ + { + "type": "Container", + "items": [ + { + "type": "Image", + "url": "https://raw.githubusercontent.com/SharePoint/sp-dev-docs/main/assets/ace/calendar-top.png" + }, + { + "type": "TextBlock", + "text": "This control displays the latest calendar events. You can open the event in Outlook or, if it's a meeting, you can join it simply clicking on the button next to the event.", + "wrap": true + } + ] + }, + { + "type": "Container", + "$data": "${value}", + "items": [ + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "width": "stretch", + "items": [ + { + "type": "TextBlock", + "text": "${subject}", + "size": "Medium" + }, + { + "type": "TextBlock", + "text": "${location.displayName}", + "spacing": "None" + }, + { + "type": "TextBlock", + "text": "${formatDateTime(substring(start.dateTime,0,19), 'dd/MM/yyyy hh:mm')}-${formatDateTime(substring(end.dateTime,0,19), 'hh:mm')}", + "spacing": "None", + "size": "Small" + } + ] + }, + { + "type": "Column", + "width": "auto", + "items": [ + { + "type": "Image", + "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAvBJREFUSEvtVUtIalEUXdeKiDDIiIY1i7CIBkqRRrNCAqFM6AsRQhMLx5VSVvTBoqwIIqTIoCYV1aBZ/4EDk4gkmgg16iP9cFQaez+89N4zrz148AZvw+XCufectddeZ68tRCKRCP5iCP8MgM/nQ39/P9bX15Gfnw+bzYb6+nokJyfH5Z8Qg0AggObmZqjVarS2tsLr9WJ4eBhjY2PQ6/UMEA6H8fT0BJlMhoyMDAiCwOsJAayuroKehYUFZGZmgmSbm5vD+fk5HA4H3t/f0d3djcnJScjlcvT29sJisTC7hADcbjd2d3cxMzPDB1AsLS3h5OQEExMTODo64kNnZ2dxe3uLnp4eLC4uQqlUQgiHwxGPx4PDw0POJFbc3NzwhunpaTQ0NODy8hKdnZ1cHnqvra2JDB8fH7mcxKy0tBTC/f19pKmpiTP8TnR1dWFwcBDp6emIahQKhUCPRqPB+Pj4Dy0+A9DNqKys/A1nb28PfX190Gq1XIqioiLk5OSIQtKGh4cHbG1tMaBOp+M3i/wZYHl5GcTm1yANiLZCoUBxcTFSUlIkydbW1qK9vf1ngJKSEmRnZ6OmpgZmsxlOpxPb29u4u7vD6ekpCgoKYDQakZaWJgIEg0Fsbm6yHpQABWl2dXUFSiymBtRQVAq73Q6r1SoeVlVVxZuysrLEtajgU1NT3IAUx8fHvPc/AJfjj0pkMpnQ2NiIlZUVzM/Pf1uDg4MDDA0Nfa3BV3cwEZHf3t7YaV9fXzE6OhrfKigTioqKCiQlJXGjkaNGnZK+nZ2dwWAw8A0qKysD2TpZD92g8vLy+GZH7rmzsyO6aCxm9I/L5YJKpcLFxQUKCwu5h/Ly8qTtOuoxpElLSwt7/efw+/1oa2vjA2M5QELzYH9/HwRAndrR0YHc3Fy8vLxgY2MDIyMjqK6uFk0vFkPJeUDDhWxiYGCAx2U0qObU5XV1dUhNTf3SmyQBojsJ6Pn5GdfX1+xXZBdS8zihEknapsQPH6Mh/FGBh+hUAAAAAElFTkSuQmCC", + "selectAction": { + "type": "Action.OpenUrl", + "url": "${onlineMeeting.joinUrl}" + }, + "$when": "${isOnlineMeeting}" + } + ] + }, + { + "type": "Column", + "width": "auto", + "items": [ + { + "type": "Image", + "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAR5JREFUSEvtljGuRFAUhv8rIdGQSHQahc4ORG8PbMICVBZgE+xBL3agU2h0RIJCQsLkSt4kM2/e3Fu8ea+hPef4zvnOjYscx3Hggw95BizLgjAM4boufN/nQmdZhqIokCQJZFl+qCHzPB9pmmIcxzOwbRvyPIdpmrBtmwtQVRWapoHneRBF8axRVRVBEID0fX/QTilAURTs+466rqFpGnRd5wJ0XYdhGGBZFgRBwDRNJ4BOdgdEUQTHcfAbisqyRBzHrwF057QDSZK++fxpHNrUuq6nAUIIXgLoeIZhcClhJbVte2p+UPS1A1YxT/ztDnhewMp5uwNWMU/8AjAtXYouRUwDzIT/OUUf+9g9X5nM+TkT7lfmn/9VcDbInXYDn/BFftWPiLMAAAAASUVORK5CYII=", + "selectAction": { + "type": "Action.OpenUrl", + "url": "${webLink}" + } + } + ] + } + ] + } + ], + "separator": true + } + ], + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json" +} \ No newline at end of file diff --git a/assets/ace/messages-quick-view.json b/assets/ace/messages-quick-view.json new file mode 100644 index 000000000..74e7f40a1 --- /dev/null +++ b/assets/ace/messages-quick-view.json @@ -0,0 +1,84 @@ +{ + "type": "AdaptiveCard", + "version": "1.5", + "@odata.type": "#microsoft.graph.message", + "body": [ + { + "type": "Container", + "items": [ + { + "type": "Image", + "url": "https://raw.githubusercontent.com/SharePoint/sp-dev-docs/main/assets/ace/email-top.png" + }, + { + "type": "TextBlock", + "text": "This control displays the last email message received in your inbox. To view the message, simply click on the button. The message will open directly in Outlook, allowing you to read and respond to it as needed.", + "wrap": true + } + ] + }, + { + "type": "Container", + "$data": "${value}", + "items": [ + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "width": "stretch", + "items": [ + { + "type": "TextBlock", + "text": "${from.emailAddress.name}", + "size": "Medium", + "weight": "${if(isRead, 'normal', 'bolder')}" + }, + { + "type": "TextBlock", + "text": "${subject}", + "spacing": "None", + "weight": "${if(isRead, 'normal', 'bolder')}" + } + ] + }, + { + "type": "Column", + "width": "auto", + "items": [ + { + "type": "TextBlock", + "text": "${if(hasAttachments, '📎', '')} ${if(importance == 'normal', '', '❗')} ${if(flag.flagStatus == 'flagged', '🚩', '')}", + "horizontalAlignment": "Right" + }, + { + "type": "TextBlock", + "text": "{{DATE(${sentDateTime}, COMPACT)}} {{TIME(${sentDateTime})}}", + "spacing": "None", + "size": "Small" + } + ], + "verticalContentAlignment": "Center" + }, + { + "type": "Column", + "width": "auto", + "items": [ + { + "type": "Image", + "url": "${if(isRead, 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAY5JREFUSEvt1aGLwlAcB/DvQ2FNg6BFMPg3WDRZRayGLWkxKViUgUkYWgRNKy5psG52kxb/BoOwMtEwTaLwjudxntObb3onHMe9uvH97Pd9vDdCKaV44SK/Btjv9zAMAz6fD5lMBoIgeJqbOwELHo/HaLfbME3zFBqNRlGr1ZDNZrmQK3AZvFqtUKlUUCwWT0C/30e320U4HOZCN4BbcCAQcFSy3W49QWfAa/B18TyIHA4Hqus6Wq0WLqu4/mLejl5D9XoduVwOZL1eU1EUEYlE0Ol0EAqFeFl3n282G1SrVViWheFw+AnMZjMoioJSqQS/3/8UcjweoaoqZFlGMpl0AolEAqPRCOVy+SnkI7zX6yGfz2M+nzuBRqMBttFsgkeRy3A2ATuEzWbzFmBjTSYTFAoFLJfLh2qKxWLQNA3pdBqs7i+BVCoFdvctFovzqfWqsNMdj8dBCMF0OnUHvAbee+8f4Lb4RyuybRuPXnBuXbGLLxgMvh+03W5HB4MBGPCTiwGSJIH7y/wu+nLgDSewZ7NrDNFAAAAAAElFTkSuQmCC', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAARBJREFUSEvtlS2qhUAYhl+LRbALYhMsrsAF2MXmLhRsJpugu7CJ3QW4AotgE8EiBsFimYNevJxz8Th6YZpThpnv55nvnT+OEELAsHEPgKYue4nGcSS+76NtW9pibtkVRUEUReCGYSCO46Cua6y9KIq3Ev11nqYJaZpC07St/wUURQFd1+F5HmzbhiAIt0DzPCPLMsRxjKqqYJrmJ8B1XfR9vzms7SroPfEeJ0kSkiT5BARBAMMwcBRwVNGZX1mWCMPwGLDr8i3Bat+l+FbpJcARaFmWbZrn+VMJbwHeQXmeb0PLsk4Pwb8Ad47UA6CqdSiRqqqQZZkafMWh6zo0TfNzD5g/ds+PRtsT9j8a6z14AbwnH7bn+xIdAAAAAElFTkSuQmCC')}", + "selectAction": { + "type": "Action.OpenUrl", + "url": "${webLink}" + } + } + ] + } + ] + } + ], + "separator": true + } + ], + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json" +} \ No newline at end of file diff --git a/assets/bot-powered/Media/Collect-Feedback.png b/assets/bot-powered/Media/Collect-Feedback.png new file mode 100644 index 000000000..16aecc8a0 Binary files /dev/null and b/assets/bot-powered/Media/Collect-Feedback.png differ diff --git a/assets/bot-powered/Media/Ok-Feedback.png b/assets/bot-powered/Media/Ok-Feedback.png new file mode 100644 index 000000000..ea5aa3a3b Binary files /dev/null and b/assets/bot-powered/Media/Ok-Feedback.png differ diff --git a/assets/bot-powered/TeamsAppManifest/icon-color.png b/assets/bot-powered/TeamsAppManifest/icon-color.png new file mode 100644 index 000000000..b8cf81afb Binary files /dev/null and b/assets/bot-powered/TeamsAppManifest/icon-color.png differ diff --git a/assets/bot-powered/TeamsAppManifest/icon-outline.png b/assets/bot-powered/TeamsAppManifest/icon-outline.png new file mode 100644 index 000000000..2c3bf6fa6 Binary files /dev/null and b/assets/bot-powered/TeamsAppManifest/icon-outline.png differ diff --git a/assets/bot-powered/TeamsAppManifest/manifest.json b/assets/bot-powered/TeamsAppManifest/manifest.json new file mode 100644 index 000000000..7a502770d --- /dev/null +++ b/assets/bot-powered/TeamsAppManifest/manifest.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.14/MicrosoftTeams.schema.json", + "manifestVersion": "1.16", + "version": "1.0.0", + "id": "", + "packageName": "collectfeedback.botpoweredace", + "developer": { + "name": "", + "websiteUrl": "", + "privacyUrl": "", + "termsOfUseUrl": "", + "mpnId": "" + }, + "name": { + "short": "Collect Feedaback Bot Powered ACE", + "full": "This is a basic sample of a Bot Powered ACE for Microsoft Viva Connections Dashboard to collect user's feedback" + }, + "description": { + "short": "Basic sample of a Bot Powered ACE for Microsoft Viva Connections Dashboard to collect user's feedback", + "full": "Basic sample of how to use the latest release of the Bot Framework SDK to build a Bot Powered ACE for Microsoft Viva Connections Dashboard to collect user's feedback" + }, + "icons": { + "outline": "icon-outline.png", + "color": "icon-color.png" + }, + "accentColor": "#FFFFFF", + "bots": [ + { + "botId": "", + "needsChannelSelector": false, + "isNotificationOnly": false, + "supportsCalling": false, + "supportsVideo": false, + "supportsFiles": false, + "scopes": [ + "team", + "personal", + "groupchat" + ] + } + ], + "dashboardCards": [ + { + "id": "", + "displayName": "Collect Feedaback", + "description": "Bot Powered ACE to collect user's feedback", + "icon": { + "officeUIFabricIconName": "Feedback" + }, + "contentSource": { + "sourceType": "bot", + "botConfiguration": { + "botId": "" + } + }, + "defaultSize": "medium" + } + ], + "permissions": [ + "identity" + ], + "validDomains": [ + ".ngrok.io" + ] +} \ No newline at end of file diff --git a/assets/spfx/spfx-matrix.json b/assets/spfx/spfx-matrix.json new file mode 100644 index 000000000..66ddda059 --- /dev/null +++ b/assets/spfx/spfx-matrix.json @@ -0,0 +1,545 @@ +[ + { + "spfx": "1.21.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.21.1", + "node": [ + "v22" + ], + "typescript": [ + "v5.3" + ], + "react": [ + "v17.0.1" + ] + }, + { + "spfx": "1.21.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.21", + "node": [ + "v22" + ], + "typescript": [ + "v5.3" + ], + "react": [ + "v17.0.1" + ] + }, + { + "spfx": "1.20.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.20", + "node": [ + "v18" + ], + "typescript": [ + "v4.5", + "v4.7" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2024-09-26" + }, + { + "spfx": "1.19.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.19", + "node": [ + "v18" + ], + "typescript": [ + "v4.5", + "v4.7" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2024-05-01" + }, + { + "spfx": "1.18.2", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.18.2", + "node": [ + "v16", + "v18" + ], + "typescript": [ + "v4.5", + "v4.7" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-11-21" + }, + { + "spfx": "1.18.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.18.1", + "node": [ + "v16", + "v18" + ], + "typescript": [ + "v4.5", + "v4.7" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-11-07" + }, + { + "spfx": "1.18", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.18", + "node": [ + "v16", + "v18" + ], + "typescript": [ + "v4.5", + "v4.7" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-09-12" + }, + { + "spfx": "1.17.4", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.17.4", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ] + }, + { + "spfx": "1.17.3", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.17.3", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-06-21" + }, + { + "spfx": "1.17.2", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.17.2", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-05-08" + }, + { + "spfx": "1.17.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.17.1", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-04-12" + }, + { + "spfx": "1.17.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.17", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2023-04-04" + }, + { + "spfx": "1.16.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.16.1", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2022-11-30" + }, + { + "spfx": "1.16.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.16", + "node": [ + "v16.13+" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v17.0.1" + ], + "releaseDate": "2022-11-15" + }, + { + "spfx": "1.15.2", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.15.2", + "node": [ + "v12", + "v14", + "v16" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v16.13.1" + ], + "releaseDate": "2022-08-02" + }, + { + "spfx": "1.15.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.15", + "node": [ + "v12", + "v14", + "v16" + ], + "typescript": [ + "v4.5" + ], + "react": [ + "v16.13.1" + ], + "releaseDate": "2022-06-21" + }, + { + "spfx": "1.14.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.14", + "node": [ + "v12", + "v14" + ], + "typescript": [ + "v3.9" + ], + "react": [ + "v16.13.1" + ], + "releaseDate": "2022-02-17" + }, + { + "spfx": "1.13.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.13.1", + "node": [ + "v12", + "v14" + ], + "typescript": [ + "v3.9" + ], + "react": [ + "v16.13.1" + ], + "releaseDate": "2021-11-23" + }, + { + "spfx": "1.13.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.13", + "node": [ + "v12", + "v14" + ], + "typescript": [ + "v3.9" + ], + "react": [ + "v16.13.1" + ], + "releaseDate": "2021-10-21" + }, + { + "spfx": "1.12.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.12.1", + "node": [ + "v10", + "v12", + "v14" + ], + "typescript": [ + "v3.7" + ], + "react": [ + "v16.9.0" + ], + "releaseDate": "2021-04-28" + }, + { + "spfx": "1.12.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.12.0", + "node": [ + "v12", + "v10" + ], + "typescript": [ + "v3.7" + ], + "react": [ + "v16.9.0" + ], + "deprecated": true, + "releaseDate": "2021-03-15" + }, + { + "spfx": "1.11.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.11.0", + "node": [ + "v10" + ], + "typescript": [ + "v3.3" + ], + "react": [ + "v16.8.5" + ] + }, + { + "spfx": "1.10.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.10.0", + "node": [ + "v8", + "v10" + ], + "typescript": [ + "v3.3" + ], + "react": [ + "v16.8.5" + ], + "releaseDate": "2020-07-16" + }, + { + "spfx": "1.9.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.9.1", + "node": [ + "v8", + "v10" + ], + "typescript": [ + "v2.9" + ], + "react": [ + "v16.8.5" + ], + "releaseDate": "2019-08-14" + }, + { + "spfx": "1.8.2", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.8.2", + "node": [ + "v8", + "v10" + ], + "typescript": [ + "v2.9" + ], + "react": [ + "v16.7.0" + ], + "releaseDate": "2019-05-07" + }, + { + "spfx": "1.8.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.8.1", + "node": [ + "v8" + ], + "typescript": [ + "v2.7", + "v2.9", + "v3" + ], + "react": [ + "v16.7.0" + ], + "releaseDate": "2019-04-16" + }, + { + "spfx": "1.8.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.8.0", + "node": [ + "v8" + ], + "typescript": [ + "v2.7", + "v2.9", + "v3" + ], + "react": [ + "v16.7.0" + ], + "releaseDate": "2019-03-14" + }, + { + "spfx": "1.7.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.7.1", + "node": [ + "v8" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v16.3.2" + ], + "releaseDate": "2018-12-18" + }, + { + "spfx": "1.7.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.7", + "node": [ + "v8" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v16.3.2" + ], + "releaseDate": "2018-11-08" + }, + { + "spfx": "1.6.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.6", + "node": [ + "v6", + "v8" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ] + }, + { + "spfx": "1.5.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.5.1", + "node": [ + "v6", + "v8" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2018-06-26" + }, + { + "spfx": "1.5.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.5", + "node": [ + "v6", + "v8" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2018-06-05" + }, + { + "spfx": "1.4.1", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.4.1", + "node": [ + "v6", + "v8" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2018-02-18" + }, + { + "spfx": "1.4.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.4", + "node": [ + "v6" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2017-12-07" + }, + { + "spfx": "1.3.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.3", + "node": [ + "v6" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2017-08-25" + }, + { + "spfx": "1.1.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.1", + "node": [ + "v6" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2017-06-06" + }, + { + "spfx": "1.0.0", + "url": "https://learn.microsoft.com/sharepoint/dev/spfx/release-1.0.0", + "node": [ + "v6" + ], + "typescript": [ + "v2.4" + ], + "react": [ + "v15" + ], + "releaseDate": "2017-02-22" + } +] \ No newline at end of file diff --git a/assets/vc-backgrounds/01_Teal.png b/assets/vc-backgrounds/01_Teal.png new file mode 100644 index 000000000..98158b37b Binary files /dev/null and b/assets/vc-backgrounds/01_Teal.png differ diff --git a/assets/vc-backgrounds/02_Blue.png b/assets/vc-backgrounds/02_Blue.png new file mode 100644 index 000000000..a9c23fb91 Binary files /dev/null and b/assets/vc-backgrounds/02_Blue.png differ diff --git a/assets/vc-backgrounds/03_Orange.png b/assets/vc-backgrounds/03_Orange.png new file mode 100644 index 000000000..8e811de8f Binary files /dev/null and b/assets/vc-backgrounds/03_Orange.png differ diff --git a/assets/vc-backgrounds/04_Red.png b/assets/vc-backgrounds/04_Red.png new file mode 100644 index 000000000..b42888406 Binary files /dev/null and b/assets/vc-backgrounds/04_Red.png differ diff --git a/assets/vc-backgrounds/05_Purple.png b/assets/vc-backgrounds/05_Purple.png new file mode 100644 index 000000000..888e21a84 Binary files /dev/null and b/assets/vc-backgrounds/05_Purple.png differ diff --git a/assets/vc-backgrounds/06_Green.png b/assets/vc-backgrounds/06_Green.png new file mode 100644 index 000000000..494d7dd31 Binary files /dev/null and b/assets/vc-backgrounds/06_Green.png differ diff --git a/assets/vc-backgrounds/07_Gray.png b/assets/vc-backgrounds/07_Gray.png new file mode 100644 index 000000000..3ec725883 Binary files /dev/null and b/assets/vc-backgrounds/07_Gray.png differ diff --git a/assets/vc-backgrounds/08_Periwinkle.png b/assets/vc-backgrounds/08_Periwinkle.png new file mode 100644 index 000000000..23b6fa00a Binary files /dev/null and b/assets/vc-backgrounds/08_Periwinkle.png differ diff --git a/assets/vc-backgrounds/09_Black.png b/assets/vc-backgrounds/09_Black.png new file mode 100644 index 000000000..4a1837aa9 Binary files /dev/null and b/assets/vc-backgrounds/09_Black.png differ diff --git a/assets/vc-backgrounds/10_Cerulean.png b/assets/vc-backgrounds/10_Cerulean.png new file mode 100644 index 000000000..86c8be663 Binary files /dev/null and b/assets/vc-backgrounds/10_Cerulean.png differ diff --git a/assets/vc-backgrounds/11_Cobalt.png b/assets/vc-backgrounds/11_Cobalt.png new file mode 100644 index 000000000..a2f354798 Binary files /dev/null and b/assets/vc-backgrounds/11_Cobalt.png differ diff --git a/assets/vc-backgrounds/12_Dark Yellow.png b/assets/vc-backgrounds/12_Dark Yellow.png new file mode 100644 index 000000000..224126c84 Binary files /dev/null and b/assets/vc-backgrounds/12_Dark Yellow.png differ diff --git a/assets/vc-backgrounds/13_Dark Blue.png b/assets/vc-backgrounds/13_Dark Blue.png new file mode 100644 index 000000000..f38b33e1f Binary files /dev/null and b/assets/vc-backgrounds/13_Dark Blue.png differ diff --git a/assets/vc-backgrounds/14_Custom_Color.png b/assets/vc-backgrounds/14_Custom_Color.png new file mode 100644 index 000000000..624e7605d Binary files /dev/null and b/assets/vc-backgrounds/14_Custom_Color.png differ diff --git a/assets/vc-backgrounds/15_Hero_Connections_Dark.png b/assets/vc-backgrounds/15_Hero_Connections_Dark.png new file mode 100644 index 000000000..90cf818b5 Binary files /dev/null and b/assets/vc-backgrounds/15_Hero_Connections_Dark.png differ diff --git a/docs/apis/addin-management-apis.md b/docs/apis/addin-management-apis.md new file mode 100644 index 000000000..f5cab6571 --- /dev/null +++ b/docs/apis/addin-management-apis.md @@ -0,0 +1,346 @@ +--- +title: SharePoint Add-in related APIs +description: We provided some Add-in related APIs to get Add-in's installation info and uninstall the Add-in. +audience: admin +ms.date: 03/25/2023 +ms.localizationpriority: medium +--- + +# SharePoint Add-in Management APIs + +This documentation will introduce some APIs which related to SharePoint Add-ins. They could help to have a clear view +and better management of the Add-ins in tenant level, including these: + +- Get available Add-ins in sites +- Get Add-in permissions in site collections +- Get tenant ACS service principals +- Get Add-in principals in site collections +- Uninstall Add-ins +- Get uninstall Add-in job status + +For more information about SharePoint Add-in, see [SharePoint Add-ins](../sp-add-ins/sharepoint-add-ins.md). + +## Prerequisites + +- App-only mode token. [Get token example](https://github.com/pnp/pnpcore/blob/dev/docs/polyglot/Getting%20started%20-%20application%20permissions.ipynb) +- Called on the admin site. Example: https://www.contoso-admin.sharepoint.com +- For uninstall Add-in API, the app needs to have Sites.FullControl.All permission. For others, the app needs at least Sites.Read.All permission. + +## Get available Add-ins in sites + +This API will return the Add-ins that could be used on the given sites. This contains two kinds of install, one is the Add-in installed on the site. +The other is the Add-in installed on the tenant level app catalog site, and it matches the conditions to use the Add-in. +For more information, see [Tenancies and deployment scopes for SharePoint Add-ins](../sp-add-ins/tenancies-and-deployment-scopes-for-sharepoint-add-ins.md). + +This API needs the app to have at least Sites.Read.All permission. + +### HTTP request + +```HTTP +POST {adminSiteUrl}/_api/web/AvailableAddIns +``` + +### Request body + +| Name | Required | Type | Description | +|--------------------|----------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| serverRelativeUrls | no | string[] | List of the server relative url of sites that want to get the available Add-ins. Maximum size is 500. | +| urls | no | string[] | List of the url of sites that want to get the available Add-ins, both server relative url and absolute url are acceptable. Maximum size is 500. | + +When urls is not null, serverRelativeUrls will be disregarded. + +### Responses + +| Name | Type | Description | +|-----------------------------|--------------------------------|--------------------------------------------------------------------------------------| +| addins | SPAddinInstanceInfo[] | Available Add-in instance object. | +| errorsWithServerRelativeUrl | SPErrorWithServerRelativeUrl[] | Server relative urls that failed to get available add-ins and corresponding reasons. | + +#### SPAddinInstanceInfo + +| Name | Type | Description | +|-------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| title | string | Title of the Add-in. | +| appInstanceId | Guid | Id of the installation. | +| launchUrl | String | The Add-in's launch page address. | +| installedSiteId | Guid | Site collection id where the Add-in installed. | +| installedWebId | Guid | Site id where the Add-in installed. | +| installedWebName | string | Site name where the Add-in installed. | +| installedWebUrl | string | Site url where the Add-in installed. | +| currentSiteId | Guid | Site collection id of current site. | +| currentWebId | Guid | Site id of current site. | +| currentWebName | string | Site name of current site. | +| currentWebUrl | string | Site url of current site. | +| status | string | The status of current Add-in. | +| appWebFullUrl | string | The full url of the app web. The SharePoint components are generally in a special child web of the host web called the app web. The app web will be created during install the add-in. | +| appWebId | Guid | Id of the app web. | +| appWebName | string | Name of the app web. | +| installedBy | string | User name of who installed the add-in. | +| appIdentifier | string | The identifier of the app principal. It could be used to get the Add-in's permission. | +| creationTimeUtc | DateTime | Date time when installed the add-in. | +| productId | Guid | The global unique id of the add-in. It is same for all tenants. | +| assetId | string | The id of the app in the office store, this will be empty for app catalog user uploaded apps. | +| purchaserIdentity | string | The identify of person who bought the license of the add-in. | +| licensePurchaseTime | DateTime | When purchased the app license. | +| locale | string | which locale installed on the site. | +| appSource | string | Indicate where the app come from. | +| tenantAppData | string | After the Add-in installed in the tenant app catalog site. It could enable tenant level usage. This data indicates the conditions how to filter the sites. If this field is not empty, it means this Add-in installed on tenant app catalog site, deployed to tenant level, and current site matches the conditions. For more information, see [Tenancies and deployment scopes for SharePoint Add-ins](../sp-add-ins/tenancies-and-deployment-scopes-for-sharepoint-add-ins.md). | +| tenantAppDataUpdateTime | DateTime | The tenant app data update time. | + +### SPErrorWithServerRelativeUrl + +| Name | Type | Description | +|-------------------|--------|--------------------------------------------------------| +| serverRelativeUrl | string | The serverRelativeUrl or url in the request body. | +| errorMessage | string | The error message why fetch the site's Add-ins failed. | + +## Get Add-in permissions in site collections + +This API will return the permissions that were granted to the add-in. For more information, see [Add-in permissions in SharePoint](../sp-add-ins/add-in-permissions-in-sharepoint.md). + +This API needs the app to have at least Sites.Read.All permission. + +### HTTP request + +```HTTP +POST {adminSiteUrl}/_api/web/AddinPermissions +``` + +### Request body + +| Name | Required | Type | Description | +|--------|----------|----------------------------|----------------------------------------------------------------------------------| +| addins | yes | SPAddinPermissionRequest[] | List of the Add-in that want to get the permissions. Maximum Add-in size is 500. | + +#### SPAddinPermissionRequest + +| Name | Type | Description | +|-------------------|----------|-------------------------------------------------------------------------------------------| +| serverRelativeUrl | string | The server relative url of the site collection. | +| url | string | The url of the site collection, both server relative url and absolute url are acceptable. | +| appIdentifiers | string[] | The identifier list of the Add-ins. | + +The serverRelativeUrl and url can't be both null. If both serverRelativeUrl and url are provided, the url will be used. + +### Responses +| Name | Type | Description | +|------------------|-------------------------------|-----------------------------------------------------------------------| +| addinPermissions | SPAddinPermissionInfo[] | The returned permissions. | +| failedAddins | SPAddinPermissionFailedInfo[] | The Add-ins that failed to get permissions and corresponding reasons. | + +#### SPAddinPermissionInfo + +| Name | Type | Description | +|---------------------------------|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| tenantScopedPermissions | SPTenantScopedPermissionInfo[] | This is the permissions grant in tenant scope level. | +| siteCollectionScopedPermissions | SPSiteCollectionScopedPermissionInfo[] | This is the permissions grant in site collection scope level. | +| appIdentifier | string | The identifier of the Add-in. | +| serverRelativeUrl | string | The server relative url of the site collection. | +| absoluteUrl | string | The absolute url of the site collection. | +| allowAppOnly | bool | This identifies if the Add-in allows app only mode. For more information, see [Add-in authorization policy types in SharePoint](../sp-add-ins/add-in-authorization-policy-types-in-sharepoint.md). | + +#### SPTenantScopedPermissionInfo + +| Name | Type | Description | +|---------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| feature | string | The feature name of the permissions, it should be one of these:
  • Taxonomy
  • Social
  • ProjectServer
  • Search
  • BcsConnection
  • Content
| +| scope | string | The scope of the permission. | +| right | string | The right of the permission. | +| id | Guid | The id of the resource that the Add-in have permission to. For example, it may be the id of one specific project when the feature is ProjectServer and the scope is projectserver/projects/project. | + + +#### SPSiteCollectionScopedPermissionInfo + +| Name | Type | Description | +|--------|--------|------------------------------------------------------------------------------------------------------------------------------------------------| +| siteId | Guid | The site collection id which the Add-in has access to. | +| webId | Guid | The site id which the Add-in has access to. If this field is empty, then the permission grant in site collection level. | +| listId | Guid | The list id which the Add-in has access to. If this field is empty, then the permission grant in site collection level or grant is site level. | +| right | string | Available rights: Guest, Read, Write, Manage, FullControl. | + + +#### SPAddinPermissionFailedInfo + +| Name | Type | Description | +|-------------------|--------|-----------------------------------------------------------------| +| serverRelativeUrl | string | The server relative url or absolute url of the site collection. | +| appIdentifier | string | The identifier list of the Add-in. | +| errorMessage | string | The error message why fetch the Add-in permission failed. | + +## Get tenant ACS service principals + +This API takes the app id list as input, it will filter the ones that present ACS service principals. +For more information, see [Register SharePoint Add-ins](../sp-add-ins/register-sharepoint-add-ins.md). + +This API needs the app to have at least Sites.Read.All permission. + +### HTTP request + +```HTTP +POST {adminSiteUrl}/_api/web/GetACSServicePrincipals +``` + +### Request body + +| Name | Required | Type | Description | +|--------|----------|--------|------------------------------------| +| appIds | yes | Guid[] | List app ids. Maximum size is 500. | + +### Responses + +| Name | Type | Description | +|------|-----------------------------|-------------------------------------| +| | SPACSServicePrincipalInfo[] | The SPACSServicePrincipalInfo list. | + +#### SPACSServicePrincipalInfo + +| Name | Type | Description | +|---------------|----------|-----------------------------------------------------------------------------------------------| +| appIdentifier | string | The app identifier of the Add-in. | +| appId | Guid | The app id of the Add-in. | +| title | string | A user friendly title. | +| redirectUri | string | The endpoint in your remote application or service to which ACS sends an authentication code. | +| appDomains | string[] | The host name of the remote component of the SharePoint Add-in. | + +## Get Add-in principals in site collections + +This API takes the site collections' server relative url as input, it will return the Add-in principals that have permissions in given sites. + +This API needs the app to have at least Sites.Read.All permission. + +### HTTP request + +```HTTP +POST {adminSiteUrl}/_api/web/GetAddinPrincipalsHavingPermissionsInSites +``` + +### Request body + +| Name | Required | Type | Description | +|--------------------|----------|----------|------------------------------------------------------------------------------------------------------------| +| serverRelativeUrls | no | string[] | List site collections' server relative url. Maximum size is 500. | +| urls | no | string[] | List site collections' url, both server relative url and absolute url are acceptable. Maximum size is 500. | + +When urls is not null, serverRelativeUrls will be disregarded. + +### Responses + +| Name | Type | Description | +|-----------------------------|--------------------------------|-------------| +| addinPrincipals | SPAddinPrincipalInfo[] | | +| errorsWithServerRelativeUrl | SPErrorWithServerRelativeUrl[] | | + +#### SPAddinPrincipalInfo + +| Name | Type | Description | +|-------------------|--------|-------------------------------------------------| +| title | string | The title of the Add-in. | +| appIdentifier | string | The app identifier. | +| serverRelativeUrl | string | The server relative url of the site collection. | +| absoluteUrl | string | The absolute url of the site collection. | + + +#### SPErrorWithServerRelativeUrl + +| Name | Type | Description | +|-------------------|--------|------------------------------------------------------------| +| serverRelativeUrl | string | The site collection's server relative url or absolute url. | +| errorMessage | string | The error message why fetch the Add-in principal failed. | + +## Uninstall Add-ins + +This API will trigger an async job to uninstall the Add-in. If the job triggered successfully, the job id will be returned. + +This API needs the app to have Sites.FullControl.All permission. + +### HTTP request + +```HTTP +POST {adminSiteUrl}/_api/web/UninstallAddins +``` + +### Request body + +| Name | Required | Type | Description | +|-----------------|----------|---------------------------|---------------------------------------------------------------| +| uninstallAddins | yes | SPUninstallAddinRequest[] | List of Add-ins need to uninstall. Maximum Add-in size is 50. | + +#### SPUninstallAddinRequest + +| Name | Type | Description | +|-------------------|--------|---------------------------------------------------------------------------| +| serverRelativeUrl | string | The site's server relative url. | +| url | string | The site's url, both server relative url and absolute url are acceptable. | +| appInstanceIds | Guid[] | The instance ids of the Add-ins. | + +The serverRelativeUrl and url can't be both null. If both serverRelativeUrl and url are provided, the url will be used. + +### Responses + +| Name | Type | Description | +|-----------|--------------------------------------------|---------------------------------------------------------------------------| +| executing | SPTriggeredUninstallAddinJobResponse[] | This field contains the ones that successed to trigger the uninstall job. | +| failed | SPFailToTriggerUninstallAddinJobResponse[] | This field contains the ones that failed to trigger the uninstall job. | + +#### SPTriggeredUninstallAddinJobResponse + +| Name | Type | Description | +|-------------------|--------|---------------------------------| +| appInstanceId | Guid | The instance id of the Add-in. | +| serverRelativeUrl | string | The site's server relative url. | +| absoluteUrl | string | The site's absolute url. | +| uninstallJobId | Guid | The triggered uninstall job id. | + +#### SPFailToTriggerUninstallAddinJobResponse + +| Name | Type | Description | +|-------------------|--------|---------------------------------------------------------| +| appInstanceId | Guid | The instance id of the Add-in. | +| serverRelativeUrl | string | The site's server relative url. | +| errorMessage | Guid | The error message why the uninstall job trigger failed. | + + +## Get uninstall Add-in job status + +Since the uninstall Add-in is an async process, this API will provide the ability to check if the uninstall ends successfully. +If the job ends successfully, then the job will be not found. If the job ends with failure, then it will return the error detail. + +This API needs the app to have at least Sites.Read.All permission. + +### HTTP request + +```HTTP +POST {adminSiteUrl}/_api/web/GetAddinUninstallJobDetail +``` + +### Request body + +| Name | Required | Type | Description | +|-------------------|----------|--------|----------------------------------------------------------------------------| +| jobId | yes | Guid | This uninstall job id. | +| serverRelativeUrl | no | string | The site's server relative url. | +| url | no | string | The site's url, both server relative url and absolute url are acceptable. | + +The serverRelativeUrl and url can't be both null. If both serverRelativeUrl and url are provided, the url will be used. + +### Responses + +| Name | Type | Description | +|-------------------|-------------------------------|--------------------------------------------------| +| serverRelativeUrl | string | The site's server relative url. | +| absoluteUrl | string | The site's absolute url. | +| taskStartTime | DateTime | The time when the task starts executing. | +| jobId | Guid | The uninstall job id. | +| siteId | Guid | The site collection id. | +| appInstanceId | Guid | The id of the app instance. | +| errorDetails | SPUninstallAddinErrorDetail[] | The error details for the job ends with failure. | + +#### SPUninstallAddinErrorDetail + +| Name | Type | Description | +|------------------|--------|-------------------------------------| +| detail | string | The error detail. | +| exceptionMessage | string | The exception message of the error. | +| source | string | The source of the error. | +| type | string | The type of the error. | +| correlationId | Guid | The job's correlation id. | diff --git a/docs/apis/amr-api-reference.md b/docs/apis/amr-api-reference.md new file mode 100644 index 000000000..2c3e44aa8 --- /dev/null +++ b/docs/apis/amr-api-reference.md @@ -0,0 +1,253 @@ +--- +title: "SharePoint Asynchronous Metadata Read (AMR) API Reference Guide" +description: "This article provides in-depth information on how to use the SharePoint AMR API." +ms.date: 04/18/2024 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- +# SharePoint Asynchronous Metadata Read (AMR) API Reference Guide + +Use this document as the guide when using SharePoint Asynchronous Metadata Read (AMR) API. + +AMR API aggregates SharePoint metadata into a manifest package. Use the package for incremental migration, structure creation, post-migration validation, or permission management. + +## CSOM and REST + +AMR API supports both SharePoint Client Side Object Model (CSOM) and REST. + +### Use NuGet Packages with CSOM + +To reference the SharePoint Client Side Object Model (CSOM) in your solution, use NuGet packages. + +Manage dependencies easily and ensure your solution is using the latest version of the CSOM library with NuGet packages. + +Get the latest version of the CSOM package at the [SharePoint Client-side Object Model Libraries](https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM) with the ID `Microsoft.SharePointOnline.CSOM`. + +Check [Get to know SharePoint REST service](/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service) for instructions on REST API. + +## CreateSPAsyncReadJob method + +Creates an AMR job to read all the metadata of the specified SharePoint URL and its children into the specified manifest container. + +### CreateSPAsyncReadJob syntax + +```csharp +public SPAsyncReadJobInfo CreateSPAsyncReadJob(String url, +SPAsyncReadOptions readOptions, +EncryptionOption encryptionOption, +string azureContainerManifestUri, +string azureQueueReportUri) +``` + +### CreateSPAsyncReadJob parameters + +#### url + +Required. + +A **String** value containing the full path URL of the path of the SharePoint List, files/folders, or Document Library **to read**. AMR API returns all the metadata of files, folders, and root objects, **including subfolders and any children content**. + +##### Example + +This example `url` returns all metadata of Shared Document, and its children: + +```http +https://www.contoso.com/Shared%20Document +``` + +#### readOptions + +Required. + +A `SPAsyncReadOptions` structure, with `readOption` values specifying the types of metadata to read. + +##### IncludeVersions + +Optional. + +A **Bool** value to indicate if AMR API reads multiple versions of files and List Items. + +Default value is `false`. When absent or set to `false`, AMR API only reads the latest version of items. + +##### IncludeSecurity + +Optional. + +A **Bool** value to indicate if AMR API reads Users and Groups information related to a Site. + +Default value is `false`. + +AMR API reads Users and Groups as Authors or Modifiers as part of the metadata of the objects. + +If set to `true`, AMR API reads all Users in Site Collections. When reading multiple Document Libraries under the same Site Collection, the same Users and Group might appear in the read package multiple times. + +##### IncludeDirectDescendantsOnly + +Optional. + +A **Bool** value to indicate if AMR API reads only the metadata of the direct descendants. + +Default value is `false`. + +If set to `true`, AMR API reads only the metadata of the direct descendants. + +Use this `readOption` along with `IncludeSecurity` `readOption` together to improve performance when reading metadata from a Document Library containing large number of items, as described in [Best practice](export-amr-api.md) to avoid slow performance. + +##### IncludeExtendedMetadata + +Optional. + +Default value is `false`. + +When set to `false`, AMR API reads basic metadata: + +- List +- Folder +- File +- List Item +- Roles +- Role Assignments + +When set to `true`, AMR API reads all metadata available: + +For Files: + +- Web Part +- Web Part personalization +- Links +- Version events +- Event receivers +- Attachment metadata + +For Lists: + +- Custom actions +- List shortcuts + +For List Items: + +- Comments +- Documents set links +- Activities +- List Item shortcuts + +Including extended metadata slows down the read significantly. For file share migrations, keep the default value `false`. Set to `true` only when necessary, for complex migration projects. + +##### IncludePermission + +Optional. + +A **Bool** value to indicate if permissions read is needed. Default value is `false`. + +When set to `true`, AMR API reads permission metadata in `RoleAssignments` tags in `Manifest.xml` files. The file includes all distinguished permission metadata for each read SharePoint object, along with property `ScopeId`. + +##### StartChangeToken + +Optional. + +A **Integer** value containing the changeToken item. + +By default, when no `StartChangeToken` is provided, `CreateSPAsyncReadJob` method returns all items available, based on the parameters. A `CurrentChangeToken` value is returned every time. + +To read only the items that changed since last read, set a `StartChangeToken` in subsequent calls to `CreateSPAsyncReadJob`. Use `CurrentChangeToken` returned from last call as the value of `StartChangeToken`. + +AMR API returns an error and stops the read, if it receives an invalid `StartChangeToken` value. + +Be careful when using this feature with large number of items. The read job could run for extended duration. AMR API cancels jobs that run over 10 minutes to protect the SharePoint infrastructure. + +#### encryptionOption + +Optional. + +A `EncryptionOption` object, containing the AES-256-CBC Key used to decrypt the output. + +By default, AMR API doesn't encrypt the output and event queue. If set with AES-256-CBC Key, AMR API encrypts the output with the key supplied. + +See [`EncryptionOption`](/dotnet/api/microsoft.sharepoint.client.encryptionoption) class for details. + +#### azureContainerManifestUri + +Required. + +A **String** value, which is the destination URL of the Azure Blob Storage Container containing the output manifest package. + +See [Azure](migration-azure.md) for instructions of using Azure Blob Storage Container in migration. + +#### azureQueueReportUri + +Required. + +A **String** value, which is the URL of the Azure Queue to receive read status messages. + +Share `azureQueueReportUri` among different jobs if necessary. AMR API returns `JobID` to identify individual jobs created. + +See [Azure](migration-azure.md) for instructions of using Azure Queue in migration. Check [Migration events in Azure Queue](migration-events.md) for types of events. + +### CreateSPAsyncReadJob return values + +#### Job ID + +A **Guid** value, which contains Job ID, the unique identifier of the migration job. The method returns a `null` value, if it fails to create the job. + +AMR API generates a `JobEnd` event when it estimates item count for each `url`. Check [Events](migration-events.md) for details. + +#### AzureContainerManifest + +A **Uri** value that contains the URL to access the Azure Blob Storage Container, which contains the metadata read. + +#### JobQueueUri + +A **Uri** value that contains the URL of the Azure Queue used for read status. + +#### EncryptionKey + +A **Byte Array** value that contains the AES-256-CBC Key for decrypting the manifest files and messages in the Azure Queue. + +## CreateSPAsyncReadJobWithMultiUrl method + +Creates an AMR job to read all the metadata of all SharePoint URLs specified, and their children into the specified manifest container. + +### CreateSPAsyncReadJobWithMultiUrl syntax + +```csharp +public SPAsyncReadJobInfo CreateSPAsyncReadJobWithMultiUrl( + String[] urls, + SPAsyncReadOptions readOptions, + EncryptionOption encryptionOption, + String azureContainerManifestUri, + String azureQueueReportUri) +``` + +### CreateSPAsyncReadJobWithMultiUrl parameters + +See `CreateSPAsyncReadJob` method for details of `readOptions`, `encryptionOption`, `azureContainerManifestUri`, and `azureQueueReportUri`. + +#### urls + +Required. + +A **Uri** **Array** containing the full path URLs of the root paths of the SharePoint Lists, files/folders, or Document Libraries to read. AMR API returns all the metadata of files, folders, and root objects, **including subfolders and any children content**. + +Specify multiple URLs when needed. Aggravated call with multiple URLs might improve the performance. See [Performance](export-amr-api.md#performance) for details. + +## Errors + +### -2146232832 + +The changeToken refers to a time before the start of the current change log. + +The change log is limited to 60 days immediately before the current date. AMR API returns this error code when the specified `changeToken` refers to a time outside the 60-day window. + +### -2147213196 + +Operation canceled. + +AMR API received a cancellation request from the client and cancels the read operation. diff --git a/docs/apis/csom-methods-for-applying-retention-labels.md b/docs/apis/csom-methods-for-applying-retention-labels.md new file mode 100644 index 000000000..ddde1e391 --- /dev/null +++ b/docs/apis/csom-methods-for-applying-retention-labels.md @@ -0,0 +1,143 @@ +--- +title: CSOM methods for retention labels +description: CSOM methods are available to apply (set) a retention label (ComplianceTag) on one or many items (ListItems) in SharePoint. Also includes settings of retention labels in ODB and SPO. +author: kyracatwork +ms.author: kyrachurney +ms.date: 9/30/2024 +--- + +# CSOM methods for applying retention labels and managing settings of record labels + +Retention labels let you apply retention settings for governance control at the item level, and are part of the Microsoft Purview compliance solutions. [Learn more about retention labels.](/microsoft-365/compliance/retention#retention-labels) + +Retention labels may classify contents as records, which place restrictions on what actions are allowed or blocked. [Learn more about declaring records by using retention labels](/microsoft-365/compliance/declare-records) + +CSOM methods are available to apply (set) a retention label (ComplianceTag) on one or many items (ListItems) in SharePoint, and change retention labels settings for deleting, versioning, and changing properties of records. Retention labels can be applied using this method without being published to the location by an existing label policy. + +## SetComplianceTagOnBulkItems + +This method can be used to set a ComplianceTag on one or many ListItems. It is strongly recommended to use this method for this purpose. + +```c# +public List SetComplianceTagOnBulkItems( + List itemIds, + string listUrl, + string complianceTagValue) +``` + +### Parameters + +- 'List' [Int](/en-us/dotnet/api/system.int32) +- 'ItemsIds' [String](/dotnet/api/system.string) +- 'ListURL' [String](/dotnet/api/system.string) +- 'ComplianceTagValue' [String](/dotnet/api/system.string) + +Attribute [RemoteAttribute](/dotnet/api/microsoft.sharepoint.client.remoteattribute) + +## GetAllowFilesWithKeepLabelToBeDeletedODB + +Get whether files with Keep Label can be deleted in ODB. + + +```c# + +public static bool GetAllowFilesWithKeepLabelToBeDeletedODB() +``` + +## SetAllowFilesWithKeepLabelToBeDeletedODB + +Set whether files with Keep Label can be deleted in ODB + + +```c# +public static void SetAllowFilesWithKeepLabelToBeDeletedODB(bool allowDeletion) +``` + +Parameters + +- 'allowDeletion' [Boolean](/dotnet/api/system.boolean) + +## GetAllowFilesWithKeepLabelToBeDeletedSPO +Get whether files with Keep Label can be deleted in SPO. + +```c# + +public static bool GetAllowFilesWithKeepLabelToBeDeletedSPO() +``` + +## SetAllowFilesWithKeepLabelToBeDeletedSPO + +Set whether files with Keep Label can be deleted in SPO. + +```c# +public static void SetAllowFilesWithKeepLabelToBeDeletedSPO(bool allowDeletion) +``` + +Parameters + +- 'allowDeletion' [Boolean](/dotnet/api/system.boolean) + +## GetAdvancedRecordVersioningDisabled + +Get whether advanced record versioning is disabled. + +```c# + +public static bool GetAdvancedRecordVersioningDisabled() +``` + +## SetAdvancedRecordVersioningDisabled + +Set to enable or disable the advanced record versioning. + +```c# +public static void SetAdvancedRecordVersioningDisabled(bool disabled) +``` + +Parameters + +- 'disabled' [Boolean](/dotnet/api/system.boolean) + +## GetMetadataEditBlockingEnabled + +Get whether metadata edit blocking is enabled. + +```c# + +public static bool GetMetadataEditBlockingEnabled() + +``` + +## SetMetadataEditBlockingEnabled + +Set metadata edit blocking enabled setting. + + +```c# +public static void SetMetadataEditBlockingEnabled(bool enabled) +``` + +Parameters + +- 'enabled' [Boolean](/dotnet/api/system.boolean) + +### Applies to + +|Product|Versions| +|:---|:---| +|SharePoint CSOM|latest| + +## Other + +> [!NOTE] +> It is strongly recommended to use SetComplianceTagOnBulkItems instead of these methods. + +The following methods are also available, but are no longer updated and may be subject to deprecation in the future. If you are using these methods, we strongly recommend use of the SetComplianceTagOnBulkItems method instead. + +* [SetComplianceTag](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetag) +* [SetComplianceTagWithExplicitMetaInfo](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetagwithexplicitmetasupdate) +* [SetComplianceTagWithExplicitMetasUpdate](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetagwithexplicitmetasupdate) +* [SetComplianceTagWithHold](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetagwithhold) +* [SetComplianceTagWithMetaInfo](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetagwithmetainfo) +* [SetComplianceTagWithNoHold](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetagwithnohold) +* [SetComplianceTagWithRecord](/dotnet/api/microsoft.sharepoint.client.listitem.setcompliancetagwithrecord) diff --git a/docs/apis/export-amr-api-permission-guide.md b/docs/apis/export-amr-api-permission-guide.md new file mode 100644 index 000000000..55a921cc2 --- /dev/null +++ b/docs/apis/export-amr-api-permission-guide.md @@ -0,0 +1,167 @@ +--- +title: "SharePoint Migration Export (Asynchronous Metadata Read) API permission guide" +description: This article targets ISVs and any third-party vendors/developers who are developing and maintaining a migration tool and explains the permission details and options in the export API. +ms.date: 08/25/2023 +ms.author: jhendr +author: JoanneHendrickson +manager: Serdars +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- + +# AMR Export Permission Guide + +The Asynchronous Metadata Read (AMR) API export permission lets you export SharePoint Online metadata permission info using a new export option. This guide will show you how to use this option and what changes have been introduced to the export result. + +## How to use AMR export permission option + +For both CSOM and RESTFul calls, add the below option to enable/disable AMR export permission: + +- For CSOM, when building `AsyncReadOptions` object, set `IncludePermission` property to `true` or `false`. + - If you cannot use `IncludePermission` property, please update your CSOM nuget package to the latest version. +- For RESTFul, add `IncludePermission` key to the request JSON payload's `readOptions` section, and set it to `true` or `false`. + - For example: `{..., "readOptions":{...,"IncludePermission":true,...}...}` + +## What changes have been introduced to the export result + +The new `IncludePermission=true` option will involve an additional tag called `` into **Manifest.xml** file in the export result, which includes all distinguished permission info for each exported SPO object with property `ScopeId`, like below: + +```xml +<...> + + + + + ... + + +<...> +``` + +The `RoleAssignments` tag is a list of `RoleAssignment` tags, each `RoleAssignment` tag represents a unique permission scope from exported SPO objects, identified by `ScopeId`. Each `RoleAssignment` tag contains multiple `Assignment` tags, representing an entity within that specific unique permission scope each, such as a user, a group, etc., with a principal ID. + +In the meantime, all involved entities will be listed in **UserGroup.xml** file in the export result, to help further user resolution. + +Here is an example of **Manifest.xml** file and **UserGroup.xml** with `IncludePermission=true` option: + +```xml + +<...> + + + +<...> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<...> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## Option interaction between `IncludeSecurity` and `IncludePermission` + +Before the `IncludePermission` option, the `IncludeSecurity` option has been already used to get a full list of all user & group information of the target site. It isn't necessary that you use the `IncludePermission` option with `IncludeSecurity` option. However, if you still want to get a full list of all user and group information of target sites with permission information, you can use `IncludePermission` option with `IncludeSecurity` option together, here are the 4 combinations of the two options with expected results: + +- `IncludeSecurity=true` only: get a full list of all user & group information of the target site without permission information. +- `IncludePermission=true` only: get exported items' permission information, with a list of corresponding user & group information of exported permissions. +- `IncludeSecurity=true` + `IncludePermission=true`: get exported items' permission information, with a full list of all user & group information of the target site. +- None of them is used: get no permission, nor related user & group information. diff --git a/docs/apis/export-amr-api.md b/docs/apis/export-amr-api.md index 75cb957f7..fe7248b8f 100644 --- a/docs/apis/export-amr-api.md +++ b/docs/apis/export-amr-api.md @@ -1,10 +1,10 @@ --- -title: "SharePoint Migration Export (Asynchronous Metadata Read) API" -description: This document targets ISVs and any third-party vendors/developers who are developing and maintaining a migration tool. -ms.date: 06/28/2022 -ms.author: jhendr -author: JoanneHendrickson -manager: pamgreen +title: "SharePoint Asynchronous Metadata Read (AMR) API Introduction" +description: Overview how to read metadata from SharePoint, targeted to SharePoint migration tool developers. +ms.date: 07/23/2025 +ms.author: ranren +author: underreview +manager: dapodean audience: ITPro ms.subservice: migration-tool ms.topic: article @@ -13,351 +13,111 @@ ms.collection: - SPMigration - m365-collaboration --- -# SharePoint Migration Export (Asynchronous Metadata Read) API +# SharePoint Asynchronous Metadata Read (AMR) API Introduction -## Overview +The SharePoint Asynchronous Metadata Read (AMR) API enables the asynchronous export of metadata from SharePoint and OneDrive. -The goal of the new Migration Asynchronous Metadata Read (AMR) API is to reduce the number of calls, reduce throttling, and improve overall migration performance for our customers. Instead of calling thousands of calls to query information from SPO, the new Migration Asynchronous Metadata Read can return the same amount of data in a single read. +Use AMR API to export metadata from SharePoint for incremental migration and post-migration validation. -When the new SharePoint Migration Export (Asynchronous Metadata Read) API performs a read operation of a provided URL, the Microsoft backend software aggregates all the information into a designated manifest. The ISV can read back from the manifest and parse the metadata without sending thousands of calls individually. The AMR API also has the ability to load balance the server, and supports an unlimited amount of metadata to be migrated. +AMR is designed exclusively for import scenarios. It exhibits poor scalability when handling requests for metadata, permissions, or versions. We can't provide performance assurances for AMR usage in data export scenarios, such as cross-tenant migrations. -This document targets ISVs and any third-party vendors/developers who are developing and maintaining a migration tool. +## What's new -### Background +### January 2024 -Currently, the [SharePoint Online Migration API](migration-api-overview.md), lets your migration tool efficiently migrate large amounts data to SharePoint Online. However, the lack of an official API to read content from SharePoint Online means that these tools must rely on CSOM/Vroom function calls to perform individual metadata read operations. +We reformatted this document to bring clarity and correct errors. -Large numbers of calls increase the likelihood of throttling, which impacts migration performance and customer experience. Ineffective call usage results in large SQL round trip per function calls that can potentially bring down the database and impact its reliability. +## Export steps overview -A migration performance study identified four areas where a high number of calls are heavily used: +Export metadata from SharePoint in three steps: -- **Incremental migration** relies on calls to retrieve the SharePoint online (SPO) content. It compares it with the source location to determine if there have been any changes to the content and whether to proceed with migration. -- **Structure creation** leverages calls for site, web part and navigation creation. -- **After migration verification** is done when migration is completed and is used to ensure the source and destination file metadata matches. -- **Permission settings** function calls are made to get user permission information. +### Provision the destination containers and the queue -## SharePoint Migration Export (Asynchronous Metadata Read) API - -The SharePoint Migration Export (Asynchronous Metadata Read) API aims to reduce the calls in areas: incremental migration, after migration verification and permission settings. - -> [!Note] -> The first version of the SharePoint Migration Export (Asynchronous Metadata Read) API supports files, folders, lists, list items, and the document library. Permissions are expected to be covered in a subsequent version. - -Key supported features: - -- Ability to aggregate small metadata requests calls (for example, CSOM) into a single AMR call with the multiple URL feature -- Ability to read unlimited items with a single API call. -- Incremental migration feature support returning of item changed since last query with *changeToken* feature -- Ability to include a rich set of metadata per item -- Ability to return only top-level structure without subfolders or children. - -More detailed information about the features and the API description is covered in the section below. - - -The Migration Asynchronous Read APIs are: - -Single - -```csharp -public SPAsyncReadJobInfo CreateSPAsyncReadJob( - Uri url, - SPAsyncReadOptions readOptions, - EncryptionOption encryptionOption, - string azureContainerManifestUri, - string azureQueueReportUri) -``` - -Multiple - -```csharp -public SPAsyncReadJobInfo CreateSPAsyncReadJobWithMultiUrl( - Uri[] urls, - SPAsyncReadOptions readOptions, - EncryptionOption encryptionOption, - string azureContainerManifestUri, - string azureQueueReportUri) -``` - -The API is made up of five input parameters and one output structure field. - -## Input Parameters - -### URL - -The full path URL lets your migration tool to specify the root URL path of the SharePoint list, files/folder document library to be read. By default, the server-side code will read and return all the metadata of files, folders, and root objects including subfolders and their children content. - -*Example:* -This document library URL, `https://www.contoso.com/Shared%20Document`, will be read back for metadata of any files or folders that live under the root URL. `https://www.contoso.com/Shared%20Documents/FolderA/` will be read back for children metadata in FolderA. - -#### Multiple URLs - -With the latest API update in Q1 2020, AMR will now support multiple URL inputs. This means the user can input multiple root URLs or subfolder URLs and aggregate them into a single call. - -As there is a fixed overhead, AMR is most effective when there is a large number of reads when processing AMR. There are cases when the migration software may not want to read the whole root level URL. The multiple URL feature lets the software to aggregate multiple requests into a single request to improve performance while reducing number of calls. - -(For more information regarding the size recommendation, see the performance section) - -*Example:* The document library URL, `https://www.contoso.com/Shared%20Document`, has folders A through J . The customer only wants to migrate folders A, B, C, D, and E. Instead of issuing a single read at the root level and returning large unnecessary content, or issuing AMR per individual folder, which is not effective, the software can issue URI [A, B, C, D, E] in the input parameters returning only required metadata. - -Currently there is a maximum of 5000 URL aggregation limits per call. - -#### readOptions Flag - -The read asynchronous function will include the SPAsyncReadOptions structure, which covers the optional flags to allow the user to specify version and security setting on the site level more is described below. - -```csharp -IncludeVersions{ get; set; } -``` - -If set, this indicates all the files and list item version history is to be included in the export operation. If absent, only the most recent version is provided. - -```csharp -IncludeSecurity{ get; set; } -``` - -This flag indicates whether to include all user or group information from a site. By default, users and groups that are part of the object metadata will be returned, such as author or modifier. - -If you use this flag, all users in the site collection will be included. If you are issuing AMR calls for different document libraries that are under the same site collection, the same set of users will be included each time, unless there has been a change. - ->[!Important] ->Using this option can result in very slow performance. Use it only as described in the steps below. - -If you have a large number of objects in a document library, it is faster to do the following two calls to read the security setting and its child folders: - -1. To get user/group info, call the AMR job on the top root folder with security on using this setting: -("IncludeSecurity=true" & "IncludeDirectDescendantsOnly=true"). -1. For the rest of the structure, call the AMR job with the security off: -"IncludeSecurity=false" - -```csharp -public bool IncludeDirectDescendantsOnly { get; set;} -``` - -If specified only the top-level metadata item is read back. Example: The root URL contains file A and folder B. If this flag is specified, the manifest returns only file A and folder B metadata. It will not return any metadata included inside folder B. - -The use case for this function: The ISV can issue a default read to retrieve the top-level items and then issue multiple `CreateSPAsyncReadJob` to read back all the sub folder content in parallel to improve throughput. - -```csharp -public bool IncludeExtendedMetadata { get; set; } -``` - -This flag indicates whether to return the extended set of metadata content of object query. By default this option is off and only basic content is provided (for example, names, URL, author, modifier, dates) . Turning on this flag provides all the metadata content; however, it will also impact the performance as query will take longer. - -Recommendation is to keep the default for file share migration, but consider setting this flag on for SharePoint on-premises or other more complex migration. - -```csharp -public string StartChangeToken { get; set; } -``` - -This option applies to input URL of list or document library only. - -One of the key calls contributor is incremental migration. ChangeToken idea is introduced to reduce the unnecessary calls. If StartChangeToken is not specified, the CreateSPAsyncReadJob will query and read back all the items specified by the API function. Once specified with the ChangeToken value, only the item changed since last query is returned. - -During incremental migration, instead of query everything again, by populating StartChangeToken with the change token received from the CurrentChangeToken output in returning job info, createSPAsyncReadJob then returns only the items that got changed since the specified StartChangeToken, reducing the overall calls. - -Below is a sample of how the `startChangeToken` might work. This example uses the optional feature setting for initial call and the parameter setting for incremental passes. - -![Export API process](../images/async-read-api-flow.png) - -#### Invalid Value - -If an invalid value is detected, other than NULL, an error will be generated, and the operation will be terminated. - -#### encryptionOption - -This is an optional parameter. If it is specified, the AES256CBCKey is used to encrypt output files and queue messages. Otherwise, there is no encryption. - -For more information, see [EncryptionOption Class](/dotnet/api/microsoft.sharepoint.client.encryptionoption). - -#### azureContainerManifestUri - -The valid URL including SAS token for accessing the Azure Blob Storage Container, which contains the block blobs for the manifest and other package describing XML files. This location will also be used for the log output response. The SAS token must have been created with only Read and Write permissions or the asynchronous metadata read job will fail. The SAS token should at least have a lifetime that starts at from no later than when the job was submitted, until a reasonable time for successful import to have concluded. - -#### azureQueueReportUri - -The valid URL including SAS token for accessing the user provided Azure Queue used for returning notifications of asynchronous metadata read job progress. If this value is not null and proper access is granted in the SAS token in this URI, it will be used for real-time status update. The SAS token must have been created with Add permissions or the migration job will be unable to add events to the queue. - -Once accepted, the job ID will be written to the notification queue if it was provided and access is valid. The notification queue can be used for multiple migration jobs at the same time, as each job will identify itself in values sent back to the notification queue. - -## Output Parameters - -### CurrentChangeToken - -```csharp -public string CurrentChangeToken { get; set; } -``` - -This function returns the changeToken associates with this query. By specifying this changeToken in the input field with subsequent read, the API will return only items changed since this last query. - -#### Manifest Output - -After the *asyncMigrationRead* function prepares execution, the final manifest will be placed in the container specified, under a folder named **JobId**. The manifest export package structure will be like the *createMigration* Import Package structure. The general output structure is summarized in table below. - -> [!NOTE] -> Once the AMR manifest package reaches 25MB, it will split into multiple packages per request. - -Below is an example on how to query the folder: - -```csharp -CloudBlobDirectory folder = blobContainerObj.GetDirectoryReference(jobid); -CloudBlockBlob blob = folder.GetBlockBlobReference(manifestFileName); -``` - -|XML file|Schema File|Description| -|:-----|:-----|:-----| -|ExportSettings.XML|DeploymentExportSettings Schema|ExportSettings.XML does the following:

- Contains the export settings specified by using the SPExportSettings class and other classes that are part of the content migration object model.

- Ensures that the subsequent export process (at the migration target site) enforces the directives specified in the export settings.

- Maintains a catalog of all objects exported to the migration package.| -|LookupListMap.XML|DeploymentLookupListMap Schema|Provides validation for the LookupListMap.XML file exported into the content migration package. LookupListMap.XML maintains a simple lookup list that records SharePoint list item (list item to list item) references.| -|Manifest.XML|DeploymentManifest Schema|Provides validation for the Manifest.xml file that is exported into the content migration package. Provides a comprehensive manifest containing listings of both the contents and the structure of the destination site (for example, SPO) . | -|Requirements.XML|DeploymentRequirements Schema|"Provides validation for the Requirements.xml file exported into the content migration package. Requirements.xml maintains list of deployment requirements in the form of installation requirements on the migration target, such as feature definitions, template versions, Web Part assemblies, and language packs."| -|RootObjectMap.XML|DeploymentRootObjectMap Schema|"Provides validation for the RootObjectMap.xml file exported into the content migration package.RootObjectMap.xml maintains a list of mappings of secondary (dependent) objects, which allows the import phase of the migration operation to correctly place the dependent objects relative to the locations of the root object mappings."| -|SystemData.XML|DeploymentSystemData Schema|Provides validation for the SystemData.xml file exported into the content migration package.SystemData.xml does the following: Collects a variety of low-level system data. Records the number and names of Manifest.xml files (in cases where the migration uses multiple manifests).| -|UserGroupMap.XML|DeploymentUserGroupMap Schema|Provides validation for the UserGroup.xml file exported into the content migration package. UserGroup.xml maintains a list of users and user security groups with respect to access security and permissions.| -|ViewFormsList.XML|DeploymentViewFormsList Schema|Provides validation for the ViewFormsList.xml file exported into the content migration package.ViewFormsList.xml maintains a list of Web Parts and tracks whether each is a view or form.| - -#### How to retrieve the manifest from the Azure blob - -The following example code demonstrates how to get the Azure blob of a manifest file and decipher it: - -```csharp -// Get Azure blob of a manifest file -CloudBlockBlob blob = folder.GetBlockBlobReference(blobName); -blob.FetchAttributes(); - -using (Stream stmTemp = new MemoryStream()) -{ - // Download current manifest file - blob.DownloadToStream(stmTemp); - - // Get IV and decrypt the content into output dir - byte[] IV = Convert.FromBase64String(blob.Metadata[“IV”]); +> [!IMPORTANT] +> Use [GetMigrationJobProgress API](migration-job-progress-api-reference.md) to retrieve migration job status. +> +> Provisioning Azure Queues for migration job status tracking is no longer required. Deprecation of Azure Queues is planned for the second half of 2026. Until then, Azure Queues will remain available for status retrieval. - using (Stream targetStream = System.IO.File.Open(outputFileFullPath, FileMode.Append)) - { - using (Aes alg = new AesCryptoServiceProvider()) - { - stmTemp.Seek(0, SeekOrigin.Begin); - using (CryptoStream csDecrypt = new CryptoStream( - stmTemp, - alg.CreateDecryptor(key, IV), - CryptoStreamMode.Read)) - { - csDecrypt.CopyTo(targetStream); - } - } - } -} -``` +Use `ProvisionMigrationContainers` method to provision the containers. Check [Use Azure Blob Storage Containers and Azure Queues with Migration API](migration-azure.md) for details. You can also use your own containers and queues if needed. -#### JobQueueUri +### Use `CreateSPAsyncReadJob` method to start the export -```csharp -public Uri JobQueueUri { get; set; } -``` +Use `CreateSPAsyncReadJob` method to export metadata from a single URL, or `CreateSPAsyncReadJobWithMultiUrl` from multiple URLs if needed. Check [AMR API Reference](amr-api-reference.md) for details. -The reporting features are the same as they are for `CreateMigrationJob`. Logging is provided to track the status of the asynchronous metadata read. After a scan of the database and an estimate of your tools, the log provides an estimate of the number of items to be read per URL. By default, blob queue permissions and settings are set to "all access", the same as when the ISV calls `ProvisionMigrationContainer` during the `CreateMigrationJob`. +Get incremental updates with `ChangeToken` feature. -In addition to the events supported by the Import API (CreationMigrationJob), a new job event called `FinishManifestFileUpload` will be added to the status queue in real time. This is added after the manifest file is generated and uploaded. +Both methods return the Job ID, which can be used to track the export status. -As it’s a real time event, ISVs and developers can also immediately download and parse the manifest files once `FinishManifestFileUpload` is generated. Use the field `ManifestFileName` to parse this event to get every manifest file name, including systemdata.xml, usergroup.xml, etc. +Check [AMR API Reference](amr-api-reference.md) for details. -The new event will look like this: +### Checking status -```json -{"Event", "FinishManifestFileUpload"}, -{"JobId", “f8d7d577-676e-47ce-ab69-ae7803979883”}, -{"Time", “2019-09-03T19:11:33.903”}, -{"ManifestFileName", “f8d7d577-676e-47ce-ab69-ae7803979883/ExportSettings.xml”} -``` +> [!IMPORTANT] +> Use [GetMigrationJobProgress API](migration-job-progress-api-reference.md) to retrieve migration job status. +> +> Provisioning Azure Queues for migration job status tracking is no longer required. Deprecation of Azure Queues is planned for the second half of 2026. Until then, Azure Queues will remain available for status retrieval. -#### EncryptionKey +Check Azure Queue supplied for export status. Monitor events as listed in [Events](migration-events.md) for details. -```csharp -public byte[] EncryptionKey { get; set; } -``` -It returns the AES256CBC encryption key used to decrypt the message in azureManifest container and azureReport Queue. +AMR API exports metadata in the manifest container supplied, under a folder named by `JobID`. Check [Manifest files](migration-manifest.md) for the format and validation of the metadata. -|Output parameter|Description| -|:-----|:-----| -|JobID/GUID|Return a unique Job ID associated with this asynchronous read| -|AzureContainerManifest|Return the URL for accessing the async read manifest| -|JobQueueUri|URL for accessing Azure queue used for returning notification of migration job process| -|EncryptionKey|AES256CBC encryption key used to decrypt messages from job/manifest queue| +AMR API splits manifest packages larger than 25 MB into multiple manifest files per request. -## Set up Guidelines +## Best practice -The following provides high-level guidelines for implementing the asynchronous metadata migration function. This documentation does not go into details on how to interact with SharePoint RESTful service. It is assumed that the ISV has prior knowledge and will be able to access the target website with proper permission. +AMR API is powerful. Ensure good performance to achieve the scale for large migration projects. -For more information on how to access the SharePoint website, see [Get to know the SharePoint REST service](../sp-add-ins/get-to-know-the-sharepoint-rest-service.md). +### Export security and permissions on top level if possible -1. Install and update the latest Microsoft.SharePointOnline.CSOM version. The minimum version requirement is V16.1.9119.1200 or later. -1. ISVs figure out the folder, document library or files of interested to be query and issued with CreateSPAsyncReadJob function. -1. Once successfully created, query the job status using the *jobQueueUri*. It provides the job process status and any error logging. After job completion, parse the manifest to retrieve the metadata. +Exporting security with `IncludeSecurity` consumes more resources and slows down the export. It's faster to export this metadata at the upper-level folder first, then export the children without them. -### SharePoint Migration Export (Asynchronous Metadata Read) API Example +### Metadata export on a single item -#### Scenario: Large file share (> 1 million) with nested files/folders +Use Microsoft Graph instead of AMR. -Suggestion: -1. Issue CreateSPAsyncReadJob - - URL = root URL (for example, `www.contoso.com/my-resource-document`) - - Optional Flag: `IncludeDirectDescendantsOnly(true)` +### Folders with less than 10,000 items - For each of the sub folders, issue createSPAsyncReadJob if the folder has > 10K +Use `CreateSPAsyncReadJobWithMultiUrl` to combine the URLs of multiple folders into a single export job. - **Sample source code** +### Folders with 10,000 to 1 million items - ```powershell - $site = get-spsite https://test.sharepoint.com # get site - $web = get-spweb https://test.sharepoint.com # get web - $list = $web.GetList("Shared Documents") # get the document library under this web +Use `CreateSPAsyncReadJob`, and set **readOption** `IncludeDirectDescendantsOnly` to `false`. This value is the default setting. - # Get the Doclib root folder - $rootFolder = $web.GetFolder($list.Rootfolder.ServerRelativeUrl) +### Nested folders with over 1 million items - # You can call 1 AMR job here, to get metadata of the direct children of the root folder only - CreateAMRJob($rootFolder) +Plan carefully when dividing folders into jobs. Object count in export jobs is the major factor of export performance. - # Create parallel AMR jobs for the direct level subfolders - Foreach ($folder in $rootFolder.SubFolders) - { - // Create 1 AMR job per folder tree - CreateAMRJob($folder) - } - ``` +This example shows how to export metadata from nested folders with over 1 million items. AMR API has the highest performance when the item count is large. - The ISV can optimize the recursive highlight part by leveraging the $ folder.item["SMTotalFileCount"] that will return the cumulative file count in the folder tree for a given folder item. Follow the recommendations in the performance section on type of AMR jobs to issue +- Use `CreateSPAsyncReadJob` method at the root URL, for example: `www.contoso.com/my-resource-document`, and set **readOption** `IncludeDirectDescendantsOnly` to `true`. +- Utilize `SMTotalFileCount` attribute to get the file count in folders. +- Continue to use `createSPAsyncReadJob` method at subfolder level, on each of the subfolders, if the folder has more than 10,000 items. +- Use `CreateSPAsyncReadJobWithMultiUrl` method, combining subfolders with less than 10,000 items. -1. object, issued in multiple URLs if < 10K objects +## Performance -> [!IMPORTANT] -> This scenario is only recommended for top level folders or if the sub-folder contains greater than one million objects. The performance of the AMR API is *not as effective* when reading a small set of items. +AMR API processes jobs through a queue mechanism with preconfigured workload management settings. AMR API processes the jobs on a best-effort basis, without Service Level Agreement (SLA) or guaranteed performance. -#### Scenario: Incremental Migration of FileShare for a sub folder +### Lab-tested performance baseline -1. Issue CreateSPAsyncReadJob:
- 1. URL = root URL (for example, `www.contoso.com/my-resource-document/a`) - 1. Remembered the `CurrentChangeToken` +We tested the performance in a lab setting. AMR API exported about 400 items per second for every 250-K objects, in the average case. The peak performance reached 700 items per second. -1. After some time, the software wishes to perform incremental migration. Issue CreateSPAsyncReadJob with following term:
- 1. URL = root URL (for example, `www.contoso.com/my-resource-document/a`) - 1. Optional Flag: `StartChangeToken(CurrentChangeToken)` +Multiple factors affect real-life performance. These factors include: -## Limitations +- The number of items that are being exported +- The way AMR API is implemented +- Throttling -Asynchronous Metadata Read (Export API) now supports unlimited list, document library, file, and folder metadata export. +### Optimize migration performance -## Performance Expectation +In order to ensure optimal performance for your migration projects, it's important to plan carefully, especially when dealing with large-scale migrations. For more information on how to estimate timespans and optimize performance, see our [performance guide](/sharepointmigration/sharepoint-online-and-onedrive-migration-speed). -The preliminary performance test provides a rough estimate of more than 400 items per second throughput for every 250K of objects read. We have seen over 700 items per second throughput in a testing environment. However, this is highly dependent on the number of items that are being read plus the implementation of the AMR API. This does not account for any potential throttle over the network. If the asynchronous read function fails to reach the server due to throttling, then performance will be impacted. +### I'm seeing throttling messages -This measure of throughput assumes the software package has a sufficient number of items per read. Microsoft recommends the following: +To ensure good user experiences for all Microsoft 365 customers, SharePoint uses throttling to protect the SharePoint infrastructure. Avoid getting throttled by following [throttling guidance](https://aka.ms/spo429). -| Folder size | Recommendation | -| :------------------------------------------------ | :----------------------------------------------------------------------------------------------------------- | -| Less than 10,000 items | Combine the URLs of multiple folders into a single call | -| Greater than 10,000 items but less than 1,000,000 | Run AMR at the root folder level | -| Greater than 1,000,000 | Use the recursive call logic to explore that folder's direct level children until there are no more folders. | +### Tenant-to-Tenant migrations -For a single read query, it is faster to use the Graph API or a RESTful/CSOM query. +AMR isn't intended for scenarios where contents from a SharePoint tenant are moved to another. This type of migration requires the use of many resource-heavy read options. The long processing time of these read options slows down the overall migration significantly. -One of the key performance benefits of using the asynchronous metadata read is the ability to balance the server-side load and the backend query. It is much more efficient than using individual CSOM load reducing to lessen your chance of throttling. +Microsoft provides no performance guarantee in this scenario. Use Graph or CSOM as needed. diff --git a/docs/apis/migration-api-overview.md b/docs/apis/migration-api-overview.md index 1d293cf55..d09416b7e 100644 --- a/docs/apis/migration-api-overview.md +++ b/docs/apis/migration-api-overview.md @@ -1,1653 +1,131 @@ --- -title: "SharePoint Online Import Migration API" -description: "This article provides in depth information on how to use the SPO Migration API." -ms.date: 12/05/2022 -ms.author: jhendr -author: JoanneHendrickson -manager: serdars -search.appverid: MET150 +title: "SharePoint Import Migration API" +description: "This article provides an overview of how to use the SharePoint Migration API." +ms.date: 07/16/2025 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro ms.subservice: migration-tool +ms.topic: article ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration --- -# SharePoint Import Migration API (CreationMigrationJob) +# SharePoint Migration API Introduction -## API Documention +The SharePoint Migration API imports content into SharePoint at scale. It processes content and manifest packages as jobs in a queue. The API provides process status and logs, making it easy to monitor the progress of each migration job. -The following API description is based upon use of the SharePoint Client Side Object Model (CSOM). We do recommend using NuGet packages when you reference CSOM in your solution. +Use Migration API to migrate content from file shares, SharePoint Server, and other cloud-based services. -You can find latest version of the SharePoint Online Client Side Object Model (CSOM) package from the [NuGet gallery](https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM/). Use the ID `Microsoft.SharePointOnline.CSOM`. +## What's new -> [!IMPORTANT] -> Files larger than 15 GB must now create the required checksum using [QuickXorHash](/onedrive/developer/code-snippets/quickxorhash). We have provided an example [here](#what-is-stored-in-those-azure-blob-containers). -> -> The QuickXorHash/Checksum has to be computed for the original file **before** encryption (if the file is being encrypted). This is different from the MD5hash requirement. -> -> The previous method of MD5Hash is still required for files smaller than 2 GB; however this requirement will be removed at some point in the future. - - -## Methods - -### CreateMigrationJob - -This method creates a new migration import job and queues it up for later processing by a separate timer job. The job will consume a well formed (pre-defined format) import package that is located in the Azure Blob Storage Containers specified in this method. The SLA for migration job processing is be controlled through pre-configured queue and work load throttling settings, and there is no guaranteed SLA or return time for a submitted job. - -#### Syntax - -```csharp -public Guid CreateMigrationJob( - Guid gWebId, - string azureContainerSourceUri, - string azureContainerManifestUri, - string azureQueueReportUri) -``` - -#### Parameters - -##### gWebID - -The unique identifier of the destination web targeted for the package import. Additional information and identifiers for the import are specified within the import package itself. This identifier can be found programmatically by querying the target web using CSOM calls. - -##### azureContainerSourceUri - -The valid URL including SAS token for accessing the Azure Blob Storage Container which contains the binary files of type block. The SAS token must have been created with only Read and List permissions or the migration job will fail. The SAS token should at least have a lifetime that starts no later than when the job was submitted, until a reasonable time for successful import to have concluded.
- -The required permissions are as follows in the Azure Storage API: - -```csharp -(SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List) -``` - -> [!NOTE] -> The change to enforce Read and List permissions on the SAS token is coming in a future build. Until then it will not be enforced. However, it is a best practice to use these values. - -All files in the container must have at least a single snapshot applied to them to ensure that no file modification is made by the customer during the import. Any file that does not have a snapshot will be skipped during import and have an error thrown, although the job will attempt to continue the import. The import pipeline will use the latest snapshot of the file available at the time of import. The following is an example of the code that might be used to create a snapshot on a file after it is uploaded to Azure Blob Storage: - -```csharp -CloudBlockBlob blob = blobContainerObj.GetBlockBlobReference(file); -blob.UploadFromStream(stm); -blob.CreateSnapshot(); -``` - -> [!NOTE] -> The change to require and use the latest SnapShots on all files is coming in a future build, and until then will be ignored. - -##### azureContainerManifestUri - -The valid URL including SAS token for accessing the Azure Blob Storage Container which contains the block blobs for the manifest and other package describing XML files. This location will also be used for the log output. This container cannot be the same as the one used for the azureContainerSourceUri. The SAS token must have been created with only Read, List and Write permissions or the migration job will fail. The SAS token should at least have a lifetime that starts no later than when the job was submitted, until a reasonable time for successful import to have concluded. - -> [!NOTE] -> The change to enforce Read, List and Write permissions on the SAS token is coming in a future build, and until then will be not be enforced, however it is best practice to use these values. If an issue arises using a current build, try removing the List permission as a temporary workaround, noting that it will become required soon. - -All files in the container must have at least a single snapshot applied to them to ensure that no file modification is made by the customer during the import. Any file that does not have a snapshot will cause failures during the import and have errors thrown, potentially failing the entire migration job. - -> [!NOTE] -> The change to require and use the latest SnapShots on all files is coming in a future build. Until then they will be ignored. - -##### azureQueueReportUri - -The valid URL including SAS token for accessing the user provided Azure Queue used for returning notifications of migration job progress. This value can be null if no notification queue will be used during the import. If this value is not null and proper access is granted in the SAS token in this URI, it will be used for real time status update. The SAS token must have been created with only Add, Read and Update permissions or the migration job will be unable to add events to the queue. The required permissions are as follows in the Azure Storage API: - -``` -(SharedAccessQueuePermissions.Add | SharedAccessQueuePermissions.Read | SharedAccessQueuePermissions.Update) -``` - -Once accepted, the job ID will be written to the notification queue if it was provided and access is valid. The notification queue can be used for multiple migration jobs at the same time, as each job will identify itself in values sent back to the notification queue. - -The following are examples of all event types logged into the Azure reporting queue: - -**Event:JobQueued** -JobId:845daca4-5529-4b0e-85ab-a603efee5b12 -Time:09/29/2020 19:56:02.883 -SiteId:48917234-de43-474a-9f1b-8d98ffa08425 -DbId:8fd09323-b23f-430d-8957-213586ce3861 -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -CorrelationId:c8d97e9f-802f-0000-ceac-44663834d510 - -**Event:JobPostponed** -JobId:845daca4-5529-4b0e-85ab-a603efee5b12 -Time:09/29/2020 19:56:57.598 -NextPickupTime:09/29/2020 20:16:57.519 -SiteId:48917234-de43-474a-9f1b-8d98ffa08425 -DbId:8fd09323-b23f-430d-8957-213586ce3861 -JobsInQueue: -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -CorrelationId:d5d97e9f-702c-0000-ceb9-354fefa5e9f6 - -**Event:JobLogFileCreate** -JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecd -Time:09/29/2020 19:56:29.053 -FileName:Import-071f9aad-36e6-4bef-9f09-40b5c7498ecd-1.log -CorrelationId:22ca20ec-23de-468b-add3-4e52e90d3a68 - -**Event:JobStart** -JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecd -Time:09/29/2020 19:56:29.100 -SiteId:48917234-de43-474a-9f1b-8d98ffa08425 -WebId:36b66979-4a43-4b93-9b92-909c7186ff98 -DBId:8fd09323-b23f-430d-8957-213586ce3861 -FarmId:211e600c-f48d-4319-ba92-61150c8e8e8c -ServerId:cfd27448-822a-420b-bcc8-4f39629b01bc -SubscriptionId:51812136-3cba-482d-9696-532cddceab31 -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -CorrelationId:c308c0ea-a7f5-4be9-acd4-1ebd39867434 - -**Event:JobProgress** -JobId:845daca4-5529-4b0e-85ab-a603efee5b12 -Time:09/29/2020 19:56:32.265 -FilesCreated:15 -BytesProcessed:45 -ObjectsProcessed:217 -TotalExpectedSPObjects:403 -TotalErrors:0 -TotalWarnings:0 -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -WaitTimeOnSqlThrottlingMilliseconds:0 -TotalDurationInMs:0 -CpuDurationInMs:0 -SqlDurationInMs:0 -SqlQueryCount:0 -CreatedOrUpdatedFileStatsBySize:{"0-1K":{"Count":15,"TotalSize":45,"TotalDownloadTime":251,"TotalCreationTime":6754}} -ObjectsStatsByType:{"SPUser":{"Count":1,"TotalTime":289,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPFolder":{"Count":2,"TotalTime":144,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPDocumentLibrary":{"Count":1,"TotalTime":173,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPFile":{"Count":200,"TotalTime":6765,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPListItem":{"Count":14,"TotalTime":2111,"AccumulatedVersions":0,"ObjectsWithVersions":0}} -TotalExpectedBytes:0 -CorrelationId:ccd97e9f-a0cc-0000-ceb9-37a900bec68d - -**Event:JobEnd** -JobId:16d658cf-ecd3-485f-9c9e-1ca268565e24 -Time:09/29/2020 20:29:38.180 -FilesCreated:200 -BytesProcessed:600 -ObjectsProcessed:403 -TotalExpectedSPObjects:403 -TotalErrors:0 -TotalWarnings:0 -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -WaitTimeOnSqlThrottlingMilliseconds:0 -TotalDurationInMs:372294.0861 -CpuDurationInMs:17351 -SqlDurationInMs:98359 -SqlQueryCount:1998 -CreatedOrUpdatedFileStatsBySize:{"0-1K":{"Count":200,"TotalSize":600,"TotalDownloadTime":15448,"TotalCreationTime":275662}} -ObjectsStatsByType:{"SPUser":{"Count":1,"TotalTime":44,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPFolder":{"Count":2,"TotalTime":108,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPDocumentLibrary":{"Count":1,"TotalTime":50,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPFile":{"Count":200,"TotalTime":293628,"AccumulatedVersions":0,"ObjectsWithVersions":0},"SPListItem":{"Count":200,"TotalTime":76541,"AccumulatedVersions":0,"ObjectsWithVersions":0}} -TotalExpectedBytes:0 -CorrelationId:59db7e9f-a003-0000-ceb9-300001119ee3 - -**Event:JobDeleted** -JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecd -Time:09/29/2020 19:56:29.053 -CorrelationId:22ca20ec-23de-468b-add3-4e52e90d3a68 - -**Event:JobCancelled** -JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecd -Time:09/29/2020 19:58:29.053 -TotalRetryCount:0 -CancelledByUser:false -MigrationType:None -MigrationDirection:Import -CorrelationId:22ca20ec-23de-468b-add3-4e52e90d3a68 - -**Event:JobError** -JobId:b427d8d7-2b91-4da0-aee5-4b5a5a5d867e -Time: 02/05/2019 06:56:09.732 -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -ObjectType:File -Url:Shared Documents/file.pdf -Id:fae7b4b0-2912-11e9-b0f3-7b554a52d6ab -ErrorCode:-2147024816 -ErrorType:Microsoft.SharePoint.SPException -Message:ErrorMessage -CorrelationId:d8e9bc9e-20e2-8000-aa83-48a62fc5ce75 - -**Event:JobWarning** -JobId:b427d8d7-2b91-4da0-aee5-4b5a5a5d867e -Time: 02/05/2019 06:56:09.732 -TotalRetryCount:0 -MigrationType:None -MigrationDirection:Import -ObjectType:File -Url:Shared Documents/file.pdf -Id:fae7b4b0-2912-11e9-b0f3-7b554a52d6ab -ErrorCode:-2147024816 -ErrorType:Microsoft.SharePoint.SPException -Message:ErrorMessage -CorrelationId:d8e9bc9e-20e2-8000-aa83-48a62fc5ce75 - -**Event:FinishManifestFileUpload** -JobId:b427d8d7-2b91-4da0-aee5-4b5a5a5d867e -Time:02/05/2019 06:56:09.732 -ManifestFileName:Filename -CorrelationId:d8e9bc9e-20e2-8000-aa83-48a62fc5ce75 - - -#### Return values - -The unique identifier for the migration job is returned if the job is successfully queued, or if unsuccessful, a null value will be returned. The migration job unique identifier can be used to query the migration job status while it is in the queue or being processed by using the GetMigrationJobStatus method. - -**Example:** - -```csharp -Guid MigrationJobId = TargetSite.CreateMigrationJob( - TargetWebId, - azureContainerSourceUri, - azureContainerManifestUri, - azureQueueReportUri); -``` - -### GetMigrationJobStatus - -This method queries the queue status for the specified migration job. It is an optional check after calling the CreateMigrationJob method. Once the migration job has completed, it will no longer show up in the queue and the notification queue and/or log output should be checked for detailed status. - -#### Syntax - -```xml -[ClientNS.ClientCallableMethod] -public SPMigrationJobState GetMigrationJobStatus(Guid MigrationJobId) -``` - -#### Parameters - -##### Id - -The unique identifier of the migration job returned from CreateMigrationJob method. - -#### Return values - -The migration job status is returned using a SPMigrationJobState object if the job is found in the queue, or if unsuccessful, a value of none (0) will be returned. - -**Example** - -```csharp -SPMigrationJobState CurrentJobState = TargetSite.GetMigrationJobStatus(MigrationJobId); -``` - -## Enumerations - -### SPMigrationJobState - -SPMigrationJobState is an enumeration that tracks possible major states in the import queue. - -#### Members - -| Member name | Description | -| ----------- | --------------------------------------------------------------------------------------------------------------------------- | -| None | Migration job is currently unknown to the queue, either through completion and removal, or invalid job identifier. Value=0. | -| Queued | Migration job is currently known by the queue and not being processed. Value=2. | -| Processing | Migration job is currently known by the queue and is being actively processed. Value=4. | - -## Import Package Structure - -Package structure is based on a constrained version of the Content Deployment package schema. Documentation for the original full schema can be found in [Content migration schemas](../schema/content-migration-schemas.md). Until published on Microsoft Docs, the constrained structure can be found in this document in the appendix. - -| XML file | Schema File | Description | -| ------------------ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| ExportSettings.xml | DeploymentExportSettings Schema | Provides validation for the ExportSettings.XML file exported into the content migration package. ExportSettings.XML does the following:
- Contains the export settings specified by using the SPExportSettings class and other classes that are part of the content migration object model.
- Ensures that the subsequent import process (at the migration target site) enforces the directives specified in the export settings.
- Maintains a catalog of all objects exported to the migration package. | -| LookupListMap.xml | DeploymentLookupListMap Schema | Provides validation for the LookupListMap.XML file exported into the content migration package. LookupListMap.XML maintains a simple lookup list that records SharePoint list item (list item to list item) references. | -| Manifest.xml | DeploymentManifest Schema | Provides validation for the Manifest.xml file that is exported into the content migration package. Provides a comprehensive manifest containing listings of both the contents and the structure of the source site. The migration operation uses the manifest file to reconstitute the source site and its components when it is imported to the destination site. | -| Requirements.xml | DeploymentRequirements Schema | Provides validation for the Requirements.xml file exported into the content migration package. Requirements.xml maintains list of deployment requirements in the form of installation requirements on the migration target, such as feature definitions, template versions, Web Part assemblies, language packs, and so forth. | -| RootObjectMap.xml | DeploymentRootObjectMap Schema | Provides validation for the RootObjectMap.xml file exported into the content migration package.RootObjectMap.xml maintains a list of mappings of secondary (dependent) objects, which allows the import phase of the migration operation to correctly place the dependent objects relative to the locations of the root object mappings. | -| SystemData.xml | DeploymentSystemData Schema | Provides validation for the SystemData.xml file exported into the content migration package.SystemData.xml does the following: Collects a variety of low-level system data. Records the number and names of Manifest.xml files (in cases where the migration uses multiple manifests). | -| UserGroupMap.xml | DeploymentUserGroupMap Schema | Provides validation for the UserGroup.xml file exported into the content migration package. UserGroup.xml maintains a list of users and user security groups with respect to access security and permissions. | -| ViewFormsList.xml | DeploymentViewFormsList Schema | Provides validation for the ViewFormsList.xml file exported into the content migration package.ViewFormsList.xml maintains a list of Web Parts and tracks whether each is a view or form. | - -### Content structure - -File content that is referenced within the manifest of the package structure must be stored in either a flat or hierarchical structure within the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerSourceUri` parameter. For example, import packages generated form a legacy version export will not be hierarchical, and will instead have all files stored at the root level with a pattern like ########.dat where the # symbols are hexadecimal characters starting at 0 and no file names are repeated within a package. Alternately, a package generated from a file share can have the source folder hierarchy and file names preserved in the same hierarchy. - -The main requirement for the structure is that the FileValue references in the **Manifest.XML** file must refer to the exact name and physical hierarchy that the content is stored in within the Azure Blob Store location for import. The destination file names and folder hierarchy from the import operation are not directly related to the physical naming and hierarchy and are instead defined through the **Manifest.XML** file. - -### ExportSettings.XML - -The **ExportSettings.XML** file is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerManifestUri` parameter. This required file is validated using the constrained DeploymentExportSettings.XSD, which has some limited changes from current published [full 2013 package schema](../schema/content-migration-schemas.md). - -The main requirement is that the ExportSettings `SiteUrl` value must be populated with a URL consistent with the source URL used for the rest of the import package. In the case of file shares as a source, the URL would be pre-specified to be the source URL in the rest of the package, whereas a package generated through an export operation at a source site would be its original source site collection URL. - -#### SourceType required - -Beginning January 1, 2023, the SourceType field will be mandatory when calling the Migration API. Starting October 1st, 2022, a warning message will be sent if the field is missing. - -Accepted SourceType values: - -- AmazonS3 -- AzureStorage -- Box -- Dropbox -- Egnyte -- FileShare -- GoogleCloudStorage -- GoogleDrive -- MicrosoftStream -- OneDrive -- SharePointOnline -- SharePointOnPremServer -- Other - -When declaring to **Other**, include *DetailedSource* to provide us the detailed information. - -**Example**: - -```powershell - - - - - -``` - -### LookupListMap.XML - -The **LookupListMap.XML** file, if included, is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s azureContainerManifestUri parameter. This optional file is validated using the constrained **DeploymentLookupListMap.XSD**, which has no change from current published [full 2013 package schema](../schema/content-migration-schemas.md). - -Since an import package for the pipeline does not include defining fields or views on a list or document library, the **LookupListMap.XML** file will normally include no child nodes under the root and as such can also be excluded from the package if not required, although a warning may be logged in this case. - -### Manifest.XML - -All instances of the **Manifest.XML** file for a package are expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerManifestUri` parameter. This required file is validated using the constrained **DeploymentManifest.XSD**, which has multiple major changes and significant reduction in types from current published [full 2013 package schema](../schema/content-migration-schemas.md). - -The **Manifest.XML** is the primary descriptor for metadata within the package, and provides the list/folder/item hierarchy, along with metadata for the items including references back to users and groups defined in the **UserGroupMap.XML** file. There may be more than one **Manifest.XML** file (which can be identified using different file names to uniquely identify them), and all are found by the import pipeline through references within the **SystemData.XML** file’s ManifestFile entries. - -The main requirements for **Manifest.XML** to be able to successfully import through the pipeline is that the Web Id and Document Library ID/List ID be consistent with the target location. If a Web ID is used which doesn’t match the target location, errors will occur because the parent web for the import operation cannot be found. - -Likewise, an incorrect Document Library ID/List ID will prevent the importation into the target Document Library or List. IDs should never be reused within the same site collection, so same packages should not be imported to the same target site collection regardless of the destination web. - -For individual files and folders within the document library or list, their identifiers should be consistent between import events to the same location. Specifically, performing an import of a package generated from a file share would initially require generating new GUIDs for each file and folder, along with matching GUIDs for the list items that represent them. Therefore, performing a second import against the same target using the same package would keep the same IDs, but performing a second import against the same target using a new package for the same content would result in ID conflicts and import errors for all items in conflict. - -The package generated initially from a file share is effectively a form of record for the original generated IDs and can potentially be used as a reference for follow up package generation to prevent ID collisions when unintended, and to allow like IDs to ensure correct overwrite, deletion or move activities. - -### Requirements.XML - -The **Requirements.XML** file is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s azureContainerManifestUri parameter. This optional file is validated using the constrained DeploymentRequirements.XSD, which has no change from current published [full 2013 package schema](../schema/content-migration-schemas.md). - -For file shares this is expected to normally include no child nodes under the root and as such can also be excluded from the package if not required, although a warning will be logged in this case. - -### RootObjectMap.XML - -The **RootObjectMap.XML** file is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerManifestUri` parameter. This required file is validated using the constrained **DeploymentRootObjectMap.XSD**, which has some limited changes from current published [full 2013 package schema](../schema/content-migration-schemas.md). The most common `RootObject` that will be included will be a single object of type List. The Id for this item should be the List Id for the target list, and the `ParentWebID` should match the Id of the parent target web containing this list in order for migration to be successful. The Id, WebUrl and Url values of this object must also match the related structure laid out in the **Manifest.XML** file. - -### SystemData.XML - -The **SystemData.XML** file is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerManifestUri` parameter. This required file is validated using the constrained **DeploymentSystemData.XSD**, which has no change from current published [full 2013 package schema](../schema/content-migration-schemas.md). - -The `SchemaVersion` information is expected to reference the current Build and DatabaseVersion of the target farm, a Version of “15.0.0.0”, and the `SiteVersion` value is expected to always match the target site collection `UIVersion` (i.e. most commonly this will be “15”). Each **Manifest.XML** file for the package is expected to be listed in this file within the `ManifestFile` entries. - -The SystemObjects that define dependent objects that should remain immutable by the migration code should also be listed here to ensure correct behavior of the import operation. The following is an example of the common objects in the **SystemObjects.XML** file from a file share based import, noting that the IDs are expected to be different for each package, and the URLs may be different. - -#### Table 1: Example SystemData.XML file - -```xml - - - - - - - - - - - - - - -``` - -### UserGroupMap.XML - -The **UserGroupMap.XML** file is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerManifestUri` parameter. This required file is validated using the constrained **DeploymentUserGroupMap.XSD**, which has no change from current published full 2013 package schema. - -The **UserGroupMap.XML** file may not contain any User or Group entries but doing so will prevent author or security information from being populated during import and warnings will be logged in this case. Login and SID values for users must be either adjusted to match the values in SharePoint Online, or if the account no longer should exist can be listed as `IsDeleted = “true”` to prevent lookup failures and additional slowdown during the import operation. - -### ViewFormsList.XML - -The **ViewForms.XML** file, if included, is expected to be at the root of the Azure Blob Store Container defined by the CreateMigrationJob’s `azureContainerManifestUri` parameter. This optional file is validated using the constrained **DeploymentViewFormsList.XSD**, which has no change from current published full 2013 package schema. - -Since an import package for the pipeline does not include defining fields or views on a list or document library, the **ViewFormsList.XML** file will normally include no child nodes under the root and as such can also be excluded from the package if not required, although a warning may be logged in this case. - -## Logging - -The logs that the import pipeline creates must be easily parsed by machine with a goal of being able to pinpoint when and where failures occur, including errors and warnings, and will tell the consumer or the ISV where and why the failure occurred. - -Upon completion, these logs will be copied to the `azureContainerManifestUri` location as the SAS token specified in the URI allows write access. The same output logs are also placed at the *“_catalogs/Maintenance Logs”* location of the target site collection as a text file. The logs will only be copied to the destination locations once the job has finished and removed from the queue. - -Several log types can be included such as the full import log, along with warning and error files that contain only the subset of import warnings or errors respectively. Log files have unique `datetime` and `job id` stamps to allow each attempted import event to have a unique log for better debugging purposes. - -## Changes for those using the "Ship Disk" option - -To use the Migration API, you must have a temporary storage container in Azure. When uploading files into the temporary storage, a checksum is required as a property on every file. For files larger than 15GB, this is done using QuickXorHash (see example below). For files 2 GB or smaller, MD5 is required as a property on every file. - -However, when shipping the data on hard drives this property doesn’t get assigned automatically. As a work around, we have adapted the Migration API to allow the checksum to be passed for every file as part of the manifest. This also applies for IV values when encrypting the data. - -Since the MD5 is generated at the source instead of at the upload time in Azure, Microsoft can confirm the integrity of the file directly against the source MD5. - -## What is stored in those Azure Blob Containers? - -The Migration API requires the Azure Container for content passing and also for log and queue reporting. It can be split down as a summary as follows:
- -| Content | Manifest | -| ----------------- | --------- | -| Files and folders | XML files | - -There are two new optional parameters in manifest.xml: - -- Checksum -- MD5Hash - -### Preparing the package -The method for calling the migration job doesn’t change; only the package generation needs to be changed. - -In the Manifest container one file is named Manifest.xml. There are 2 optional attributes added to the file node: *Checksum* and *MD5Hash*.
- -**Example for files over 15 GB:** - -```xml - - - - - - - - - - - - - - - - - - - - ``` - -**Example for files under 2 GB:** - -```xml - -``` - -## Best Practices and Special Mentions - -### Package size - -Even if the API support 15GB files, we recommend package sizes of up to 250 MB OR 250 items (depending which one comes first). If you have a file larger than that recommended size limit then you should send it in its own package. The same applies to versions; each version counts against the size limit and item count. Additionally, all the versions of a file should be in the same package. - -### File size - -> [!Note] -> The Migration API supports individual files over **15 GB**. The maximum size is current to that set by SharePoint Online. - -### Only un-compressed packages are supported - -The import pipeline does not support compressed packages. The file content must be stored in a different Azure Storage container from the manifest and related descriptive XML files. This decision was made to prevent the overhead of processing time on both ends of the migration (to compress and decompress), and also to ease package creation and modification. Compression of individual files such as into zip archives is supported as long as they are referenced in the import package as the archive itself, not the contents. - -### API supports import of multiple file versions - -Import packages can have references to multiple versions of a file, major and minor, up to regular limits imposed within SharePoint. It is important that each version of that file be included in the package even if some of the versions already exist in SPO. - -### API supports preservation of identifiers - -The identifiers used within the import package explicitly are used during import to identify content. This allows preservation of existing identifiers for document library contents from a source environment. However, it also imposes a complexity during import package creation or transformation that mandates that the package explicitly reference the target web and list identifiers. Content type identifiers, file/folder item GUIDs, and list item integer identifiers are all preserved during import. If incorrect identifiers are specified in the package, import will fail. +### December 2024 -Additionally, due to identifier preservation, import events can potentially be done in successive iterations using different packages, allowing items to potentially move in location if their identifiers have not changed. +We applied quota on *Share with Me* items per user. Check [ShareWithMe event quota](/sharepoint/dev/apis/migration-api-shared#quota) for more detail. -### This is an overwrite API +### November 2024 -The import pipeline does support import of versioning data on files and list item metadata, but as of now if you submit a file and then resubmit the same file with changes the import process will delete and replace the original and all versions with the ones included in the ones in the current package being imported. +We enabled logging all file-level events during migration, such as file deletion, to support auditing. -### We do not support Active-Active scenario +### July 2024 -This means we expect that the target site will remain non-active for users until the migration is over. The source may be kept in a read write state until the final migration event, as a method of reducing downtime for end users, but once the migration is complete there should be a switch for the users to start using their new SPO destinations and stop using the previous repository. +We started enforcing HTTPS connections to SharePoint-provided Azure Blob Storage Containers by adding a `spr=https` field in SAS tokens. This enforcement will be fully effective on July 21, 2024. Check [Use Azure Blob Storage Containers and Azure Queues with SharePoint Migration API](migration-azure.md) for details. -### Permissions in Azure +### April 2024 -To ensure immutability of source blobs, the import pipeline will accept a SAS key with only the Read and List access flags set for the File container. Likewise, the import pipeline requires a SAS key with Read, List and Write access for the Manifest container so that we can write back log files at the end of the import operation. If these criteria are not met, the pipeline will reject it during job creation. +We added new fields in `JobEnd` events to indicate the count and bytes imported for files. Check [Migration events in Azure Queue](migration-events.md#jobend-import) for details. -### All files in Azure must have snapshot created to import successfully +### January 2024 -To prevent unintended file modification of the source blobs, the import pipeline will only import files if they have a snapshot created for them within Azure. If they do not, then the import pipeline will skip the files in this state and throw errors. The import pipeline will use the latest snapshot of the file available at the time of import. +We reformatted this document to bring clarity and correct errors. -### Security and encryption +## Migration steps overview -The import pipeline is using Azure Blob Storage security model as is. This means we will not do any special treatment for those azure containers that would differentiate from any other azure containers. Additionally, the import pipeline currently does not accept encryption keys for content from the customer. Any encrypted content will be treated as opaque files that SharePoint may list, but be unable to index, the same as if encrypted files were uploaded through the UI to the environment. +Start a migration job with three steps. Check the guidance in each of the steps in this section. -### Events and event handlers +### Provision the destination containers and the queue -The import pipeline allows event handlers to be referenced on list items but doesn’t allow defining event handlers at the list level at this time. The import pipeline does not fire events as items are imported, so existing event handlers will not fire due to the import event. -### Entering user identifiers in UserGroup.XML - -Follow these guidelines when generating the **UserGroup.XML** in the submitted package: - -- A person can be identified only once in a single package -- The 'login' attribute of the user identifier requires a UPN. **Do not** enter a non-UPN email address. - - -> [!Important] -> As of March 2, 2022, the Migration API now validates and enforces a maximum of one identifier per user in a single package. -> -> While using a non-UPN email won't result in a failed job, it may bring unexpected results in SharePoint Online. - -**Examples** - -The following examples show the correct and incorrect ways of entering the user identifier in UserGroup.XML. - -In this case, the user has the following identifiers: - -- **UPN**: robert@contoso.com -- **Email**: robert.downey@contoso.com. - - -**Correct** - -- In this example, the user is entered only once, using a UPN email address. - - ```xml - - ``` - -**Incorrect** - -- **Example 1:** This example uses a non-UPN email address and incorrectly includes more than identifier for a single user. - - ```xml - - - ``` - -- **Example 2:** This example incorrectly uses a non-UPN email address. - - ```xml - - ``` - -### Resolving Users - -If the Migration API was unable to resolve a user using the login provided in the UserGroup.xml and no System ID is provided, then: - -1. This user will be replaced by “System Account” in the associated metadata within the package ( author, editor etc.). -1. A warning will be reported in the ImportLogs – “Failed to ensure user 'user@contoso.com'” - - If the migration API was unable to resolve a user using the login provided in the UserGroup.xml and the System ID is provided (which is the SID for the user in the on-premises AD), then: - -1. A new deleted user with the provided login and SystemId is created and is used in the associated metadata within the package. -1. A warning will be reported in the ImportLogs- “Failed to retrieve user 'user@contoso.com' attributes from the SiteUsers; falling back to passed in values” - -## Appendices - -### Acronyms Defined - -| Acronym | Definition | -| ------- | --------------------------------------------------------- | -| BOT | SharePoint server running timer jobs | -| CDB | Content database, containing site collections and content | -| CFE | Content farm front end server | -| SPO | SharePoint Online | -| ABS | Azure Blob Storage | - -### Helpful Resources - -- [SharePoint Online Client Components SDK](https://www.microsoft.com/download/details.aspx?id=42038) -- [Azure Windows Azure SDK for .NET - 2.4](https://azure.microsoft.com/downloads/) -- [Bulk Creation of OneDrive for Business sites](https://msdn.microsoft.com/library/office/jj163783(v=office.15).aspx) -- [Restrictions and limitations when you sync SharePoint libraries to your computer through OneDrive for Business](https://support.office.com/article/restrictions-and-limitations-when-you-sync-files-and-folders-7787566e-c352-4bd4-9409-fd100a0165f6) -- [Types of files that cannot be added to a list or library](https://support.office.com/Article/Types-of-files-that-cannot-be-added-to-a-list-or-library-30be234d-e551-4c2a-8de8-f8546ffbf5b3?ui=en-US&rs=en-US&ad=US) - -## Working with import package security structures - -This section covers a brief overview of what is contained within an export package that includes security with regard to permissions. This can allow the system to determine user and group membership along with roles, and specific assignments (unique permissions set at the object level and its children unless overridden at a deeper child object). - -### How to interpret the security identifiers in the package files - -UserGroup.xml file defines all users and groups within the exported web(s). The items within this file do the following: - -- User objects include the information about specific users, including identification of a specific security principle as a domain group or not, login, and the base 64 encoded SystemId (SID) of the security principle. -- Group objects include the information about specific groups and the direct membership list of that group. -- Owner values on group objects and UserId values on member objects within group objects map to other Id values of other user or group objects respectively. - -#### Table 2: Users and Groups annotated in UserGroupMap - -```xml - - - - - … - - - - - - - - - - … - - -``` - -**Manifest.xml** contains the metadata about all the content within the exported web(s). The items within this file do the following: - -- Roles objects include the list of defined roles on the web. -- Role objects define the individual role, including ID, internal permissions rights mask flags and display information. - - RoleId values define the identifiers of the Role objects. - - PermMask values contain the rights mask flags. -- RoleAssignments objects include the list of unique permissions (RoleAssignment objects). -- RoleAssignment objects include the list of distinct Assignment objects (if any). -- Individual RoleAssignment objects contain the actual membership of one distinct user or group and their actual Role. - - RoleId values map to the RoleId values of the Role objects. - - PrincipalId values map to Id values of user or group objects respectively in UserGroups.xml. - -#### Table 3: Roles and RoleAssignments annotated in manifest - -```xml - - … - - - - - - - - - - - - - - … - - - … - -``` - -## Constrained XSD structures - -Included below are the XSD files used for package validation in the import pipeline, when different than the original 2013 full schema which can be found at [official SharePoint documentation](../schema/content-migration-schemas.md). - -### DeploymentExportSettings.XSD - -#### Table 4: Constrained DeploymentExportSettings.XSD - -```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -``` - -### DeploymentLookupListMap.XSD -There is no change from current published full 2013 package schema. - -### DeploymentManifest.XSD - -##### Table 5: Constrained DeploymentManifest.XSD - -```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +> [!IMPORTANT] +> Use [GetMigrationJobProgress API](migration-job-progress-api-reference.md) to retrieve migration job status. +> +> Provisioning Azure Queues for migration job status tracking is no longer required. Deprecation is planned for the second half of 2026. Until then, Azure Queues will remain available for status retrieval. - - +Use the `ProvisionMigrationContainers` method to provision the containers. Check [Use Azure Blob Storage Containers and Azure Queues with Migration API](migration-azure.md) for details. You can also use your own containers and queues if needed. - - +### Prepare the content - - - - - - - - - +Package the contents in the defined format and upload them to Azure Blob Storage Containers as the content package. - - - - - - - +Check [Content package](migration-content-package.md) to see the detailed requirements. - - +### Create the manifest files - - - - - - +Based on the contents, create manifest files in XML format, and upload them to Azure Blob Storage Containers as the manifest package. - - - - +Check [Manifest files](migration-manifest.md) to see the detailed requirements. - - - - - - - - - - - - +### Use Migration API to start the migration and get status - - +The `CreateMigrationJob` method creates a migration job, which is queued up for processing. Migration API manages the queue and returns status and logs. Use the `CreateMigrationEncrypted` method to migrate encrypted contents. Check [SharePoint Migration API Reference](migration-api-reference.md) for details. - - - - +> [!IMPORTANT] +> Use GetMigrationJobProgress API to track migration job status. - +Upon creation of a new migration job, Migration API returns the Job ID. Track the status of the import with [GetMigrationJobProgress API](migration-job-progress-api-reference.md). - - +Migration API generates logs in the manifest container. Check the log entries for migration results. - - +Migration API also generates logs of file-level activities performed by migration. The supported file-level activities include FileUploaded, FileDeleted, FileRenamed, FileMoved. Check M365 Admin Center for activity details when needed. - - +## Best Practice - - - - - +### Use app-based authentication - - - - - - - -``` +Migration generates workload to the SharePoint backend differently from end user-generated traffic. To properly allocate resources with our elastic capability, only use app-based authentication in your migration solution. -### DeploymentRequirements.XSD +Don't use user mode in your migration solution. Running migration in user mode triggers increased throttling, resulting in poor performance. -There is no change from current published [full 2013 package schema](../schema/content-migration-schemas.md). +To learn more about how to register an app ID and how to implement app-based authentication, check [How to register an app ID](/azure/active-directory/develop/active-directory-v2-registration-portal) and [Microsoft Graph Auth guidance](/graph/auth). -### DeploymentRootObjectMap.XSD +### Microsoft Entra ID Permissions -#### Table 6: Constrained DeploymentRootObjectMap.XSD +Microsoft Entra ID provides two types of permission: Delegated Permission and Application Permissions. Check[ +Permissions and consent in the Azure Active Directory v1.0 endpoint](/azure/active-directory/develop/v1-permissions-and-consent) for details. -```xml - - +For SharePoint and OneDrive migration scenarios, follow the Microsoft Entra ID permission specification. - - - - +For migration tools that rely on end-user sign-in and presence, use Delegated permission. - - - - - - - - +For service-based migration tools that run without a signed-in user present, such as applications that run as background services, use Application permission. - - - - - - - - +### App IDs - - - - - +You can choose to share a single App ID to cover multiple migration solutions created or create an individual App ID for each of the products. Make sure to register App IDs. Sharing App IDs doesn't affect performance or throttling. - - -``` +### Keep destination SharePoint Site unactivated -### DeploymentSystemData.XSD +To avoid migration issues, deactivate the target site for users until migration completion. The source could remain active, allowing read and write access to keep productivity. Switch users to the new SharePoint destination sites after migration completion. -There is no change from current published [full 2013 package schema](../schema/content-migration-schemas.md). +## Performance -### DeploymentUserGroupMap.XSD +Migration API processes jobs through a queue mechanism with preconfigured workload management settings. Migration API processes the jobs on a best-effort basis, without Service Level Agreement (SLA) or guaranteed performance. -There is no change from current published full 2013 [full 2013 package schema](../schema/content-migration-schemas.md). +### Optimize migration performance -### DeploymentViewFormsList.XSD +In order to ensure optimal performance for your migration projects, it's important to plan carefully, especially when dealing with large-scale migrations. For more information on how to estimate timespans and optimize performance, see our [performance guide](/sharepointmigration/sharepoint-online-and-onedrive-migration-speed). -There is no change from current published [full 2013 package schema](../schema/content-migration-schemas.md). +### I'm seeing throttling messages -## Sample: Using REST to call the API +To ensure good user experiences for all Microsoft 365 customers, SharePoint uses throttling to protect the SharePoint infrastructure. Avoid getting throttled by following [throttling guidance](https://aka.ms/spo429). -```http -https://{site_url}/_api/site/CreateMigrationJobEncrypted +## Special articles -{ - "options": { - "AES256CBCKey": "000000000000000000000000000000000000000000000000000000=" - }, - "gWebId": "00000000-0000-0000-0000-000000000000", - "azureContainerSourceUri": "https://tenant.blob.core.windows.net:443/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000=rw", - "azureContainerManifestUri": "https://tenant.blob.core.windows.net:443/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000=rw" -} -``` +### Migrating sharing events of files and folders -For the container: +Check [Sharing events](/sharepoint/dev/apis/migration-api-shared) article for instructions when migrating shared events metadata with files and folders. -```http -https://{site_url}/_api/site/ProvisionMigrationContainers -``` +### Web Parts -> [!NOTE] -> The **Migration API** is not available for users of Office 365 operated by 21Vianet in China. It is also not available for users of Office 365 with the German cloud using the data trustee, *German Telekom*. However, it is supported for users in Germany whose data location is not in the German data center. +Use SharePoint Migration Tool (SPMT)'s Web Part serializer DLL to migrate Web Parts into SharePoint. Check [Migrate Web Parts](/sharepoint/dev/apis/migrate-webparts-with-migrationapi) for instructions. diff --git a/docs/apis/migration-api-reference.md b/docs/apis/migration-api-reference.md new file mode 100644 index 000000000..0db09f400 --- /dev/null +++ b/docs/apis/migration-api-reference.md @@ -0,0 +1,232 @@ +--- +title: "SharePoint Migration API Reference Guide" +description: "This article provides in-depth information on how to use the SharePoint Migration API." +ms.date: 07/16/2025 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- + +# SharePoint Migration API Reference Guide + +This guide describes the usage of SharePoint Migration API, which imports content into SharePoint, based on manifest files. + +## CSOM and REST + +Migration API supports both SharePoint Client Side Object Model (CSOM) and REST. + +### Use NuGet Packages with CSOM + +To reference the SharePoint Client Side Object Model (CSOM) in your solution, use NuGet packages. + +Manage dependencies easily and ensure your solution is using the latest version of the CSOM library with NuGet packages. + +Get the latest version of the CSOM package at the [SharePoint Client-side Object Model Libraries](https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM) with the ID `Microsoft.SharePointOnline.CSOM`. + +Check [Get to know SharePoint REST service](/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service) for instructions on REST API. + +## CreateMigrationJob method + +Creates a new migration import job with the import package specified in `azureContainerSourceUri` parameter. + +### CreateMigrationJob syntax + +```csharp +public Guid CreateMigrationJobEncrypted( +Guid gWebId, +string azureContainerSourceUri, +string azureContainerManifestUri, +string azureQueueReportUri, +EncryptionOption AES256CBCKey +) +``` + +```rest +POST https://{site_url}/_api/site/CreateMigrationJobEncrypted +{ + "options": { + "AES256CBCKey": "000000000000000000000000000000000000000000000000000000=" + }, + "gWebId": "00000000-0000-0000-0000-000000000000", + "azureContainerSourceUri": "https://tenant.blob.core.windows.net:443/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000=rw", + "azureContainerManifestUri": "https://tenant.blob.core.windows.net:443/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000=rw" +} +``` + +### CreateMigrationJob parameters + +#### gWebID + +Required. + +A **String** value that contains the unique identifier of the destination web targeted for the package import. The import package itself specifies additional information and identifiers for the import. You can programmatically find this identifier by querying the target web using CSOM calls. + +#### azureContainerSourceUri + +Required. + +A **String** value that contains the valid URI, including the SAS token, to access the Azure Blob Storage Container that contains the binary files of type block. + +See [Use Azure Blob Storage Containers and Azure Queues with SharePoint Migration API](migration-azure.md) for instructions on using Azure Blob Storage Containers in migration. + +When using content containers not provided by this method, Migration API requires `Read`, and `List` permissions only. Ensure that the start time of the SAS token is set at or before the job submission. Also, when setting the expiration time, allow a reasonable duration for the import process to complete. + +Migration API doesn't require `List` permission from containers provisioned with `ProvisionMigrationContainers` method. + +#### azureContainerManifestUri + +Required. + +A **String** value that contains the valid URI, including the SAS token, to access the Azure Blob Storage Container, which contains the block blobs for the manifest and other packages describing XML files. Migration API writes log to this container. This container can't be the same as the one used for the `azureContainerSourceUri`. + +See [Use Azure Blob Storage Containers and Azure Queues with SharePoint Migration API](migration-azure.md) for instructions on using Azure Blob Storage Containers in migration. + +When using content containers not provided by this method, Migration API requires `Read`, `List`, and `Write` permissions only. Ensure that the start time of the SAS token is set at or before the job submission. Also, when setting the expiration time, allow a reasonable duration for the import process to complete. + +#### azureQueueReportUri + +Optional. + +A **String** value that contains the valid URL, including the SAS token, to access the user-provided Azure Queue for migration job progress. Use `null` if receiving import status updates isn't necessary. + +If this value isn't `null`, and the SAS token contains the correct permissions, Migration API writes import status updates to the queue at the URL provided. + +Share the notification queue among multiple migration jobs. Migration API identifies each job with unique Job ID values in the notification queue. + +See [Azure](migration-azure.md) for instructions on using Azure Queue in migration. Check [Migration events in Azure Queue](migration-events.md) for types of events. + +Requires `Add`, `Read`, and `Update` permissions only. If the SAS token has other permissions, the migration job will be unable to add events to the queue. + +### CreateMigrationJob return value + +#### Job ID + +A **Guid** value, which contains Job ID, the unique identifier of the migration job. The method returns a `null` value, if it fails to create the job. Use Job ID to query the status of migration jobs with `GetMigrationJobStatus` method. + +### Example + +```csharp +Guid MigrationJobId = TargetSite.CreateMigrationJob( +TargetWebId, +azureContainerSourceUri, +azureContainerManifestUri, +azureQueueReportUri); +``` + +## CreateMigrationJobEncrypted method + +Creates a new migration import job with an encrypted PRIME package. + +Check the encryption instructions in [Azure](migration-azure.md) for Azure Blob Storage Container and Azure Queue encryption used. + +### CreateMigrationJobEncrypted syntax + +```csharp +public Guid CreateMigrationJobEncrypted( +Guid gWebId, +string azureContainerSourceUri, +string azureContainerManifestUri, +string azureQueueReportUri, +EncryptionOption AES256CBCKey +) +``` + +```rest +POST https://{site_url}/_api/site/CreateMigrationJobEncrypted +{ + "options": { + "AES256CBCKey": "000000000000000000000000000000000000000000000000000000=" + }, + "gWebId": "00000000-0000-0000-0000-000000000000", + "azureContainerSourceUri": "https://tenant.blob.core.windows.net:443/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000=rw", + "azureContainerManifestUri": "https://tenant.blob.core.windows.net:443/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000=rw" +} +``` + +### CreateMigrationJobEncrypted parameters + +`gWebID`, `azureContainerSourceUri`, `azureContainerManifestUri`, and `azureQueueReportUri` parameters have the same requirements as in `CreateMigrationJob` method. + +Provide `EncryptionOption` parameter as instructed below. + +#### EncryptionOption + +Required. + +A `EncryptionOption` object, containing the AES256CBCKey used to decrypt the output. + +Migration API encrypts the output with the AES256CBCKey key supplied. + +See `[EncryptionOption](https://learn.microsoft.com/en-us/dotnet/api/microsoft.sharepoint.client.encryptionoption)` class for details. + +### CreateMigrationJobEncrypted return value + +See Return value in `CreateMigrationJob` method. + +## GetMigrationJobStatus method + +> [!IMPORTANT] +> Use [GetMigrationJobProgress API](migration-job-progress-api-reference.md) to retrieve migration job status. Deprecation of GetMigrationJobStatus API is planned for the second half of 2026. Until then, it will remain available for status retrieval. + +Retrieves the processing status for a designated migration job. + +Migration API removes completed migration jobs from the timer job queue. Check the notification queue and/or log outputs for import results. + +### GetMigrationJobStatus syntax + +```csharp +[ClientNS.ClientCallableMethod] +public SPMigrationJobState GetMigrationJobStatus(Guid MigrationJobId) +``` + +### GetMigrationJobStatus parameters + +#### ID + +Required. + +A **Guid** value, which contains the migration Job ID, is returned from `CreateMigrationJob`. + +### GetMigrationJobStatus return value + +A `SPMigrationJobState` object, which contains the status of the migration job. + +### GetMigrationJobStatus example + +```csharp +SPMigrationJobState CurrentJobState = TargetSite.GetMigrationJobStatus(MigrationJobId); +``` + +## SPMigrationJobState enumeration + +Contains members representing the status of migration jobs in the import queue. + +### SPMigrationJobState members + +#### None + +Value: 0 + +The queue doesn't contain the migration job with the Job ID. The possible reasons are: + +- Migration API has completed the job and removed it from the queue. +- The Job ID is invalid. + +#### Queued + +Value: 2 + +The queue contains the migration job. Migration API isn't processing the job. + +#### Processing + +Value: 4 + +The queue contains the migration job. Migration API is processing the job. diff --git a/docs/apis/migration-api-shared.md b/docs/apis/migration-api-shared.md index 42aa9660d..dfcc26fd9 100644 --- a/docs/apis/migration-api-shared.md +++ b/docs/apis/migration-api-shared.md @@ -2,9 +2,9 @@ title: "SPO Migration API: Migrating shared files and folders" description: "Migrating shared files and folders using item references." ms.date: 06/28/2022 -ms.author: jhendr -author: JoanneHendrickson -manager: pamgreen +ms.author: jihongzuo +author: shiongzuo +manager: Dan.Podeanu ms.topic: article ms.subservice: migration-tool --- @@ -34,26 +34,32 @@ Add a SharedWithMember block for each person that the item was shared with durin - ``` + ## Best Practices + ### The basics + For each file or folder that was shared with a user in the source, create an item reference for that item in the recipient’s OneDrive. Every item reference created will appear in the user’s *Shared with Me* view in OneDrive. Remember to give the user permission to access the item as well. ### Inheritance + Be sure to use inheritance correctly for sharing. When creating an item reference for a file or folder, check if its parent folder (or higher) already has an item reference created for it. If so, do not create another one for the child item. This will prevent users from seeing duplicate items in their *Shared with Me* view and reduce migration and service load as well. -**Example:** When a folder is shared and the recipient can access all of the folder’s contents, an item reference should *only* be created for the shared folder -- not for its contents. The only item that should appear in the recipients *Shared with Me* is the shared folder. +**Example:** When a folder is shared and the recipient can access all of the folder’s contents, an item reference should *only* be created for the shared folder -- not for its contents. The only item that should appear in the recipient's *Shared with Me* is the shared folder. -This same guidance should also be used for permissions (ACLs). Only apply permissions on a child item where the required permissions are different than its parent item. Make sure not to exceed 5000 unique ACLs on a site. It may be useful to check how many ACLs you create and warn the user prior to migration. There is also a hard limit of 50,000 unique ACL's that will be enforced. If you are close to reaching the 5000 limits, we recommend that the permission model be simplified on the source before migration. +This same guidance should also be used for permissions (*access control lists, also known as ACLs*). Only apply permissions on a child item where the required permissions are different than its parent item. Make sure not to exceed 5000 unique ACLs on a site. It may be useful to check how many ACLs you create and warn the user prior to migration. There is also a hard limit of 50,000 unique ACLs that will be enforced. If you are close to reaching the 5000 limits, we recommend that the permission model be simplified on the source before migration. ### Sharing with groups + For items shared with a group of individuals in the source, the content may be migrated into a shared library (eg. a team site) in which all of those individuals are given access. ### Anonymous sharing links + Do not migrate anonymous sharing links from the source; this is not useful as it’s not possible to know which users used that link in the source. Users should evaluate whether anonymous links are still needed and create new ones on the destination if so. ### Sharing with external users + Before starting migration, you must ensure all users are provisioned in the customer tenant. For users external to the tenant (ie. from a different organization), provision them as B2B collaboration users in Azure Active Directory. This is done in the Azure portal following these steps: - [Add Azure Active Directory B2B collaboration users in the Azure portal](/azure/active-directory/b2b/add-users-administrator). @@ -61,7 +67,8 @@ Before starting migration, you must ensure all users are provisioned in the cust Once the external users are provisioned, share files and folders with them during migration the same way as internal users. ### Permission and Sharing -The per user sharing model in SharePoint relies on both permissions and “Shared With” data references for an object to be considered shared with an individual. If a user has access to content, but no “Shared With” references, they will not see the content show up in their Shared With Me view within their OneDrive For Business site. + +The per-user sharing model in SharePoint relies on both permissions and “Shared With” data references for an object to be considered shared with an individual. If a user has access to content, but no “Shared With” references, they will not see the content show up in their Shared With Me view within their OneDrive For Business site. However, if they are indicated in “Shared With” references but do not have any access to the content, they will either never see the content show up in their Shared With Me view within their OneDrive For Business site or when they try to use a link from there it will be denied access. To preserve sharing information, both the permissions and “Shared With” references will need to be correctly set. The permissions can be set at different levels of the content hierarchy using scopes (unique ACLs), that apply to that object and any of its children unless they themselves have unique permissions. @@ -71,3 +78,7 @@ Permissions migration is performed using the DeploymentRoleAssignments object wi > [!NOTE] > The **Migration API** is not available for users of Office 365 operated by 21Vianet in China. + +### Quota + +Do not migrate more than 1,000 *Share with Me* events for any receiver within 24 hours. If a receiver already has 1,000 *Share with Me* events being imported within 24 hours, they will NOT receive any additional *Share with Me* events during the time window. And Import API will send back warning messages indicating some *Share with Me* events have been throttled. diff --git a/docs/apis/migration-api-video-transcripts.md b/docs/apis/migration-api-video-transcripts.md new file mode 100644 index 000000000..324d77d57 --- /dev/null +++ b/docs/apis/migration-api-video-transcripts.md @@ -0,0 +1,66 @@ +--- +title: "Exporting video transcripts when using the SharePoint Import Migration API" +description: "Learn how to export videos that contains a transcript as an alternate content stream." +ms.date: 06/30/2023 +ms.author: jhendr +author: JoanneHendrickson +manager: serdars +search.appverid: MET150 +ms.subservice: migration-tool +--- + +# How to export video transcripts using the SharePoint Important Migration API + +Transcripts of video files, like those in Teams meeting recordings, are stored in a format similar to a zip file. If you are migrating videos from one source to another, you must use a new flag to ensure the entire zip file is migrated to the destination. Otherwise, you will inadvertently leave behind the alternate content stream, the transcript. + +## Step 1: Check if the file contains alternate content streams + +1. Check to see if the SPFile object has the property **SPFile.HasAlternateContentStreams**. Use the [REST or CSOM API](/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest) to fetch this property value. +3. If set to **True**, the file contains alternate content streams. + + +***Example:*** + +```powershell + +GET https://{site_url}/_api/web/GetFileByServerRelativeUrl(‘/serverrelativeurl’)/HasAlternateContentStreams + +``` + +## Step 2: Download the file with alternate content streams + +A zip formatted stream including primary and alternate streams can be downloaded if the file request includes **SPOpenBinaryOptions.GetAsZipWithAltStreamsIfAvailable**. + +1. Use [REST or CSOM API](/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest) to download the zip formatted content stream. +2. You must include **SPOpenBinaryOptions.GetAsZipWithAltStreamsIfAvailable**. If this is not specified, only the primary file content stream is returned. + +***Example:*** + +```powershell + +GET https://{site_url}/_api/web/GetFileByServerRelativeUrl(‘/serverrelativeurl’)/OpenBinaryStreamWithOptions(openOptions=1048576) + +``` +Note: In the example above, "1048576" corresponds to the integer value of enum *SPOpenBinaryOptions.GetAsZipWithAltStreamsIfAvailable*. + +## Step 3: Import the file with alternate content streams + +Use the Migration API to import the zip formatted stream for a file with alternate content streams to SPO. The main steps involved are: + + +1. Upload the zip formatted stream downloaded with *SPOpenBinaryOptions.GetAsZipWithAltStreamsIfAvailable* as the primary file to the Azure location. +2. When preparing the migration Manifest .xml file, add the property **vti_hasAlternateContentStreams** to the SPFile object with the value of **TRUE**. +3. Call the Migration API as normal. Internally, SPO will unzip the provided content stream and set the primary file stream and associated alternate content streams correctly. +4. After the import, verify the property **SPFile.HasAlternateContentStreams** to confirm if it’s set to **True**. + +***Example:*** + +```powershell + + + + + + + +``` diff --git a/docs/apis/migration-api-whats-new.md b/docs/apis/migration-api-whats-new.md index f6b50802c..aec43a338 100644 --- a/docs/apis/migration-api-whats-new.md +++ b/docs/apis/migration-api-whats-new.md @@ -1,7 +1,7 @@ --- title: "Migration API What's new" description: "Learn about the new features and updates to the Migration API." -ms.date: 11/20/2022 +ms.date: 09/26/2023 ms.reviewer: jhendr author: JoanneHendrickson ms.author: jhendr @@ -16,9 +16,55 @@ ms.custom: admindeeplinkSPO Check here to see what features or updates have been added to the Migration API. Here's a summary of what's included. -## New requirement +## Encoding invalid XML characters -Beginning January 1, 2023, the SourceType field will be mandatory when calling the Migration API. Starting October 1st, 2022, a warning message will be sent if the field is missing. +When invalid XML characters are detected in relevant fields, they're encoded. For any attribute that is XML encoded, decoding is needed for the value. Encoded fields are included in `EncodedAttributes`, in a comma-separated attribute list. + +**Example** + +In this example, these attributes are encoded: URL, ParentWebURL, Name, and Version. + +```xml + +``` + +>[!Warning] +>If XSD is replied on to parse manifest files, parsing may fail when **EncodedAttributes** is used. + + +## Updated reason code and descriptions + +We have updated Migration API to provide detailed reasons in case a job is postponed. We encourage ISVs take appropriate actions, based on the reasons. + +|Possible reasons |Code|Description| +|:-----|:-----|:-----| +|JobInQueue:Resource|1,2,3,4, 5, 6, 12|The job is now in a queue for resource allocation. It is expected to start in [P75] time.| +|JobInQueue:DBMaint|7|The destination tenant's database is currently in maintenance. The job is in a queue to be executed when the maintenance is completed. We expect the maintenance to be completed at [P75] time.| +|JobFailure:TenantBlock|10|Migration is blocked at the destination tenant. The job is cancelled. Please check tenant status before resubmitting.| +|JobCancelled:Unknown|11|The migration job is canceled for unknown reason.| + + +## New: Speed up small file migration + +The migration package includes multiple files, which are each uploaded/downloaded individually. If you have a large number of small-sized files, migration speed drops dramatically. By using the new **ArchivedFiles.XML** file in your prime package you can transfer files in batch resulting in a faster migration. [Learn more about using the ArchivedFiles.XML](/sharepoint/dev/apis/migration-api-overview#archivedfilessxml) + +## SourceType field required + +Beginning April 1, 2023, the SourceType field is mandatory when calling the Migration API. Starting October 1st, 2022, a warning message will be sent if the field is missing. To learn more, including examples, see: **[SharePoint Import Migration API - ExportSettings.xml](/sharepoint/dev/apis/migration-api-overview#exportsettingsxml)** diff --git a/docs/apis/migration-azure.md b/docs/apis/migration-azure.md new file mode 100644 index 000000000..3dddc87b8 --- /dev/null +++ b/docs/apis/migration-azure.md @@ -0,0 +1,149 @@ +--- +title: "Use Azure Blob Storage Containers and Azure Queues with SharePoint Migration API" +description: "This article provides in-depth information on how to use the SharePoint Migration API with Azure Containers and Queues." +ms.date: 07/03/2024 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- + +# Use Azure Blob Storage Containers and Azure Queues with SharePoint Migration API + +Use Azure Blob Storage Containers to store contents, manifest files, and logs. Access migration status updates with Azure Queues. + +This guide provides provisioning, permission, and other requirements with SharePoint-provided Azure resources. + +## Azure Blob Storage Containers + +Migration API uses Azure Blob Storage Containers for temporary storage of content and manifest. SharePoint provides default containers for migration. Alternatively, you can provide your own containers. + +### Using SharePoint-provided containers + +SharePoint-provided containers have no extra cost to the customer. Provision SharePoint-provided containers with `ProvisionMigrationContainers` method, without the need to manually set up in the Azure admin console. + +Migration API provisions the containers in the same datacenter of the SharePoint instance. Migration API uses a container exclusively once for each request, to ensure security. + +Migration API destroys Used containers 30-90 days after completing migration jobs. + +#### Avoid throttling by decorating the traffic + +Avoid throttling by [decorating your HTTP traffic](/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online#how-to-decorate-your-http-traffic). + +#### Encryption + +The contents stored in SharePoint-provided containers are encrypted at rest with AES256CBC algorithm. This practice is mandatory. Migration API rejects migration jobs generated from unencrypted SharePoint-provided containers. + +This encryption requirement doesn't apply to user-provided containers. + +When using `CreateMigrationJobEncrypted` method, encrypt each file with AES CBC 256 standard as the encryption algorithm. + +Use the `AesCryptoServiceProvider.GenerateIV` method to generate a unique cryptographically random IV for each file, including the manifests in the package. Store the IV as a property on each file. + +##### Name + +IV + +##### Value + +A `BASE64` encoded **Byte Array** of the generated IV + +#### ProvisionMigrationContainers method + +Provisions new SharePoint-provided migration containers for content and manifest. + +##### Syntax + +```csharp +public SPProvisionedMigrationContainersInfo ProvisionMigrationContainers() +``` + +##### Return values + +An `SPProvisionedMigrationContainersInfo` object, containing the URI, access tokens, and encryption key of the provisioned containers. + +###### DataContainerUri value + +A **Uri** value containing the URI of the newly created container for storing migration **content**, along with the SAS access token. + +Pass this value to `CreateMigrationJob` method as `azureContainerSourceUri` parameter. + +The SAS access token contains `Read` and `Write` permissions only. It doesn't contain `List`. + +SharePoint enforces HTTPS connections to containers by setting `spr=https` field in SAS tokens. + +###### MetadataContainer value + +A **Uri** value containing the URI of the newly created container for storing **manifest** files, along with the SAS access token. + +Pass this value to `CreateMigrationJob` method as `azureContainerManifestUri` parameter. + +The SAS access token contains `Read` and `Write` permissions only. It doesn't contain `List`. + +SharePoint enforces HTTPS connections to containers by setting `spr=https` field in SAS tokens. + +###### EncryptionKey + +A **Byte Array** value containing the AES256CBC encryption key for both containers provisioned. + +### Use your own containers + +You can also provide your own Azure Blob Storage Containers. Provide the URI with SAS access tokens as required in the Migration API reference. + +## Azure Queues + +SharePoint-provided Azure Queues have no extra cost to the customer. Provision the queue with `ProvisionMigrationQueue` method, without the need to manually set up in Azure admin console. + +Migration API provisions Azure Queues in the same datacenter of the SharePoint instance. + +Alternatively, use user-provided Azure Queues if desired. Check the requirement in the Migration API Reference document. + +### Azure Queue Encryption + +`CreateMigrationJobEncrypted` method encrypts the messages written to the Azure Queue. + +To decrypt the messages, make sure you preserve `JobId` and the `IV` values returned by `CreateMigrationJobEncrypted` method. + +#### Encrypted message sample + +```json +{"Label": "Encrypted"}, +{"JobId": "[JobId value]"}, +{"IV": "[IV value, encoded in BASE64]"}, +{"Content": "[encrypted message, encoded in BASE64]"} +``` + +### ProvisionMigrationQueue method + +Provisions a new instance of Azure Queue for migration use. + +#### ProvisionMigrationQueue Syntax + +```csharp +public SPProvisionedMigrationQueueInfo ProvisionMigrationQueue() +``` + +#### Return value + +A `SPProvisionedMigrationQueueInfo` object containing the information of the newly created Azure Queue. + +##### JobQueueUri value + +A `Uri` value containing the URI and SAS access token of the newly created Azure Queue. + +Pass this value to `CreateMigrationJob` method's `azureQueueReportUri` parameter. + +## Use endpoints in Azure Government + +Use Azure Government endpoints for Microsoft 365 Government. + +### Required endpoints in Azure Government + +- `https://*.blob.core.usgovcloudapi.net` +- `https://*.queue.core.usgovcloudapi.net` diff --git a/docs/apis/migration-content-package.md b/docs/apis/migration-content-package.md new file mode 100644 index 000000000..6de44cbfe --- /dev/null +++ b/docs/apis/migration-content-package.md @@ -0,0 +1,113 @@ +--- +title: "Preparing the content for Migration API" +description: "This article provides in-depth information on how to use create and use content packages with SharePoint Migration API" +ms.date: 04/18/2024 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- + +# Preparing the content for Migration API + +Use this document to prepare the contents to migrate with SharePoint Migration API. + +## Files and folders + +### File and package size limits + +Migration API supports importing files with sizes up to 15 GB (the limit set by SharePoint). + +For the best performance, keep the package size under 250 MB or 250 items. + +For larger files, create a package for the individual file. + +### File versions + +Migration API supports importing multiple versions of a file, including major and minor, up to the limit set by SharePoint. + +Each version of the file counts against the file size limit and item count limit. + +Include each version of the file, even if some of the versions already exist in SharePoint. + +### File overwriting + +Migration API deletes the original file along with all the versions, then replaces it with all versions of the resubmitted file, when a file is resubmitted. + +### No decryption + +Migration API doesn't decrypt contents. It treats any encrypted content as opaque files. While SharePoint lists these files, it doesn't index them. This behavior is the same as when a user uploads encrypted files through the SharePoint UI. + +### File compression + +Migration API doesn't decompress packages by default. Don't compress content and manifest packages together. Make sure you store the content package and the manifest package in different Azure Storage Blob Containers. + +Migration API imports **\*.zip** files as compressed archive files if referenced in the import package as the archive itself. To import the individual files within the **\*.zip** file, see [Archive Small Files](#archive-small-files-for-performance). + +### Archive small files for performance + +Migrate small files in batches for improved performance. Migration API **optionally** uncompresses a compressed **\*.zip** archive to improve the performance, based on manifest in **ArchivedFiles.xml**. + +Include `QuickXorHash` value of the archive when using this feature. Compute it with [QuickXorHash Algorithm](/onedrive/developer/code-snippets/quickxorhash). + +Migration API processes non-archived files in **Manifest.xml** without manifest in **ArchiveFiles.xml** as usual. + +This feature requires all the following prerequisites: + +#### Archive file size limit + +10 MB maximum. + +#### Archive file per package + +Two maximum. + +#### Archive file encryption + +Required. + +#### Individual file size + +Less than 100 kb after encryption. + +#### Don't compress individual files + +**Don't compress** the individual files, only compress the archive. + +## SharePoint Events and Event Handlers + +Migration API allows referencing Event Handlers on List Items. However, Migration API doesn't support defining new Event Handlers at the List level. + +Migration API doesn't generate Events when importing items. Therefore, existing Event Handlers don't fire during import. + +## Azure Containers + +### Azure Blob Storage Security Model + +Migration API uses Azure Blob Storage security model. There's no special treatment for Azure Blob Storage Containers used for Migration API that would differentiate from a standard container. + +### Snapshot + +Each file in the container must have at least one snapshot created. Avoid modifying the file during the import. Any file without a snapshot fails to import with errors. Migration API uses the latest snapshot of the file available at the time of import. + +To create a snapshot of a file after uploading to the Azure Blob Storage, use the following code: + +```csharp +CloudBlockBlob blob = blobContainerObj.GetBlockBlobReference(file); +blob.UploadFromStream(stm); +blob.CreateSnapshot(); +``` + +### Permissions + +To ensure the immutability of source blobs, Migration API accepts an SAS key with only `Read` and `List` access flags set for the content package container. + +Likewise, Migration API accepts a SAS key with only `Read`, `List`, and `Write` access for the Manifest container. Migration API requires the `Write` access for writing backlog files at the end of the import. + +Migration API checks SAS keys for these required access flags. Migration API rejects attempts to create migration jobs with incorrect access flags on SAS keys. diff --git a/docs/apis/migration-events.md b/docs/apis/migration-events.md new file mode 100644 index 000000000..dcd8c2209 --- /dev/null +++ b/docs/apis/migration-events.md @@ -0,0 +1,269 @@ +--- +title: "Migration events in Azure Queue" +description: "This article provides in-depth information on how to use Azure Queue events in migration." +ms.date: 04/18/2024 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- +# Migration events in Azure Queue + +This document lists all types of events Migration API and AMR API written to the Azure Queue. Use these events to get status updates on migration jobs. + +## JobQueued + +```log +JobId:845daca4-5529-4b0e-85ab-a603efee5b12 +Time:09/29/2020 19:56:02.883 +SiteId:48917234-de43-474a-9f1b-8d98ffa08425 +DbId:8fd09323-b23f-430d-8957-213586ce3861 +TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +CorrelationId:c8d97e9f-802f-0000-ceac-44663834d510 +``` + +## JobPostponed + +```log +JobId:845daca4-5529-4b0e-85ab-a603efee5b12 +Time:09/29/2020 19:56:57.598 +NextPickupTime:09/29/2020 20:16:57.519 +SiteId:48917234-de43-474a-9f1b-8d98ffa08425 +DbId:8fd09323-b23f-430d-8957-213586ce3861 +JobsInQueue:TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +CorrelationId:d5d97e9f-702c-0000-ceb9-354fefa5e9f6 +``` + +## JobLogFileCreate + +```log +JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecdTime:09/29/2020 19:56:29053 +FileName:Import-071f9aad-36e6-4bef-9f09-40b5c7498ecd-1.log +CorrelationId:22ca20ec-23de-468b-add3-4e52e90d3a68 +JobStart +JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecdTime:09/29/2020 19:56:29:100 +SiteId:48917234-de43-474a-9f1b-8d98ffa08425 +WebId:36b66979-4a43-4b93-9b92-909c7186ff98 +DBId:8fd09323-b23f-430d-8957-213586ce3861 +FarmId:211e600c-f48d-4319-ba92-61150c8e8e8c +ServerId:cfd27448-822a-420b-bcc8-4f39629b01bc +SubscriptionId:51812136-3cba-482d-9696-532cddceab31 +TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +CorrelationId:c308c0ea-a7f5-4be9-acd4-1ebd39867434 +``` + +## JobProgress + +```log +JobId:845daca4-5529-4b0e-85ab-a603efee5b12 +Time:09/29/2020 19:56:32.265 +FilesCreated:15 +BytesProcessed:45 +ObjectsProcessed:217 +TotalExpectedSPObjects:403 +TotalErrors:0 +TotalWarnings:0 +TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +WaitTimeOnSqlThrottlingMilliseconds:0 +TotalDurationInMs:0 +CpuDurationInMs:0 +SqlDurationInMs:0 +SqlQueryCount:0 +CreatedOrUpdatedFileStatsBySize: +{ + "0-1K": { + "Count": 15, + "TotalSize": 45, + "TotalDownloadTime": 251, + "TotalCreationTime": 6754 + } +} +ObjectsStatsByType: +{ + "SPUser": { + "Count": 1, + "TotalTime": 289, + "AccumulatedVersions": 0, + "ObjectsWithVersions": 0 + }, + "SPFolder": { + "Count": 2, + "TotalTime": 144, + "AccumulatedVersions": 0, + "ObjectsWithVersions": 0 + }, + "SPDocumentLibrary": { + "Count": 1, + "TotalTime": 173, + "AccumulatedVersions": 0, + "ObjectsWithVersions": 0 + }, + "SPFile": { + "Count": 200, + "TotalTime": 6765, + "AccumulatedVersions": 0, + "ObjectsWithVersions": 0 + }, + "SPListItem": { + "Count": 14, + "TotalTime": 2111, + "AccumulatedVersions": 0, + "ObjectsWithVersions": 0 + } +} +TotalExpectedBytes:0 +CorrelationId:ccd97e9f-a0cc-0000-ceb9-37a900bec68d +``` + +## JobEnd (Import) + +```json +{ +"Event": "JobEnd", +"JobId": "aed28dcc-efc3-46c3-89f2-b5df71ccfe85", +"Time": "04/11/2024 14:51:53.531", +"FilesCreated": "5", +"BytesProcessed": "260999", +"ObjectsProcessed": "6", +"TotalErrors": "2", +"TotalWarnings": "0", +"FilesCreatedIrrespectiveOfVersions": "1", +"BytesProcessedOnlyCurrentVersion": "111001" +} +``` + +### **FilesCreatedIrrespectiveOfVersions** property + +An integer. + +The number of files created, exclusive of file versions. If a file has multiple versions, this count increases by 1 only when all the versions are migrated. + +List items aren't counted in this property. + +### **BytesProcessedOnlyCurrentVersion** property + +An integer. The bytes are processed with the last version of the file. If a file has multiple versions, this byte count increases only when all the versions are migrated. + +List items aren't counted in this property. + +## JobEnd (AMR) + +AMR API generates `JobEnd` event with estimation of item counts in `TotalExpectedSPObjects` field: + +```log +Event:JobEnd +JobId:e915f93a-b377-476e-995c-952fd28c0a12 +Time:11/28/2023 13:41:06.109 +FilesCreated:182 +BytesProcessed:441084014 +ObjectsProcessed:425 +TotalExpectedSPObjects:425 +TotalErrors:2 +TotalWarnings:0 +TotalRetryCount:0 +MigrationType:AsyncRead +MigrationDirection:Export +``` + +## JobDeleted + +```log +JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecd +Time:09/29/2020 19:56:29.053 +CorrelationId:22ca20ec-23de-468b-add3-4e52e90d3a68 +``` + +### JobCancelled + +```log +JobId:071f9aad-36e6-4bef-9f09-40b5c7498ecd +Time:09/29/2020 19:58:29053 +TotalRetryCount:0 +CancelledByUser:false +MigrationType:None +MigrationDirection:Import +CorrelationId:22ca20ec-23de-468b-add3-4e52e90d3a68 +``` + +## JobError + +```log +JobId:b427d8d7-2b91-4da0-aee5-4b5a5a5d867e +Time: 02/05/2019 06:56:09.732 +TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +ObjectType:File +Url:Shared Documents/file.pdf +Id:fae7b4b0-2912-11e9-b0f3-7b554a52d6ab +ErrorCode:-2147024816 +ErrorType:Microsoft.SharePoint.SPException +Message:ErrorMessage +CorrelationId:d8e9bc9e-20e2-8000-aa83-48a62fc5ce75 +``` + +## JobFatalError + +```log +JobId:8f728c13-95d0-4d54-96bc-4ee912bd32ce +Time: 02/05/2019 06:57:20.523 +TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +ObjectType: +Url: +Id: +ErrorCode:-2147213196 +ErrorType:Microsoft.SharePoint.SPException +Message:ErrorMessage +CorrelationId:b370d5a0-105d-4000-241f-9b2d70449d7b +``` + +## JobWarning + +```log +JobId:b427d8d7-2b91-4da0-aee5-4b5a5a5d867e +Time: 02/05/2019 06:56:09.732 +TotalRetryCount:0 +MigrationType:None +MigrationDirection:Import +ObjectType:File +Url:Shared Documents/file.pdf +Id:fae7b4b0-2912-11e9-b0f3-7b554a52d6ab +ErrorCode:-2147024816 +ErrorType:Microsoft.SharePointSPException +Message:ErrorMessage +CorrelationId:d8e9bc9e-20e2-8000-aa83-48a62fc5ce75 +FinishManifestFileUpload +JobId:b427d8d7-2b91-4da0-aee5-4b5a5a5d867e +Time:02/05/2019 06:56:09.732 +ManifestFileName:Filename +CorrelationId:d8e9bc9e-20e2-8000-aa83-48a62fc5ce75 +``` + +## FinishManifestFileUpload + +Indicates that AMR API exported metadata. Find exported manifest files in the Azure Blob Storage Container supplied. The event also contains the location and file names of the exported files. + +### Example + +```json +{"Event", "FinishManifestFileUpload"}, +{"JobId", “f8d7d577-676e-47ce-ab69-ae7803979883”}, +{"Time", “2019-09-03T19:11:33.903”}, +{"ManifestFileName", “f8d7d577-676e-47ce-ab69-ae7803979883/ExportSettings.xml”} +``` diff --git a/docs/apis/migration-job-progress-api-reference.md b/docs/apis/migration-job-progress-api-reference.md new file mode 100644 index 000000000..d6f6eff66 --- /dev/null +++ b/docs/apis/migration-job-progress-api-reference.md @@ -0,0 +1,171 @@ +--- +title: "SharePoint Migration Job Progress API" +description: "This article explains how to retrieve migration job status with GetMigrationJobProgress API." +ms.date: 06/15/2025 +ms.author: jihongzuo +author: shiongzuo +manager: dapodean +audience: ISV +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- +# SharePoint GetMigrationJobProgress API + +After submitting a migration job—whether an import job or an Asynchronous Metadata Read (AMR) job—you can use the GetMigrationJobProgress API to track its progress. The API is available via both SDK and REST interfaces. + +It returns a sequence of job status events, including: JobQueued, JobStart, JobProgress, JobError, and JobEnd. + +## Permissions + +Use application-based authentication when submitting a migration job. Ensure the application is granted the Sites.Read.All permission or higher. + +## GetMigrationJobProgress Method (SDK) + +### Syntax + +```csharp +public ClientResult Site.GetMigrationJobProgress( + Guid jobId, + String nextToken +) +``` + +### Method Parameters + +| Name | Type | Required | Description | +| :--------- | :------- | :------- | :----------------------------------------------------- | +| jobId | Guid | Yes | Unique identifier of the migration job | +| nextToken | String | Yes | Token for paging position. Use "0" for initial request | + +For a completed job, requests using nextToken are idempotent—repeating the same request will consistently return the same result. + +### Return Values + +| Name | Type | Description | +| :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------ | +| Logs | IList | Returns a collection of job status events when new progress is available, or an empty collection if there are no updates. | +| NextToken | String | Returns an updated string value when new progress is available, or the same value as the nextToken parameter if there are no updates. | + +### Method Usage Example + +```csharp +ClientResult result = context.Site.GetMigrationJobProgress(jobId, nextToken ?? "0"); +context.ExecuteQuery(); +IList logs = result.Value.Logs; +string newNextToken = result.Value.NextToken; +``` + +## GetMigrationJobProgress REST API + +### HTTP Request + +```http +GET https://{site_url}/_api/site/GetMigrationJobProgress(jobId='{jobId}',nextToken=0) +``` + +### URI Parameters + +| Name | Type | Required | Description | +| :--------- | :------- | :------- | :----------------------------------------------------- | +| jobId | Guid | Yes | Unique identifier of the migration job | +| nextToken | String | Yes | Token for paging position. Use "0" for initial request | + +### Request Headers + +| Header | Required | +| :------------------------------------- | :------- | +| Authorization: Bearer {token} | Yes | +| Accept: application/json;odata=verbose | Yes | + +### Response + +A JSON object when the HTTP status code is 200. + +An empty JSON object when the HTTP status code is other than 200. + +### Error Handling + +| Status Code | Meaning | Action | +| :---------- | :------------- | :---------------------------------------------------------------------- | +| 403 | Unauthorized | Ensure the app/user has at least Sites.Read.All permissions. | +| 429 | Too Many Requests | Parse Retry-After header and retry after the specified delay. | +| 500 | Internal Server Error | Parse error responses to identify internal errors. Do Not Retry. | +| 503 | Service Unavailable | Parse Retry-After header and retry after the specified delay. | + +| Internal Error Code | Meaning | +| :------------------ | :---------------------------------------------- | +| -2147213145 | Job not found | +| -2147213146 | Job status expired (valid for less than 5 days) | + +### API Usage Example + +#### Request Sample + +```http +GET https://contoso.sharepoint.com/_api/site/GetMigrationJobProgress(jobId=' 3e280efa-78a3-4ba1-bac6-e447aa538ca5', nextToken=0) +``` + +#### Successful Response Sample + +Status code: 200 +Response body: + +```json +{ + "d": { + "GetMigrationJobProgress": { + "Logs": { + "__metadata": { + "type": "Collection(Edm.String)" + }, + "results": [ + "{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"SiteId\":\"48f1898f-77d9-4a1b-bddc-1f49bb6dc134\",\"DbId\":\"de6b85cd-726e-4b13-ae04-629798fddbf3\",\"TotalRetryCount\":\"0\",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:18:48.132\",\"CorrelationId\":\"91884a0c-5ee8-4e1f-a23f-e4f7ec170182\",\"Event\":\"JobQueued\"}", + "{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"SiteId\":\"48f1898f-77d9-4a1b-bddc-1f49bb6dc134\",\"WebId\":\"7206fc09-e4af-48b3-8730-ed7321396d7a\",\"DbId\":\"de6b85cd-726e-4b13-ae04-629798fddbf3\",\"FarmId\":\"f77d7b6c-ef43-4609-8fce-0e93142ce8a0\",\"ServerId\":\"44af885c-393b-4236-9417-bae7a9edc44e\",\"SubscriptionId\":\"82abb045-250e-4186-ba83-b9295930f272\",\"TotalRetryCount\":\"0\",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:20:51.129\",\"CorrelationId\":\"7d3e7a8e-4445-4ce0-adb1-078e78cbf686\",\"Event\":\"JobStart\"}", + "{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"TotalRetryCount\":\"0\",\"ObjectType\":\"ListItem\",\"Url\":\"\",\"Id\":\"cb471d5f-593f-4a63-b59e-8eae3e35b08a\",\"SourceListItemIntId\":\"3\",\"TargetListItemIntId\":\"3\",\"ErrorCode\":\"-2147286782\",\"ErrorType\":\"Microsoft.SharePoint.SPException\",\"Message\":\"Attempted to use an object that has ceased to exist. (Exception from HRESULT: 0x80030102 (STG_E_REVERTED)) \",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:20:55.490\",\"CorrelationId\":\"7d3e7a8e-4445-4ce0-adb1-078e78cbf686\",\"Event\":\"JobError\"}", + "{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"TotalRetryCount\":\"0\",\"FilesCreated\":\"0\",\"BytesProcessed\":\"0\",\"ObjectsProcessed\":\"4\",\"TotalExpectedSPObjects\":\"15\",\"TotalErrors\":\"3\",\"TotalWarnings\":\"0\",\"WaitTimeOnSqlThrottlingMilliseconds\":\"0\",\"TotalDurationInMs\":\"0\",\"CpuDurationInMs\":\"0\",\"SqlDurationInMs\":\"0\",\"SqlQueryCount\":\"0\",\"IsShallowCopy\":\"False\",\"CreatedOrUpdatedFileStatsBySize\":\"{}\",\"ObjectsStatsByType\":\"{\\\"SPUser\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":124,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPFolder\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":153,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPDocumentLibrary\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":404,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPFile\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":0,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPListItem\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":1880,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0}}\",\"TotalExpectedBytes\":\"0\",\"FilesCreatedIrrespectiveOfVersions\":\"0\",\"BytesProcessedOnlyCurrentVersion\":\"0\",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:20:57.380\",\"CorrelationId\":\"7d3e7a8e-4445-4ce0-adb1-078e78cbf686\",\"Event\":\"JobEnd\"}" + ] + }, + "NextToken": "1764", + "__metadata": { + "type": "SP.MigrationJobProgress" + } + } + } +} +``` + +#### Error Response Sample + +Status code: 500 +Response body: + +```json +{ + "error": { + "code": "-2147213145, Microsoft.SharePoint.SPException", + "innererror": { + "message": "Job not found", + "stacktrace": "STACK_TRACE" + }, + "message": { + "lang": "en-US", + "value": "Job not found" + } + } +} +``` + +## Best Practice + +Begin with `nextToken=0`, store the returned token, and poll at certain intervals. This method is well-suited for long-running jobs and helps ensure no updates are missed. + +Since migration jobs typically take several minutes or more, polling every minute is advised, while adhering to the [guideline](https://aka.ms/spo429) to avoid throttling. + +## See Also + +- [SharePoint Migration API](migration-api-overview.md) +- [Migration Events](migration-events.md) diff --git a/docs/apis/migration-manifest.md b/docs/apis/migration-manifest.md new file mode 100644 index 000000000..770fd670b --- /dev/null +++ b/docs/apis/migration-manifest.md @@ -0,0 +1,405 @@ +--- +title: "Preparing the manifest for Migration API" +description: "This article provides in-depth information on how to use create and use manifest packages with SharePoint Migration API" +ms.date: 04/18/2024 +ms.author: ranren +author: underreview +manager: dapodean +audience: ITPro +ms.subservice: migration-tool +ms.topic: article +ms.localizationpriority: high +ms.collection: + - SPMigration + - m365-collaboration +--- + +# XML manifest files + +Migration API relies on XML manifest files to process the content import correctly. Create manifest files in a well-defined format. AMR API also exports metadata in this format. + +## XML Validation + +The package structure for Manifest files is based on a constrained version of [SharePoint Content Migration Schemas](/sharepoint/dev/schema/content-migration-schemas). + +## Encoding invalid XML characters + +AMR API encodes invalid XML characters in fields. Decode the attributes listed in `EncodedAttributes`. + +Migration API doesn't support invalid XML character encoding. + +### Example + +In this example, these attributes are encoded: URL, ParentWebURL, Name, and Version. + +```xml + +``` + +## Location + +Placed all manifest files at the root level of the Azure Blob Storage Container for manifest files. + +## ArchivedFiles.xml + +Optional. + +Used to process archived small files in batch. + +### ArchivedFiles.xml Example + +```xml + + + + + + + + + + + + + + + + + + + +``` + +## ExportSettings.xml + +Required. + +An XML file contains the export settings specified with the `SPExportSettings` and other classes. It also specifies the export settings, used in the subsequent import process at the migration target site. It also maintains a catalog of all objects exported to the migration package. + +### Ignore Web Parts + +Migration API checks and processes SharePoint Web Parts in certain types of files. For sources other than SharePoint Server and SharePoint Online, bypass these checks by setting `IgnoreWebParts` to `true`. This practice improves the performance of migration tasks when not migrating Web Parts. + +### Specify content source + +Migration API requires a `SourceType` value, containing the source of the content. It should contain a value from the following list: + +#### Accepted `SourceType` values + +- `AmazonS3` +- `AzureStorage` +- `Box` +- `Dropbox` +- `Egnyte` +- `FileShare` +- `GoogleCloudStorage` +- `GoogleDrive` +- `MicrosoftStream` +- `OneDrive` +- `SharePointOnline` +- `SharePointOnPremServer` +- `Other` + +When declaring to `Other`, include an extra `DetailedSource` value to provide more detail on the content source information. + +### ExportSettings.xml Example + +```xml + + + + + +``` + +## LookupListMap.xml + +Optional. + +An XML manifest file that maintains a simple lookup list, which records all SharePoint List Item references. Place it at the root of the Azure Blob Store Container defined by the `CreateMigrationJob`’s `azureContainerManifestUri` parameter. + +Not required if the import package doesn't contain Defining Fields or Views on a List or Document Library. The omission of this file generates a warning message in the log. Include a file with a childless `root` node to avoid this warning message. + +## Manifest.xml + +Required. + +An XML manifest file that contains the complete list of both the contents and the structure of the content package. Migration API uses this manifest file to reconstitute the source and its components. + +Place all instances of the **Manifest.xml** file for a package at the root of the Azure Blob Store Container. + +This manifest file is also the primary descriptor for metadata within the package, and provides the List, Folder, and Item hierarchy, along with metadata for the items including references back to users and groups defined in **UserGroupMap.xml** file. + +Use more than one **Manifest.xml** if needed. The manifests are identified with different file names. Migration API locates all manifests through references in **SystemData.xml** file’s `ManifestFile` entries. + +### Document Library/List ID consistency + +Use consistent Web ID and Document Library ID/List ID at the source and the target location. Inconsistent Web IDs generate errors as Migration API can't find the parent web for the import operation. + +Likewise, Migration API can't import items with incorrect Document Library IDs and List IDs into the target Document Library or List. Don't reuse IDs within the same site collection, to avoid Migration API importing packages to the same target site collection, regardless of the destination web. + +### GUID consistency + +To avoid GUID conflicts and import errors, use the same package for the same target. Importing a new package with the same content will cause problems. The package from a file share assigns GUIDs to files, folders, and list items. Keep the package from the file share as a record of the original GUIDs. Use the same GUIDs for later packages to avoid conflicts and track changes. + +### Preserve content identifiers + +The identifiers in the Import Packages are **explicitly** used during import to identify content. This practice preserves existing identifiers for Document Library contents. + +Reference the target Web and List identifiers **explicitly**. + +Migration API preserves content type identifiers, file/folder item GUIDs, and List Item integer identifiers during import. Import fails when Migration API encounters incorrect identifiers in the package. + +This preservation enables successive import iterations with different packages, allowing items to move locations. + +### Permission Roles + +Manifest.xml contains the following Roles-related objects: + +#### Roles object + +Contains the list of all defined Roles on the Web. + +#### Role object + +Defines a Role with ID, internal permissions rights mask flags, and display information. + +##### RoleId value + +Defines the identifiers of the Role object. + +##### PermMask value + +Contains the rights mask flags. + +#### RoleAssignments object + +Contains the list of all unique permissions (RoleAssignment objects). + +#### RoleAssignment object + +Includes the list of distinct Assignment objects (if any). + +##### Assignment object + +Contains the actual membership of one distinct User or Group and their actual Role, where + +- RoleId values map to the RoleId values of the Role objects. +- PrincipalId values map to ID values of User or Group objects respectively in **UserGroups.xml**. + +#### Permissions Example + +```xml + + … + + + + + + + + + + + + + + … + + + … + +``` + +## Requirements.xml + +Optional. + +SharePoint Server usually generates this XML manifest file. It contains a list of deployment requirements in the form of installation requirements on the migration target, such as + +- feature definitions +- template versions +- Web Part assemblies +- language packs +- and so forth. + +Include no child node under the root for file shares. The omission of this file generates a warning message in the log. + +## RootObjectMap.xml + +Optional. + +Maintains a list of mappings of secondary (dependent) objects. Migration API uses this manifest file to correctly place dependent objects. + +The most common `RootObject` included is a single object of type List. The `ID` of this item should be the List `ID` of the target list, and the `ParentWebID` should match the `ID` of the parent target web containing this list in order for migration to be successful. The `ID`, `WebUrl`, and `Url` values of this object must also match the related structure laid out in the **Manifest.xml** file. + +## SystemData.xml + +Required. + +Contains various low-level system data. It also records the number and paths of **Manifest.xml** files in the manifest package, when there are multiple manifests. + +### Versions + +`SchemaVersion` references to the current `Build` and `DatabaseVersion` of the target farm, currently “15.0.0.0”. + +`SiteVersion` should match the target site collection `UIVersion`, currently `15`. + +### Multiple Manifests + +List all **Manifest.xml** files in the package in **SystemData.xml**, as `ManifestFile` entries. + +### Immutable SystemObjects + +List all `SystemObjects` defining dependent objects that remain immutable by Migration API. + +### SystemData.xml example + +This example **SystemData.xml** file shows the common objects from a file share import. Use different `ID`s for each package, and the `URL`s may be different. + +```xml + + + + + + + + + + + + + + +``` + +## UserGroupMap.xml + +Required. + +Records Users and User Security Groups for managing permissions. Migration API uses the manifest to ascertain the membership of Users and Groups, along with their roles and specific assignments. These assignments include unique permissions set at the level of the object and its offspring, unless a deeper child object overrides them. + +User or Group entries aren't mandatory, but omission prevents author or security information from the population during import. Migration API generates warnings in such cases. + +### User identifiers + +Identify a User only once in a single package. + +Manifest all Users and Groups within the exported Web(s). + +#### User object + +Includes the information about specific Users, including identification of a specific security principle as a domain group or not, sign-in, and the base64 encoded SystemId (SID) of the security principle. + +#### Group object + +Includes the information about specific Groups and the direct membership list of that Group. + +Owner values on Group objects and UserId values on member objects within group objects map to other ID values of other User or Group objects respectively. + +The following example shows how to manifest Users and Groups. + +```xml + + + + + … + + + + + + + + + + … + + +``` + +Make sure the Sign-in and SystemId values of users match the values in SharePoint. + +### Deleted Users + +Include an `IsDeleted` value as `true` for deleted accounts. This practice prevents lookup failures in the import process, which negatively impacts performance. + +### Unresolved User identifiers + +If Migration API is unable to resolve a User with the Sign-in information, and SystemId **is not** provided, Migration API replaces this User with `System Account` in the associated metadata (such as Author or Editor) in the package and generates a warning in the import logs: + +```text +Failed to ensure user 'user@contoso.com' +``` + +If Migration API is unable to resolve a User with the Sign-in while the SystemId **is** provided, Migration API creates a new deleted User with the provided Sign-in and SystemId. Migration API uses this User with associated metadata within the package. Migration API generates a warning in the import logs: + +```text +Failed to retrieve user 'user@contoso.com' attributes from the SiteUsers; falling back to passed in values +``` + +### Avoid non-UPN email addresses in User identifiers + +The `Login` attribute of the User identifier requires a UPN. **Do not use** non-UPN email addresses. Using non-UPN email addresses causes unexpected behavior in SharePoint Online. + +### Examples + +The following examples show the correct and incorrect ways of using the User identifiers. + +In this case, the user has the following identifiers: + +- UPN: +- Email: . + +#### Correct example + +This example manifests the User only once, with a UPN email address. + +```xml + +``` + +#### Incorrect example + +This example **incorrectly** uses a non-UPN email address and **incorrectly** includes more than one identifier for a single user. + +```xml + + +``` + +This example **incorrectly** uses a non-UPN email address. + +```xml + +``` + +## ViewFormsList.xml + +Optional. + +This XML manifest file maintains a list of Web Parts and tracks whether each is a view or form. + +This file is optional if the Import Package doesn't contain Web Parts. The omission of this file generates a warning message in the log. Alternatively, include a manifest file with a childless `root` node to avoid the warning message. diff --git a/docs/apis/migration-perm-guidance.md b/docs/apis/migration-perm-guidance.md index 4e50f0406..f46fb025c 100644 --- a/docs/apis/migration-perm-guidance.md +++ b/docs/apis/migration-perm-guidance.md @@ -1,7 +1,7 @@ --- title: Migration permission guidance description: "Migration permission guidance" -ms.date: 06/28/2022 +ms.date: 03/30/2023 ms.subservice: migration-tool ms.author: jhendr author: JoanneHendrickson @@ -22,9 +22,9 @@ You need to be aware of three key numbers as you plan your migration to OneDrive ## Permissions: Inherited and unique -Inherited permissions are set as the default at the root site collection level and are applied to the other locations and objects within that site collection. Unique permissions are all other permissions that differ (or “break”) from what is set at the root. In SharePoint, you can set unique permissions all the way down to the item level. +Inherited permissions are set as the default at the root site collection level and are applied to the other locations and objects within that site collection. Unique permissions are all other permissions that differ (or "break") from what is set at the root. In SharePoint, you can set unique permissions all the way down to the item level. -Each time you break inheritance by granting access to a new user account or group at any level in a site, even on a single item, you are creating a new unique security “scope” ID. That scope is counted as a unique permission towards the total limit. A library (or list) cannot have greater than 50,000 unique security scopes. +Each time you break inheritance by granting access to a new user account or group at any level in a site, even on a single item, you create a new unique security "scope" ID. That scope is counted as a unique permission towards the total limit. A library (or list) can't have greater than 50,000 unique security scopes. ![Site hierarchy](../images/hierarchy-perms.png) @@ -33,23 +33,23 @@ When migrating, we recommend that you have less than 5,000 unique scopes per lib ## Role assignments -A role assignment is a mapping between a user, a SharePoint object (Web, list, file) and a role (Design, Full Control, Contribute, etc.). The role assignment ties together the role definition (permission level) with the specific user or group, and the scope that that permission level will be applied to (such as list, folder, item). +A role assignment is a mapping between a user, a SharePoint object (web, list, file) and a role (for example, Design, Full Control, or Contribute). The role assignment ties together the role definition (permission level) with the specific user or group, and the scope that that permission level will be applied to (such as list, folder, item). -There is a role assignment limit of 5,000 per security scope. +The maximum number of role assignments allowed per security scope is 5,000. ## Item limits -When a library (or list) contains more than 100,000 items (files and folders or list items), you cannot break permissions inheritance on the list itself. There is a limit of 100,000 items that can be updated or removed as a part of creating a new SharePoint security scope. +When a library (or list) contains more than 100,000 items (files and folders or list items), you can't break permissions inheritance on the list itself. There's a limit of 100,000 items that can be updated or removed as a part of creating a new SharePoint security scope. -If you are migrating a structure that has more than 100,000 children (such as files, folders, lists, or other object types), you need to restructure the migration by importing security in multiple phases to avoid exceeding this limit. Any VROOM invite, REST share link, or any other permission-modifying function call will trigger an HTTP 429 throttle if the threshold is reached. Permissions will not be updated. Unlike other throttles, waiting and trying again will not resolve the situation as you have reached a hard limit of 100,000. +If you're migrating a structure that has more than 100,000 children (such as files, folders, lists, or other object types), you need to restructure the migration by importing security in multiple phases to avoid exceeding this limit. Any VROOM invite, REST share link, or any other permission-modifying function call will trigger an HTTP 429 throttle if the threshold is reached. Permissions won't be updated. Unlike other throttles, waiting and trying again won't resolve the situation as you've reached a hard limit of 100,000. To learn more about the service limits in SharePoint for Microsoft 365, see [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#items-in-lists-and-libraries). -## Folders containing fewer than 100,000 items +## Folders with less than 100,000 items -If your library (or list) has fewer than 100,000 items, and you have less than 50,000 unique scopes, you can migrate using the migration API and apply unique scopes to create folders with less 100K items to break inheritance as needed. +If your library (or list) has fewer than 100,000 items, and you have less than 50,000 unique scopes, you can migrate using the Migration API and apply unique scopes to create folders with fewer 100-K items to break inheritance as needed. -## Folders containing more than 100,000 items +## Folders with more than 100,000 items If you have a folder with more than 100,000 items, we recommend one of the following approaches. Determine how many items are in your source or root folder, including lists or other object types. Scan and determine which folder structures have greater than 100,000 items. @@ -57,30 +57,30 @@ If you have a folder with more than 100,000 items, we recommend one of the follo The first option is to restructure your *source* layout. -For example, divide a single folder of 250,000 items into four folders at the root so each folder has less than 100,000 items. There is still “room to grow”, presuming users will continue to add content and make changes here. +For example, divide a single folder of 250,000 items into four folders at the root so each folder has less than 100,000 items. There's still "room to grow", presuming users will continue to add content and make changes here. Make sure that there are no more than 50,000 unique scopes in the structure: ideally less than 5,000. -In this example, at the source, break up the structure into four folders, A, B, C, and D, each having less than 100,000 items. Then perform the migration. See the illustration below. +In this example, at the source, break up the structure into four folders, A, B, C, and D, each having less than 100,000 items. Then perform the migration. For details, see the following illustration. ![Hierarchy ABCD](../images/hierarchy-ABCD.png) > [!NOTE] -> There are other limits that must be considered during migration. See [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#items-in-lists-and-libraries) for details. +> There are other limits that must be considered during migration. For details, see [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#items-in-lists-and-libraries). ### Method 2: Create your destination layout to avoid exceeding limits The alternate approach is to keep your source layout, applying unique scopes at the destination before migration. **Example:** Your source folder has 250,000 items within it. At your target location, create folders A, B, C, and D and apply the unique scopes and scope ID. This will break inheritance. Then proceed with your content migration. -If you do not want your end users to share items until migration is completed, use the Migration API to migrate the content & scopes, but set the scope to NULL to prevent any use. +If you don't want your end users to share items until migration is completed, use the Migration API to migrate the content and scopes, but set the scope to NULL to prevent any use. After all the content and incremental migrations are completed, apply the proper scope. After the incremental migration has completed, and only if you previously set the scope to NULL, you can reapply the unique scope for folders A, B, C, D separately. When you reapply the scope, evaluate your folder size starting at the lowest level of hierarchy. -## Other Sharing/Permission related considerations +## Other sharing/permission-related considerations -The REST share link or any other permission-modifying function will not take effect if you attempt to update the permission on a file that is checked out by a user. +The REST share link or any other permission-modifying function won't take effect if you attempt to update the permission on a file that is checked out by a user. Finally, if a SharePoint site or OneDrive location is being actively used during migration, the existing permissions applied on that site, user or document will be enforced. -**Example:** If you attempt to modify the permission on a site that only allows access to existing users already defined on the site, and the user you are trying to add to a file or folder does not already have permissions on the site itself, the permission call (e.g. VROOM Invite) will not be able to make the modification. +**Example:** If you attempt to modify the permission on a site that only allows access to existing users already defined on the site, and the user you're trying to add to a file or folder doesn't already have permissions on the site itself, the permission call (for example, VROOM Invite) won't be able to make the modification. diff --git a/docs/apis/site-creation-rest.md b/docs/apis/site-creation-rest.md index 8988e7ec6..530ad6137 100644 --- a/docs/apis/site-creation-rest.md +++ b/docs/apis/site-creation-rest.md @@ -62,7 +62,7 @@ body: The site design id can be retrieved by using the [Get-SPOSiteDesign](/powershell/module/sharepoint-online/get-spositedesign) (Microsoft SharePoint Online Management Shell) or [Get-PnPSiteDesign](/sharepoint/dev/declarative-customization/site-design-pnppowershell) (PnP PowerShell) cmdlets. If you want to apply an out-of-the-box available site design, use the following values: -- Topic: `96c933ac-3698-44c7-9f4a-5fd17d71af9e` or null +- Standard communication: `96c933ac-3698-44c7-9f4a-5fd17d71af9e` or null - Showcase: `6142d2a0-63a5-4ba0-aede-d9fefca2c767` - Blank: `f6cc5403-0d63-442e-96c0-285923709ffc` diff --git a/docs/apis/spod-copy-move-api.md b/docs/apis/spod-copy-move-api.md index e6536b673..202977581 100644 --- a/docs/apis/spod-copy-move-api.md +++ b/docs/apis/spod-copy-move-api.md @@ -1,10 +1,10 @@ --- title: Microsoft 365 Copy and Move API (CreateCopyJobs) description: "Microsoft 365 Copy and Move API (CreateCopyJobs)" -ms.date: 06/29/2022 +ms.date: 10/05/2023 ms.author: jhendr author: JoanneHendrickson -manager: pamgreen +manager: serdars audience: ITPro f1.keywords: - NOCSH @@ -140,6 +140,6 @@ Currently, the following limitations are: | What | Limitation | | :---------------- | :---------------------------------- | -| File size | A file must be less than 2 GB. | -| Number of items | No more than 30,000 items in a job. | -| Total size of job | Job size not to exceed 100 GB. | +| File size | [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#moving-and-copying-across-sites) | +| Number of items | [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#moving-and-copying-across-sites) | +| Total size of job | [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#moving-and-copying-across-sites) | diff --git a/docs/apis/syntex/syntex-model-rest-api.md b/docs/apis/syntex/syntex-model-rest-api.md index 746de3421..277c633dd 100644 --- a/docs/apis/syntex/syntex-model-rest-api.md +++ b/docs/apis/syntex/syntex-model-rest-api.md @@ -1,7 +1,7 @@ --- -title: Microsoft Syntex document understanding model REST API -description: Overview of the Microsoft Syntex document understanding model REST API. -ms.date: 10/20/2022 +title: Unstructured document understanding model REST API +description: Overview of the document understanding model REST API. +ms.date: 07/21/2025 ms.author: chucked author: chuckedmonson manager: pamgreen @@ -12,7 +12,7 @@ ms.collection: m365initiative-syntex ms.localizationpriority: medium --- -# Microsoft Syntex unstructured document processing model REST API +# Unstructured document processing model REST API You can use the SharePoint REST interface to create an unstructured document processing model, apply or remove the model to one or more libraries, and obtain or update information about the model. @@ -29,14 +29,14 @@ Before you get started, make sure that you're familiar with the following: ## REST commands -The following REST commands are available for working with Syntex unstructured document processing models: +The following REST commands are available for working with unstructured document processing models: - [Create model](rest-createmodel-method.md) – Creates a model and its associated content type. -- [GetByUniqueId](rest-getbyuniqueid-method.md) – Gets or updates information about a Syntex unstructured document processing model. -- [GetByTitle](rest-getbytitle-method.md) – Gets or updates information about a Syntex unstructured document processing model using the model title. +- [GetByUniqueId](rest-getbyuniqueid-method.md) – Gets or updates information about an unstructured document processing model. +- [GetByTitle](rest-getbytitle-method.md) – Gets or updates information about an unstructured document processing model using the model title. - [Apply model](rest-applymodel-method.md) – Applies (or syncs) a trained unstructured document processing model to one or more libraries. - [Get model and library information](rest-getmodelandlibraryinfo.md) – Gets information about a model and the library where it has been applied. -- [UpdateModelSettings](rest-updatemodelsettings-method.md) – Updates available models settings (associated retention label and model description) for a Syntex unstructured document processing model. +- [UpdateModelSettings](rest-updatemodelsettings-method.md) – Updates available models settings (associated retention label and model description) for an unstructured document processing model. - [BatchDelete](rest-batchdelete-method.md) – Removes an applied unstructured document processing model from one or more libraries. - [Create file classification request](rest-createclassificationrequest.md) – Creates a request to classify a specified file or files using the applied model. - [Create folder classification request](rest-createclassificationrequest.md) – Creates a request to classify an entire folder using the applied model. diff --git a/docs/apis/webhooks/get-started-webhooks.md b/docs/apis/webhooks/get-started-webhooks.md index d899884da..c3b73e38a 100644 --- a/docs/apis/webhooks/get-started-webhooks.md +++ b/docs/apis/webhooks/get-started-webhooks.md @@ -23,24 +23,22 @@ To complete the step-by-step instructions in this article, download and install In order for the Postman client to communicate with SharePoint, you need to register a Microsoft Azure Active Directory (Azure AD) app in your Azure AD tenant associated with your Office 365 tenant. 1. Ensure that you register the application as a **Web Application**. +1. To access SharePoint Online, it's important to grant the Azure AD app permissions to the **Office 365 SharePoint Online** application and select the **read and write items and lists in all site collections** permission. -2. To access SharePoint Online, it's important to grant the Azure AD app permissions to the **Office 365 SharePoint Online** application and select the **read and write items and lists in all site collections** permission. + > [!NOTE] + > For more information about adding an Azure AD application and granting permissions to applications, see [Adding an application](/azure/active-directory/develop/active-directory-integrating-applications#adding-an-application). - > [!NOTE] - > For more information about adding an Azure AD application and granting permissions to applications, see [Adding an application](/azure/active-directory/develop/active-directory-integrating-applications#adding-an-application). +1. Enter the following endpoint as the Reply (Redirect) URL for the app. This is the endpoint to which Azure AD will send the authentication response, including the access token, if authentication was successful. -3. Enter the following endpoint as the Reply (Redirect) URL for the app. This is the endpoint to which Azure AD will send the authentication response, including the access token, if authentication was successful. + ```html + https://www.getpostman.com/oauth2/callback + ``` - ```html - https://www.getpostman.com/oauth2/callback - ``` +1. Generate a **Key**, which will be the client secret. +1. The following properties are required in later steps, so copy them to a safe place: -4. Generate a **Key**, which will be the client secret. - -5. The following properties are required in later steps, so copy them to a safe place: - - * Client Id - * Client Secret + * Client Id + * Client Secret ## Step 2: Build a webhook receiver @@ -49,22 +47,14 @@ For this project, use the Visual Studio Web API project to build the webhook rec ### Create a new ASP.NET Web API project 1. Open Visual Studio. - -2. Select **File** > **New** > **Project**. - -3. In the **Templates** pane, select **Installed Templates**, and expand the **Visual C#** node. - -4. Under **Visual C#**, select **Web**. - -5. In the list of project templates, select **ASP.NET Web Application**. - -6. Name the project **SPWebhooksReceiver**, and select **OK**. - -7. In the **New ASP.NET Project** dialog, select the **Web API** template from the **ASP.NET 4.5.** group. - -8. Change the authentication to **No Authentication** by selecting the **Change Authentication** button. - -9. Select **OK** to create the Web API project. +1. Select **File** > **New** > **Project**. +1. In the **Templates** pane, select **Installed Templates**, and expand the **Visual C#** node. +1. Under **Visual C#**, select **Web**. +1. In the list of project templates, select **ASP.NET Web Application**. +1. Name the project **SPWebhooksReceiver**, and select **OK**. +1. In the **New ASP.NET Project** dialog, select the **Web API** template from the **ASP.NET 4.5.** group. +1. Change the authentication to **No Authentication** by selecting the **Change Authentication** button. +1. Select **OK** to create the Web API project. > [!NOTE] > You can clear the **Host in the cloud** check box because this project will not be deployed to the cloud. @@ -78,56 +68,41 @@ Visual Studio creates your project. Use ASP.NET Web API Tracing to log the requests coming from SharePoint. The following steps install the tracing package: 1. Go to **Solution Explorer** in Visual Studio. - -2. Open the context menu (right-click) for the project, and select **Manage NuGet Packages**. - -3. In the search box, enter **Microsoft.AspNet.WebApi.Tracing**. - -4. In the search results, select the **Microsoft.AspNet.WebApi.Tracing** package, and then select **Install** to install the package. +1. Open the context menu (right-click) for the project, and select **Manage NuGet Packages**. +1. In the search box, enter **Microsoft.AspNet.WebApi.Tracing**. +1. In the search results, select the **Microsoft.AspNet.WebApi.Tracing** package, and then select **Install** to install the package. #### Build SPWebhookNotification model Each notification generated by the service is serialized into a **webhookNotification** instance. You need to build a simple model that represents this notification instance. 1. Go to **Solution Explorer** in Visual Studio. - -2. Open the context menu (right-click) for the **Models** folder, and select **Add** > **Class**. - -3. Enter **SPWebhookNotification** as the class name and select **Add** to add the class to your project. - -4. Add the following code to the body of the **SPWebhookNotification** class: - - ```csharp - public string SubscriptionId { get; set; } - - public string ClientState { get; set; } - - public string ExpirationDateTime { get; set; } - - public string Resource { get; set; } - - public string TenantId { get; set; } - - public string SiteUrl { get; set; } - - public string WebId { get; set; } - ``` +1. Open the context menu (right-click) for the **Models** folder, and select **Add** > **Class**. +1. Enter **SPWebhookNotification** as the class name and select **Add** to add the class to your project. +1. Add the following code to the body of the **SPWebhookNotification** class: + + ```csharp + public string SubscriptionId { get; set; } + public string ClientState { get; set; } + public string ExpirationDateTime { get; set; } + public string Resource { get; set; } + public string TenantId { get; set; } + public string SiteUrl { get; set; } + public string WebId { get; set; } + ``` #### Build SPWebhookContent model Because multiple notifications can be submitted to your webhook receiver in a single request, they are combined together in an object with a single array value. Build a simple model that represents the array. 1. Go to **Solution Explorer** in Visual Studio. +1. Open the context menu (right-click) for the **Models** folder, and select **Add** > **Class**. +1. Enter **SPWebhookContent** as the class name, and select **Add** to add the class to your project. +1. Add the following code to the body of the **SPWebhookContent** class: -2. Open the context menu (right-click) for the **Models** folder, and select **Add** > **Class**. - -3. Enter **SPWebhookContent** as the class name, and select **Add** to add the class to your project. - -4. Add the following code to the body of the **SPWebhookContent** class: - - ```csharp - public List Value { get; set; } - ``` + ```csharp + public List Value { get; set; } + ``` #### Add SharePoint webhook client state @@ -136,12 +111,11 @@ Webhooks provide the ability to use an optional string value that is passed back Add a client state value with which the application can verify the incoming requests. 1. Go to **Solution Explorer** in Visual Studio. +1. Open the **web.config** file, and add the following key as the client state to the `` section: -2. Open the **web.config** file, and add the following key as the client state to the `` section: - - ```xml - - ``` + ```xml + + ``` #### Enable tracing @@ -154,162 +128,152 @@ In the **web.config** file, enable tracing by adding the following key inside th A trace writer is required, so you must add a trace writer to the controller configuration (in this case use the one from **System.Diagnostics**). 1. Go to **Solution Explorer** in Visual Studio. +1. Open **WebApiConfig.cs** in the **App_Start** folder. +1. Add the following line inside the **Register** method: -2. Open **WebApiConfig.cs** in the **App_Start** folder. - -3. Add the following line inside the **Register** method: - - ```csharp - config.EnableSystemDiagnosticsTracing(); - ``` + ```csharp + config.EnableSystemDiagnosticsTracing(); + ``` #### Build SharePoint webhook controller Now build the webhook receiver controller that handles the incoming requests from SharePoint and take action accordingly. 1. Go to **Solution Explorer** in Visual Studio. - -2. Open the context menu (right-click) for the **Controllers** folder, and select **Add** > **Controller**. - -3. In the **Add Scaffold** dialog, select **Web API 2 Controller - Empty**. - -4. Select **Add**. - -5. Name the controller **SPWebhookController**, and select **Add** to add the API controller to your project. - -6. Replace the `using` statements with the following code: - - ```csharp - using Newtonsoft.Json; - using SPWebhooksReceiver.Models; - using System.Collections.Generic; - using System.Configuration; - using System.Linq; - using System.Net; - using System.Net.Http; - using System.Threading.Tasks; - using System.Web; - using System.Web.Http; - using System.Web.Http.Tracing; - ``` - -7. Replace the code in the **SPWebhookController** class with the following code: - - ```csharp - [HttpPost] - public HttpResponseMessage HandleRequest() - { - HttpResponseMessage httpResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); - var traceWriter = Configuration.Services.GetTraceWriter(); - string validationToken = string.Empty; - IEnumerable clientStateHeader = new List(); - string webhookClientState = ConfigurationManager.AppSettings["webhookclientstate"].ToString(); - - if (Request.Headers.TryGetValues("ClientState", out clientStateHeader)) - { - string clientStateHeaderValue = clientStateHeader.FirstOrDefault() ?? string.Empty; - - if (!string.IsNullOrEmpty(clientStateHeaderValue) && clientStateHeaderValue.Equals(webhookClientState)) - { - traceWriter.Trace(Request, "SPWebhooks", - TraceLevel.Info, - string.Format("Received client state: {0}", clientStateHeaderValue)); - - var queryStringParams = HttpUtility.ParseQueryString(Request.RequestUri.Query); - - if (queryStringParams.AllKeys.Contains("validationtoken")) - { - httpResponse = new HttpResponseMessage(HttpStatusCode.OK); - validationToken = queryStringParams.GetValues("validationtoken")[0].ToString(); - httpResponse.Content = new StringContent(validationToken); - - traceWriter.Trace(Request, "SPWebhooks", - TraceLevel.Info, - string.Format("Received validation token: {0}", validationToken)); - return httpResponse; - } - else - { - var requestContent = Request.Content.ReadAsStringAsync().Result; - - if (!string.IsNullOrEmpty(requestContent)) - { - SPWebhookNotification notification = null; - - try - { - var objNotification = JsonConvert.DeserializeObject(requestContent); - notification = objNotification.Value[0]; - } - catch (JsonException ex) - { - traceWriter.Trace(Request, "SPWebhooks", - TraceLevel.Error, - string.Format("JSON deserialization error: {0}", ex.InnerException)); - return httpResponse; - } - - if (notification != null) - { - Task.Factory.StartNew(() => - { - //handle the notification here - //you can send this to an Azure queue to be processed later - //for this sample, we just log to the trace - - traceWriter.Trace(Request, "SPWebhook Notification", - TraceLevel.Info, string.Format("Resource: {0}", notification.Resource)); - traceWriter.Trace(Request, "SPWebhook Notification", - TraceLevel.Info, string.Format("SubscriptionId: {0}", notification.SubscriptionId)); - traceWriter.Trace(Request, "SPWebhook Notification", - TraceLevel.Info, string.Format("TenantId: {0}", notification.TenantId)); - traceWriter.Trace(Request, "SPWebhook Notification", - TraceLevel.Info, string.Format("SiteUrl: {0}", notification.SiteUrl)); - traceWriter.Trace(Request, "SPWebhook Notification", - TraceLevel.Info, string.Format("WebId: {0}", notification.WebId)); - traceWriter.Trace(Request, "SPWebhook Notification", - TraceLevel.Info, string.Format("ExpirationDateTime: {0}", notification.ExpirationDateTime)); - - }); - - httpResponse = new HttpResponseMessage(HttpStatusCode.OK); - } - } - } - } - else - { - httpResponse = new HttpResponseMessage(HttpStatusCode.Forbidden); - } - } - - return httpResponse; - } - ``` - -8. Save the file. +1. Open the context menu (right-click) for the **Controllers** folder, and select **Add** > **Controller**. +1. In the **Add Scaffold** dialog, select **Web API 2 Controller - Empty**. +1. Select **Add**. +1. Name the controller **SPWebhookController**, and select **Add** to add the API controller to your project. +1. Replace the `using` statements with the following code: + + ```csharp + using Newtonsoft.Json; + using SPWebhooksReceiver.Models; + using System.Collections.Generic; + using System.Configuration; + using System.Linq; + using System.Net; + using System.Net.Http; + using System.Threading.Tasks; + using System.Web; + using System.Web.Http; + using System.Web.Http.Tracing; + ``` + +1. Replace the code in the **SPWebhookController** class with the following code: + + ```csharp + [HttpPost] + public HttpResponseMessage HandleRequest() + { + HttpResponseMessage httpResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + var traceWriter = Configuration.Services.GetTraceWriter(); + string validationToken = string.Empty; + IEnumerable clientStateHeader = new List(); + string webhookClientState = ConfigurationManager.AppSettings["webhookclientstate"].ToString(); + + if (Request.Headers.TryGetValues("ClientState", out clientStateHeader)) + { + string clientStateHeaderValue = clientStateHeader.FirstOrDefault() ?? string.Empty; + + if (!string.IsNullOrEmpty(clientStateHeaderValue) && clientStateHeaderValue.Equals(webhookClientState)) + { + traceWriter.Trace(Request, "SPWebhooks", + TraceLevel.Info, + string.Format("Received client state: {0}", clientStateHeaderValue)); + + var queryStringParams = HttpUtility.ParseQueryString(Request.RequestUri.Query); + + if (queryStringParams.AllKeys.Contains("validationtoken")) + { + httpResponse = new HttpResponseMessage(HttpStatusCode.OK); + validationToken = queryStringParams.GetValues("validationtoken")[0].ToString(); + httpResponse.Content = new StringContent(validationToken); + + traceWriter.Trace(Request, "SPWebhooks", + TraceLevel.Info, + string.Format("Received validation token: {0}", validationToken)); + return httpResponse; + } + else + { + var requestContent = Request.Content.ReadAsStringAsync().Result; + + if (!string.IsNullOrEmpty(requestContent)) + { + SPWebhookNotification notification = null; + + try + { + var objNotification = JsonConvert.DeserializeObject(requestContent); + notification = objNotification.Value[0]; + } + catch (JsonException ex) + { + traceWriter.Trace(Request, "SPWebhooks", + TraceLevel.Error, + string.Format("JSON deserialization error: {0}", ex.InnerException)); + return httpResponse; + } + + if (notification != null) + { + Task.Factory.StartNew(() => + { + //handle the notification here + //you can send this to an Azure queue to be processed later + //for this sample, we just log to the trace + + traceWriter.Trace(Request, "SPWebhook Notification", + TraceLevel.Info, string.Format("Resource: {0}", notification.Resource)); + traceWriter.Trace(Request, "SPWebhook Notification", + TraceLevel.Info, string.Format("SubscriptionId: {0}", notification.SubscriptionId)); + traceWriter.Trace(Request, "SPWebhook Notification", + TraceLevel.Info, string.Format("TenantId: {0}", notification.TenantId)); + traceWriter.Trace(Request, "SPWebhook Notification", + TraceLevel.Info, string.Format("SiteUrl: {0}", notification.SiteUrl)); + traceWriter.Trace(Request, "SPWebhook Notification", + TraceLevel.Info, string.Format("WebId: {0}", notification.WebId)); + traceWriter.Trace(Request, "SPWebhook Notification", + TraceLevel.Info, string.Format("ExpirationDateTime: {0}", notification.ExpirationDateTime)); + + }); + + httpResponse = new HttpResponseMessage(HttpStatusCode.OK); + } + } + } + } + else + { + httpResponse = new HttpResponseMessage(HttpStatusCode.Forbidden); + } + } + + return httpResponse; + } + ``` + +1. Save the file. ## Step 3: Debug the webhook receiver 1. Select **F5** to debug the webhook receiver. - -2. When you have the browser open, copy the port number from the address bar. For example: `http://localhost:<_port-number_>` +1. When you have the browser open, copy the port number from the address bar. For example: `http://localhost:<_port-number_>` ## Step 4: Run ngrok proxy 1. Open a console terminal. +1. Go to the extracted ngrok folder. +1. Enter the following with the port number URL from the previous step to start ngrok: -2. Go to the extracted ngrok folder. - -3. Enter the following with the port number URL from the previous step to start ngrok: + ``` + ./ngrok http port-number --host-header=localhost:port-number + ``` - ``` - ./ngrok http port-number --host-header=localhost:port-number - ``` + You should see ngrok running. - You should see ngrok running. - -4. Copy the **Forwarding** HTTPS address. You will use this address as the service proxy for SharePoint to send requests. +1. Copy the **Forwarding** HTTPS address. You will use this address as the service proxy for SharePoint to send requests. ## Step 5: Add webhook subscription using Postman @@ -318,14 +282,11 @@ Now build the webhook receiver controller that handles the incoming requests fro Postman makes it really simple to work with APIs. The first step is to configure Postman to authenticate with Azure AD so you can send API requests to SharePoint. You will use the Azure AD app that you registered in Step 1. 1. Open Postman. You are presented with a **Sidebar** and **Request Editor**. +1. Select the **Authorization** tab in the **Request Editor**. +1. Select **OAuth 2.0** in the **Type** list. +1. Select the **Get New Access Token** button. +1. In the dialog window, enter the following: -2. Select the **Authorization** tab in the **Request Editor**. - -3. Select **OAuth 2.0** in the **Type** list. - -4. Select the **Get New Access Token** button. - -5. In the dialog window, enter the following: * **Auth URL**: * `https://login.microsoftonline.com/common/oauth2/authorize?resource=https%3A%2F%2F<_your-sharepoint-tenant-url-without-https_>` * Replace `your-sharepoint-tenant-url-without-https` with your tenant url without the **https** prefix. @@ -335,15 +296,12 @@ Postman makes it really simple to work with APIs. The first step is to configure * **Token name**: sp_webhooks_token * **Grant type**: Authorization Code -6. Select the **Request Token** to sign in, consent, and get the token for the session. - -7. When the token is successfully retrieved, you should see **access\_token** variable added to the **Authorization** tab. - -8. Select the option to **Add token to header**. - -9. Double-click the **access\_token** variable to add the token to the header for the request. +1. Select the **Request Token** to sign in, consent, and get the token for the session. +1. When the token is successfully retrieved, you should see **access\_token** variable added to the **Authorization** tab. +1. Select the option to **Add token to header**. +1. Double-click the **access\_token** variable to add the token to the header for the request. - ![Postman get new access token](../../images/postman-get-new-access-token.png) + ![Postman get new access token](../../images/postman-get-new-access-token.png) ### Get Documents list Id @@ -351,172 +309,156 @@ You need to manage webhooks for the default document library, which is provision 1. Enter the following request URL: - ``` - https://site-collection/_api/web/lists/getbytitle('Documents')?$select=Title,Id - ``` + ```http + https://site-collection/_api/web/lists/getbytitle('Documents')?$select=Title,Id + ``` -2. Replace _site-collection_ with your site collection. +1. Replace _site-collection_ with your site collection. - Postman executes your request and if successful, you should see the result. + Postman executes your request and if successful, you should see the result. -3. Copy the **Id** from the results. Later you will use the **Id** to make webhook requests. +1. Copy the **Id** from the results. Later you will use the **Id** to make webhook requests. ### Add webhook subscription Now that you have the required information, construct the query and the request to add a webhook subscription. Use the request editor for the following steps: 1. Change the request to **POST** from **GET**. - -2. Enter the following as the request URL: - - ``` - https://site-collection/_api/web/lists('list-id')/subscriptions - ``` - -3. Replace _site-collection_ with your site collection. - -4. Go to the **Headers** tab. - -5. Make sure you still have the **Authorization** header. If not, you need to request a new access token. - -6. Add the following header **key** > **value** pairs: - * Accept > application/json;odata=nometadata - * Content-Type > application/json - -7. Go to the **Body** tab and select **raw** format. - -8. Paste the following JSON as the body: - - ```json - { - "resource": "https://site-collection/_api/web/lists('list-id')", - "notificationUrl": "https://ngrok-forwarding-address/api/spwebhook/handlerequest", - "expirationDateTime": "2016-10-27T16:17:57+00:00", - "clientState": "A0A354EC-97D4-4D83-9DDB-144077ADB449" - } - ``` - -
- - ![postman add webhook body](../../images/postman-add-webhook-body.png) - -9. Make sure the **expirationDateTime** is at most 6 months from today. - -10. Make sure you are debugging the webhook receiver as in Step 4. - -11. Select **Send** to execute the request. - - If the request is successful, you should see the response from SharePoint that provides the subscription details. The following example shows a response for a newly created subscription: - - ```json - { - "clientState": "A0A354EC-97D4-4D83-9DDB-144077ADB449", - "expirationDateTime": "2016-10-27T16:17:57Z", - "id": "32b95d9-4d20-4a17-bfa3-2957cb38ead8", - "notificationUrl": "https://85557d4b.ngrok.io/api/spwebhook/handlerequest", - "resource": "c34420f9-2ad7-4e54-94c9-b67798d2299b" - } - ``` - -12. Copy the subscription **id**. You will need it for the next set of requests. - -13. Go to the webhook receiver project in Visual Studio and examine the **Output** window. You should see the trace logs that look similar to the following trace, along with other messages: - - ``` - iisexpress.exe Information: 0 : Message='Received client state: A0A354EC-97D4-4D83-9DDB-144077ADB449' - iisexpress.exe Information: 0 : Message='Received validation token: daf2803c-43cf-44c7-8dff-7066eaa40f13' - ``` - - The trace indicates that the webhook received initially received a validation request. If you look at the code, you'll see that it returns the validation token immediately so that SharePoint can validate the request: - - ```csharp - if (queryStringParams.AllKeys.Contains("validationtoken")) - { - httpResponse = new HttpResponseMessage(HttpStatusCode.OK); - validationToken = queryStringParams.GetValues("validationtoken")[0].ToString(); - httpResponse.Content = new StringContent(validationToken); - - traceWriter.Trace(Request, "SPWebhooks", - TraceLevel.Info, - string.Format("Received validation token: {0}", validationToken)); - return httpResponse; - } - ``` +1. Enter the following as the request URL: + + ```http + https://site-collection/_api/web/lists('list-id')/subscriptions + ``` + +1. Replace _site-collection_ with your site collection. +1. Go to the **Headers** tab. +1. Make sure you still have the **Authorization** header. If not, you need to request a new access token. +1. Add the following header **key** > **value** pairs: + + * **Accept**: `application/json;odata=nometadata` + * **Content-Type**: `application/json` + +1. Go to the **Body** tab and select **raw** format. +1. Paste the following JSON as the body: + + ```json + { + "resource": "https://site-collection/_api/web/lists('list-id')", + "notificationUrl": "https://ngrok-forwarding-address/api/spwebhook/handlerequest", + "expirationDateTime": "2016-10-27T16:17:57+00:00", + "clientState": "A0A354EC-97D4-4D83-9DDB-144077ADB449" + } + ``` + + ![postman add webhook body](../../images/postman-add-webhook-body.png) + +1. Make sure the **expirationDateTime** is at most 6 months from today. +1. Make sure you are debugging the webhook receiver as in Step 4. +1. Select **Send** to execute the request. + + If the request is successful, you should see the response from SharePoint that provides the subscription details. The following example shows a response for a newly created subscription: + + ```json + { + "clientState": "A0A354EC-97D4-4D83-9DDB-144077ADB449", + "expirationDateTime": "2016-10-27T16:17:57Z", + "id": "32b95d9-4d20-4a17-bfa3-2957cb38ead8", + "notificationUrl": "https://85557d4b.ngrok.io/api/spwebhook/handlerequest", + "resource": "c34420f9-2ad7-4e54-94c9-b67798d2299b" + } + ``` + +1. Copy the subscription **id**. You will need it for the next set of requests. +1. Go to the webhook receiver project in Visual Studio and examine the **Output** window. You should see the trace logs that look similar to the following trace, along with other messages: + + ```console + iisexpress.exe Information: 0 : Message='Received client state: A0A354EC-97D4-4D83-9DDB-144077ADB449' + iisexpress.exe Information: 0 : Message='Received validation token: daf2803c-43cf-44c7-8dff-7066eaa40f13' + ``` + + The trace indicates that the webhook received initially received a validation request. If you look at the code, you'll see that it returns the validation token immediately so that SharePoint can validate the request: + + ```csharp + if (queryStringParams.AllKeys.Contains("validationtoken")) + { + httpResponse = new HttpResponseMessage(HttpStatusCode.OK); + validationToken = queryStringParams.GetValues("validationtoken")[0].ToString(); + httpResponse.Content = new StringContent(validationToken); + + traceWriter.Trace(Request, "SPWebhooks", + TraceLevel.Info, + string.Format("Received validation token: {0}", validationToken)); + return httpResponse; + } + ``` ## Step 6: Get subscription details Now you'll run queries in Postman to get the subscription details. 1. Open the Postman client. +1. Change the request to **GET** from **POST**. +1. Enter the following as the request: -2. Change the request to **GET** from **POST**. - -3. Enter the following as the request: - - ``` - https://site-collection/_api/web/lists('list-id')/subscriptions - ``` - -4. Replace _site-collection_ with your site collection. + ```http + https://site-collection/_api/web/lists('list-id')/subscriptions + ``` -5. Select **Send** to execute the request. +1. Replace _site-collection_ with your site collection. +1. Select **Send** to execute the request. - If successful, you should see SharePoint return the subscriptions for this list resource. Because we just added one, you should at least see one subscription returned. The following example shows a response with one subscription: + If successful, you should see SharePoint return the subscriptions for this list resource. Because we just added one, you should at least see one subscription returned. The following example shows a response with one subscription: - ```json - { - "value": [ - { - "clientState": "A0A354EC-97D4-4D83-9DDB-144077ADB449", - "expirationDateTime": "2016-10-27T16:17:57Z", - "id": "32b95add-4d20-4a17-bfa3-2957cb38ead8", - "notificationUrl": "https://85557d4b.ngrok.io/api/spwebhook/handlerequest", - "resource": "c34420f9-2a67-4e54-94c9-b67798229f9b" - } - ] - } - ``` + ```json + { + "value": [ + { + "clientState": "A0A354EC-97D4-4D83-9DDB-144077ADB449", + "expirationDateTime": "2016-10-27T16:17:57Z", + "id": "32b95add-4d20-4a17-bfa3-2957cb38ead8", + "notificationUrl": "https://85557d4b.ngrok.io/api/spwebhook/handlerequest", + "resource": "c34420f9-2a67-4e54-94c9-b67798229f9b" + } + ] + } + ``` -6. Run the following query to get details of the specific subscription: +1. Run the following query to get details of the specific subscription: - ``` - https://site-collection/_api/web/lists('list-id')/subscriptions('subscription-id') - ``` + ```http + https://site-collection/_api/web/lists('list-id')/subscriptions('subscription-id') + ``` -7. Replace `subscription-id` with your subscription id. +1. Replace `subscription-id` with your subscription id. ## Step 7: Test webhook notification Now add a file to the Documents library and test if you get a notification from SharePoint in the webhook receiver. 1. Go to Visual Studio. +1. In the **SPWebhookController**, place a breakpoint on the following line of code: -2. In the **SPWebhookController**, place a breakpoint on the following line of code: - - ```csharp - var requestContent = Request.Content.ReadAsStringAsync().Result; - ``` - -3. Go to the **Documents** library. It is named **Shared Documents** library in your default site collection. - -4. Add a new file. - -5. Go to Visual Studio and wait for the breakpoint to be hit. + ```csharp + var requestContent = Request.Content.ReadAsStringAsync().Result; + ``` - The wait time may vary from a few seconds to up to five minutes. When the breakpoint is hit, the webhook receiver has just received a notification from SharePoint. +1. Go to the **Documents** library. It is named **Shared Documents** library in your default site collection. +1. Add a new file. +1. Go to Visual Studio and wait for the breakpoint to be hit. -6. Select **F5** to continue. + The wait time may vary from a few seconds to up to five minutes. When the breakpoint is hit, the webhook receiver has just received a notification from SharePoint. -7. To see the notification data, look in the **Output** window for the following entries, since you added the notification data into the trace log: +1. Select **F5** to continue. +1. To see the notification data, look in the **Output** window for the following entries, since you added the notification data into the trace log: - ``` - iisexpress.exe Information: 0 : Message='Resource: c34420f9-2a67-4e54-94c9-b6770892299b' - iisexpress.exe Information: 0 : Message='SubscriptionId: 32b95ad9-4d20-4a17-bfa3-2957cb38ead8' - iisexpress.exe Information: 0 : Message='TenantId: 7a17cb7d-6898-423f-8839-45f363076f06' - iisexpress.exe Information: 0 : Message='SiteUrl: /' - iisexpress.exe Information: 0 : Message='WebId: 62b80e0b-f889-4974-a519-cc138413be40' - iisexpress.exe Information: 0 : Message='ExpirationDateTime: 2016-10-27T16:17:57.0000000Z' - ``` + ```console + iisexpress.exe Information: 0 : Message='Resource: c34420f9-2a67-4e54-94c9-b6770892299b' + iisexpress.exe Information: 0 : Message='SubscriptionId: 32b95ad9-4d20-4a17-bfa3-2957cb38ead8' + iisexpress.exe Information: 0 : Message='TenantId: 7a17cb7d-6898-423f-8839-45f363076f06' + iisexpress.exe Information: 0 : Message='SiteUrl: /' + iisexpress.exe Information: 0 : Message='WebId: 62b80e0b-f889-4974-a519-cc138413be40' + iisexpress.exe Information: 0 : Message='ExpirationDateTime: 2016-10-27T16:17:57.0000000Z' + ``` This project only writes the information to the trace log. However, in your receiver, you send this information into a table or a queue that can process the received data to get information from SharePoint. diff --git a/docs/apis/webhooks/sharepoint-webhooks-using-azd-template.md b/docs/apis/webhooks/sharepoint-webhooks-using-azd-template.md new file mode 100644 index 000000000..1de5d665e --- /dev/null +++ b/docs/apis/webhooks/sharepoint-webhooks-using-azd-template.md @@ -0,0 +1,178 @@ +--- +title: Create Azure Functions for SharePoint webhooks using an azd template +description: Use Azure Developer cli (azd) to deploy an Azure function app that connects to your SharePoint Online + tenant, to register and manage webhooks, and process the notifications from SharePoint. +ms.date: 07/07/2025 +ms.localizationpriority: low +--- +# Azure Functions for SharePoint webhooks using azd + +[Azure Developer CLI (azd)](https://aka.ms/azd) is an open-source tool that accelerates provisioning and deploying app resources in Azure. + +This article uses the [Azure function app for SharePoint webhooks public template](https://github.com/Azure-Samples/azd-functions-sharepoint-webhooks) to deploy an Azure function app that connects to your SharePoint Online tenant, to register and manage [webhooks](overview-sharepoint-webhooks.md), and process the notifications from SharePoint. + +## Prerequisites + +- [Node.js 22](https://www.nodejs.org/) +- [Azure Functions Core Tools](/azure/azure-functions/functions-run-local) +- [Azure Developer CLI (azd)](/azure/developer/azure-developer-cli/install-azd) +- An Azure subscription that trusts the same Microsoft Entra ID directory as the SharePoint tenant + +## Permissions required to provision the resources in Azure + +The account running **azd** must have at least the following roles to successfully provision the resources: + +- Azure role **[Contributor](/azure/role-based-access-control/built-in-roles/privileged#contributor)**: To create all the resources needed +- Azure role **[Role Based Access Control Administrator](/azure/role-based-access-control/built-in-roles/privileged#role-based-access-control-administrator)**: To assign roles (to access the storage account and Application Insights) to the managed identity of the function app + +## Deploy the function app in Azure + +1. Run **azd init** from an empty local (root) folder: + + ```console + azd init --template azd-functions-sharepoint-webhooks + ``` + + Enter an environment name, such as **spofuncs-quickstart** when prompted. In **azd**, the environment is used to maintain a unique deployment context for your app. + +1. Open the file **infra/main.parameters.json**, and set the variables `TenantPrefix` and `siteRelativePath` to match your SharePoint tenant. + + Review the article on [Manage environment variables](/azure/developer/azure-developer-cli/manage-environment-variables) to manage the azd's environment variables. + +1. Finally, run the command **azd up** to build the app, provision the resources in Azure and deploy the app package. + +## Grant the function app access to SharePoint Online + +The authentication to SharePoint is done using `DefaultAzureCredential`, so the credential used depends on whether the function app runs locally, or in Azure. + +If you never heard about `DefaultAzureCredential`, you should familiarize yourself with its concept by referring to the section **Use DefaultAzureCredential for flexibility** in [Credential chains in the Azure Identity client library for JavaScript](/azure/developer/javascript/sdk/authentication/credential-chains). + +### Using its managed identity + +`DefaultAzureCredential` will use a managed identity to authenticate to SharePoint. This may be the existing, system-assigned managed identity of the function app service or a user-assigned managed identity. + +This tutorial assumes the system-assigned managed identity is used. + +#### Grant the SharePoint API permission Sites.Selected to the managed identity + +Navigate to your function app in the [Azure portal](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Web%2Fsites/kind/functionapp) > select **Identity** and note the **Object (principal) ID** of the system-assigned managed identity. + +> [!NOTE] +> In this tutorial, it is **d3e8dc41-94f2-4b0f-82ff-ed03c363f0f8**. + +Then, use one of the scripts below to grant this identity the app-only permission **Sites.Selected** on the SharePoint API: + +> [!IMPORTANT] +> The scripts below require at least the delegated permission [`AppRoleAssignment.ReadWrite.All`](/graph/permissions-reference#approleassignmentreadwriteall) (requires admin consent) + +
+ Using the Microsoft Graph PowerShell SDK + +```powershell +# This script requires the modules Microsoft.Graph.Authentication, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns, which can be installed with the cmdlet Install-Module below: +# Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns -Scope CurrentUser -Repository PSGallery -Force +Connect-MgGraph -Scope "Application.Read.All", "AppRoleAssignment.ReadWrite.All" +$managedIdentityObjectId = "d3e8dc41-94f2-4b0f-82ff-ed03c363f0f8" # 'Object (principal) ID' of the managed identity +$scopeName = "Sites.Selected" +$resourceAppPrincipalObj = Get-MgServicePrincipal -Filter "displayName eq 'Office 365 SharePoint Online'" # SPO +$targetAppPrincipalAppRole = $resourceAppPrincipalObj.AppRoles | ? Value -eq $scopeName + +$appRoleAssignment = @{ + "principalId" = $managedIdentityObjectId + "resourceId" = $resourceAppPrincipalObj.Id + "appRoleId" = $targetAppPrincipalAppRole.Id +} +New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $managedIdentityObjectId -BodyParameter $appRoleAssignment | Format-List +``` +
+ +
+ Using az cli in Bash + +```bash +managedIdentityObjectId="d3e8dc41-94f2-4b0f-82ff-ed03c363f0f8" # 'Object (principal) ID' of the managed identity +resourceServicePrincipalId=$(az ad sp list --query '[].[id]' --filter "displayName eq 'Office 365 SharePoint Online'" -o tsv) +resourceServicePrincipalAppRoleId="$(az ad sp show --id $resourceServicePrincipalId --query "appRoles[?starts_with(value, 'Sites.Selected')].[id]" -o tsv)" + +az rest --method POST --uri "https://graph.microsoft.com/v1.0/servicePrincipals/${managedIdentityObjectId}/appRoleAssignments" --headers 'Content-Type=application/json' --body "{ 'principalId': '${managedIdentityObjectId}', 'resourceId': '${resourceServicePrincipalId}', 'appRoleId': '${resourceServicePrincipalAppRoleId}' }" +``` +
+ +#### Grant the managed identity effective access to a SharePoint site + +Navigate to the [Enterprise applications](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/StartboardApplicationsMenuBlade/) > Set the **Application type** filter to **Managed Identities** > select your managed identity and note its **Application ID**. + +> [!NOTE] +> In this tutorial, it is **3150363e-afbe-421f-9785-9d5404c5ae34**. + +Then, use one of the scripts below to grant it the app-only permission **manage** (minimum required to register a webhook) on a specific SharePoint site: + +> [!IMPORTANT] +> The app registration used to run those scripts must have at least the following permissions: +> +> - Delegated permission **Application.ReadWrite.All** in the Graph API (requires admin consent) +> - Delegated permission **AllSites.FullControl** in the SharePoint API (requires admin consent) + +
+ Using PnP PowerShell + +[PnP PowerShell](https://pnp.github.io/powershell/cmdlets/Grant-PnPAzureADAppSitePermission.html) + +```powershell +Connect-PnPOnline -Url "https://YOUR_SHAREPOINT_TENANT_PREFIX.sharepoint.com/sites/YOUR_SHAREPOINT_SITE_NAME" -Interactive -ClientId "YOUR_PNP_APP_CLIENT_ID" +Grant-PnPAzureADAppSitePermission -AppId "3150363e-afbe-421f-9785-9d5404c5ae34" -DisplayName "YOUR_FUNC_APP_NAME" -Permissions Manage +``` +
+ +
+ Using m365 cli in Bash + +[m365 cli](https://pnp.github.io/cli-microsoft365/cmd/spo/site/site-apppermission-add/) + +```bash +targetapp="3150363e-afbe-421f-9785-9d5404c5ae34" +siteUrl="https://YOUR_SHAREPOINT_TENANT_PREFIX.sharepoint.com/sites/YOUR_SHAREPOINT_SITE_NAME" +m365 spo site apppermission add --appId $targetapp --permission manage --siteUrl $siteUrl +``` +
+ +## Call the function app + +For security reasons, when running in Azure, the function app requires an app key to pass in the query string parameter **code**. The app keys are found in the function app service's **App Keys** keys page. + +Most HTTP functions take optional parameters `TenantPrefix` and `siteRelativePath`. If they are not specified, the values in the app's environment variables are used. + +Below is a sample script in PowerShell to call the function app: + +```powershell +# Edit those variables to match your environment +$funchost = "YOUR_FUNC_APP_NAME" +$code = "YOUR_HOST_KEY" +$listTitle = "YOUR_SHAREPOINT_LIST" +$notificationUrl = "https://${funchost}.azurewebsites.net/api/webhooks/service?code=${code}" + +# List all the webhooks registered on a list +Invoke-RestMethod -Method GET -Uri "https://${funchost}.azurewebsites.net/api/webhooks/list?code=${code}&listTitle=${listTitle}" + +# Register a webhook in a list +Invoke-RestMethod -Method POST -Uri "https://${funchost}.azurewebsites.net/api/webhooks/register?code=${code}&listTitle=${listTitle}¬ificationUrl=${notificationUrl}" + +# Show this webhook registered on a list +Invoke-RestMethod -Method GET -Uri "https://${funchost}.azurewebsites.net/api/webhooks/show?code=${code}&listTitle=${listTitle}¬ificationUrl=${notificationUrl}" + +# Remove the webhook from a list +# Step 1: Call the function /webhooks/show to get the webhook id +$webhookId = $(Invoke-RestMethod -Method GET -Uri "https://${funchost}.azurewebsites.net/api/webhooks/show?code=${code}&listTitle=${listTitle}¬ificationUrl=${notificationUrl}").Id +# Step 2: Call the function /webhooks/remove and pass the webhook id +Invoke-RestMethod -Method POST -Uri "https://${funchost}.azurewebsites.net/api/webhooks/remove?code=${code}&listTitle=${listTitle}&webhookId=${webhookId}" +``` + +## Cleanup the resources in Azure + +You can delete all the resources this project created in Azure, by running the command **azd down**. + +Alternatively, you can delete the resource group, that has the azd environment's name by default. + +## See also + +- [Overview of SharePoint webhooks](overview-sharepoint-webhooks.md) diff --git a/docs/apis/webhooks/sharepoint-webhooks-using-azure-functions.md b/docs/apis/webhooks/sharepoint-webhooks-using-azure-functions.md index eb8812dbc..967d0e43d 100644 --- a/docs/apis/webhooks/sharepoint-webhooks-using-azure-functions.md +++ b/docs/apis/webhooks/sharepoint-webhooks-using-azure-functions.md @@ -6,7 +6,9 @@ ms.localizationpriority: high --- # Using Azure Functions with SharePoint webhooks -[Azure Functions](/azure/azure-functions/functions-overview) offers an easy way to host your SharePoint webhooks: you can add your webhook C# or JavaScript code via the browser, and Azure takes care of the hosting and scaling of your function. This guide shows how to set up and use Azure Functions for your webhooks. +[Azure Functions](/azure/azure-functions/functions-overview) offers an easy way to host your SharePoint webhooks: you can add your webhook C# or JavaScript code via the browser, and Azure takes care of the hosting and scaling of your function. + +This guide shows how to set up and use Azure Functions for your webhooks using the Azure portal. Alternatively, you can refer to article [Create Azure Functions for SharePoint webhooks using an azd template](sharepoint-webhooks-using-azd-template.md), to automate the whole process using an **azd** template. ## Create an Azure Function App diff --git a/docs/apis/webhooks/webhooks-reference-implementation.md b/docs/apis/webhooks/webhooks-reference-implementation.md index 2c07579a2..f6285aaf7 100644 --- a/docs/apis/webhooks/webhooks-reference-implementation.md +++ b/docs/apis/webhooks/webhooks-reference-implementation.md @@ -1,7 +1,7 @@ --- title: SharePoint webhooks sample reference implementation description: This SharePoint Patterns and Practices (PnP) reference implementation shows how you can use SharePoint webhooks in your application. -ms.date: 09/23/2022 +ms.date: 06/05/2024 ms.localizationpriority: high --- # SharePoint webhooks sample reference implementation @@ -10,19 +10,16 @@ The SharePoint Patterns and Practices (PnP) reference implementation shows how y The reference implementation only works with [SharePoint list webhooks](./lists/overview-sharepoint-list-webhooks.md). -You can also follow these steps by watching the video on the Microsoft 365 Platform Communtiy (PnP) YouTube Channel: - -
+You can also follow these steps by watching the video on the Microsoft 365 Platform Community (PnP) YouTube Channel: > [!Video https://www.youtube.com/embed/P4a1_EWokwM] -
- **Applies to** Office 365 Multi Tenant (MT). Microsoft Azure is used to host the various components needed to implement SharePoint webhooks. Source code and other materials for the reference implementation are available in two flavors: + - A SharePoint provider-hosted application version - An Office 365 Azure AD application, which can be found in the [SharePoint developer samples GitHub repository](https://aka.ms/sp-webhooks-sample-reference). @@ -35,9 +32,7 @@ The application shows you how to manage webhooks, specifically for a SharePoint ### Deployment guides - The [SharePoint webhooks reference implementation deployment guide](https://github.com/SharePoint/sp-dev-samples/blob/master/Samples/WebHooks.List/Deployment%20guide.md) lists the deployment steps used to deploy the SharePoint provider-hosted reference implementation. - - To deploy the Office 365 Azure AD application, use the steps described at [SharePoint webhooks Azure AD reference implementation deployment guide](https://github.com/SharePoint/sp-dev-samples/blob/master/Samples/WebHooks.List.AzureAD/Deployment%20guide.md), which shows you how to use a Web API function as webhook service. - - If you're more interested in using Azure Functions, see the [Azure Functions guide](https://github.com/SharePoint/sp-dev-samples/blob/master/Samples/WebHooks.List.AzureAD/azure%20functions%20guide.md) for more details on how to use Azure Functions in this reference implementation. ### Introduction to webhooks @@ -48,9 +43,9 @@ Webhooks notify your application about changes in SharePoint that the applicatio The reference implementation works with a SharePoint list. To add a webhook to a SharePoint list, your application first creates a webhook subscription by sending a [`POST /_api/web/lists('list-id')/subscriptions`](./lists/create-subscription.md) request. The request includes the following items: -* A payload that identifies the list that you're adding the webhook for. -* The location of your webhook service URL to send the notifications. -* The expiration date of the webhook. +- A payload that identifies the list that you're adding the webhook for. +- The location of your webhook service URL to send the notifications. +- The expiration date of the webhook. After you've requested SharePoint to add your webhook, SharePoint validates that your webhook service endpoint exists. It sends a validation string to your service endpoint. SharePoint expects that your service endpoint returns the validation string within 5 seconds. If this process fails, the webhook creation is canceled. If you've deployed your service, this works and SharePoint returns an HTTP 201 message on the POST request that the application initially sent. The payload in the response contains the ID of the new webhook subscription. @@ -74,8 +69,6 @@ public async Task AddListWebHookAsync(string siteUrl, string } ``` -
- When making a call to SharePoint, you need to provide authentication information, and in this case you're using a **Bearer** authentication header with an **access token**. To obtain the access token, intercept the token via an **ExecutingWebRequest** event handler: ```csharp @@ -89,7 +82,7 @@ cc.ExecutingWebRequest += Cc_ExecutingWebRequest; // Capture the OAuth access token since we want to reuse that one in our REST requests private void Cc_ExecutingWebRequest(object sender, WebRequestEventArgs e) { - this.accessToken = e.WebRequestExecutor.RequestHeaders.Get("Authorization").Replace("Bearer ", ""); + this.accessToken = e.WebRequestExecutor.RequestHeaders.Get("Authorization").Replace("Bearer ", ""); } ``` @@ -123,7 +116,6 @@ To avoid getting the same change repeatedly, it's important that you inform Shar The following are some key things to note about changes: - SharePoint does not call your service in real-time: when a change happens on a list that has a webhook, SharePoint queues a webhook callout. Once each minute, this queue is read and the appropriate service endpoints are called. This batching of requests is important. For example, if a bulk upload of 1000 records occurred at once, batching prevents SharePoint from calling your endpoint 1000 times. So your endpoint is only called once, but when you call the `GetChanges()` method, you get 1000 change events that you need to process. - - To guarantee an immediate response, regardless of the number of changes there, it's important that the workload of your service endpoint runs asynchronously. In the reference implementation, we leveraged the power of Azure: the service serializes the incoming payload and stores it in an Azure Storage queue while there's an Azure web job that runs continuously and checks for messages in the queue. When there are messages in the queue, the web job processes them and also executes your logic asynchronously. ## Complete end-to-end flow @@ -133,14 +125,14 @@ The following diagram describes the complete end-to-end webhook flow. ![Webhooks reference implementation end-to-end flow](../../images/webhook-sample-end-to-end-flow.png) 1. Your application creates a webhook subscription. When it does, it gets the current **changeToken** from the list it created the webhook for. -2. Your application persists the **changeToken** in a persistent storage, such as SQL Azure in this case. -3. A change in SharePoint occurs, and SharePoint calls your service endpoint. -4. Your service endpoint serializes the notification request and stores it in a storage queue. -5. Your web job sees the message in the queue and starts your message processing logic. -6. Your message processing logic retrieves the last used change token from the persistent storage. -7. Your message processing logic uses the `GetChanges()`API to determine what changed. -8. The returned changes are processed and now your application performs what it needs to do based on the changes. -9. Finally, the application persists the last retrieved **changeToken** so that next time it does not receive changes that were already processed. +1. Your application persists the **changeToken** in a persistent storage, such as SQL Azure in this case. +1. A change in SharePoint occurs, and SharePoint calls your service endpoint. +1. Your service endpoint serializes the notification request and stores it in a storage queue. +1. Your web job sees the message in the queue and starts your message processing logic. +1. Your message processing logic retrieves the last used change token from the persistent storage. +1. Your message processing logic uses the `GetChanges()`API to determine what changed. +1. The returned changes are processed and now your application performs what it needs to do based on the changes. +1. Finally, the application persists the last retrieved **changeToken** so that next time it does not receive changes that were already processed. ## Work with webhook renewal @@ -176,7 +168,7 @@ Updating a webhook is done by using the **UpdateListWebHookAsync** method: /// true if successful, exception in case something went wrong public async Task UpdateListWebHookAsync(string siteUrl, string listId, string subscriptionId, string webHookEndPoint, DateTime expirationDateTime, string accessToken) { - // webhook update code... + // webhook update code... } ``` @@ -184,10 +176,8 @@ public async Task UpdateListWebHookAsync(string siteUrl, string listId, st Because SharePoint is calling out to your webhook service endpoint, your endpoint needs to be reachable by SharePoint. This makes development and debugging slightly more complex. The following are some strategies that you can use to make your life easier: -* During initial development, you provide your own serialized payload to your service processing logic. This makes it possible to completely test your processing logic without deploying the service endpoint (and even without configuring a webhook). - -* If you have access to Azure resources, you can deploy your endpoint to Azure by using a debug build and configuring the Azure App Service for debugging. This allows you to set a remote breakpoint and do remote debugging using Visual Studio. - +- During initial development, you provide your own serialized payload to your service processing logic. This makes it possible to completely test your processing logic without deploying the service endpoint (and even without configuring a webhook). +- If you have access to Azure resources, you can deploy your endpoint to Azure by using a debug build and configuring the Azure App Service for debugging. This allows you to set a remote breakpoint and do remote debugging using Visual Studio. - If you do not want to deploy your service during development time, you need to use a secure tunnel for your service. The idea is that you tell SharePoint that the notification service is located on a shared public endpoint. In the client, you install a component that connects to that shared public service, and whenever a call is made to the public endpoint, the client component is notified and it pushes the payload to your service running on localhost. [ngrok](https://ngrok.com/) is an implementation of such a secure tunnel tool that you can use to debug your webhook service locally. ## See also diff --git a/docs/business-apps/get-started/set-up-sharepoint-site-lists-libraries.md b/docs/business-apps/get-started/set-up-sharepoint-site-lists-libraries.md index a57975b02..6bdb52272 100644 --- a/docs/business-apps/get-started/set-up-sharepoint-site-lists-libraries.md +++ b/docs/business-apps/get-started/set-up-sharepoint-site-lists-libraries.md @@ -2,7 +2,6 @@ title: Set up your SharePoint site with lists and libraries description: Set up your SharePoint site with lists and libraries ms.date: 6/23/2020 -ms.prod: sharepoint ms.localizationpriority: high --- diff --git a/docs/business-apps/power-automate/guidance/migrate-from-classic-workflows-to-power-automate-flows.md b/docs/business-apps/power-automate/guidance/migrate-from-classic-workflows-to-power-automate-flows.md index 0d35fdc12..c2a03fc9c 100644 --- a/docs/business-apps/power-automate/guidance/migrate-from-classic-workflows-to-power-automate-flows.md +++ b/docs/business-apps/power-automate/guidance/migrate-from-classic-workflows-to-power-automate-flows.md @@ -1,7 +1,7 @@ --- title: Guidance - Migrate from classic workflows to Power Automate flows in SharePoint description: This article specifically provides guidance about how to plan for transitioning from classic SharePoint Workflows to Power Automate flows. -ms.date: 02/27/2023 +ms.date: 05/12/2023 ms.service: power-automate search.app: - Flow @@ -61,13 +61,13 @@ To learn more about building workflows using Power Automate in SharePoint, start Many people feel there are significant gaps between SharePoint Designer (classic) workflows and Power Automate flows, but the list is not long. Of course, there are some workarounds you should consider in your planning as you move from classic workflows to Power Automate flows. -- **30 day run limit for flows** – SharePoint Designer workflows can run endlessly, but flows have a 30 day lifespan. Getting beyond this limitation means your flow will need to call itself in a re-entrant way to restart the clock ticking. -- **HTTP Connector** – If you make calls to SharePoint's REST API, then you can use the ['Send HTTP Request to SharePoint'](../guidance/working-with-send-sp-http-request.md) action available in the SharePoint connector. Flow also has a generic HTTP connector (as an action), but it is a Premium connector. If you use HTTP calls extensively, you may want to create a “service account” user with a Power Automate license and run these flows with that user account. This also will make it easier to manage the set of flows you consider "enterprise" flows. -- **Reusable Flows** – Using some modular thinking, you can create a master flow which a flow per list or library can call to do the heavy lifting. (In some ways this is even preferable, as you can edit a flow which is used in many locations centrally.) Alternatively, you can use flow actions to discover all of the lists or libraries which match some criteria and run the flow on them all on a timer rather than based on events. -- **Workflow history storage** – Flows maintain a history in the context of the flow itself in the Power Automate dashboard. If you need tracking in your sites, you can have the flow log information in a list you create. -- **Impersonation** - In SharePoint 2010 workflows, you can add an impersonation step to act as a different user. This capability is not readily available in flows. +- **30 day run limit for flows** – SharePoint Designer workflows can run endlessly, but flows have a 30 day lifespan. Getting beyond this limitation means your flow will need to call itself in a re-entrant way to restart the clock ticking. Depending on the solution you choose to accomplish this, this may require a Premium Power Automate license. +- **HTTP Connector** – If you make calls to SharePoint's REST API, then you can use the ['Send HTTP Request to SharePoint'](../guidance/working-with-send-sp-http-request.md) action available in the SharePoint connector. Flow also has a generic HTTP connector (as an action), but it is a Premium connector. If you use HTTP calls extensively, you may want to create a “service account” user with a Power Automate license and run these flows with that user account. This also will make it easier to manage the set of flows you consider "enterprise" flows. +- **Reusable Flows** – Using some modular thinking, you can create a master flow which a flow per list or library can call to do the heavy lifting. In some ways this is even preferable, as you can edit a flow which is used in many locations centrally. This will however require a Premium Power Automate license. Alternatively, you can use flow actions to discover all of the lists or libraries which match some criteria and run the flow on them all on a timer rather than based on events. +- **Workflow history storage** – Flows maintain an extensively detailed history in the context of the flow itself in the Power Automate dashboard for the runs that have occured in the last 28 days. If you need tracking in your sites, or keep historical logging longer than 28 days, you can have the flow log information in a list you create. +- **Impersonation** - In SharePoint 2010 workflows, you can add an impersonation step to act as a different user. You could achieve similar functionality by using different user accounts with different (elevated) priviledges for certain actions. Alternatively you can consider using an Azure Active Directory Application registration, assigning it permissions and using that to directly call into the APIs. The latter will require a Premium Power Automate license and requires more manual effort to make the calls. -While these pain points do exist, you can see there are workarounds for each of them. +While these pain points do exist, you can see there are workarounds for each of them. Do beware that some of these workarounds will require a Power Automate Premium license. Read more about the [license implications](/power-platform/admin/power-automate-licensing/faqs#i-have-multiple-flows-running-under-a-shared-service-account-what-licenses-do-i-need) of doing so and [who will require to have a Premium license](/power-platform/admin/power-automate-licensing/faqs#who-needs-to-purchase-a-premium-license). ## Modern approvals with Power Automate flows diff --git a/docs/business-apps/power-automate/guidance/require-doc-approval.md b/docs/business-apps/power-automate/guidance/require-doc-approval.md index 3dd73b2d9..c5c548834 100644 --- a/docs/business-apps/power-automate/guidance/require-doc-approval.md +++ b/docs/business-apps/power-automate/guidance/require-doc-approval.md @@ -84,10 +84,10 @@ You must ensure you enter the correct site and library name. However, you can ge - Using the *Id* property from the *trigger output* - Comments - Using the *comments* property from the *approval response* - - ETAG -- Using the *ETag* property from the *Get file metadata* action output +- ETAG + - Using the *ETag* property from the *Get file metadata* action output -You can now use the content approval status action to approve and reject the document based on the approval response. +You can now use the content approval status action to approve or reject the document based on the approval response. The end result is that: diff --git a/docs/business-apps/power-automate/guidance/working-with-send-sp-http-request.md b/docs/business-apps/power-automate/guidance/working-with-send-sp-http-request.md index 37de3fa89..18c911428 100644 --- a/docs/business-apps/power-automate/guidance/working-with-send-sp-http-request.md +++ b/docs/business-apps/power-automate/guidance/working-with-send-sp-http-request.md @@ -16,6 +16,8 @@ To work effectively with the SharePoint Send HTTP Request action, see the follow > [!NOTE] > This is a developer-focused action. You must understand how SharePoint REST API works and also how to parse JSON strings in Power Automate. +> +> Additionally, this action only supports SharePoint REST APIs (excluding any deprecated APIs), if you need to access another Microsoft service, you will need to leverage the "HTTP with Microsoft Entra ID" connector. ## Get to know the SharePoint REST/OData APIs diff --git a/docs/business-apps/power-automate/sharepoint-connector-actions-triggers.md b/docs/business-apps/power-automate/sharepoint-connector-actions-triggers.md index 86b1f2efb..6566e5ef0 100644 --- a/docs/business-apps/power-automate/sharepoint-connector-actions-triggers.md +++ b/docs/business-apps/power-automate/sharepoint-connector-actions-triggers.md @@ -1,7 +1,7 @@ --- title: Microsoft SharePoint Connector for Power Automate description: In Power Automate, Microsoft SharePoint Connector supports the following flow triggers and actions. -ms.date: 09/27/2022 +ms.date: 10/23/2024 ms.service: power-automate search.app: - Flow @@ -32,7 +32,7 @@ For more info about how to use this trigger, see this tutorial video: [Introduci ### When an item is deleted -Triggers the flow when you delete an item in a list. To get the properties of a deleted item, you must connect this trigger to the associated SharePoint site on which it is expected to run, using a site collection user account. +Triggers the flow when you delete an item in a list. To get the properties of a deleted item, you must connect this trigger to the associated SharePoint site on which it is expected to run, using a site collection admin account. ### For a selected item @@ -48,7 +48,7 @@ For more info about when Microsoft Syntex and how it classifies files see: [Intr ### When a file is created (properties only) -Triggers the flow when you create a file in a document library, and returns only the custom file properties associated with that file. +Triggers the flow when you create a file in a document library and returns only the custom file properties associated with that file. ### When a file is created in a folder [deprecated] @@ -59,7 +59,7 @@ Triggers the flow when you create a file in a SharePoint folder. This trigger do ### When a file is created or modified (properties only) -Triggers the flow when you create a file, and each time you modify the file properties in a library. Returns only the custom file properties associated with that file. +Triggers the flow when you create a file, and each time you modify the file properties in a library. Specify a value in the "Folder" property to target a specific folder; otherwise, the trigger applies to the entire library. Returns only the custom file properties associated with that file. ### When a file is created or modified in a folder [deprecated] @@ -68,13 +68,9 @@ Triggers the flow when you create a file, and each time you modify the file prop Triggers when a file is created, and also each time it is modified in a SharePoint folder. The trigger does not fire if a file is added/updated in a subfolder. If it is required to trigger on subfolders, multiple triggers should be created. -### When a file is created or modified in a folder (properties only) - -Triggers the flow when you create a file, and each time you modify the file properties in the selected SharePoint folder. The trigger does not activate if you add or update a file in a subfolder. If the flow is required to trigger on subfolders, create different flows for one or more subfolder(s). - ### When a file is deleted -Triggers the flow when you delete a file in a document library. You can optionally specify a folder to watch. When you delete a folder, the trigger activates only once for the deleted folder, including its subfolders. To get the properties of the deleted file, you must connect this trigger to the associated SharePoint site on which the trigger is epxected to run, using a site collection user account. +Triggers the flow when you delete a file in a document library. You can optionally specify a folder to watch. When you delete a folder, the trigger activates only once for the deleted folder, including its subfolders. To get the properties of the deleted file, you must connect this trigger to the associated SharePoint site on which the trigger is expected to run, using a site collection admin account. ### For a selected file @@ -103,7 +99,7 @@ Cancels hub join request. If applicable, specify the same Approval Correlation I ### Check in file -Checks in a checked out file in a document library, which makes the version of the document available to others. +Checks in a checked-out file in a document library, which makes the version of the document available to others. ### Check out file @@ -176,13 +172,13 @@ Returns the list of attachments for the specified list item. To get to the conte Gets all the columns or file properties changed since and until a specified time interval. To get all the columns changed when an item or a file is modified: - Use the _when an item or file is modified_ trigger, and, -- Use the _Trigger Window Start Token_ & _Trigger Window End Token_ outputs from the _when an item or file is modified_ trigger to infer what columnns changed since last time flow checked for item or file updates. +- Use the _Trigger Window Start Token_ & _Trigger Window End Token_ outputs from the _when an item or file is modified_ trigger to infer what columns changed since the last time flow checked for item or file updates. For more info about how to use this action, see this tutorial video: [Introducing 'when an item or file modified' trigger and 'Get changes' action](https://youtu.be/AaWB3xlhJdc) > [!NOTE] > - The list or library should have versioning configured in order to infer what columns or properties got modified since last change. -> - Only column changes are suported for lists and libraries. +> - Only column changes are supported for lists and libraries. > - File content changes are not supported. > - Attachment changes are not supported. > - _Trigger Window Start Token_ & _Trigger Window End Token_ are only available when you use _when an item or file is modified_ trigger. @@ -241,7 +237,7 @@ Grants access to an item or a folder in SharePoint to specific people. ### Join hub site -Joins the requested site to the hub site. An Approval Token is required to complete the join successfully, if that hub requires approval. If applicable, specify the same Approval Correlation Id as used in the **Set hub site join status to pending** action. +Joins the requested site to the hub site. An Approval Token is required to complete the join successfully if that hub requires approval. If applicable, specify the same Approval Correlation Id as used in the **Set hub site join status to pending** action. ### List folder @@ -261,7 +257,7 @@ Moves a folder. Works similarly to the **Move to** command in SharePoint librari ### Resolve person -Returns a single matching user value so it can be assigned to a column of type person. If there are no matches, or multiple matches, this action errors out. +Returns a single matching user value so it can be assigned to a column of type person. If there are no matches or multiple matches, this action errors out. ### Send an HTTP request to SharePoint @@ -372,9 +368,9 @@ When you build a Power Automate flow to be triggered for an item, or for creatin ### Move files and flow runs -When you move one or more files from one document library to another, the original file is moved from the source library to the destination library. Moving the file does not alter any custom metadata, including when the file was created and modified. Hence, this action does not trigger any flows for those file updates associated in the library where it was moved. +When you move one or more files from one document library to another, the original file is moved from the source library to the destination library. Moving the file does not alter any custom metadata, including when the file was created and modified. Hence, this action does not trigger any flows for those file updates associated with the library where it was moved. -### Syncing files to your OneDrive for business and SharePoint document libraries +### Syncing files to your OneDrive for Business and SharePoint document libraries When users sync one or more files from one document library to another, the original file is moved (synced) from your client to the destination library. Syncing the file will not alter any custom metadata including when the file was created and modified. Hence, this action will not trigger any flows for those file syncs in that library or in your OneDrive for business. diff --git a/docs/community/community.md b/docs/community/community.md index 9f661390b..79d2ffccc 100644 --- a/docs/community/community.md +++ b/docs/community/community.md @@ -37,15 +37,15 @@ Found an issue related to SharePoint development around the APIs, documentation, There are numerous community calls for SharePoint development, and you can choose which of them you'd like to join based on your interest and availability. Each call has live demos from SharePoint Engineering, MVPs, or other community members. > [!TIP] -> If you are interested in doing a live demo in any of our community calls, please reach out by leaving a comment on this page and we'll get you a spot for 10-15 minutes for demonstrating your SharePoint development topic(s). +> If you are interested in doing a live demo in any of our community calls, please reach out by [requesting a demo slot](https://aka.ms/community/request/demo) and we'll get you a spot for 10-15 minutes for demonstrating your Microsoft 365 & Power Platform development topic(s). > > **Do's & Dont's**: Interested in presenting during one of the community calls? Keep in mind these are community calls. The focus of these demos should be on learning and topics beneficial to the community. Please refrain from commercial activities such as selling or promoting products or services. Commercial activities in the community calls are not well received by the community and in certain instances may result in stopping the demo early. In your request to present, please be descriptive about what you intend to show to avoid any confusion. If you are not sure if what you want to present is appropriate, just ask in the submission. | Community call | When | Description | Microsoft Teams Link | | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -| [Monthly community call](https://aka.ms/sppnp-call) | Second Tuesday of each month at 8:00 AM PT / 3:00 PM GMT | Monthly community call covering the latest changes in SharePoint development-related topics within the last month, including news, UserVoice updates, and community contributions | [Direct MS Teams link to meeting](https://aka.ms/spdev-call-join) | -| [Special interest group call for SharePoint Framework](https://aka.ms/spdev-spfx-call) | Bi-weekly on Thursdays at 7:00 AM PT / 2:00 PM GMT | SharePoint Engineering updates, SharePoint Framework, PnPJS, CLI for Microsoft 365, and reusable SPFx controls | [Direct MS Teams link to meeting](https://aka.ms/spdev-spfx-call-join) | -| [Special interest group call for general SharePoint development](https://aka.ms/spdev-sig-call) | Bi-weekly on Thursdays at 7:00 AM PT / 2:00 PM GMT | SharePoint Engineering updates, end-to-end solution designs, provisioning, PnP CSOM, and PnP PowerShell | [Direct MS Teams link to meeting](https://aka.ms/spdev-sig-call-join) | +| [Microsoft 365 & Power Platform Call (Microsoft Speakers)](https://aka.ms/community/ms-speakers-call-invite) | Weekly on Tuesdays at 8:00 AM PT / 3:00 PM GMT | Community call with Microsoft speakers covering the latest news from Microsoft engineerung on the Microsoft 365 & Power Platform topics including news, UserVoice updates, and demos | [Direct MS Teams link to meeting](https://aka.ms/community/ms-speakers-call-join) | +| [Viva Connections and SharePoint Framework community call](https://aka.ms/spdev-spfx-call) | Bi-weekly on Thursdays at 7:00 AM PT / 2:00 PM GMT | SharePoint Engineering updates, SharePoint Framework, PnPJS, CLI for Microsoft 365, and reusable SPFx controls | [Direct MS Teams link to meeting](https://aka.ms/spdev-spfx-call-join)| +| [Microsoft 365 & Power Platform Development Community call](https://aka.ms/community/m365-powerplat-dev-call-invite) | Bi-weekly on Thursdays at 7:00 AM PT / 2:00 PM GMT | Latest on Latest on PnP Framework and Core SDK extension, PnP PowerShell, yo Teams, Microsoft Graph Toolkit, Independent Publisher Connector Updates plus community demos | [Direct MS Teams link to meeting](https://aka.ms/community/m365-powerplat-dev-call-join) | ## What’s the supportability statement around PnP open-source components and solutions? diff --git a/docs/community/contribute.md b/docs/community/contribute.md index eb969636d..dfe50aef8 100644 --- a/docs/community/contribute.md +++ b/docs/community/contribute.md @@ -2,7 +2,6 @@ title: SharePoint Developer Community contribution description: Contribution options towards the SharePoint Developer Community. ms.date: 06/07/2022 -ms.prod: sharepoint ms.localizationpriority: medium --- diff --git a/docs/community/open-source-projects.md b/docs/community/open-source-projects.md index 1e60530d7..e3f81365e 100644 --- a/docs/community/open-source-projects.md +++ b/docs/community/open-source-projects.md @@ -2,7 +2,6 @@ title: SharePoint Developer Community open source projects description: Open-source projects coordinated by the SharePoint PnP initiative ms.date: 06/07/2022 -ms.prod: sharepoint ms.localizationpriority: high --- @@ -13,7 +12,7 @@ There are numerous open-source projects that are coordinated by the SharePoint P | Repository | Description | |--------|--------| | [SharePoint Starter kit](https://github.com/SharePoint/sp-starter-kit) | A starter kit for showing how to extend modern experiences in SharePoint Online by extending them with modern extensibility options. | -| [SharePoint Provisioning Service templates](https://github.com/SharePoint/sp-dev-provisioning-templates) | Tenant templates used by the [SharePoint Provisioning Service](https://lookbook.microsoft.com/service-description) to easily provision sample content and structures demonstrating what's possible with modern SharePoint experiences. | +| [SharePoint Provisioning Service templates](https://github.com/SharePoint/sp-dev-provisioning-templates) | Tenant templates previously used by the Look Book Services to easily provision sample content and structures demonstrating what's possible with modern SharePoint experiences. | | [CLI for Microsoft 365](https://pnp.github.io/cli-microsoft365/) | A cross-platform command-line interface (CLI) that allows users on any platform to manage their Microsoft 365 and SharePoint Framework projects. | | [Office 365 Developer PnP Core Component](https://github.com/SharePoint/PnP-Sites-Core) | An extension component that encapsulates commonly used remote CSOM/REST operations as reusable extension methods on out-of-the box CSOM objects. | | [PnP PowerShell cmdlets](/powershell/sharepoint/sharepoint-pnp/sharepoint-pnp-cmdlets) | Allow you to perform complex provisioning and artifact management actions for SharePoint. The commands use CSOM and can work against both SharePoint Online as well as SharePoint on-premises. | diff --git a/docs/community/repositories.md b/docs/community/repositories.md index 1f2fda32d..7f09fcba3 100644 --- a/docs/community/repositories.md +++ b/docs/community/repositories.md @@ -2,7 +2,6 @@ title: SharePoint Developer GitHub repositories description: List of different SharePoint Developer GitHub repositories and their description ms.date: 09/23/2022 -ms.prod: sharepoint ms.localizationpriority: high --- diff --git a/docs/community/social-media.md b/docs/community/social-media.md index d8b5c98ee..de4293a18 100644 --- a/docs/community/social-media.md +++ b/docs/community/social-media.md @@ -5,7 +5,6 @@ author: andrewconnell ms.author: v-johnco ms.date: 06/03/2022 ms.audience: Developer -ms.prod: sharepoint ms.localizationpriority: high --- diff --git a/docs/declarative-customization/column-formatting.md b/docs/declarative-customization/column-formatting.md index 3b82faf18..7e933a74c 100644 --- a/docs/declarative-customization/column-formatting.md +++ b/docs/declarative-customization/column-formatting.md @@ -7,7 +7,7 @@ ms.localizationpriority: high # Use column formatting to customize SharePoint -You can use column formatting to customize how fields in SharePoint lists and libraries are displayed. To do this, you construct a JSON object that describes the elements that are displayed when a field is included in a list view, and the styles to be applied to those elements. The column formatting does not change the data in the list item or file; it only changes how it’s displayed to users who browse the list. Anyone who can create and manage views in a list can use column formatting to configure how view fields are displayed. +You can use column formatting to customize how fields in SharePoint lists and libraries are displayed. To do this, you construct a JSON object that describes the elements that are displayed when a field is included in a list view, and the styles to be applied to those elements. The column formatting doesn't change the data in the list item or file; it only changes how it’s displayed to users who browse the list. Anyone who can create and manage views in a list can use column formatting to configure how view fields are displayed. For example, a list with the fields Title, Effort, Assigned To, and Status with no customizations applied might look like this: @@ -24,17 +24,17 @@ A list with the appearance of the **Effort**, **Assigned To**, and **Status** fi Both column formatting and [SharePoint Framework Field Customizer](../spfx/extensions/get-started/building-simple-field-customizer.md) extensions enable you to customize how fields in SharePoint lists are displayed. The Field Customizer is more powerful because you can use it to write any code that you want to control how a field is displayed. -Column formatting is more easily and broadly applied. However, it is less flexible, because it does not allow for custom code; it only allows for certain predefined elements and attributes. +Column formatting is more easily and broadly applied. However, it's less flexible, because it doesn't allow for custom code; it only allows for certain predefined elements and attributes. The following table compares column formatting and the Field Customizer. | Field type | Column formatting | Field Customizer | | ------------- |:-------------| :-----| | Conditional formatting based on item values and value ranges | Supported | Supported | -| Action links | Support for static hyperlinks that do not launch script | Support for any hyperlink, including those that invoke custom script | +| Action links | Support for static hyperlinks that don't launch script | Support for any hyperlink, including those that invoke custom script | | Data visualizations | Support for simple visualizations that can be expressed using HTML and CSS | Support for arbitrary data visualizations | -If you can accomplish your scenario by using column formatting, it’s typically quicker and easier to do that than to use a Field Customizer. Anyone who can create and manage views in a list can use column formatting to create and publish customizations. Use a Field Customizer for more advanced scenarios that column formatting does not support. +If you can accomplish your scenario by using column formatting, it’s typically quicker and easier to do that than to use a Field Customizer. Anyone who can create and manage views in a list can use column formatting to create and publish customizations. Use a Field Customizer for more advanced scenarios that column formatting doesn't support. ## Get started with column formatting @@ -174,7 +174,7 @@ The following image shows a field with conditional date formatting applied: ![Status field with the Overdue text colored red](../images/sp-columnformatting-overdue.png) -This example colors the current field red when the value inside an item's DueDate is before the current date/time. Unlike some of the previous examples, this example applies formatting to one field by looking at the value inside another field. Note that DueDate is referenced using the `[$FieldName]` syntax. FieldName is assumed to be the internal name of the field. This example also takes advantage of a special value that can be used in date/time fields - `@now`, which resolves to the current date/time, evaluated when the user loads the list view. +This example colors the current field red when the value inside an item's DueDate is before the current date/time. Unlike some of the previous examples, this example applies formatting to one field by looking at the value inside another field. Note that `DueDate` is referenced using the `[$FieldName]` syntax. FieldName is assumed to be the internal name of the field. This example also takes advantage of a special value that can be used in date/time fields - `@now`, which resolves to the current date/time, evaluated when the user loads the list view. > [!NOTE] > If you have spaces in the field name, those are defined as `_x0020_`. For example, a field named "Due Date" should be referenced as `$Due_x0020_Date`. @@ -555,7 +555,7 @@ The following image shows an example of constructing a simple sentence from the ![Screenshot of a field reads "North America, APAC, and Europe"](../images/sp-columnformatting-multi-value-1.png) -This examples uses operator `loopIndex` and `length` to identify the last member of the field, and attribute `forEach` to duplicate HTML elements. +This example uses operator `loopIndex` and `length` to identify the last member of the field, and attribute `forEach` to duplicate HTML elements. ```json { @@ -589,11 +589,12 @@ This examples uses operator `loopIndex` and `length` to identify the last member ``` ### Complex HTML elements formatting + The following image shows an example of building a list of users with pictures, email addresses and a simple counter for the number of members at the top. ![List with name "Owners" and 3 rows where each user in the field has a profile picture, name and email displayed, and a small gray counter of owners at top left corner that has a different color when it says 0.](../images/sp-columnformatting-multi-value-2.png) -This examples uses operator `loopIndex` to control the margins all rows but the first one, and attribute `forEach` to build the list of members. +This example uses operator `loopIndex` to control the margins all rows but the first one, and attribute `forEach` to build the list of members. ```json { @@ -746,7 +747,7 @@ You can use predefined icons from Fluent UI. For details, see the [Fluent UI web ## Creating custom JSON -Creating custom column formatting JSON from scratch is simple if user understands the schema, Monaco Editor is integrated in the formatting pane with pre-filled JSON column schema reference to assist in creation of column formatting, Monaco editor has validation and autocomplete to help in crafting right JSON. User can start adding JSON after the first line that defines the schema location. +Creating custom column formatting JSON from scratch is simple if user understands the schema, Monaco Editor is integrated in the formatting pane with pre-filled JSON column schema reference to help creation of column formatting, Monaco editor has validation and autocomplete to help in crafting right JSON. User can start adding JSON after the first line that defines the schema location. > [!TIP] > At any point, select **Ctrl**+**Space** for property/value suggestions. diff --git a/docs/declarative-customization/customize-default-site-design.md b/docs/declarative-customization/customize-default-site-design.md index e9fc60fb7..afffc07db 100644 --- a/docs/declarative-customization/customize-default-site-design.md +++ b/docs/declarative-customization/customize-default-site-design.md @@ -20,7 +20,6 @@ To customize a default site template, apply a new template script using PowerShe | WebTemplate | 68 | Communication site template | | WebTemplate | 69 | Channel site template | - The following example shows how to use the **IsDefault** switch to apply the Contoso company theme to the default site templates. The site script referenced by ID contains the JSON script to apply the correct theme. ```powershell @@ -32,8 +31,6 @@ C:\> Add-SPOSiteDesign ` -IsDefault ``` -
- ```javascript RestRequest("/_api/Microsoft.SharePoint.Utilities.WebTemplateExtensions.SiteScriptUtility.CreateSiteDesign", {info:{Title:"Contoso company theme", Description:"Applies standard company theme to site", SiteScriptIds:["89516c6d-9f4d-4a57-ae79-36b0c95a817b"], WebTemplate:"68", IsDefault: true}}); ``` @@ -42,7 +39,6 @@ RestRequest("/_api/Microsoft.SharePoint.Utilities.WebTemplateExtensions.SiteScri The default site template for a communication site is the **Topic** template. The default for a team site is the **Team collaboration** template. When you apply a new default site template, it updates the Microsoft-provided default templates. - ## Restore the default site templates To restore a site template to the defaults, remove the site template script that you applied. In the previous example, if the site template created had the ID `db752673-18fd-44db-865a-aa3e0b28698e`, you would remove it as shown in the following example. @@ -51,8 +47,6 @@ To restore a site template to the defaults, remove the site template script that C:\> Remove-SPOSiteDesign db752673-18fd-44db-865a-aa3e0b28698e ``` -
- ```javascript RestRequest("/_api/Microsoft.SharePoint.Utilities.WebTemplateExtensions.SiteScriptUtility.DeleteSiteDesign", {id:"db752673-18fd-44db-865a-aa3e0b28698e"}); ``` diff --git a/docs/declarative-customization/formatting-advanced.md b/docs/declarative-customization/formatting-advanced.md index 6eced27a4..5a4d79813 100644 --- a/docs/declarative-customization/formatting-advanced.md +++ b/docs/declarative-customization/formatting-advanced.md @@ -1,12 +1,12 @@ --- title: Advanced formatting concepts description: Advanced formatting concepts -ms.date: 08/24/2022 +ms.date: 07/16/2025 ms.localizationpriority: high --- # Advanced formatting concepts -You can use some of the following features to make your view and column formatting more information rich and interactable. +You can use some of the following features to make your view and column formatting more information-rich and interactive. ## Create a button to launch a Flow @@ -14,9 +14,9 @@ The following screenshot shows a list with a Flow button added to the Action col ![screenshot of the sample](../images/sp-columnformatting-flow.png) -You can use column formatting to create buttons that, when selected, run Flows on the corresponding list item. For flows that are [solution-aware](/power-automate/overview-solution-flows), the Flow Launch Panel will be displayed after choosing the button and you must select Run Flow to start the flow. For flows that are not solution-aware, The Flow Launch Panel will be displayed after choosing the button and the Flow will just run. +You can use column formatting to create buttons that, when selected, run Flows on the corresponding list item. For flows that are [solution-aware](/power-automate/overview-solution-flows), the Flow Launch Panel will be displayed after choosing the button, and you must select Run Flow to start the flow. For flows that aren't solution-aware, the Flow Launch Panel will be displayed after selecting the button, and the Flow will just run. -To use the sample below, you must substitute the ID of the Flow you want to run. This ID is contained within the `actionParams` property of the `customRowAction` attribute inside the `button` element. +To use the sample below, you must substitute the ID of the Flow you want to run. This ID is contained within the `actionParams` property of the `customRowAction` attribute inside the `button` element. To obtain the ID of a flow that is solution-aware: @@ -28,45 +28,46 @@ To obtain the ID of a flow that is solution-aware: 1. Select Export > Get flow identifier. 1. Copy the ID. -To obtain the ID of a flow that is not solution-aware: +To obtain the ID of a flow that isn't solution-aware: -1. Select **Flow > See your flows** in the SharePoint list where the Flow is configured. +1. Switch to the environment in which the Flow is hosted. 1. Select the Flow you want to run. -1. Copy the ID from the end of the URL. +1. Select Export > Get flow identifier. +1. Copy the ID. -```JSON -{ - "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", - "elmType": "button", - "customRowAction": { - "action": "executeFlow", - "actionParams": "{\"id\": \"edf627d9-20f4-45ba-8bc9-4494bf2ff1be\"}" - }, - "attributes": { - "class": "ms-fontColor-themePrimary ms-fontColor-themeDarker--hover" - }, - "style": { - "border": "none", - "background-color": "transparent", - "cursor": "pointer" - }, - "children": [ + ```JSON { - "elmType": "span", + "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", + "elmType": "button", + "customRowAction": { + "action": "executeFlow", + "actionParams": "{\"id\": \"edf627d9-20f4-45ba-8bc9-4494bf2ff1be\"}" + }, "attributes": { - "iconName": "Flow" + "class": "ms-fontColor-themePrimary ms-fontColor-themeDarker--hover" }, "style": { - "padding-right": "6px" - } - }, - { - "elmType": "span", - "txtContent": "Send to Manager" + "border": "none", + "background-color": "transparent", + "cursor": "pointer" + }, + "children": [ + { + "elmType": "span", + "attributes": { + "iconName": "Flow" + }, + "style": { + "padding-right": "6px" + } + }, + { + "elmType": "span", + "txtContent": "Send to Manager" + } + ] } - ] -} -``` + ``` Additionally, you can use `headerText` and `runFlowButtonText` options within the `actionParams` property to customize portions of the Flow panel itself! See the [button elements](./formatting-syntax-reference.md#customrowaction) portion of the Detailed syntax reference for more details. @@ -82,9 +83,9 @@ On hover - Metadata on the column "Status" is made available in column formattin ![Preview Image 2](../images/HoverImage-2.png) -You can use formatting to define custom call out that can be commissioned basis user defined actions like click or hover. +You can use formatting to define a custom callout that can be commissioned user-defined basis, actions like click or hover. -This example uses `customCardProps`, `openOnEvent`, `directionalHint` and `isBeakVisible`: +This example uses `customCardProps`, `openOnEvent`, `directionalHint`, and `isBeakVisible`: ```JSON { @@ -110,20 +111,20 @@ This example uses `customCardProps`, `openOnEvent`, `directionalHint` and `isBea ## Default cards on hover -Users can now have profile card or file hover card on formatters too, some of the things users can now do: +Users can now have a profile card or a file hover card on formatters too. Some of the things users can now do: -1. Profile card or File Hover card on any column -1. Profile card or Hover card with view formatting +- Profile card or File Hover card on any column +- Profile card or Hover card with view formatting -Hover on a filename with formatting with default file card: +Hover on a filename with formatting with the default file card: ![Preview Image 3](../images/HoverImage-3.png) -Hover on a person column with formatting with default Profile card: +Hover on a person column with formatting with the default Profile card: ![Preview Image 4](../images/HoverImage-4.png) -Both the example uses defaultHoverField +This example uses `defaultHoverField`: ```JSON { @@ -257,9 +258,9 @@ The following image shows a list with a Gallery layout referencing the Category ## Inline Editing With inline editing, formatters have the ability to load field editors to edit field data on an item. -Users need to have edit permissions on the list item and the field type should belong to set of supported types for this feature to work. +Users need to have edit permissions on the list item, and the field type should belong to a set of supported types for this feature to work. -A special json property `inlineEditField` is used with value as the field internal name __`[$FieldName]`__ at the target element in the json. +A special JSON property `inlineEditField` is used with value as the field internal name __`[$FieldName]`__ at the target element in the JSON. ```json { @@ -271,23 +272,23 @@ A special json property `inlineEditField` is used with value as the field intern ![Inline Editing using inlineEditField property](../images/sp-columnformatting-inline-editing.gif) -This allows the users to edit items in-place, within the view, without navigating away to grid based editing or to a item edit form. +This allows the users to edit items in-place, within the view, without navigating away to grid-based editing or to an item edit form. ### Supported Field Types List of supported field types for inline editing: - Single line text -- Multi line text (without RTF) +- Multiline text (without RTF) - Number - DateTime - Choice and MultiChoice -- User and Multi user +- User and Multiuser - Lookup ### Hover Borders and Customizations -The inline editing adds a hover border on the elements to indicate these elements have an associated action. The default border is `neutralSecondary` , and on click, the editor appears with a `themePrimary` border. These border colors can be overriden via setting style on the same element with `inlineEditField` by using some special attributes - `--inline-editor-border-width`, `--inline-editor-border-style`, `--inline-editor-border-radius`, and `--inline-editor-border-color`. +The inline editing adds a hover border on the elements to indicate that these elements have an associated action. The default border is `neutralSecondary`, and on click, the editor appears with a `themePrimary` border. These border colors can be overridden via setting style on the same element with `inlineEditField` by using some special attributes - `--inline-editor-border-width`, `--inline-editor-border-style`, `--inline-editor-border-radius`, and `--inline-editor-border-color`. ```json { @@ -305,9 +306,9 @@ The inline editing adds a hover border on the elements to indicate these element ## Set multiple field values of an Item using customRowAction -With the new `setValue` and `customRowAction` properties, formatters can render action buttons which modify the item internally without opening editors or forms. `setValue` also allows setting multiple field values of the item at once. +With the new `setValue` and `customRowAction` properties, formatters can render action buttons that modify the item internally without opening editors or forms. `setValue` also allows setting multiple field values of the item at once. -The below JSON will set value of `FieldInternalName_1`, `FieldInternalName_2`, and `FieldInternalName_3`with the values provided: +The below JSON will set the value of `FieldInternalName_1`, `FieldInternalName_2`, and `FieldInternalName_3`with the values provided: ```json { @@ -327,45 +328,49 @@ The below JSON will set value of `FieldInternalName_1`, `FieldInternalName_2`, a ### Supported Field Types - Single line text -- Multi line text (without RTF) +- Multiline text (without RTF) - Number - DateTime - Choice and MultiChoice -- User and Multi user +- User and Multiuser ### Value Field values in `actionInput`: - Text values: - a valid string like `"Choice 1"` - - value from other columns : `[$ColumnName]` + - value from other columns: `[$ColumnName]` - an [expression](./formatting-syntax-reference.md#expressions) such as: - `"if([$column]> 10, "Choice A", "Choice B")"` + ``` + "if([$column]> 10, "Choice A", "Choice B")" + ``` or - `{operator: "+", operands" : ["Choice", "A"]}` + ``` + {operator: "+", operands" : ["Choice", "A"]} + ``` - Number: - a valid number - - value from other columns : `[$ColumnName]` + - value from other columns: `[$ColumnName]` - an [expression](./formatting-syntax-reference.md#expressions) - Date values: - a date string - `@now` token - - [expressions](./formatting-syntax-reference.md#expressions) which return a date using builtin date functions - - `addDays` and `addMinutes`, two new functions to support [expressions](./formatting-syntax-reference.md#expressions) like 7 days from today + - [expressions](./formatting-syntax-reference.md#expressions) that return a date using built-in date functions + - `addDays` and `addMinutes`, two new functions to support [expressions](./formatting-syntax-reference.md#expressions) like seven days from today - an empty string `""` clears the field value - Multi-Choice and Multi-Person: - - Multi value fields are special, as they need an array value to save multiple values. - - `appendTo`, `removeFrom`, and `replace`, three functions which can operate on multivalue fields. + - Multi-value fields are special, as they need an array value to save multiple values. + - `appendTo`, `removeFrom`, and `replace`, three functions that can operate on multivalue fields. - `appendTo([$MultiChoiceField], 'MyValue')` - `removeFrom([$MultiUserField], @me)`: removes all occurrences that match the second parameter - - `replace([$MultiChoiceField], 'Choice 1', 'Choice 3')`: replaces all occurrences of second parameter with third. + - `replace([$MultiChoiceField], 'Choice 1', 'Choice 3')`: replaces all occurrences of the second parameter with the third. - Person field values: - user name or email - An empty string `""` clears the field value - an [expression](./formatting-syntax-reference.md#expressions) which returns these values - > [!NOTE] - > A query runs with the string value provided on people column and the first person in the returned results is used. + > [!NOTE] + > A query runs with the string value provided on the people column, and the first person in the returned results is used. diff --git a/docs/declarative-customization/formatting-syntax-reference.md b/docs/declarative-customization/formatting-syntax-reference.md index d3f3b0ce0..bf3f244cf 100644 --- a/docs/declarative-customization/formatting-syntax-reference.md +++ b/docs/declarative-customization/formatting-syntax-reference.md @@ -1,7 +1,7 @@ --- title: Formatting syntax reference description: Formatting syntax reference -ms.date: 12/28/2022 +ms.date: 02/19/2025 ms.localizationpriority: high --- @@ -11,30 +11,40 @@ ms.localizationpriority: high Specifies the type of element to create. Valid elements include: -- div -- span -- a -- img -- svg -- path -- button -- p -- [filepreview](#filepreview) +- `div` +- `span` +- `a` +- [`img`](#img-src-security) +- `svg` +- `path` +- `button` +- `p` +- [`filepreview`](#filepreview) Any other value will result in an error. ### filepreview -Use the special elmType `filepreview` in conjunction with the `src` attribute set to [`@thumbnail.`](#thumbnails) to view thumbnails for files in your document libary. -If the thumbnail loads successfully, a small [brand type icon](https://developer.microsoft.com/en-us/fluentui#/styles/web/office-brand-icons) is visible on the bottom left. If the thumbanil fails to load (or if the file type doesn't support thumbnails), a [file type icon](https://developer.microsoft.com/en-us/fluentui#/styles/web/file-type-icons) is shown instead. +Use the special `elmType` `filepreview` with the `src` attribute set to [`@thumbnail.`](#thumbnails) to view thumbnails for files in your document library. + +If the thumbnail loads successfully, a small [brand type icon](https://developer.microsoft.com/fluentui#/styles/web/office-brand-icons) is visible on the bottom left. If the thumbnail fails to load (or if the file type doesn't support thumbnails), a [file type icon](https://developer.microsoft.com/fluentui#/styles/web/file-type-icons) is shown instead. ```json "elmType": "filepreview", "attributes": { "src": "@thumbnail.medium" - } +} ``` +### img src security + +Images from the following domains are allowed: + +- tenant domain, configured multi-geo domains and vanity domains (`company.sharepoint.com`) +- `cdn.office.net`, `akamaihd.net`, `static2.sharepointonline.com` CDNs + +Most other external image sources are blocked by default in custom formatters. To include external images and allow specific domains or CDNs, the domain needs to be added to a site-level setting. For more information see: [Allow or restrict the ability to embed content on SharePoint pages](https://support.microsoft.com/office/allow-or-restrict-the-ability-to-embed-content-on-sharepoint-pages-e7baf83f-09d0-4bd1-9058-4aa483ee137b) + ## txtContent An optional property that specifies the text content of the element specified by `elmType`. The value of this property can either be a string (including special strings) or an Expression object. @@ -43,6 +53,9 @@ An optional property that specifies the text content of the element specified by An optional property that specifies style attributes to apply to the element specified by `elmType`. This is an object with name-value pairs that correspond to CSS names and values. The values of each property in the style object can either be a string (including special strings) or an Expression object. The following style attributes are allowed. +> [!CAUTION] +> Float style prop no longer supported in custom formatter. Users are encouraged to use Gallery View as a more stable alternative. + ```javascript 'background-color' 'fill' @@ -153,7 +166,7 @@ An optional property that specifies style attributes to apply to the element spe 'clear' 'clip' 'display' -'float' +'float' (Deprecated) 'left' 'overflow' 'position' @@ -203,12 +216,11 @@ An optional property that specifies style attributes to apply to the element spe 'object-fit' 'transform' // Only translate(arg) and translate(arg, arg) are currently supported - ``` -The following example shows the value of a style object. In this example, two style properties (`padding` and `background-color`) will be applied. The `padding` value is a hard-coded string value. The `background-color` value is an Expression that is evaluated to either red (`#ff0000`) or green (`#00ff00`) depending on whether the value of the current field (specified by `@currentField`) is less than 40. For more information, see the Expression object section. +The following example shows the value of a style object. In this example, two style properties (`padding` and `background-color`) will be applied. The `padding` value is a hard-coded string value. The `background-color` value is an Expression that is evaluated to either red (`#ff0000`) or green (`#00ff00`) depending on whether the value of the current field (specified by `@currentField`) is less than 40. For more information, see the [Expression object section](#expressions). -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", @@ -234,7 +246,7 @@ The following example shows the value of a style object. In this example, two st Here's the same sample from above, using the Excel-style expression syntax: -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", @@ -247,7 +259,7 @@ Here's the same sample from above, using the Excel-style expression syntax: ## attributes -An optional property that specifies additional attributes to add to the element specified by `elmType`. This is an object with name-value pairs. Attribute names must be one of the following: +The `attributes` optional property specifies more attributes to add to the element specified by `elmType`. This is an object with name-value pairs. Attribute names must be one of the following: - href - rel @@ -266,7 +278,7 @@ An optional property that specifies additional attributes to add to the element Any other attribute name will result in an error. Attribute values can either be Expression objects or strings. The following example adds two attributes (`target` and `href`) to the element specified by `elmType`. The `target` attribute is hard-coded to a string. The `href` attribute is an expression that will be evaluated at runtime to `http://finance.yahoo.com/quote/` + the value of the current field (`@currentField`). -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "target": "_blank", @@ -276,33 +288,33 @@ Any other attribute name will result in an error. Attribute values can either be ## children -An optional property that specifies child elements of the element specified by `elmType`. The value is specified as an array of `elm` objects. There can be an arbitrary level of nesting. If an element has the `txtContent` property, the child properties are ignored. +The `children` optional property specifies child elements of the element specified by `elmType`. The value is specified as an array of `elm` objects. There can be an arbitrary level of nesting. If an element has the `txtContent` property, the child properties are ignored. ## debugMode -An optional property that is meant for debugging. It outputs error messages and logs warnings to the console. +The `debugMode` optional property is meant for debugging. It outputs error messages and logs warnings to the console. ## forEach -An optional property that allows an element to duplicate itself for each member of a specific multi-value field or an array. The value of `"forEach"` property should be in the format of either `"iteratorName in @currentField"` or `"iteratorName in [$FieldName]"` or `"iteratorName in Expression-Returning-An-Array"`. +The `forEach` optional property allows an element to duplicate itself for each member of a specific multi-value field or an array. The value of `"forEach"` property should be in the format of either `"iteratorName in @currentField"` or `"iteratorName in [$FieldName]"` or `"iteratorName in Expression-Returning-An-Array"`. -`iteratorName` represents the name of iterator variable that is used to represent the current member of the multi-value field. The name of the iterator can be any combination of alphanumeric characters and underscore (`_`) that does not start with a digit. +`iteratorName` represents the name of the iterator variable that is used to represent the current member of the multi-value field. The name of the iterator can be any combination of alphanumeric characters and an underscore (`_`) that doesn't start with a digit. -The field used in the loop must be in a supported field type with multi-value option enabled: Person, Lookup, and Choice. An expression returning an array can also be used. +The field used in the loop must be in a supported field type with multi-value options enabled: Person, Lookup, and Choice. An expression returning an array can also be used. -In the element with `forEach` or its children elements, the iterator variable can be referred as if it is a new field. The index of the iterator can be accessed with `loopIndex` operator. +In the element with `forEach` or its children elements, the iterator variable can be referred to as if it's a new field. The index of the iterator can be accessed with `loopIndex` operator. -`forEach` cannot be applied to the root element, and will render no element if there is no value in the field. +`forEach` can't be applied to the root element, and will render no element if there's no value in the field. -See [here](./column-formatting.md#formatting-multi-value-fields) for examples. +See [Formatting multi-value fields](column-formatting.md#formatting-multi-value-fields) for examples. ## customRowAction -`button` elements can be used to launch a specific action on the parent item. Every `button` element has a required property, `customRowAction`, that specifies an `action` that's taken when the button is clicked. This action must be one of the following values: +`button` elements can be used to launch a specific action on the parent item. Every `button` element has a required property, `customRowAction`, that specifies an `action` that's taken when the button is selected. This action must be one of the following values: -- **defaultClick**: buttons with this action will do the same thing as clicking the list item in an uncustomized view. Below is an example of a button that, when clicked, simulates a click on the item, which results in opening the list item. Adding this example button to a document library simulates a click on the file or folder, which results in the file or folder being opened. +- **defaultClick**: buttons with this action will do the same thing as clicking the list item in an uncustomized view. The following example demonstrates a button that, when selected, simulates a selection on the item, which results in opening the list item. Adding this example button to a document library simulates a selection on the file or folder, which results in the file or folder being opened. - ```JSON + ```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "button", @@ -313,9 +325,9 @@ See [here](./column-formatting.md#formatting-multi-value-fields) for examples. } ``` -- **share**: Clicking the button will open the sharing dialog. Below is an example of this type of button. +- **share**: Selecting the button will open the sharing dialog. The following is an example of this type of button: - ```JSON + ```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "button", @@ -326,12 +338,12 @@ See [here](./column-formatting.md#formatting-multi-value-fields) for examples. } ``` -- **delete**: Clicking the button will open the delete confirmation dialog. -- **editProps**: Clicking the button will open the item properties page in edit mode. -- **openContextMenu**: Clicking the button will open the item's default context menu. -- **setValue**: Clicking the element will update the item with the field values provided. +- **delete**: Selecting the button will open the delete confirmation dialog. +- **editProps**: Selecting the button will open the item properties page in edit mode. +- **openContextMenu**: Selecting the button will open the item's default context menu. +- **setValue**: Selecting the element will update the item with the field values provided. - ```JSON + ```json { "elmType": "div", "txtContent": "[$FieldName]", @@ -339,15 +351,15 @@ See [here](./column-formatting.md#formatting-multi-value-fields) for examples. "action": "setValue", "actionInput": { "FieldInternalName_1": "FieldValue_1", - "FieldInternalName_2": "FieldValue_2", + "FieldInternalName_2": "FieldValue_2" } } } ``` -- **executeFlow**: Clicking the button will launch the specified Flow, specified by ID inside the `actionParams` attribute. For an example of this, see [Create a button to launch a Flow](./formatting-advanced.md#create-a-button-to-launch-a-flow). Below is an example of this type of button. +- **executeFlow**: Selecting the button will launch the specified Flow, specified by ID inside the `actionParams` attribute. For an example of this, see [Create a button to launch a Flow](./formatting-advanced.md#create-a-button-to-launch-a-flow). The following example demonstrates this type of button: - ```JSON + ```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/column-formatting.schema.json", "elmType": "button", @@ -359,36 +371,70 @@ See [here](./column-formatting.md#formatting-multi-value-fields) for examples. } ``` -The `actionParams` attribute can have the following options when using the `executeFlow` action: + The `actionParams` attribute can have the following options when using the `executeFlow` action: + + - **id**: ID of the Flow to launch _(required)_ + - **headerText**: Sets the text at the top of the flow panel _(optional)_ + - **runFlowButtonText**: Sets the text of the primary button in the flow panel _(optional)_ + +- **embed**: Clicking on the button will open a callout with content embedded in it. The content will be determined by the URL provided in the `src` attribute in `actionInput`. You can also control the `height` and `width` of the callout using the `actionInput`. -- **id**: ID of the Flow to launch _(required)_ -- **headerText**: Sets the text at the top of the flow panel _(optional)_ -- **runFlowButtonText**: Sets the text of the primary button in the flow panel _(optional)_ + > [!NOTE] + > + > - The `src` needs to be just the `url` part of an embeddable code generated by an app (usually found in the `src` attribute of the `iframe` element). + > - This action is only available in the newer version of the Microsoft Lists App. + + For more information about allowing or restricting domains, see [Allow or restrict the ability to embed content on SharePoint Lists using custom formatters](https://go.microsoft.com/fwlink/p/?linkid=2258033). + + + ```json + { + "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", + "elmType": "button", + "customRowAction": { + "action": "embed", + "actionInput": { + "src": "https://www.relecloud.com/embed/ll00hWQMJxQ", + "height": "350", + "width": "700" + } + }, + "txtContent": "Click here to open recipe video 👩‍🍳" + } + ``` + + The `actionInput` attribute can have the following options when using the `embed` action: + + - **src**: The URL of the content you want to embed. _(required)_ + - **height**: The height of the callout within which the embedded content will render. The default value is 300. _(optional)_ + - **width**: The width of the callout within which the embedded content will render. The default value is 300. _(optional)_ ## customCardProps -Add a custom card to the element, that shows up on hover or click event. Following customization is available - +Add a custom card to the element, that shows up on hover or `click` event. The following customizations are available: - `"formatter"`: JSON object that defines formatting for custom cards. - `"openOnEvent"`: Event on which the customCard should open. - Valid values: `click`, `hover` -- `"directionalHint"`: Specify the direction relative to the target in which custom card will be positioned. This is the preferred location but is not guaranteed depending on space. +- `"directionalHint"`: Specify the direction relative to the target in which the custom card will be positioned. This is the preferred location but it isn't guaranteed depending on space. - Valid values: `bottomAutoEdge`, `bottomCenter`, `bottomLeftEdge`, `bottomRightEdge`, `leftBottomEdge`, `leftCenter`, `leftTopEdge`, `rightBottomEdge`, `rightCenter`, `rightTopEdge`, `topAutoEdge`, `topCenter`, `topLeftEdge`, `topRightEdge` - `"isBeakVisible"`: Specify if the beak is to be shown or not. -- `"beakStyle"`: Specifies the style object for custom card's beak. +- `"beakStyle"`: Specifies the style object for the custom card's beak. ## defaultHoverField -Adds the profile card for the people fields or file hover card for files in document library. +Adds the profile card for the people fields or file hovercard for files in the document library. - `"defaultHoverField": "[$Editor]"` adds a profile card for the editor field - `"defaultHoverField": "[$FileLeafRef]"` adds a file hover card in documentLibrary ## columnFormatterReference -This will be replaced with the referenced column's formatter JSON. Multi level reference is not supported. +This will be replaced with the referenced column's formatter JSON. Multi-level reference isn't supported. -```JSON +References for multi-choice column formatter templates and column formatters not based on templates are not supported. + +```json { "columnFormatterReference": "[$FieldName]" } @@ -398,20 +444,21 @@ This will be replaced with the referenced column's formatter JSON. Multi level r Adds the field editor for the referenced column. -```JSON +```json { "elmType": "div", "inlineEditField": "[$FieldName]", "txtContent": "[$FieldName]" } ``` + ## filePreviewProps -An optional property, that allows overriding the default styles of file type icon and brand type icon in `filepreview` elmType. +The `filePreviewProps` is an optional property that allows overriding the default styles of file type icon and brand type icon in `filepreview`.elmType. -- `fileTypeIconClass` and `brandTypeIconClass` can be used to provide CSS class names to the file type icon and the brand type icon elements respectively. +The `fileTypeIconClass` and `brandTypeIconClass` can be used to provide CSS class names to the file type icon and the brand type icon elements respectively. -- `fileTypeIconStyle` and `brandTypeIconStyle` can be used to provide [styles](#style) to the file type icon and the brand type icon respectively. These styles will take precedence over the same styles coming from the CSS classes provided by the above 2 properties. +The `fileTypeIconStyle` and `brandTypeIconStyle` can be used to provide [styles](#style) to the file type icon and the brand type icon respectively. These styles will take precedence over the same styles coming from the CSS classes provided by the above two properties. ```json "elmType": "filepreview", @@ -432,49 +479,49 @@ An optional property, that allows overriding the default styles of file type ico ## Expressions -Values for `txtContent`, style properties, and attribute properties can be expressed as expressions, so that they are evaluated at runtime based on the context of the current field (or row). Expression objects can be nested to contain other Expression objects. +Values for `txtContent`, style properties, and attribute properties can be expressed as expressions so that they're evaluated at runtime based on the context of the current field (or row). Expression objects can be nested to contain other Expression objects. -Expressions can be written using Excel-style expressions in SharePoint Online and SharePoint Server Subscription Edition starting with the Version 22H2 feature update, or by using Abstract Syntax Tree expressions in SharePoint Online, SharePoint Server Subscription Edition, and SharePoint Server 2019. +Expressions can be written using Excel-style expressions in SharePoint Online and SharePoint Server Subscription Edition starting with the 22H2 feature update, or by using Abstract Syntax Tree expressions in SharePoint Online, SharePoint Server Subscription Edition, and SharePoint Server 2019. -All fields in ViewFields can be referred in expresisons, even if it is marked `Explicit`. +All fields in `ViewFields` can be referred to in expressions, even if it's marked `Explicit`. ### Excel-style expressions -All Excel-style expressions begin with an equal (`=`) sign. This style of expression is only available in SharePoint Online and SharePoint Server Subscription Edition starting with the Version 22H2 feature update. This style of expression is not available in SharePoint Server Subscription Edition before the Version 22H2 feature update nor SharePoint Server 2019. +All Excel-style expressions begin with an equal (`=`) sign. This style of expression is only available in SharePoint Online and SharePoint Server Subscription Edition starting with the 22H2 feature update. This style of expression isn't available in SharePoint Server 2019 or SharePoint Server Subscription Edition prior to the 22H2 feature update. -This simple conditional expression evaluates to `none` if `@me` is not equal to `[$Author.email]`, and evaluates to `''` otherwise: +This simple conditional expression evaluates to `none` if `@me` isn't equal to `[$Author.email]`, and evaluates to `''` otherwise: -```JSON +```json =if(@me != [$Author.email], 'none', '') ``` -More complex if/else statements can be written like this: +More complex if/else statements can be written like the following: -```JSON +```json =if([$Sentiment] <= 0.3, 'sp-field-severity--blocked', if([$Sentiment] < 0.9,'sp-field-severity--warning','sp-field-severity--good')) ``` -Non-conditional operators that take one or two operands can be written like this: +Non-conditional operators that take one or two operands can be written like the following: -```JSON +```json =[$foo] * -7 ``` -```JSON +```json =sin(@currentField) ``` -```JSON +```json =toString(60 + (sin(6.2831853 * @currentField) * 60)) ``` ### Abstract Syntax Tree expressions -The following example contains an Expression object that performs the following expression: +The following example contains an Expression object that performs the expression: `(@currentField > 40) ? '100%' : (((@currentField * 2.5).toString() + '%')` -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "operator": "?", @@ -511,218 +558,223 @@ The following example contains an Expression object that performs the following ## Operators -Operators specify the type of operation to perform. The following operators are valid values: - -- \+ -- \- -- / -- \* -- < -- \> -- \% -- == -- != -- <= -- \>= -- || -- && -- toString() -- Number() -- Date() -- cos -- sin -- ? -- : -- toLocaleString() -- toLocaleDateString() -- toLocaleTimeString() -- indexOf -- toLowerCase -- join -- length -- abs -- loopIndex -- floor -- ceiling -- pow -- substring -- getDate -- getMonth -- getYear -- toUpperCase -- lastIndexOf -- startsWith -- endsWith -- replace -- replaceAll -- padStart -- padEnd -- getUserImage -- addDays -- addMinutes -- appendTo -- removeFrom -- split - -**Binary arithmetic operators** - The following are the standard arithmetic binary operators that expect two operands: - -- \+ -- \- -- / -- \* -- < -- \> -- \% -- == -- != -- <= -- \>= - -**Unary operators** - The following are standard unary operators that expect only one operand: - -- **toString()**: returns a string representing the object +Operators specify the type of operation to perform. Valid operator values include: + +- `+` +- `-` +- `/` +- `*` +- `<` +- `>` +- `%` +- `==` +- `!=` +- `<=` +- `>=` +- `||` +- `&&` +- `toString()` +- `Number()` +- `Date()` +- `cos` +- `sin` +- `?` +- `:` +- `toLocaleString()` +- `toLocaleDateString()` +- `toLocaleTimeString()` +- `indexOf` +- `toLowerCase` +- `join` +- `length` +- `abs` +- `loopIndex` +- `floor` +- `ceiling` +- `pow` +- `substring` +- `getDate` +- `getMonth` +- `getYear` +- `toUpperCase` +- `lastIndexOf` +- `startsWith` +- `endsWith` +- `replace` +- `replaceAll` +- `padStart` +- `padEnd` +- `getThumbnailImage` +- `getUserImage` +- `addDays` +- `addMinutes` +- `appendTo` +- `removeFrom` +- `split` + +**Binary arithmetic operators** - The standard arithmetic binary operators that expect two operands include are: + +- `+` +- `-` +- `/` +- `*` +- `<` +- `>` +- `%` +- `==` +- `!=` +- `<=` +- `>=` + +**Unary operators** - The standard unary operators that expect only one operand are: + +- `toString()`: returns a string representing the object - `"txtContent": "=toString(45)"` results in _"45"_ -- **Number()**: returns the numeric value, if the operand is not a number, NaN is returned +- `Number()`: returns the numeric value, if the operand isn't a number, NaN is returned - `"txtContent": "=Number('365')"` results in _365_ - `"txtContent": "=Number('Wowee')"` results in _NaN_ - `"txtContent": "=Number(Date('12/26/1981'))"` results in _378190800000_ -- **Date()**: returns a datetime object from the parameter (converts strings or numbers to dates, sensitive to locale) +- `Date()`: returns a datetime object from the parameter (converts strings or numbers to dates, sensitive to locale) - `"txtContent": "=Date('12/26/1981')"` results in _12/26/1981, 12:00:00 AM_ -- **cos**: returns the cosine of the specified angle which should be specified in radians +- `cos`: returns the cosine of the specified angle that should be specified in radians - `"txtContent": "=cos(5)"` results in _0.28366218546322625_ -- **sin**: returns the sine of a number +- `sin`: returns the sine of a number - `"txtContent": "=sin(90)"` results in _0.8939966636005579_ -- **toDateString()**: returns a date in a short-friendly format - - `"txtContent": "=toDateString(@now)"` result doesn't vary based on user's locale and it will look like _"Wed Aug 03 2022"_ -- **toLocaleString()**: returns a language sensitive representation of a date - - `"txtContent":"=toLocaleString(@now)"` results vary based on user's locale, but en-us looks like _"2/5/2019, 1:22:24 PM"_ -- **toLocaleDateString()**: returns a language sensitive representation of just the date portion of a date - - `"txtContent":"=toLocaleDateString(@now)"` results vary based on user's locale, but en-us looks like _"2/5/2019"_ -- **toLocaleTimeString()**: returns a language sensitive representation of just the time portion of a date - - `"txtContent":"=toLocaleTimeString(@now)"` results vary based on user's locale, but en-us looks like _"1:22:24 PM"_ -- **toLowerCase**: returns the value converted to lower case (only works on strings) - _Only available in SharePoint Online_ +- `toDateString()`: returns a date in a short-friendly format + - `"txtContent": "=toDateString(@now)"` result doesn't vary based on the user's locale and it will look like _"Wed Aug 03 2022"_ +- `toLocaleString()`: returns a language-sensitive representation of a date + - `"txtContent":"=toLocaleString(@now)"` results vary based on the user's locale, but en-us looks like _"2/5/2019, 1:22:24 PM"_ +- `toLocaleDateString()`: returns a language-sensitive representation of just the date portion of a date + - `"txtContent":"=toLocaleDateString(@now)"` results vary based on the user's locale, but en-us looks like _"2/5/2019"_ +- `toLocaleTimeString()`: returns a language-sensitive representation of just the time portion of a date + - `"txtContent":"=toLocaleTimeString(@now)"` results vary based on the user's locale, but en-us looks like _"1:22:24 PM"_ +- `toLowerCase`: returns the value converted to lower case (only works on strings) - _Only available in SharePoint Online_ - `"txtContent":"=toLowerCase('DogFood')"` results in _"dogfood"_ -- **abs**: returns the absolute value for a given number - _Only available in SharePoint Online_ +- `abs`: returns the absolute value for a given number - _Only available in SharePoint Online_ - `"txtContent":"=abs(-45)"` results in _45_ -- **length**: returns the number of items in an array (multi-select person or choice field), for all other value types it returns 1 when true and 0 when false. It does NOT provide the length of a string value (*see the `indexOf` workaround explained later on for such operation*). - _Only available in SharePoint Online_ - - `"txtContent":"=length(@currentField)"` might result in _2_ if there are 2 selected values +- `length`: returns the number of items in an array (multi-select person or choice field), for all other value types it returns 1 when true and 0 when false. It does NOT provide the length of a string value (*see the `indexOf` workaround explained later on for such operation*). - _Only available in SharePoint Online_ + - `"txtContent":"=length(@currentField)"` might result in _2_ if there are two selected values - `"txtContent":"=length('Some Text')"` results in _1_ - `"txtContent":"=length('')"` results in _0_ - `"txtContent":"=length(45)"` results in _1_ - `"txtContent":"=length(0)"` results in _0_ -- **floor**: returns the largest integer less than or equal to a given number. - _Only available in SharePoint Online_ +- `floor`: returns the largest integer less than or equal to a given number. - _Only available in SharePoint Online_ - `"txtContent":"=floor(45.5)"` results in _45_ -- **ceiling**: rounds the given number up to the next largest whole number or integer. - _Only available in SharePoint Online_ +- `ceiling`: rounds the given number up to the next largest whole number or integer. - _Only available in SharePoint Online_ - `"txtContent":"=ceiling(45.5)"` results in _46_ -- **getDate**: returns the day of the month of the given date. - _Only available in SharePoint Online_ +- `getDate`: returns the day of the month of the given date. - _Only available in SharePoint Online_ - `"txtContent":"=getDate(Date('12/26/1981'))"` results in _26_ -- **getMonth**: returns the month in the specified date according to local time, as a zero-based value (where zero indicates the first month of the year). - _Only available in SharePoint Online_ +- `getMonth`: returns the month in the specified date according to local time, as a zero-based value (where zero indicates the first month of the year). - _Only available in SharePoint Online_ - `"txtContent":"=getMonth(Date('12/26/1981'))"` results in _11_ -- **getYear**: returns the year of the given date. - _Only available in SharePoint Online_ +- `getYear`: returns the year of the given date. - _Only available in SharePoint Online_ - `"txtContent":"=getYear(Date('12/26/1981'))"` results in _1981_ -- **toUpperCase**: returns the value converted to upper case (only works on strings) - _Only available in SharePoint Online_ +- `toUpperCase`: returns the value converted to upper case (only works on strings) - _Only available in SharePoint Online_ - `"txtContent":"=toUpperCase('DogFood')"` results in _"DOGFOOD"_ - + **Binary operators** - The following are operators that expect two operands: -- **indexOf**: takes 2 operands. The first is the text (or array) you would like to search within, the second is the text you would like to search for. Returns the index value of the first occurrence of the search term within the string (or array). Indexes start at 0. If the search term is not found within the text (or array), -1 is returned. This operator is case-sensitive. - _Only available in SharePoint Online_ +- `indexOf`: takes two operands. The first is the text (or array) you would like to search within, the second is the text you would like to search for. Returns the index value of the first occurrence of the search term within the string (or array). Indexes start at 0. If the search term isn't found within the text (or array), -1 is returned. This operator is case-sensitive. - _Only available in SharePoint Online_ - `"txtContent": "=indexOf('DogFood', 'Dog')"` results in _0_ - `"txtContent": "=indexOf('DogFood', 'F')"` results in _3_ - `"txtContent": "=indexOf('DogFood', 'Cat')"` results in _-1_ - `"txtContent": "=indexOf('DogFood', 'f')"` results in _-1_ -- **join**: takes 2 operands. The first is an array (multi-select person or choice field) and the second is the separating string. Returns a string concatenation of the array values separated by the separating string. - _Only available in SharePoint Online_ +- `join`: takes two operands. The first is an array (multi-select person or choice field) and the second is the separating string. Returns a string concatenation of the array values separated by the separating string. - _Only available in SharePoint Online_ - `"txtContent": "=join(@currentField, ', ')"` might result in _"Apple, Orange, Cherry"_ (depending on the selected values) - - `"txtContent": "=join(@currentField.title, '|')"` might result in _"Chris Kent|Vesa Juvonen|Jeff Teper"_ (depending on the selected persons) -- **pow**: returns the base to the exponent power. - _Only available in SharePoint Online_ + - `"txtContent": "=join(@currentField.title, '|')"` might result in _"Megan Bowen|Alex Wilber"_ (depending on the selected persons) +- `pow`: returns the base to the exponent power. - _Only available in SharePoint Online_ - `"txtContent":"=pow(2,3)"` results in _8_ -- **lastIndexOf**: returns the position of the last occurrence of a specified value in a string (or array) +- `lastIndexOf`: returns the position of the last occurrence of a specified value in a string (or array) - `"txtContent": "=lastIndexOf('DogFood DogFood', 'Dog')"` results in _8_ - `"txtContent": "=lastIndexOf('DogFood DogFood', 'F')"` results in _11_ - `"txtContent": "=lastIndexOf('DogFood DogFood', 'Cat')"` results in _-1_ - `"txtContent": "=lastIndexOf('DogFood DogFood', 'f')"` results in _-1_ -- **startsWith**: determines whether a string begins with the characters of a specified string +- `startsWith`: determines whether a string begins with the characters of a specified string - `"txtContent":"=startsWith('DogFood', 'Dog')"` results in _true_ - `"txtContent":"=startsWith('DogFood', 'Food')"` results in _false_ -- **endsWith**: determines whether a string ends with the characters of a specified string +- `endsWith`: determines whether a string ends with the characters of a specified string - `"txtContent":"=endsWith('DogFood', 'Dog')"` results in _false_ - `"txtContent":"=endsWith('DogFood', 'Food')"` results in _true_ -- **getUserImage**: returns a URL pointing to user's profile image for a given email and preferred size +- `getUserImage`: returns a URL pointing to user's profile image for a given email and preferred size - `"src":"=getUserImage('kaylat@contoso.com', 'small')"` returns a URL pointing to user's profile picture in small resolution - `"src":"=getUserImage('kaylat@contoso.com', 's')"` returns a URL pointing to user's profile picture in small resolution - `"src":"=getUserImage('kaylat@contoso.com', 'medium')"` returns a URL pointing to user's profile picture in medium resolution - `"src":"=getUserImage('kaylat@contoso.com', 'm')"` returns a URL pointing to user's profile picture in medium resolution - `"src":"=getUserImage('kaylat@contoso.com', 'large')"` returns a URL pointing to user's profile picture in large resolution - `"src":"=getUserImage('kaylat@contoso.com', 'l')"` returns a URL pointing to user's profile picture in large resolution -- **appendTo**: returns an array with the given entry appended to the given array +- `appendTo`: returns an array with the given entry appended to the given array - `"txtContent": "=appendTo(@currentField, 'Choice 4')"` returns an array with 'Choice 4' added to the @currentField array - `"txtContent": "=appendTo(@currentField, 'kaylat@contoso.com')"` returns an array with 'kaylat@contoso.com' added to the @currentField array -- **removeFrom**: returns an array with the given entry removed from the given array, if present +- `removeFrom`: returns an array with the given entry removed from the given array, if present - `"txtContent": "=removeFrom(@currentField, 'Choice 4')"` returns an array with 'Choice 4' removed from the @currentField array - `"txtContent": "=removeFrom(@currentField, 'kaylat@contoso.com')"` returns an array with 'kaylat@contoso.com' removed from the @currentField array -- **split**: divides the given string into an ordered list of substrings by searching for the given pattern, and returns an array of these substrings - - `"txtContent": "=split('Hello World', ' ')"` returns an array with 2 strings - 'Hello' and 'World' -- **addDays**: returns a datetime object with days added (or deducted) from the given datetime value +- `split`: divides the given string into an ordered list of substrings by searching for the given pattern, and returns an array of these substrings + - `"txtContent": "=split('Hello World', ' ')"` returns an array with two strings - 'Hello' and 'World' +- `addDays`: returns a datetime object with days added (or deducted) from the given datetime value - `"txtContent": "=addDays(Date('11/14/2021'), 3)"` returns a 11/17/2021, 12:00:00 AM - `"txtContent": "=addDays(Date('11/14/2021'), -1)"` returns a 11/13/2021, 12:00:00 AM -- **addMinutes**: returns a datetime object with minutes added (or deducted) from the given datetime value +- `addMinutes`: returns a datetime object with minutes added (or deducted) from the given datetime value - `"txtContent": "=addMinutes(Date('11/14/2021'), 3)"` returns a 11/14/2021, 12:03:00 AM - `"txtContent": "=addMinutes(Date('11/14/2021'), -1)"` returns a 11/13/2021, 11:59:00 AM **Ternary operators** - The following are operators that expect three operands: -- **substring**: returns the part of the string between the start and end indices. - _Only available in SharePoint Online_ +- `substring`: returns the part of the string between the start and end indices. - _Only available in SharePoint Online_ - `"txtContent":"=substring('DogFood', 3, 4)"` results in _F_ - `"txtContent":"=substring('DogFood', 4, 3)"` results in _F_ - `"txtContent":"=substring('DogFood', 3, 6)"` results in _Foo_ - `"txtContent":"=substring('DogFood', 6, 3)"` results in _Foo_ - The substring() method returns the part of the string between the start and end indexes, or to the end of the string. + The substring() method returns the part of the string between the start and end indexes or to the end of the string. -- **replace**: searches a string (or array) for a specified value and returns a new string (or array) where the specified value is replaced. Incase of string, only the first instance of the value will be replaced. +- `replace`: searches a string (or array) for a specified value and returns a new string (or array) where the specified value is replaced. For strings, only the first instance of the value will be replaced. - `"txtContent":"=replace('Hello world', 'world', 'everyone')"` results in _Hello everyone_ - `"txtContent":"=replace([$MultiChoiceField], 'Choice 1', 'Choice 2')"` returns an array replacing Choice 1 with Choice 2 - `"txtContent":"=replace([$MultiUserField], @me, 'kaylat@contoso.com')"` returns an array replacing @me with 'kaylat@contoso.com' -- **replaceAll**: searches a string for a specified value and returns a new string (or array) where the specified value is replaced. Incase of string, all instances of the value will be replaced. +- `replaceAll`: searches a string for a specified value and returns a new string (or array) where the specified value is replaced. For strings, all instances of the value will be replaced. - `"txtContent":"=replaceAll('H-e-l-l-o W-o-r-l-d', '-', '')"` results in _Hello World_ -- **padStart**: pads the current string with another string until the resulting string reaches the given length. The padding is applied from the start of the current string. +- `padStart`: pads the current string with another string until the resulting string reaches the given length. The padding is applied from the start of the current string. - `"txtContent":"=padStart('DogFood', 10, 'A')"` results in _AAADogFood_ - `"txtContent":"=padStart('DogFood', 10, 'AB')"` results in _ABADogFood_ - `"txtContent":"=padStart('DogFood', 5, 'A')"` results in _DogFood_ -- **padEnd**: pads the current string with a given string until the resulting string reaches the given length. The padding is applied from the end of the current string. +- `padEnd`: pads the current string with a given string until the resulting string reaches the given length. The padding is applied from the end of the current string. - `"txtContent":"=padEnd('DogFood', 10, 'A')"` results in _DogFoodAAA_ - `"txtContent":"=padEnd('DogFood', 10, 'AB')"` results in _DogFoodABA_ - `"txtContent":"=padEnd('DogFood', 5, 'A')"` results in _DogFood_ -- **getThumbnailImage**: returns a URL pointing to image for a given image field and preferred size. - - `"src":"=getThumbnailImage([$ImageField], 400, 200)"` results in a URL pointing to image for a given image field with 400 width and 200 height +- `getThumbnailImage`: returns a URL pointing to an image for a given image field and preferred size. + - `"src":"=getThumbnailImage([$ImageField], 400, 200)"` results in a URL pointing to an image for a given image field with 400 width and 200 height **Conditional operator** - The conditional operator is: -- **?**: Conditional operations written in Abstract Tree Syntax use `?` as the operator. This is to achieve an expression equivalent to a ? b : c, where if the expression a evaluates to true, then the result is b, else the result is c. For Excel style expressions you write these with an `if` statement. Regardless, there are 3 operands. The first is the condition to evaluate. The second is the result when the condition is true. The third is the result when the condition is false. +- `?`: Conditional operations written in Abstract Tree Syntax use `?` as the operator. This is to achieve an expression equivalent to `a ? b : c`, where if the expression `a` evaluates to true, then the result is `b`, else the result is `c`. For Excel-style expressions, you write these with an `if` statement. Regardless, there are three operands. The first is the condition to evaluate. The second is the result when the condition is true. The third is the result when the condition is false. - `"txtContent":"=if(4 < 5, 'yes', 'no')"` results in _"yes"_ - `"txtContent":"=if(4 > 5, 'yes', 'no')"` results in _"no"_ -**Multi-value field-related operators** - The following operators are only used in a context with multi-value field of type Person, Lookup, or Choice. +**Multi-value field-related operators** - The following operators are only used in a context with multi-value fields of type Person, Lookup, or Choice. + +- `length` +- `join` +- `loopIndex` -- length -- join -- loopIndex +`length`, when provided with a field name, returns the number of members in a multi-valued field. When a single-value field is provided, `length` will return 1 when there's a value in that field. -`length`, when provided with a field name, returns the number of members in a multi-valued field. When a single-value field is provided, `length` will return 1 when there is a value in that field. +`join` concatenates values in a multi-value field with a specified separator. The first operand shall point to a value in a multi-value field, for example `"@currentField.lookupValue"`, `"[$AssignedTo.title]"`. The second operand shall be a string literal that is the separator that joins the values together. -`join` concatenates values in a multi-value field with a specified separator. The first operand shall point to a value in a multi-value field, e.g. `"@currentField.lookupValue"`, `"[$AssignedTo.title]"`. The second operand shall be a string literal that is the separator that joins the values together. +`loopIndex`, when provided with the name of the iterator variable, returns the current index (starting from 0) of the iterator. The name of the iterator must be provided as a string literal. `loopIndex` would only work within the element with respective `forEach` enabled or its children elements. -`loopIndex`, when provided with a name of iterator variable, returns the current index (starting from 0) of the iterator. The name of iterator must be provided as a string literal. `loopIndex` would only work within the element with respective `forEach` enabled or its children elements. +For examples, see [Formatting multi-value fields](column-formatting.md#formatting-multi-value-fields). -See [here](./column-formatting.md#formatting-multi-value-fields) for examples. +**String-related operators** - Some of the previously detailed operators can be used when working with string values: -**String related operators** - Some of the previously detailed operators can be used when working with string values +- `+` +- `indexOf` (*for string length workaround*) -- \+ -- indexOf ( *for string length workaround* ) +`+` can be used when there's a need to concatenate strings, for instance: -`+` can be used when there is a need to concatenate strings, for instance : `"txtContent": "=[$column1] + ' ' + [$column2] + 'some other text'"` +```txt +"txtContent": "=[$column1] + ' ' + [$column2] + 'some other text'" +``` -`indexOf` since the operator `length` doesn't work for string value types ( it will return 1 or 0 ), `indexOf` can serve us as a nice workaround to get the length of a string, for instance: `indexOf([$column1] + '^', '^')`. We will use `'^'` or any other character we may want to use to find out the end of the string. +`indexOf` Since the operator `length` doesn't work for string value types (it will return 1 or 0), `indexOf` can serve us as a nice workaround to get the length of a string, for instance: `indexOf([$column1] + '^', '^')`. We'll use `'^'` or any other character to use to find out the end of the string. ## Operands @@ -734,7 +786,7 @@ The values for `txtContent`, styles, and attributes can be either strings or Exp ### "@currentField" -Will evaluate to the value of the current field. +Will evaluate the value of the current field. Some field types are represented as objects. To output a value from an object, refer to a particular property inside that object. For example, if the current field is a person/group field, specify `@currentField.title` to retrieve the person's name, which is normally displayed in list views. The following are the field types that are represented as objects with a list of their properties. @@ -745,7 +797,7 @@ Some field types are represented as objects. To output a value from an object, r The people field object has the following properties (with example values): -```JSON +```json { "id": "122", "title": "Kalya Tucker", @@ -777,7 +829,7 @@ The value of Date/Time fields can be retrieved a few different ways, depending o For example, the following JSON will display the current field (assuming it's a date field) as a date and time string. -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", @@ -790,7 +842,7 @@ For example, the following JSON will display the current field (assuming it's a Here's the same sample from above, using the Excel-style expression syntax: -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", @@ -802,7 +854,7 @@ Here's the same sample from above, using the Excel-style expression syntax: The location field object has the following properties (with example values): -```JSON +```json { "Address": { "City": "Knoxville", @@ -821,7 +873,7 @@ The location field object has the following properties (with example values): The following example shows how a location field might be used on a current field. -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/column-formatting.schema.json", "elmType": "div", @@ -861,7 +913,7 @@ The following example shows how a location field might be used on a current fiel The lookup field object has the following properties (with example values): -```JSON +```json { "lookupId": "100", "lookupValue": "North America", @@ -870,7 +922,7 @@ The lookup field object has the following properties (with example values): The following example shows how a lookup field might be used on a current field. -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "a", @@ -892,7 +944,7 @@ The following example shows how a lookup field might be used on a current field. The hyperlink field object has the following property (with example value): -```JSON +```json { "desc": "SharePoint Patterns and Practices", } @@ -902,7 +954,7 @@ To reference the URL value, use `@currentField`. The following example shows how a hyperlink field might be used on a current field. -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "a", @@ -916,25 +968,20 @@ The following example shows how a hyperlink field might be used on a current fie **Image fields** -The image field object has the following properties (with example values): +The image field object has the following `fileName` property: -```JSON +```json { "fileName": "image.png", - "id": "6bb1d843-0633-4c9a-9a16-90bc5abd1d8e", - "serverRelativeUrl": "/teams/Discovery/SiteAssets/Lists/ad6ed939-0db2-4d85-8a39-8f3497f41eee/image.png", - "serverUrl": "https://contoso.sharepoint.com", - "thumbnailRenderer": { - "spItemUrl": "https://contoso.sharepoint.com:443/_api/v2.1/drives/b!7196759210defdc0/items/2303b15bfa48c74a74758135a0df1201", - "fileVersion": 3, - "sponsorToken": "3u+UR6n8AgABAAAAHxxdXKmiOmUoqKnZlf8lTOhlPYy93EAkbPfs5+49YLFd/B1+omSKbW7DoqNM40/EeVnwJ8kYoXv9zy9D5C5m5A==" - } } ``` +> [!NOTE] +> As of July 2024, just the `fileName` property has a value. + The following example shows how an image field can be used on a current field. -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "img", @@ -953,26 +1000,24 @@ The following example shows how an image field can be used on a current field. The Approval Status field object has the following property (with example value): -```JSON +```json { "displayValue": "Approved", "numeric": 0 } ``` -`displayValue` is localized string of the approval status. +`displayValue` is a localized string of the approval status. -`@currentField` or `[$__ModerationStatus]`will also internally map to the following internal numeric value: +`@currentField` or `[$__ModerationStatus]` will also internally map to the following internal numeric value: -``` -- 0 : Approved -- 1 : Denied -- 2 : Pending -- 3 : Draft -- 4 : Scheduled -``` +- 0: Approved +- 1: Denied +- 2: Pending +- 3: Draft +- 4: Scheduled -`[$_ModerationStatus]` field supports comparisons to both strings as well as the numeric value. The numeric comparisons work across locales and languages, and that will be the recommended way for this field. +`[$_ModerationStatus]` field supports comparisons to both strings and the numeric value. The numeric comparisons work across locales and languages which will be the recommended way for this field. The following expressions evaluate to the output on the right, for when the status is `Pending`: @@ -998,9 +1043,9 @@ The following expressions evaluate to the output on the right, for when the stat "=if([$_ModerationStatus]=='Pending','This Works too!', 'Nope!')" => 'This Works too!' ``` -The following example shows how a approval status field might be used on a current field. +The following example shows how an approval status field might be used on a current field: -```JSON +```json { "elmType": "div", "txtContent": "@currentField.displayValue", @@ -1021,21 +1066,21 @@ If the value of a field is an object, the object's properties can be accessed. F ### "[!FieldName]" -In column and view formatting, you can refer to any field's metadata by specifying the **internal name** of the field surrounded by square brackets and preceded by a exclamation mark: `[!InternalName]`. +In column and view formatting, you can refer to any field's metadata by specifying the **internal name** of the field surrounded by square brackets and preceded by an exclamation mark: `[!InternalName]`. -Currently field's display name is available in this metadata, and can be accessed using DisplayName property: `[!SalesLead.DisplayName]`. +Currently field's display name is available in this metadata, and can be accessed using `DisplayName` property: `[!SalesLead.DisplayName]`. ### "@currentWeb" -This will evaluate to the absolute URL for the site. This is equivalent to the `webAbsoluteUrl` value within the page context. This value is only available in SharePoint Online. +This will evaluate the absolute URL for the site. This is equivalent to the `webAbsoluteUrl` value within the page context. This value is only available in SharePoint Online. ### "@me" -This will evaluate to the email address of the current logged in user. +This will evaluate the email address of the currently logged-in user. -This field can be used to display the current user's email address, but more likely it will be used within conditions. The following is an example of setting the color for a person field to red when it is equal to the current logged in user and blue otherwise: +This field can be used to display the current user's email address, but more likely it will be used within conditions. The following is an example of setting the color for a person field to red when it's equal to the currently logged-in user and blue otherwise: -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", @@ -1061,7 +1106,7 @@ This field can be used to display the current user's email address, but more lik Here's the same sample from above, using the Excel-style expression syntax: -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", @@ -1074,15 +1119,15 @@ Here's the same sample from above, using the Excel-style expression syntax: ### "@now" -This will evaluate to the current date and time. +This will evaluate the current date and time. ### "@rowIndex" -This will evaluate to the rendered index of a row within a view. This value is based on render position and will remain consistent based on position even as views are sorted and filtered. Indexes start at 0. This value is only available in SharePoint Online. +This will evaluate the rendered index of a row within a view. This value is based on render position and will remain consistent based on position even as views are sorted and filtered. Indexes start at 0. This value is only available in SharePoint Online. Here's an example of using the value within a view format to apply alternating styles to rows: -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/view-formatting.schema.json", "additionalRowClass": "=if(@rowIndex % 2 == 0,'ms-bgColor-themeLighter ms-bgColor-themeLight--hover','')" @@ -1091,7 +1136,7 @@ Here's an example of using the value within a view format to apply alternating s ### "@window.innerHeight" -This will evaluate to a number equal to the height of the browser window (in pixels) when the list was rendered. +This will be evaluated to a number equal to the height of the browser window (in pixels) when the list is rendered. ### "@window.innerWidth" @@ -1099,21 +1144,21 @@ This will evaluate to a number equal to the width of the browser window (in pixe ### Thumbnails -In a document library, there is a series of tokens that can be used to retrieve the URL to the thumbnail of a file, including: +In a document library, there's a series of tokens that can be used to retrieve the URL to the thumbnail of a file, including: -- `@thumbnail.small`, `@thumbnail.medium`, and `@thumbnail.large` evaluate to the thumbnail URL in 3 different predefined sizes. -- `@thumbnail.` evaluates to the URL to the largest thumbnails that is not larger than the bounding size in both width and height. For example, `@thumbnail.150` evaluates to the URL to a thumbnail not larger than 150×150 pixels. -- `@thumbnail.x` evaluates to the URL to the largest thumbnail that is not larger than the bounding width and bounding height. For example, `@thumbnail.100x200` evaluates to the URL to a thumbnail not wider than 100 pixels and not higher than 200 pixels. +- `@thumbnail.small`, `@thumbnail.medium`, and `@thumbnail.large` evaluate the thumbnail URL in three predefined sizes. +- `@thumbnail.` evaluates the URL to the largest thumbnail that isn't larger than the bounding size in both width and height. For example, `@thumbnail.150` evaluates to the URL to a thumbnail not larger than 150×150 pixels. +- `@thumbnail.x` evaluates the URL to the largest thumbnail that isn't larger than the bounding width and bounding height. For example, `@thumbnail.100x200` evaluates to the URL to a thumbnail not wider than 100 pixels and not higher than 200 pixels. These tokens will yield no value on non-file items including folders. > [!NOTE] -> The aspect ratio of thumbnail generated is the same as how the file looks like, changing the bounding sizes will not affect the aspect ratio of the thumbnail. +> The aspect ratio of the thumbnail generated is the same as how the file looks, changing the bounding sizes will not affect the aspect ratio of the thumbnail. > [!TIP] > Thumbnails are only available for a list of supported file formats. It means that sometimes the URL generated is not accessible due to lack of support on certain formats. However, if a valid thumbnail token is set as the _only_ `src` attribute of an `img` tag, we will take care of it and hide the image when it is not available. -```JSON +```json { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "img", @@ -1130,7 +1175,7 @@ These tokens will yield no value on non-file items including folders. Default file hover card using FileLeafRef -```JSON +```json { "elmType": "img", "style": { @@ -1147,24 +1192,24 @@ Default file hover card using FileLeafRef ### displayValue -The following column types can use displayValue property to get the default rendered value, based on the column setting +The following column types can use `displayValue` property to get the default-rendered value, based on the column setting: -* Date/Time -* Number -* Yes/No -* Currency -* Approval Status +- Date/Time +- Number +- Yes/No +- Currency +- Approval Status -```JSON +```json { "elmType": "div", "txtContent": "@currentField.displayValue" } ``` -This also works with field name +This also works with field name: -```JSON +```json { "elmType": "div", "txtContent": "[$FieldName.displayValue]" @@ -1173,12 +1218,12 @@ This also works with field name ### "@isSelected" -This will evaluate to `true` for selected item(s) in a view and `false` otherwise. +This will evaluate to `true` for the selected item(s) in a view and `false` otherwise. ### "@lcid" -This will evaluate to the LCID of current culture. This can be used to format the date, time and numbers. +This will evaluate to the LCID of the current culture. This can be used to format the date, time, and numbers. ### "@UIlcid" -This will evaluate to the LCID of current UI culture. This can be used to show localized display strings. +This will evaluate to the LCID of the current UI culture. This can be used to show localized display strings. diff --git a/docs/declarative-customization/get-started-create-site-design.md b/docs/declarative-customization/get-started-create-site-design.md index efd9912c0..92b22361c 100644 --- a/docs/declarative-customization/get-started-create-site-design.md +++ b/docs/declarative-customization/get-started-create-site-design.md @@ -19,55 +19,55 @@ Each action is specified by the "verb" value in the JSON script. Also, actions c 1. Download and install the [SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588). If you already have a previous version of the shell installed, uninstall it first and then install the latest version. 1. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. -1. Create - and assign the JSON that describes the new script - to a variable as shown in the following PowerShell code. You can view and reference the latest JSON schema file here: https://developer.microsoft.com/json-schemas/sp/site-design-script-actions.schema.json - - ```powershell - $site_script = ' - { - "$schema": "https://developer.microsoft.com/json-schemas/sp/site-design-script-actions.schema.json", - "actions": [ - { - "verb": "createSPList", - "listName": "Customer Tracking", - "templateType": 100, - "subactions": [ - { - "verb": "setDescription", - "description": "List of Customers and Orders" - }, - { - "verb": "addSPField", - "fieldType": "Text", - "displayName": "Customer Name", - "isRequired": false, - "addToDefaultView": true - }, - { - "verb": "addSPField", - "fieldType": "Number", - "displayName": "Requisition Total", - "addToDefaultView": true, - "isRequired": true - }, - { - "verb": "addSPField", - "fieldType": "User", - "displayName": "Contact", - "addToDefaultView": true, - "isRequired": true - }, - { - "verb": "addSPField", - "fieldType": "Note", - "displayName": "Meeting Notes", - "isRequired": false - } - ] - } - ] - } - ' - ``` +1. Create - and assign the JSON that describes the new script - to a variable as shown in the following PowerShell code. You can view and reference the latest JSON schema file: [https://developer.microsoft.com/json-schemas/sp/site-design-script-actions.schema.json](https://developer.microsoft.com/json-schemas/sp/site-design-script-actions.schema.json) + + ```powershell + $site_script = ' + { + "$schema": "https://developer.microsoft.com/json-schemas/sp/site-design-script-actions.schema.json", + "actions": [ + { + "verb": "createSPList", + "listName": "Customer Tracking", + "templateType": 100, + "subactions": [ + { + "verb": "setDescription", + "description": "List of Customers and Orders" + }, + { + "verb": "addSPField", + "fieldType": "Text", + "displayName": "Customer Name", + "isRequired": false, + "addToDefaultView": true + }, + { + "verb": "addSPField", + "fieldType": "Number", + "displayName": "Requisition Total", + "addToDefaultView": true, + "isRequired": true + }, + { + "verb": "addSPField", + "fieldType": "User", + "displayName": "Contact", + "addToDefaultView": true, + "isRequired": true + }, + { + "verb": "addSPField", + "fieldType": "Note", + "displayName": "Meeting Notes", + "isRequired": false + } + ] + } + ] + } + ' + ``` The previous script creates a new SharePoint list named **Customer Tracking**. It sets the description and adds four fields to the list. Note that each of these are considered an action. Site scripts are limited to 30 cumulative actions (across one or more scripts that may be called in a site template) if applied programmatically using the `Invoke-SPOSiteDesign` command. If they are applied through the UI or using the `Add-SPOSiteDesignTask` command then the limit is 300 cumulative actions (or 100K characters). @@ -102,13 +102,12 @@ C:\> Add-SPOSiteDesign The previous cmdlet creates a new site template named Contoso customer tracking. -| Parameter | Value | Site template type | -| :------------------- | :------------------- |:----------------| -| WebTemplate | 64 | Team site template | -| WebTemplate | 1 | Team site (with group creation disabled) | -| WebTemplate | 68 | Communication site template | -| WebTemplate | 69 | Channel site template | - +| Parameter | Value | Site template type | +| :---------- | :---- | :--------------------------------------- | +| WebTemplate | 64 | Team site template | +| WebTemplate | 1 | Team site (with group creation disabled) | +| WebTemplate | 68 | Communication site template | +| WebTemplate | 69 | Channel site template | The JSON response displays the **ID** of the new site template. You can use it in subsequent cmdlets to update or modify the site template. @@ -123,13 +122,13 @@ Now that you've added a site script and site template, you can use it to create 1. Go to the home page of the SharePoint site that you are using for development. 1. Choose **Create site**. 1. Choose the type of site you need to use. SharePoint will create a team site using the Microsoft **Team collaboration template** or a communication site using the Microsoft **Topic** template unless another custom site template is set as default. -2. Choose **Next**. -4. In **Site name**, enter a name for the new site **Customer order tracking**. -7. Choose **Finish**. -5. Next, go to **Settings** and select **Apply a site template**. -5. Select the site template you just created. -8. Once applied, your new template will display under the tab in the template viewer titled **From your organization.** -9. When the new template has been applied, you will see the custom list on the page. +1. Choose **Next**. +1. In **Site name**, enter a name for the new site **Customer order tracking**. +1. Choose **Finish**. +1. Next, go to **Settings** and select **Apply a site template**. +1. Select the site template you just created. +1. Once applied, your new template will display under the tab in the template viewer titled **From your organization.** +1. When the new template has been applied, you will see the custom list on the page. ### Apply to an existing site @@ -142,9 +141,9 @@ You can apply templates to existing site collections in bulk by using the [Invok 1. Group-connected team sites 1. Team sites that not connected to a Microsoft 365 group 1. Communication sites -2. Channel sites -3. Classic team sites -4. Classic publishing sites +1. Channel sites +1. Classic team sites +1. Classic publishing sites The REST API to apply a site template to an existing site collection is **ApplySiteDesign**. @@ -157,7 +156,6 @@ You can also use the `Set-SPOHubSite` cmdlet. Review the [PowerShell cmdlets for >[!NOTE] > [Channel sites](/sharepoint/teams-connected-sites) are automatically blocked from joining a hub site. - ## See also - [SharePoint site template and site script overview](site-design-overview.md) diff --git a/docs/declarative-customization/list-form-conditional-show-hide.md b/docs/declarative-customization/list-form-conditional-show-hide.md index 6a544ed16..1d4afe455 100644 --- a/docs/declarative-customization/list-form-conditional-show-hide.md +++ b/docs/declarative-customization/list-form-conditional-show-hide.md @@ -1,7 +1,7 @@ --- title: Show or hide columns in a list form description: Customize which columns to show or hide using a conditional formula in the list form by constructing a simple formula that are equations performing conditional checks on values in a SharePoint list or library. -ms.date: 06/28/2022 +ms.date: 07/28/2025 ms.localizationpriority: high --- @@ -27,7 +27,7 @@ To show or hide a column in a list or library form: 1. In the **Edit columns** pane, check (to show) or uncheck (to hide) the checkbox for the column or columns as needed. > [!NOTE] - > If you want to re-arrange the order of the columns, either drag-and-drop the column name, or first select the far right hand edge of the column name to display the options menu **(...)** and then select Move Up or Move Down as preferred. + > If you want to re-arrange the order of the columns, either drag-and-drop the column name or first select the far right-hand edge of the column name to display the options menu **(...)** and then select Move Up or Move Down as preferred. 1. When you're finished, select **Save**. @@ -38,7 +38,7 @@ You can show or hide columns in a list form based on another column's value by s To specify a conditional formula for a column, in the **Edit columns** pane: 1. Navigate to the desired column for which you want to set a conditional formula -1. Select the far right hand edge of the column name to display the options menu **(...)** +1. Select the far right-hand edge of the column name to display the options menu **(...)** 1. In the more options, select **Edit conditional formula**. 1. In the **Edit conditional formula** dialog: - To determine whether this column is shown or hidden, specify a conditional formula based on the value of another column. @@ -56,21 +56,22 @@ For example, the following formula checks if the value for the *Category* column =if([$Category] == 'Product Management', 'true', 'false') ``` -Returning _true_ results in showing the column on the form while returning _false_ hides the column. +Returning _true_ shows the column on the form while returning _false_ hides the column. -The column is represented by specifying the **internal name** of the field surrounded by square brackets and preceded by a dollar sign: `[$InternalName]`. For example, to get the value of a field with an internal name of "ProductName", use `[$ProductName]`. +The column is represented by specifying the **internal name** of the field preceded by a dollar sign and surrounded by square brackets: `[$InternalName]`. For example, to get the value of a field with an internal name of "ProductName", use `[$ProductName]`. #### Unsupported column types in conditional formulas While the formula supports many of the available column types, we do not currently support the following column types: -* Person or Group with multiple selections -* Choice with multiple selections -* Time calculations in Date and Time column -* Currency columns -* Location columns -* Calculated columns -* Managed Metadata columns +- Person or Group with multiple selections +- Choice with multiple selections +- Lookup with multiple selections +- Time calculations in **Date and Time** column +- Currency columns +- Location columns +- Calculated columns +- Managed Metadata columns #### Quick formula reference @@ -98,7 +99,7 @@ You can also do arithmetic calculations, such as adding the value of two columns ##### Date column -The following formula checks if the date column `[$StartDate]` is equal to a specific date. To do so, it uses the *Date()* function to convert a given string into a date: +The following formula checks if the date column `[$StartDate]` equals a specific date. To do so, it uses the *Date()* function to convert a given string into a date: ``` =if([$StartDate] == Date('4/6/2020'), 'true', 'false') @@ -126,17 +127,26 @@ The following formula checks if an email of person column `[$Owner]` is equal to ##### Boolean (Yes/No) column -The following formula checks if the Yes/No column `[$Promoted]` is equal to a Yes. To do so, it checks for the value _true_ which maps to _Yes_ for users. +The following formula checks if the Yes/No column `[$Promoted]` equals a Yes. To do so, it checks for the value _true_ which maps to _Yes_ for users. ``` =if([$Promoted] == true, 'true', 'false') ``` +The following are also valid: + +``` +=if([$Promoted], 'true', 'false') +``` + +``` +=[$Promoted] +``` + ##### Lookup column > [!NOTE] -> When accessing lookup columns in column or view formatting, you have access to the lookup value and lookup id as separate values. In form formatting and conditional field expressions, both values are returned as a single line of text. For instance, a lookup column referencing an item with item ID 1 (in the source list) with a value of `Toronto` will have a value of `1;#Toronto` when used in form formatting or conditional field expressions. - +> When accessing lookup columns in a column or view formatting, you can access the lookup value and lookup id as separate values. In form formatting and conditional field expressions, both values are returned as a single line of text. For instance, a lookup column referencing an item with item ID 1 (in the source list) with a value of `Toronto` will have a value of `1;#Toronto` when used in form formatting or conditional field expressions. The following formula checks if the lookup column `[$City]` has a value equal to *Toronto*. To do so, it splits the lookup value result by the separator and checks against the value. diff --git a/docs/declarative-customization/list-form-configuration.md b/docs/declarative-customization/list-form-configuration.md index 0a1ea1cab..ab641654f 100644 --- a/docs/declarative-customization/list-form-configuration.md +++ b/docs/declarative-customization/list-form-configuration.md @@ -7,9 +7,9 @@ ms.localizationpriority: high # Configure the list form -You can configure the list form in a list or library with a custom header, footer and the form body with one or more sections with fields in each of those sections. The form configuration does not change the data in the list item or file; it only changes how the form is displayed to users who browse the list or library. Anyone who can create and manage views in a list can use form configuration to configure the form with header, footer and body with sections. +You can configure the list form in a list or library with a custom header, footer and the form body with one or more sections with fields in each of those sections. The form configuration does not change the data in the list item or file; it only changes how the form is displayed to users who browse the list or library. Anyone who can create and manage views in a list can use form configuration to configure the form with header, footer, and body with sections. -To configure a form, you will use JSON formatters that you are already familiar with when formatting a [column](column-formatting.md) or a [view](view-formatting.md) in a list or library. Form configuration allows for certain predefined elements and attributes to build the custom header, footer and body with one or more sections. +To configure a form, you will use JSON formatters that you are already familiar with when formatting a [column](column-formatting.md) or a [view](view-formatting.md) in a list or library. Form configuration allows for certain predefined elements and attributes to build the custom header, footer, and body with one or more sections. ## Get started @@ -18,23 +18,24 @@ To configure the form in a list or library: 1. Go to the list or library for which you want to configure the form. 1. If you are in a list: - - Open an item to view the item details in the display form. + - Open an item to view the item details in the display form. 1. If you are in a document library: - - Select a file. - - Select ... - - Select More - - Select Properties + - Select a file. + - Select ... + - Select More + - Select Properties 1. At the top of the form, expand **Edit Form** icon and then select **Configure layout** ![Configure list form](images/list-form-configuration-menu.png) 1. In the **Format** pane, you can choose to apply formatting to the following form sections: - - Header - - Body - - Footer + + - Header + - Body + - Footer ## Configure custom header @@ -50,66 +51,67 @@ To configure the form in a list or library: ```JSON { - "elmType": "div", - "attributes": { - "class": "ms-borderColor-neutralTertiary" - }, - "style": { - "width": "99%", - "border-top-width": "0px", - "border-bottom-width": "1px", - "border-left-width": "0px", - "border-right-width": "0px", - "border-style": "solid", - "margin-bottom": "16px" - }, - "children": [ + "elmType": "div", + "attributes": { + "class": "ms-borderColor-neutralTertiary" + }, + "style": { + "width": "99%", + "border-top-width": "0px", + "border-bottom-width": "1px", + "border-left-width": "0px", + "border-right-width": "0px", + "border-style": "solid", + "margin-bottom": "16px" + }, + "children": [ + { + "elmType": "div", + "style": { + "display": "flex", + "box-sizing": "border-box", + "align-items": "center" + }, + "children": [ { - "elmType": "div", - "style": { - "display": "flex", - "box-sizing": "border-box", - "align-items": "center" - }, - "children": [ - { - "elmType": "div", - "attributes": { - "iconName": "Group", - "class": "ms-fontSize-42 ms-fontWeight-regular ms-fontColor-themePrimary", - "title": "Details" - }, - "style": { - "flex": "none", - "padding": "0px", - "padding-left": "0px", - "height": "36px" - } - } - ] - }, + "elmType": "div", + "attributes": { + "iconName": "Group", + "class": "ms-fontSize-42 ms-fontWeight-regular ms-fontColor-themePrimary", + "title": "Details" + }, + "style": { + "flex": "none", + "padding": "0px", + "padding-left": "0px", + "height": "36px" + } + } + ] + }, + { + "elmType": "div", + "attributes": { + "class": "ms-fontColor-neutralSecondary ms-fontWeight-bold ms-fontSize-24" + }, + "style": { + "box-sizing": "border-box", + "width": "100%", + "text-align": "left", + "padding": "21px 12px", + "overflow": "hidden" + }, + "children": [ { - "elmType": "div", - "attributes": { - "class": "ms-fontColor-neutralSecondary ms-fontWeight-bold ms-fontSize-24" - }, - "style": { - "box-sizing": "border-box", - "width": "100%", - "text-align": "left", - "padding": "21px 12px", - "overflow": "hidden" - }, - "children": [ - { - "elmType": "div", - "txtContent": "='Contact details for ' + [$Title]" - } - ] + "elmType": "div", + "txtContent": "='Contact details for ' + [$Title]" } - ] + ] + } + ] } ``` + 1. To preview your changes, click the **Preview** button. 1. To save your changes, click the **Save** button. 1. Close and open the form again to view the custom header. @@ -172,7 +174,7 @@ To configure the form in a list or library: - One or more sections can be defined for a body. - Each section can reference one or more columns in the list or library. - A column can be referenced only in one section. - - If a column is referenced in multiple sections, the first section where the column is referenced will take the precedence. + - If a column is referenced in multiple sections, the first section where the column is referenced will take precedence. - A column not referenced in any of the sections will be automatically referenced in the last section. - New columns added will be automatically referenced in the last section. @@ -180,23 +182,23 @@ To configure the form in a list or library: ```JSON { - "sections": [ - { - //give a display name for the section - "displayname": "", - "fields": [ - //reference your fields here using their display name - "Title" - ] - }, - { - //give a display name for the section - "displayname": "", - "fields": [ - //reference your fields here using their display name - ] - } - ] + "sections": [ + { + //give a display name for the section + "displayname": "", + "fields": [ + //reference your fields here using their display name + "Title" + ] + }, + { + //give a display name for the section + "displayname": "", + "fields": [ + //reference your fields here using their display name + ] + } + ] } ``` @@ -204,30 +206,30 @@ To configure the form in a list or library: ```JSON { - "sections": [ - { - "displayname": "", - "fields": [ - "Title" - ] - }, - { - "displayname": "Details", - "fields": [ - "Department", - "Email", - "Country" - ] - }, - { - "displayname": "Application", - "fields": [ - "Application Id", - "Approver", - "Reviewer" - ] - } - ] + "sections": [ + { + "displayname": "", + "fields": [ + "Title" + ] + }, + { + "displayname": "Details", + "fields": [ + "Department", + "Email", + "Country" + ] + }, + { + "displayname": "Application", + "fields": [ + "Application Id", + "Approver", + "Reviewer" + ] + } + ] } ``` @@ -241,3 +243,60 @@ To configure the form in a list or library: 1. To preview your changes, click the **Preview** button. 1. To save your changes, click the **Save** button. 1. Close and open the form again to view the custom body. + + +## Custom Formatter for Read-Only Fields + +### Introduction + +Microsoft Lists offers a powerful way to organize information and collaborate with your team. With the rise of AI-based list item creation, users often need to view but not edit certain fields — like system-generated data or bot-added details. To meet this need, a new custom formatter feature is proposed to allow fields to appear as read-only in list forms. + +### Why Read-Only Fields Matter + +Currently, read-only fields are hidden from New Item and Edit forms. This creates challenges when AI bots or automated processes create items containing critical data that users need to see but not modify. For example: + +- A bot creates a customer service ticket with Issue details Issue Title, Issue Description. +- Users should see this information to take actions (e.g., send an email), but not be able to change it. + +The new custom formatter solves this by allowing these fields to display as read-only. + +### How the Custom Formatter Works + +The custom formatter introduces a new JSON configuration to mark fields as read-only in the form views. + +### JSON Structure + +```json +{ + "sections": [{}], + "fieldsettings": [ + { + "name": "fieldName", + "readonly": true + } + ] +} +``` + +- name: The internal name of the field. +- readonly: When set to true, the field is displayed as read-only. + +### Behavior in Different Form Views + +The custom formatter ensures a consistent user experience: + +- New Item form: The read-only field will not be shown. +- Edit form: The field is displayed without an editable textbox, similar to a Calculated Column. +- Edit all mode: The field remains visible and uneditable. + +The Save button works as expected — no accidental modifications to the read-only fields. + +### Example Use Case + +Imagine a CRM bot creating tickets with pre-filled Issue details. Using this formatted: + +- Issue Title (read-only): Users can see and copy the Issue Title but can't modify it. +- Issue Description (read-only): Users can see and copy the Issue Description but can't modify it. +- Issue Source (read-only): Users can click on the Issue source link but can't modify it. + +![image](https://github.com/user-attachments/assets/74c21844-a966-4930-93bb-cce10d69fa0e) diff --git a/docs/declarative-customization/site-design-json-schema.md b/docs/declarative-customization/site-design-json-schema.md index 207b3a4dc..2ed0397a6 100644 --- a/docs/declarative-customization/site-design-json-schema.md +++ b/docs/declarative-customization/site-design-json-schema.md @@ -1,7 +1,7 @@ --- title: Site template JSON schema description: JSON schema reference for building site templates for SharePoint. -ms.date: 09/23/2022 +ms.date: 11/18/2024 ms.localizationpriority: high --- @@ -18,9 +18,7 @@ The overall JSON structure is specified as follows: ... ... - ], - "bindata": { }, - "version": 1 + ] } ``` @@ -432,7 +430,7 @@ Associates a ListViewCommandSet to the list #### JSON values - `title`: The title of the extension. -- `location`: A required parameter to specify where the command is displayed. Options are: ContextMenu or CommandBar. +- `location`: A required parameter to specify where the command is displayed. Options are: ClientSideExtension.ListViewCommandSet.ContextMenu or ClientSideExtension.ListViewCommandSet.CommandBar. - `clientSideComponentId`: The identifier (GUID) of the extension in the App Catalog. This property value can be found in the manifest.json file or in the elements.xml file. - `clientSideComponentProperties`: An optional parameter, which can be used to provide properties for the extension instance. @@ -466,7 +464,7 @@ Associates a ListViewCommandSet to the list { "verb": "associateListViewCommandSet", "title": "HelloWorld", - "location": "CommandBar", + "location": "ClientSideExtension.ListViewCommandSet.CommandBar", "clientSideComponentId": "13234283-d6c2-408f-a9ef-31a920c8ae78", "clientSideComponentProperties": "{\"sampleText\":\"added by a site template\"}" } diff --git a/docs/declarative-customization/site-design-o365cli.md b/docs/declarative-customization/site-design-o365cli.md index 3fb486e23..6282f7491 100644 --- a/docs/declarative-customization/site-design-o365cli.md +++ b/docs/declarative-customization/site-design-o365cli.md @@ -1,7 +1,7 @@ --- title: SharePoint site design - CLI for Microsoft 365 commands description: Use the CLI for Microsoft 365 to create, retrieve, and remove site designs and site scripts. -ms.date: 06/28/2022 +ms.date: 06/27/2024 ms.localizationpriority: high --- @@ -16,10 +16,8 @@ Use the CLI for Microsoft 365 to create, retrieve, update, and remove site desig To run the CLI for Microsoft 365 commands, you'll need to do the following: 1. Download and install [NodeJS LTS version](https://nodejs.org/en/) - -2. Follow the instructions at [Installing the CLI](https://pnp.github.io/cli-microsoft365/user-guide/installing-cli/) to install the CLI for Microsoft 365 on your machine - -3. Follow the instructions at [Logging in to Office 365](https://pnp.github.io/cli-microsoft365/user-guide/connecting-office-365/) to connect to your SharePoint tenant. +1. Follow the instructions at [Installing the CLI](https://pnp.github.io/cli-microsoft365/user-guide/installing-cli/) to install the CLI for Microsoft 365 on your machine +1. Follow the instructions at [Logging in to Office 365](https://pnp.github.io/cli-microsoft365/user-guide/connecting-microsoft-365) to connect to your SharePoint tenant. To verify your setup and connection, try using the [sitedesign list](https://pnp.github.io/cli-microsoft365/cmd/spo/sitedesign/sitedesign-list) command to read the current list of site designs. If the cmdlet runs and returns with no errors, you're ready to proceed. diff --git a/docs/declarative-customization/site-design-overview.md b/docs/declarative-customization/site-design-overview.md index a968d09ca..701efedc2 100644 --- a/docs/declarative-customization/site-design-overview.md +++ b/docs/declarative-customization/site-design-overview.md @@ -1,7 +1,7 @@ --- title: SharePoint site template and site script overview description: Use SharePoint site scripts and site templates to provide custom configurations to apply when new sites are created. -ms.date: 06/28/2022 +ms.date: 01/22/2025 ms.localizationpriority: high --- @@ -10,12 +10,12 @@ ms.localizationpriority: high > [!NOTE] > - Site templates and site scripts are currently only supported by SharePoint Online. > - In previous versions of SharePoint, site templates were called site designs but will be referred to as site templates moving forward. -> - SharePoint has a new site template experience that will be available to all SharePoint users with permissions to create SharePoint sites. [Learn more about the new site template experience](https://support.microsoft.com/office/apply-and-customize-sharepoint-site-templates-39382463-0e45-4d1b-be27-0e96aeec8398?ui=en-US&rs=en-US&ad=US). +> - SharePoint has a new site template experience that will be available to all SharePoint users with permission to create SharePoint sites. [Learn more about the new site template experience](https://support.microsoft.com/office/apply-and-customize-sharepoint-site-templates-39382463-0e45-4d1b-be27-0e96aeec8398?ui=en-US&rs=en-US&ad=US). > - As of today, the site template experience cannot be disabled. > - Site templates created by your organization and set as the default template will automatically apply when new sites are created but can be updated by the site owner by selecting **Settings** and then **Apply a site template.** > - Site template version history is not currently available for the new site template experience but will be included in future iterations. -Use site templates and site scripts to automate provisioning new or existing modern SharePoint sites that use your own custom configurations. +Use site templates and site scripts to automate the provisioning of new or existing modern SharePoint sites that use your own custom configurations. When people in your organization create new SharePoint sites, you often need to ensure some level of consistency. For example, you may need proper branding and theming applied to each new site. You may also have detailed site provisioning scripts, such as using the PnP provisioning engine, that need to be applied each time a new site is created. @@ -23,31 +23,29 @@ This article describes how you can use site templates and site scripts to provid ## How site templates work -Site templates can be used each time a new site is created to apply a consistent set of actions. They can also be applied to existing modern sites (group-connected Team and Communication sites). Most actions typically affect the site itself, such as setting the theme or creating lists. But a site template can also include other actions, such as recording the new site URL to a log, or sending a tweet. +Site templates can be used each time a new site is created to apply a consistent set of actions. They can also be applied to existing modern sites (group-connected Team and Communication sites). Most actions typically affect the site itself, such as setting the theme or creating lists. But a site template can also include other actions, such as recording the new site URL to a log or sending a tweet. > [!NOTE] > - Site templates created using custom site scripts will display in the **From your organization** tab in the site template gallery. -> - Custom site templates made by your organization will display in the site template gallery based on the type of site chosen by the user - either a communication site or a team site. Therefore, it is likely users will not see all site templates from your organization in the site template gallery. Soon, users will have the ability to browse all site templates provided by your organization regardless of which type of site was chosen. +> - Custom site templates made by your organization will be displayed in the site template gallery based on the type of site chosen by the user - either a communication site or a team site. Therefore, it is likely users will not see all site templates from your organization in the site template gallery. Soon, users will have the ability to browse all site templates provided by your organization regardless of which type of site was chosen. You create site templates and register them in SharePoint to one of the modern template sites: the Team site or the Communication site. You can see how this works in the following steps. 1. Go to the SharePoint start page on your developer tenant. - -2. Choose **Create site**. +1. Choose **Create site**. You'll see the two modern template sites: **Team site** and **Communication site**. -3. Choose the type of site needed. - -- SharePoint will automatically create a communication site using the **Topic** site template. -- Had you chosen the default Team site, SharePoint will create a new site using the **Team collaboration** template. +1. Choose the type of site needed. -For more information about how you can change the default site templates, see [Customize a default site template](customize-default-site-design.md). + - SharePoint will automatically create a communication site using the **Standard communication** site template. + - Had you chosen the default Team site, SharePoint will create a new site using the **Standard team** template. -4. Navigate to the **Settings** icon, and select **Apply site template** to review Microsoft-provided site templates based on the type of site you chose in step three. + For more information about how you can change the default site templates, see [Customize a default site template](customize-default-site-design.md). -When a site template is selected, SharePoint creates the new site, and runs site scripts for the site template. The site scripts provide the details for the template such as creating new lists or applying a theme. These script actions are run in the background. When the scripts are complete the page will refresh to display the site script details. +1. Navigate to the **Settings** icon, and select **Apply site template** to review Microsoft-provided site templates based on the type of site you chose in step three. +When a site template is selected, SharePoint creates the new site and runs site scripts for the site template. The site scripts provide the details for the template such as creating new lists or applying a theme. These script actions are run in the background. When the scripts are complete the page will refresh to display the site script details. > [!NOTE] > Site templates can now be applied to previously created modern site collections. For more information, see the [REST API](site-design-rest-api.md) and [PowerShell](site-design-powershell.md) articles. @@ -104,20 +102,17 @@ The following example is a script that has two top-level actions. First, it appl } ] } - ], - "version": 1 + ] } ``` -
- Each action in a site script is specified by a **verb** value in the JSON. In the previous script, the first action is specified by the **applyTheme** verb. Next, the **createSPList** verb creates the list. Notice that the **createSPList** verb contains its own set of verbs that run additional actions on only the list. **Available actions include:** - Creating a new list or library (or modifying the default one created with the site) - Creating site columns, content types, and configuring other list settings -- Set site branding properties like navigation layout, header layout and header background +- Set site branding properties like navigation layout, header layout, and header background - Applying a theme** - Setting a site logo - Adding links to quick launch or hub navigation** @@ -130,10 +125,11 @@ Each action in a site script is specified by a **verb** value in the JSON. In th For a complete list of available actions and their parameters, see the [JSON schema](site-design-json-schema.md). > [!NOTE] +> > - Actions marked with ** are automatically blocked for [channel sites](/sharepoint/teams-connected-sites). > - For libraries and lists, use the PowerShell command [Get-SPOSiteScriptFromList](/powershell/module/sharepoint-online/Get-SPOSiteScriptFromList) to create the site script syntax from an existing SharePoint list. -Site scripts can be run again on the same site after provisioning. Site scripts are non-destructive, so when they run again, they ensure that the site matches the configuration in the script. +Site scripts can be run again on the same site after provisioning. They are non-destructive, so when they are run again, they ensure that the site matches the configuration in the script. For example, if the site already has a list with the same name that the site script is creating, the site script will only add missing fields to the existing list. @@ -143,7 +139,7 @@ There is also a limit of 100 site scripts and 100 site templates per tenant. ## Using PowerShell or REST to work with site templates and site scripts -You can create site templates and site scripts by using PowerShell or the REST API. The following example creates a site script and a site template that uses the site script. +You can create site templates and scripts using PowerShell or the REST API. The following example creates a site script and a site template that uses the script. @@ -166,109 +162,36 @@ C:\> Add-SPOSiteDesign ` -Description "Creates customer list and applies standard theme" ``` - - -
- In the previous example, the **Add-SPOSiteScript** cmdlet or **CreateSiteScript** REST API returns a site script ID. This is used for the **SiteScripts** parameter in the subsequent call to the **Add-SPOSiteDesign** cmdlet or **CreateSiteDesign** REST API. - | Parameter | Value | Site template type | | :------------------- | :------------------- |:----------------| | WebTemplate | 64 | Team site template | -| WebTemplate 1 | 1 | Team site (with group creation disabled) | +| WebTemplate | 1 | Team site (with group creation disabled) | | WebTemplate | 68 | Communication site template | | WebTemplate | 69 | Channel site template | - - For step-by-step information about creating a site template, see [Get started creating site templates.](get-started-create-site-design.md) > [!NOTE] +> > - A site template can run multiple scripts. The script IDs are passed in an array, and they run in the order listed. > - The former term for site templates may still appear in certain cmdlet and script labels as "site design." - ## PnP provisioning and customization using Power Automate One action provided by site scripts is the ability to trigger a Power Automate flow. This allows you to specify any custom action that you need beyond the actions provided natively in site scripts. If you use the PnP provisioning engine to automate site creation, you can use a Power Automate flow to integrate with site templates. You can maintain all your existing provisioning scripts as well as create new custom provisioning scripts by using this technique. -
- ![Process of triggering a Microsoft Flow](images/process-for-triggering-a-custom-flow.png) The process works as follows: 1. The script instantiates your Power Automate flow using a URL with additional details. - -2. The flow sends a message to an Azure storage queue that you have configured. - -3. The message triggers a call to an Azure function that you have configured. - -4. The Azure function runs your custom script, such as the PnP provisioning engine, to apply your custom configurations. +1. The flow sends a message to an Azure storage queue that you have configured. +1. The message triggers a call to an Azure function that you have configured. +1. The Azure function runs your custom script, such as the PnP provisioning engine, to apply your custom configurations. For a step-by-step tutorial about how to configure your own Power Automate flow with PnP provisioning, see [Build a complete site template using the PnP provisioning engine](site-design-pnp-provisioning.md). @@ -287,12 +210,6 @@ Grant-SPOSiteDesignRights ` -Rights View ``` - - For more information about working with scopes, see [Scoping access to site templates](site-design-scoping.md). ## See also diff --git a/docs/declarative-customization/site-design-pnp-provisioning.md b/docs/declarative-customization/site-design-pnp-provisioning.md index 7926843ac..74a7db6ef 100644 --- a/docs/declarative-customization/site-design-pnp-provisioning.md +++ b/docs/declarative-customization/site-design-pnp-provisioning.md @@ -1,7 +1,7 @@ --- title: Calling the PnP provisioning engine from a site script description: Build a complete SharePoint site design using the PnP provisioning engine -ms.date: 06/28/2022 +ms.date: 08/31/2023 ms.localizationpriority: high --- @@ -10,7 +10,7 @@ ms.localizationpriority: high > [!NOTE] > This article uses the newest version of PnP PowerShell that is released in January 2021. As Azure Functions run PowerShell Core, you'll have to use this version of PnP PowerShell in your Azure Function. For more information about this version of PnP PowerShell see https://pnp.github.io/powershell. -Site designs offer a great way to standardize the look and feel of your site collections. However, you can't do some things with site designs, like add a footer to every page. You can use the PnP provisioning engine to create a template that you can use to provision an Application Customizer to a site. This Application Customizer can then update your page design, for example to register a footer on every page. +Site designs offer a great way to standardize the look and feel of your site collections. However, you can't do some things with site designs, like add a footer to every page. You can use the PnP provisioning engine to create a template that you can use to provision an Application Customizer to a site. This Application Customizer can then update your page design, for example, to register a footer on every page. This article describes how to create a site design that applies a PnP provisioning template to a site. The template will add an Application Customizer to render a footer. @@ -31,7 +31,7 @@ You'll use these components to trigger the PnP provisioning code after you creat ## Set up app-only access to your tenant -We are going to use authentication with a clientid and a certificate in this tutorial. +We are going to use authentication with a client id and a certificate in this tutorial. 1. Create a new self-signed certificate with PnP PowerShell on your computer: @@ -64,11 +64,14 @@ To set up the Azure Queue storage: ## Create the flow +> [!NOTE] +> The **Request** trigger used below is now **Premium** and will therefore require additional licensing. + To put a message in the queue, you need to create a flow. 1. Go to the [Power Automate](https://flow.microsoft.com) site, sign in, and choose **Create from Blank** at the top of the page. 1. Choose **Search hundreds of connectors and triggers** to select your trigger. -1. Search for **Request**, and select **Request - When a HTTP Request is received**. +1. Search for **Request**, and select **Request - When an HTTP Request is received [Premium]**. 1. Enter the following JSON as your request body: ```json diff --git a/docs/declarative-customization/site-design-pnppowershell.md b/docs/declarative-customization/site-design-pnppowershell.md index 4930d2556..8faccf981 100644 --- a/docs/declarative-customization/site-design-pnppowershell.md +++ b/docs/declarative-customization/site-design-pnppowershell.md @@ -17,15 +17,15 @@ To run the PnP PowerShell cmdlets, you'll need to do the following: 1. Download and install the PnP PowerShell Module by running: -```PowerShell -Install-Module PnP.PowerShell -``` + ```PowerShell + Install-Module PnP.PowerShell + ``` -2. Connect to the SharePoint Online Admin Center of your tenant: +1. Connect to the SharePoint Online Admin Center of your tenant: -```PowerShell -Connect-PnPOnline -Url https://tenant-admin.sharepoint.com -Interactive -``` + ```PowerShell + Connect-PnPOnline -Url https://tenant-admin.sharepoint.com -Interactive + ``` To verify your setup and connection, try using the `Get-PnPSiteScript` cmdlet to read the current list of site scripts. If the cmdlet runs and returns with no errors, you're ready to proceed. diff --git a/docs/declarative-customization/site-design-powershell.md b/docs/declarative-customization/site-design-powershell.md index 5da0168f5..085f6ac92 100644 --- a/docs/declarative-customization/site-design-powershell.md +++ b/docs/declarative-customization/site-design-powershell.md @@ -14,8 +14,7 @@ Use PowerShell cmdlets to create, retrieve, update, and remove site designs and To run the PowerShell cmdlets, you'll need to do the following: 1. Download and install the [SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588). If you already have a previous version of the shell installed, uninstall it first and then install the latest version. - -2. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. +1. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. To verify your setup, try using the [Get-SPOSiteScript](/powershell/module/sharepoint-online/Get-SPOSiteScript) cmdlet to read the current list of site scripts. If the cmdlet runs and returns with no errors, you're ready to proceed. diff --git a/docs/declarative-customization/site-design-trigger-flow-tutorial.md b/docs/declarative-customization/site-design-trigger-flow-tutorial.md index 30f7fe892..285da5ad0 100644 --- a/docs/declarative-customization/site-design-trigger-flow-tutorial.md +++ b/docs/declarative-customization/site-design-trigger-flow-tutorial.md @@ -1,7 +1,7 @@ --- title: Using site designs and Power Automate to track site creation requests description: Invoke a Power Automate flow using the site script triggerFlow action to capture the site creation event and build a site directory. This tutorial is intended to illustrate a simple example of using site designs and Power Automate. -ms.date: 06/28/2022 +ms.date: 06/05/2024 ms.localizationpriority: high --- @@ -24,110 +24,96 @@ You'll first create the SharePoint list and then it will be referenced in your P You need to first set up the list that will be used to record all the sites created using this site design. 1. Select a site collection to host your list. +1. Create a new list named "Site Directory" +1. Configure the following fields: -2. Create a new list named "Site Directory" - -3. Configure the following fields: - webUrl (Hyperlink or Picture) - webDescription (Single line of text) - creatorName (Single line of text) - creatorEmail (Single line of text) - createdTimeUTC (Single line of text) - ## Create the flow In order to capture the site creation event and create the corresponding list item, you need to create a flow - which can then be referenced in your site design's site script: 1. Go to the [Power Automate](https://flow.microsoft.com) site, sign in, and choose **+ Automated—from blank* at the top of the page. +1. Click **Skip** on the next screen +1. Choose **Search connectors and triggers** to select your trigger +1. Search for **Request**, and then choose **Request - When a HTTP Request is received [PREMIUM]**. **NOTE**: The **Request** trigger is now **PREMIUM** and will therefore require additional licensing. +1. Enter the following JSON as your request body: -2. Click **Skip** on the next screen - -2. Choose **Search connectors and triggers** to select your trigger - -3. Search for **Request**, and then choose **Request - When a HTTP Request is received [PREMIUM]**. **NOTE**: The **Request** trigger is now **PREMIUM** and will therefore require additional licensing. - -4. Enter the following JSON as your request body: - - ```json - { - "type": "object", - "properties": { - "webUrl": { - "type": "string" - }, - "parameters": { - "type": "object", - "properties": { - "event": { - "type": "string" - }, - "product": { - "type": "string" + ```json + { + "type": "object", + "properties": { + "webUrl": { + "type": "string" + }, + "parameters": { + "type": "object", + "properties": { + "event": { + "type": "string" + }, + "product": { + "type": "string" + } } + }, + "webDescription": { + "type": "string" + }, + "creatorName": { + "type": "string" + }, + "creatorEmail": { + "type": ["string", "null"] + }, + "createdTimeUTC": { + "type": "string" } - }, - "webDescription": { - "type": "string" - }, - "creatorName": { - "type": "string" - }, - "creatorEmail": { - "type": "string" - }, - "createdTimeUTC": { - "type": "string" } } - } - ``` - -5. Select **+ New Step**. - -6. Search for **Create item**, and select **SharePoint - Create item**. - -7. Enter the site address where the list above was created. - -8. Select the "Site Directory" list you created in the previous step. + ``` -9. Enter a value for the **Title** field - this will be the same value for each list item. For example: "Contoso Travel: New Project Site Created". +1. Select **+ New Step**. +1. Search for **Create item**, and select **SharePoint - Create item**. +1. Enter the site address where the list above was created. +1. Select the "Site Directory" list you created in the previous step. +1. Enter a value for the **Title** field - this will be the same value for each list item. For example: "Contoso Travel: New Project Site Created". +1. For each field in your list form, add the corresponding element from the Dynamic Content picker. When you are done your action should look something like this: -10. For each field in your list form, add the corresponding element from the Dynamic Content picker. When you are done your action should look something like this: + ![Screenshot of a flow named 'When an HTTP request is received', showing the URL, Request body, Queue name, and Message fields](images/site-directory-flow-configuration.png) -![Screenshot of a flow named 'When an HTTP request is received', showing the URL, Request body, Queue name, and Message fields](images/site-directory-flow-configuration.png) - -11. Choose **Save**. This generates the HTTP Post URL that you will need to copy for your site script `triggerFlow` action. - -14. Choose the first step in your flow ('When an HTTP request is received') and copy the URL. - -15. Save your flow. +1. Choose **Save**. This generates the HTTP Post URL that you will need to copy for your site script `triggerFlow` action. +1. Choose the first step in your flow ('When an HTTP request is received') and copy the URL. +1. Save your flow. ## Create the site design 1. Open PowerShell and make sure that you have the latest [SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588) installed. +1. Connect to your tenant using **Connect-SPOService**. -2. Connect to your tenant using **Connect-SPOService**. - - ```powershell + ```powershell Connect-SPOService -Url https://[yourtenant]-admin.sharepoint.com - ``` + ``` -3. Now you can get the existing site designs. +1. Now you can get the existing site designs. - ```powershell + ```powershell Get-SPOSiteDesign - ``` - -
+ ``` -To create a site design, you first need to create a site script. A site design is a container that refers to one or more site scripts. + To create a site design, you first need to create a site script. A site design is a container that refers to one or more site scripts. -1. Copy the following JSON code to your clipboard and modify it. Set the `url` property to the value that you copied when you created the flow. The URL looks similar to the following: +1. Copy the following JSON code to your clipboard and modify it. Set the **url** property to the value that you copied when you created the flow. The URL looks similar to the following: - `https://prod-27.westus.logic.azure.com:443/workflows/ef7434cf0d704dd48ef5fb6...oke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun` + ```http + https://prod-27.westus.logic.azure.com:443/workflows/ef7434cf0d704dd48ef5fb6...oke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun + ``` - ```json + ```json { "$schema": "schema.json", "actions": [ @@ -142,25 +128,24 @@ To create a site design, you first need to create a site script. A site design i } ] } - ``` + ``` -2. Select the JSON again and copy it again to your clipboard. +1. Select the JSON again and copy it again to your clipboard. +1. Open PowerShell and enter the following to copy the script into a variable and create the site script: -3. Open PowerShell and enter the following to copy the script into a variable and create the site script: - - ```powershell + ```powershell $script = Get-Clipboard -Raw Add-SPOSiteScript -Title "Site Script to record site creation event" -Content $script Get-SPOSiteScript - ``` - -4. You will see a list of one or more site scripts, including the site script you just created. Select the ID of the site script that you created, and copy it to the clipboard. + ``` -5. Use the following command to create the site design: +1. You will see a list of one or more site scripts, including the site script you just created. Select the ID of the site script that you created, and copy it to the clipboard. +1. Use the following command to create the site design: - ```powershell + ```powershell Add-SPOSiteDesign -Title "Record site creation" -Description "The creation of this site will be recorded in the site directory list" -SiteScripts [Paste the ID of the Site Script here] -WebTemplate "64" - ``` + ``` + > [!NOTE] > The **Add-SPOSiteDesign** cmdlet associates the site design with the Team site. If you want to associate the design with a Communication site, use `-WebTemplate "68"`. @@ -170,7 +155,6 @@ To test the results, create a new site. In your SharePoint tenant, select **Shar Your new site design should show up as a design option. Notice that the site design is applied after the site is created. If you configured it correctly, your flow will be triggered. You can check the run history of the flow to verify that it ran correctly. - ## See also - [SharePoint site design and site script overview](site-design-overview.md) diff --git a/docs/declarative-customization/site-theming/sharepoint-site-theming-json-schema.md b/docs/declarative-customization/site-theming/sharepoint-site-theming-json-schema.md index 7fa2f83d0..db182d93b 100644 --- a/docs/declarative-customization/site-theming/sharepoint-site-theming-json-schema.md +++ b/docs/declarative-customization/site-theming/sharepoint-site-theming-json-schema.md @@ -1,7 +1,7 @@ --- title: SharePoint site theming - JSON schema description: The new SharePoint site theming features use a JSON schema to store color settings and other information about each theme. -ms.date: 10/20/2022 +ms.date: 08/08/2024 ms.localizationpriority: high --- @@ -95,7 +95,18 @@ The SharePoint Framework includes eight built-in themes: six on light background Another option is to use the [Theme Generator tool](https://aka.ms/themedesigner) to build a custom theme. It provides an interactive UI for selecting theme colors, and automatically generates the JSON, SASS, and PowerShell definitions for your custom theme. > [!NOTE] -> The theme generator definitions do not currently include the "error" or "accent" color slots. These can be manually added to your generated definition before uploading to the tenant. +> The theme generator definitions do not currently include the following color slots and key/value pairs: +> +> - "primaryBackground" +> - "primaryText" +> - "bodyBackground" +> - "bodyText" +> - "disabledBackground" +> - "disabledText" +> - "error" +> - "accent" +> +> These can be manually added to your generated definition before uploading to the tenant. ![Theme Generator tool](../../images/theme-generator-tool.png) diff --git a/docs/declarative-customization/site-theming/sharepoint-site-theming-overview.md b/docs/declarative-customization/site-theming/sharepoint-site-theming-overview.md index 2ecb7c2d8..5762ad676 100644 --- a/docs/declarative-customization/site-theming/sharepoint-site-theming-overview.md +++ b/docs/declarative-customization/site-theming/sharepoint-site-theming-overview.md @@ -1,7 +1,7 @@ --- title: SharePoint site theming description: New options for applying custom styles and colors to sites that make it easier to define and manage themes across site collections. -ms.date: 02/16/2023 +ms.date: 04/23/2025 ms.localizationpriority: high --- @@ -72,27 +72,28 @@ The modern site theming experience has been rolled out to classic site templates To do this, you must use a Windows PowerShell script with a CSOM (client-side object model) wrapper. We recommend using the PnP PowerShell enable feature command: 1. Verify that you meet the following minimum requirements: + * You are at least a site collection owner on the site where you want to disable modern site themes * You have read about [Execution Policies](https://technet.microsoft.com/library/dd347641.aspx) -2. Download the latest [PnP PowerShell](https://github.com/pnp/powershell). +1. Download the latest [PnP PowerShell](https://github.com/pnp/powershell). [!INCLUDE [pnp-powershell](../../../includes/snippets/open-source/pnp-powershell.md)] -3. Enter `Connect-PnPOnline -Url -UseWebLogin` (replacing `` with the url of the site you wish to opt out of). - -4. Enter your credentials when prompted. - -5. To opt out of the site, you need to enable a feature: +1. Enter `Connect-PnPOnline -Url -Interactive -ClientId ` (replacing `` with the URL of the site you wish to connect to, and `` with the Client ID of your [registered Entra ID (Azure AD)](https://pnp.github.io/powershell/articles/registerapplication.html) application). +1. Enter your credentials when prompted. +1. To opt out of the site, you need to enable a feature: * Enter `Get-PnPFeature -Scope Site -Identity 5138468E-3D76-4F72-9DE4-E029F1245A7B` * Verify that nothing is returned from the previous command (this confirms the feature isn’t enabled yet) * Enter `Enable-PnPFeature -Scope Site -Identity 5138468E-3D76-4F72-9DE4-E029F1245A7B` * Enter `Get-PnPFeature -Scope Site -Identity 5138468E-3D76-4F72-9DE4-E029F1245A7B` -6. Verify that the following is returned: +1. Verify that the following is returned: - `ClientSideThemingOptOut - 5138468e-3d76-4f72-9de4-e029f1245a7b` + ```powershell + ClientSideThemingOptOut - 5138468e-3d76-4f72-9de4-e029f1245a7b + ``` For more information about Windows PowerShell, see [PowerShell](/powershell/scripting/overview). diff --git a/docs/declarative-customization/site-theming/sharepoint-site-theming-powershell.md b/docs/declarative-customization/site-theming/sharepoint-site-theming-powershell.md index f6c62cc31..37dc811ec 100644 --- a/docs/declarative-customization/site-theming/sharepoint-site-theming-powershell.md +++ b/docs/declarative-customization/site-theming/sharepoint-site-theming-powershell.md @@ -18,8 +18,7 @@ For information about how themes are defined and stored, see [JSON schema refere To run the PowerShell cmdlets for theme management, you must do the following: 1. Download and install the [SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588). If you already have a previous version of the shell installed, uninstall it first and then install the latest version. - -2. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. +1. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. To verify your setup, try using the [Get-SPOHideDefaultThemes](/powershell/module/sharepoint-online/Get-SPOHideDefaultThemes) cmdlet to read the SPOHideDefaultThemes setting. If the cmdlet runs and returns False with no errors, as shown in the following example, you're ready to proceed. @@ -33,7 +32,6 @@ The following cmdlets are available for managing site themes from PowerShell: * [Set-SPOHideDefaultThemes](/powershell/module/sharepoint-online/Set-SPOHideDefaultThemes) – Specifies whether the default themes should be available. * [Get-SPOHideDefaultThemes](/powershell/module/sharepoint-online/Get-SPOHideDefaultThemes) – Queries the current SPOHideDefaultThemes setting. - ## See also * [SharePoint site theming overview](sharepoint-site-theming-overview.md) diff --git a/docs/declarative-customization/view-commandbar-formatting.md b/docs/declarative-customization/view-commandbar-formatting.md index 3ae8b0563..f7f56e8e3 100644 --- a/docs/declarative-customization/view-commandbar-formatting.md +++ b/docs/declarative-customization/view-commandbar-formatting.md @@ -1,21 +1,24 @@ --- title: Command bar customization syntax reference description: Command bar customization syntax reference -ms.date: 08/12/2022 +ms.date: 05/21/2025 ms.localizationpriority: high --- # Command bar customization syntax reference -Command bar customization helps personalize a list to suit specific requirements. The JSON based feature allows basic changes to the command bar, including modification of icon and/or text, hiding existing options or repositioning commands. +Command bar customization helps personalize a list to suit specific requirements. The JSON-based feature allows basic changes to the command bar, including modification of icon and/or text, hiding existing options, or repositioning commands. ## commandBarProps + Properties for Command bar customization. Valid in all types of layouts. ## commands -Array of JSON objects to specify the commands for customization. + +An array of JSON objects is used to specify the commands for customization. ## key + Mandatory property to uniquely identify a command in the Command bar. Valid keys include: ```javascript @@ -83,25 +86,64 @@ Mandatory property to uniquely identify a command in the Command bar. Valid keys 'addShortcut' 'pinToQuickAccess' 'unpinFromQuickAccess' +'manageForms' +'favoriteCommand' +'createCopilot' ``` +## ⚠️ Recent updates to `commandBarCustomization` Keys + +> Some keys in the commandBarCustomization schema have been updated. To ensure your custom formatter functions correctly, please update your existing JSON to reflect these new keys. +> +> | Original Key | New Key | +> |--------------|-------------| +> | `new` | `newComposite` (Document Library)| +> | `upload` | `UploadCommand` | +> | `sync` | `syncCommand` | +> | `addShortcut`| `addShortcutToOneDriveCommand` | +> | `pinToQuickAccess` | `PinToQuickAccessCommand` | +> | `pinItem` | `pinItemCommand` | +> | `properties` | `propertiesCommand` | +> | `versionHistory` | `versionHistoryCommand` (currently not working) | +> +> Additionally, the following new command keys are now available: +> > +> - `stasherContextMenuCommand` (Add shortcut) +> - `stasherCommand.myFiles` (Add shortcut --> my Files) +> - `stasherCommand.otherLocations` (Add shortcut --> Other locations) +> - `PublishCommand` +> - `complianceDetails` (right click context menu --> More --> Compliance details) +> - `more` (right click context menu --> More) +> - `previewFileCommand` (right click context menu --> Preview) +> +> Please note that the JSON schema at https://developer.microsoft.com/json-schemas/sp/v2/command-bar-formatting.schema.json has not yet been updated to reflect these new command keys. + +> [!IMPORTANT] +> Command bar customizations also affect the item context menu (right-click menu). If a command is hidden in the command bar, it will also be hidden in the context menu. + ## hide + An optional property that specifies the condition to hide a particular command. The value of this property can either be a boolean, string or an Expression object. `false` is the default behavior (meaning the command is visible). `true` means that the command will be hidden. ## text -An optional property that specifies the text to be displayed as the name of the command. The value of this property can either be a string or an Expression object. If the value is not provided then the default name of the command will be shown. + +An optional property that specifies the text to be displayed as the name of the command. The value of this property can either be a string or an Expression object. If the value is not provided, then the default name of the command will be shown. ## title -An optional property that specifies the tooltip text to be displayed in the command. The value of this property can either be a string or an Expression object. If the value is not provided then the default tooltip of the command will be shown. + +An optional property that specifies the tooltip text to be displayed in the command. The value of this property can either be a string or an Expression object. If the value is not provided, then the default tooltip of the command will be shown. ## iconName -An optional property that specifies the [Fluent UI](https://developer.microsoft.com/fluentui#/) icon to be displayed in the command. The value of this property can either be a string or an Expression object. If the value is not provided then the default icon of the command will be shown. + +An optional property that specifies the [Fluent UI](https://developer.microsoft.com/fluentui#/) icon to be displayed in the command. The value of this property can either be a string or an Expression object. If the value is not provided, then the default icon of the command will be shown. ## primary + An optional property that specifies the condition to apply primary button styling to a command. The value of this property can either be a boolean, string or an Expression object. `false` is the default behavior (meaning the default style will be applied). `true` means the primary button styling will be applied to the command only if the command is placed at the 0th position in the command bar. The following example shows a sample Command bar formatting JSON to do the following: -- Hide the 'New' command,. + +- Hide the 'New' command. - Update the text and icon of 'Edit in grid view' command and add primary button styling to it. - Remove the icon from 'Share' command and update the tooltip text of it. @@ -130,17 +172,21 @@ The following example shows a sample Command bar formatting JSON to do the follo ``` ## position -An optional property that specifies the position where the command will be placed in the command bar. The value of this property can either be a number, string or an Expression object. If the value is not provided then the command will be placed in it's default position. This property follows zero-based indexing. + +An optional property that specifies the position where the command will be placed in the command bar. The value of this property can either be a number, a string, or an Expression object. If the value is not provided then the command will be placed in it's default position. This property follows zero-based indexing. ## sectionType + An optional property that specifies the section where the customized command will be placed in the command bar. The following strings are valid values for this property: + - Primary - Overflow The following example shows a sample Command bar formatting JSON to do the following: + - Puts the 'New' command at the third position in the primary section of the Command bar. -- Puts the 'Share' command at the second position in the overflow menu of the Command bar. -- Puts the 'Alert me' command at the fourth position in the primary section of theCommand bar. +- Puts the 'Share' command in the second position in the overflow menu of the Command bar. +- Puts the 'Alert me' command at the fourth position in the primary section of the Command bar. ```JSON { @@ -166,12 +212,15 @@ The following example shows a sample Command bar formatting JSON to do the follo ``` ## selectionModes -An optional property that specifies the selection modes in which the command customization will be applied. If the value is not provided then the customization will be applied in all the selection modes in which the command is available. The value of this property can be array of strings where the following strings are allowed: + +An optional property that specifies the selection modes in which the command customization will be applied. If the value is not provided, then the customization will be applied in all the selection modes in which the command is available. The value of this property can be an array of strings where the following strings are allowed: + - NoSelection - SingleSelection - MultiSelection The following example shows a sample Command bar formatting JSON to do the following: + - Update the text of 'Share' command if the selected item has 'NumberField' column value 3 - Update the text of 'Delete' command only if multiple items are selected. diff --git a/docs/design/accessibility.md b/docs/design/accessibility.md index fa1126333..393091803 100644 --- a/docs/design/accessibility.md +++ b/docs/design/accessibility.md @@ -84,7 +84,7 @@ Users who have vision impairments rely on screen readers to navigate the site UI ## Alt text and transcripts -Use alt text to provide descriptions of images that can be consumed by screen readers. This is useful for vision-impaired users who cannot consume information visually. Make sure that your alt text is descriptive, keeping in mind that some readers are relying on a screen reader to access the information conveyed in the image. +Use alt text to provide descriptions of images that can be consumed by screen readers. This is useful for users who have visual impairments who cannot consume information visually. Make sure that your alt text is descriptive, keeping in mind that some readers are relying on a screen reader to access the information conveyed in the image. Don't rely only on color to convey meaning; rely on both color and shape. @@ -92,7 +92,7 @@ To be fully compliant with accessibility standards, include alt text and a compl ## Minimum readable contrast -A minimum level of contrast is essential to help users with vision impairments consume the content on the page. It is also important to aid readability in low light and glare situations. +A minimum level of contrast is essential to help users who have visual impairments consume the content on the page. It is also important to aid readability in low light and glare situations. The following image shows theme colors on the left and neutral colors on the right. diff --git a/docs/design/design-guidance-overview.md b/docs/design/design-guidance-overview.md index 74fef36f4..1566fe91e 100644 --- a/docs/design/design-guidance-overview.md +++ b/docs/design/design-guidance-overview.md @@ -40,6 +40,44 @@ Accessibility is developing an equal experience for all users that enables indiv +## SharePoint Web UI Kit in Figma + +![Screenshot 2024-10-02 134843](https://github.com/user-attachments/assets/c6f4eb87-abf2-48ca-b5f2-f35ee98883c1) + +The SharePoint Web UI Kit empowers you to design communication and team sites for desktop, tablet and mobile in Figma. ​This kit delivers a set of web parts, style options, templates, and detailed guidance so you can quickly design engaging sites and pages in Figma. Figma is a subscription-based application that is the industry standard tool for web design, and provides an alternative to designing sites and pages outside of SharePoint. + +[Access the kit in Figma Community](https://aka.ms/SPWebUIkit) + +[Watch a live demo on YouTube with the product team](https://youtu.be/2UPchEYhuxI?si=x8ZWEBe3YZQL3Dkp) + +### Design without organizational limitations + +This UI kit provides SharePoint users with another tool in their toolbox. While building a page in SharePoint is easy, we wanted to provide the ability to mockup sites and pages. It allows you to explore different design options for your site without the limitation of admin privileges and tenant restrictions, and doesn’t expose organization data. + +Figma mockups provide a quick snapshot of SharePoint updates which business stakeholders can use to plan and make decisions. They can provide appropriate requirements and use this UI kit in collaboration with their design team to iterate in the life cycle of your organization's intranet. + +### Share designs with ease + +This UI kit provides you with page layouts and a selection of web parts to allow you to mockup and share new ideas across organizations and companies. Figma gives you the flexibility of reviewing and sharing your designs without having to spend time and resources creating it in SharePoint. Figma also allows you to download your designs into easy-to-use formats that can be used in documentation and presentations. Learn more at https://www.figma.com/ + +Note that Figma does not build the pages in SharePoint, so once you finalize a design in Figma, you will need to build it in SharePoint. You should evaluate if Figma is the right solution for mocking up sites and pages for SharePoint. + +### Community feedback + +Please tell us what’s missing, what doesn’t work for you, and where your biggest challenges are by leaving a comment on the [Figma SharePoint Web UI kit page](https://aka.ms/SPWebUIkit). + +### Past Tech Community blog posts for each SharePoint Web UI Kit release + +v3.0: [Figma Variables and new components available (v3.0.0) in the SharePoint Web UI Kit](https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/figma-variables-and-new-components-available-v3-0-0-in-the/ba-p/4180339) + +v2.2: [SharePoint Web UI Kit - New Figma web part components available (v2.2) and feedback requested](https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/sharepoint-web-ui-kit-new-figma-web-part-components-available-v2/ba-p/4031084) + +v2.1: [New web parts available in the SharePoint Web UI kit!](https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/new-web-parts-available-in-the-sharepoint-web-ui-kit/ba-p/3956251) + +v2.0: [Updated content for the SharePoint Web UI kit!](https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/updated-content-for-the-sharepoint-web-ui-kit/ba-p/3905250) + +v1.0: [Introducing a new SharePoint Web UI kit!](https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/introducing-a-new-sharepoint-web-ui-kit/ba-p/3870293) + ## See also - [Overview of SharePoint Framework](../spfx/sharepoint-framework-overview.md) diff --git a/docs/design/showcase-web-part.md b/docs/design/showcase-web-part.md index e832ff4ee..09965c263 100644 --- a/docs/design/showcase-web-part.md +++ b/docs/design/showcase-web-part.md @@ -9,78 +9,53 @@ ms.localizationpriority: high This article describes how to create a To-Do list web part. This example uses the single pane [property pane type](design-a-web-part.md) and is [reactive](reactive-and-nonreactive-web-parts.md) and based on the [Office UI Fabric](https://developer.microsoft.com/fabric) responsive grid. - ## Create a To-Do list web part 1. Add a description to help users understand more about the web part and its properties. - In this example, the description is "Select a source for your to-dos and customize the display for the list of tasks." - - ![Adding a description](../images/design-showcase-01.png) - -
- -2. Add a Fabric [drop-down component](https://developer.microsoft.com/fabric#/components/dropdown) connected to a list. - - ![Adding a Fabric dropdown](../images/design-showcase-02.png) - -
- -3. Add a Fabric [checkbox component](https://developer.microsoft.com/fabric#/components/checkbox) to display completed tasks. - - ![Adding a Fabric check box](../images/design-showcase-03.png) + In this example, the description is "Select a source for your to-dos and customize the display for the list of tasks." -
+ ![Adding a description](../images/design-showcase-01.png) -4. Add two more check boxes to control display options. +1. Add a Fabric [drop-down component](https://developer.microsoft.com/fabric#/components/dropdown) connected to a list. - ![Adding two more Fabric check boxes](../images/design-showcase-04.png) + ![Adding a Fabric dropdown](../images/design-showcase-02.png) -
+1. Add a Fabric [checkbox component](https://developer.microsoft.com/fabric#/components/checkbox) to display completed tasks. -5. Add a Fabric [slider](https://developer.microsoft.com/fabric#/components/slider) for the maximum number of items to display. + ![Adding a Fabric check box](../images/design-showcase-03.png) - ![Adding a Fabric slider](../images/design-showcase-05.png) +1. Add two more check boxes to control display options. -
+ ![Adding two more Fabric check boxes](../images/design-showcase-04.png) -6. Next, the author of the page selects a list or manually adds tasks to prepopulate the To-Do list web part. +1. Add a Fabric [slider](https://developer.microsoft.com/fabric#/components/slider) for the maximum number of items to display. - ![Select a list in pane](../images/design-showcase-06.png) + ![Adding a Fabric slider](../images/design-showcase-05.png) -
+1. Next, the author of the page selects a list or manually adds tasks to prepopulate the To-Do list web part. - ![Select a list in pane expanded](../images/design-showcase-07.png) + ![Select a list in pane](../images/design-showcase-06.png) -
+ ![Select a list in pane expanded](../images/design-showcase-07.png) - ![Manual addition of tasks to list](../images/design-showcase-08.png) + ![Manual addition of tasks to list](../images/design-showcase-08.png) -
+1. The web part shows an indicator of items loading onto the page. -7. The web part shows an indicator of items loading onto the page. + ![Indicator of items](../images/design-showcase-09.png) - ![Indicator of items](../images/design-showcase-09.png) +1. Items from the list load. -
+ ![List items loading](../images/design-showcase-10.png) -8. Items from the list load. + When the new tasks are loaded, they fade into view by using animation components from Office UI Fabric. - ![List items loading](../images/design-showcase-10.png) + ![New tasks loaded](../images/design-showcase-11.png) -
+1. The property pane controls the UI. Tasks with pivots enabled are displayed via the Display check boxes in the property pane. - When the new tasks are loaded, they fade into view by using animation components from Office UI Fabric. - - ![New tasks loaded](../images/design-showcase-11.png) - -
- -9. The property pane controls the UI. Tasks with pivots enabled are displayed via the Display check boxes in the property pane. - - ![Property pane controlling web part items](../images/design-showcase-12.png) - -
+ ![Property pane controlling web part items](../images/design-showcase-12.png) ## Responsive views @@ -88,20 +63,14 @@ The following example shows the 2/3 column view of the web part. ![Two thirds column view](../images/design-showcase-13.png) -
- The following example shows the 1/3 column view of the web part. ![One third column view](../images/design-showcase-14.png) -
- The following example shows the mobile (read-only) view of the web part. ![Mobile view of the to-do list web part](../images/design-showcase-15.png) -
- ## See also - [Designing great SharePoint experiences](design-guidance-overview.md) diff --git a/docs/design/themes-colors.md b/docs/design/themes-colors.md index 458bb1de4..d2eee4ec8 100644 --- a/docs/design/themes-colors.md +++ b/docs/design/themes-colors.md @@ -1,7 +1,7 @@ --- title: SharePoint themes and colors description: Design principles that help form the current SharePoint themes and color palette. -ms.date: 06/28/2022 +ms.date: 09/04/2024 ms.localizationpriority: high --- @@ -33,22 +33,6 @@ SharePoint includes a palette that supports dark themes. The SharePoint-provided ![SharePoint dark theme color palette, Red EF6950, Yellow FFC83D, Green 00b294, Blue 3a96dd, Purple 9c89e9, Grey b1adab](../images/sharepoint-themes-dark.png) -## Principles - -The following design principles helped form the current SharePoint themes and color palette. - -### Guided -Our theming system works at a global level so that updates can be made consistently across each site, allowing users to optimize their websites effortlessly. Our theming system operates in a controlled environment so that successful outcomes can be optimized quickly. - -### Smart and efficient -Our theming system expedites the site creation process by using smart algorithms to generate options that maximize aesthetic choices. - -### Professional -Our themes embody a professional look and feel that ensures coherency and conveys the brand of our enterprise audiences. - -### Accessible -Our built-in accessibility checker ensures universal design at all levels of default themes. For users who decide to customize, we provide helpful guidelines to design for accessibility. - ## See also - [Accessibility](accessibility.md) diff --git a/docs/design/use-brand-center-fonts-in-spfx-components.md b/docs/design/use-brand-center-fonts-in-spfx-components.md new file mode 100644 index 000000000..04a547908 --- /dev/null +++ b/docs/design/use-brand-center-fonts-in-spfx-components.md @@ -0,0 +1,173 @@ +--- +title: Use SharePoint brand center fonts in SharePoint Framework solutions +description: Developers can use the fonts defined in Brand center in their SharePoint Framework (SPFx) components. This article demonstrates how you can use the fonts defined in the SharePoint brand center in your SPFx components. +ms.date: 04/23/2025 +ms.localizationpriority: high +--- + +# Use SharePoint brand center fonts in SharePoint Framework solutions + +The [SharePoint brand center](/sharepoint/brand-center-overview) offers a centralized branding management application that empowers your brand managers or designated brand owners to help your organization to customize the look and feel of their experiences. This brand asset management system allows customers to manage the colors, fonts, and images, and other assets all in one place. + +Developers can use the fonts defined in Brand center in their SharePoint Framework (SPFx) components. This article demonstrates how you can use the fonts defined in the SharePoint brand center in your SPFx components. + +![Screenshot of the SharePoint brand center](../images/brand-center-spfx-01.png) + +In this article, learn how you can modify your SPFx components to use the same fonts set in the + +## Use SharePoint brand center fonts in SPFx components + +Start by creating a new SharePoint Framework component, such as a web part. + +> [!TIP] +> To learn how to create your first SPFx web part, see [Build your first SharePoint client-side web part (Hello World part 1)](../spfx/web-parts/get-started/build-a-hello-world-web-part.md). + +Within the web part, locate and open the **\*.module.scss** file in the project. For example, if you created a web part named *Hello World", the file will be found in the following location in the project: **./src/webparts/helloWorld/HelloWorldWebPart.module.scss**. + +This file contains the styles for the SPFx component. + +All fonts defined within Brand center are referenced using variables following the naming convention `--fontFamilyCustomFont###`. All start with the prefix `--fontFamily` followed by the *font slot* name. + +For example, to change the primary font in your web part, add the following style to the `.helloWorld` class: + +```css +font-family: var(--fontFamilyCustomFont100, var(--fontFamilyBase)); +``` + +This tells the web part to use the value defined in the SharePoint styling context with the variable `--fontFamilyCustomFont100`, but if that value isn't set, it will default to the `--fontFamilyBase` slot. + +The resulting class will now look like this: + +```css +.helloWorld { + font-family: var(--fontFamilyCustomFont100, var(--fontFamilyBase)); + overflow: hidden; + padding: 1em; + color: "[theme:bodyText, default: #323130]"; + color: var(--bodyText); + &.teams { + font-family: $ms-font-family-fallbacks; + } +} +``` + +Next, repeat this step for any other classes in our style where you want to apply these changes. For example, in the default web part, you'd update the `.welcome` and `.links.a` styles as well, so the resulting **\*.scss** file will look like the following: + +```css +@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss'; + +.helloWorld { + font-family: var(--fontFamilyCustomFont100, var(--fontFamilyBase)); + overflow: hidden; + padding: 1em; + color: "[theme:bodyText, default: #323130]"; + color: var(--bodyText); + &.teams { + font-family: $ms-font-family-fallbacks; + } +} + +.welcome { + text-align: center; + font-family: var(--fontFamilyCustomFont100, var(--fontFamilyBase)); +} + +.welcomeImage { + width: 100%; + max-width: 420px; +} + +.links { + a { + font-family: var(--fontFamilyCustomFont100, var(--fontFamilyBase)); + text-decoration: none; + color: "[theme:link, default:#03787c]"; + color: var(--link); // note: CSS Custom Properties support is limited to modern browsers only + + &:hover { + text-decoration: underline; + color: "[theme:linkHovered, default: #014446]"; + color: var(--linkHovered); // note: CSS Custom Properties support is limited to modern browsers only + } + } +} +``` + +### Test the web part + +To test the web part, start the local web browser, but don't launch a browser to the hosted workbench. + +1. Run the command **gulp serve** from the root of the project and include the **--nobrowser** argument: + + ```console + gulp serve --nobrowser + ``` + + > [!IMPORTANT] + > The SharePoint hosted workbench does not support custom fonts defined in the SharePoint brand center. To test your web parts, you'll need to test them on a page in a SharePoint site. + +1. In the console, the **gulp serve** command will output a line that looks similar to the following: + + ```text + [spfx-serve] To load your scripts, use this query string: ?debug=true&noredir=true#debugManifestsFile=https://localhost:4321/temp/build/manifests.js + ``` + + > [!NOTE] + > Debug query string was changed starting from the SPFx verson 1.21 from `https://localhost:4321/temp/manifests.js` to `https://localhost:4321/temp/build/manifests.js` + +1. Open the browser and navigate to a page that you have permission to add a web part to the page. +1. Add the query string from the preceding console message to the URL and load the page. + + When prompted in the **Allow debug scripts** dialog, select **Load debug scripts**. + +1. Next, put the page into edit mode and add your sample web part to the page. +1. Finally, publish the changes. + +With the web part on the page, select one of the custom fonts from the Brand center site: + +1. Select the gear icon in the top right of the Microsoft 365 suite bar, then select **Change the look**. + + ![Screenshot of the SharePoint settings menu](../images/brand-center-spfx-02.png) + +1. On the **Change the look** panel, select **Font**. + + ![Screenshot of the SharePoint setting Change the look panel](../images/brand-center-spfx-03.png) + +1. On the **Font** panel, select one of the fonts to view the changes on your web part. + + ![Screenshot of the SharePoint setting Font panel](../images/brand-center-spfx-04.png) + + Notice the fonts on the page will change, including those in our custom web part: + + ![Screenshot of a custom font selected from Brand central used in the web part](../images/brand-center-spfx-05.png) + +## Brand central font slot reference + +The following table lists all the available font slots from SharePoint brand center that developers can use in their custom SPFx components: + +| Font slot | Custom Font Token | Fluent Design Token | Short Description | Used in Product Location | +| ----------- | ----------------- | ------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| Body | CustomFont100 | caption2 | Caption small | | +| Body | CustomFont200 | caption2Strong | Caption medium | News Badge, Image caption, Site WP activity, Avatar Role/Job, Hero Badge | +| Body | CustomFont300 | caption1 | Caption large | Image Overlay | +| Interactive | CustomFont400 | caption1Strong | Label small | Avatar link | +| Interactive | CustomFont500 | caption1Stronger | Label medium | Footer links, Top Navigation links, Hub navigation links, Left navigation, Hero button | +| Interactive | CustomFont600 | body1 | Label large | Button | +| Body | CustomFont700 | body1Strong | Paragraph small | Quick links description, News sub description, Site web part information, Site web part description, Avatar name, Avatar description | +| Body | CustomFont800 | body1Stronger | Paragraph medium | News description, RTE Normal, RTE Table Cell, Hero Description | +| Body | CustomFont900 | body2 | Paragraph large | | +| Headline | CustomFont1000 | subtitle2 | Heading extra small | News subtitle, RTE H4, RTE Table Header, RTE, Table Column, Site WP site title, Call to action text, Hero call to action | +| Headline | CustomFont1100 | subtitle2Stronger | Heading small | Quick Links title, News title, Footer title, RTE H3, RTE Pull quote, Section heading, Hero title, Hero small tile title | +| Headline | CustomFont1200 | subtitle1 | Heading medium | RTE H2, Hero title large | +| Headline | CustomFont1300 | title3 | Heading large | Web part title, Hero tile title | +| Headline | CustomFont1400 | title2 | Heading extra large | | +| Title | CustomFont1500 | title1 | Title small | Hub title | +| Title | CustomFont1600 | largeTitle | Title medium | Page title, Site title | +| Title | CustomFont1700 | display | Title large | | + +> [!TIP] +> Don't forget to include the `--fontFamily` prefix when using one of the custom font slot tokens in your style sheets. + +## See also + +- Video: [Using SharePoint Brand center font settings in custom SPFx solutions](https://www.youtube.com/watch?v=IP19PeHb0Zg) diff --git a/docs/docfx.json b/docs/docfx.json index a39ebda36..1304618f8 100644 --- a/docs/docfx.json +++ b/docs/docfx.json @@ -34,8 +34,8 @@ "overwrite": [], "externalReference": [], "globalMetadata": { + "uhfHeaderId": "MSDocsHeader-SharePoint", "uhfHeaderID": "MSDocsHeader-M365-IT", - "extendBreadcrumb": "true", "breadcrumb_path":"/sharepoint/dev/breadcrumb/toc.json", "ms.suite": "office", "ms.author": "vesaj", @@ -47,9 +47,6 @@ "search.appverid": "MET150" }, "fileMetadata": { - "ms.prod": { - "solution-guidance/**.md": "sharepoint" - }, "ms.service": { "apis/*.md": "sharepoint-online", "apis/webhooks/**.md": "sharepoint-online", @@ -58,11 +55,13 @@ "business-apps/power-automate/guidance/**.md": "power-automate", "declarative-customization/**.md": "sharepoint-online", "design/**.md": "sharepoint-online", + "embedded/**.md": "sharepoint-online", "features/**.md": "sharepoint-online", - "general-development/**.md": "sharepoint", + "general-development/**.md": "sharepoint-online", "scenario-guidance/**.md": "sharepoint-online", "schema/**.md": "sharepoint-online", - "spfx/**.md": "sharepoint" + "spfx/**.md": "sharepoint-online", + "solution-guidance/**.md": "sharepoint-online" }, "ms.subservice":{ "general-development/**.md": "sharepoint-framework", @@ -73,7 +72,7 @@ "sp-addins/**.md": "sharepoint-addins" }, "ms.topic":{ - "solution-guidance/**.md": "solution" + "solution-guidance/**.md": "solution-idea" } }, "template": [], diff --git a/docs/embedded/administration/adminrole.md b/docs/embedded/administration/adminrole.md new file mode 100644 index 000000000..b15f2b7ad --- /dev/null +++ b/docs/embedded/administration/adminrole.md @@ -0,0 +1,83 @@ +--- +title: SharePoint Embedded administrator +description: This article explains the new admin role for SharePoint Embedded. +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# The SharePoint Embedded administrator + +The SharePoint Embedded administrator is a dedicated role to manage SharePoint Embedded containers through [SharePoint PowerShell](/powershell/module/sharepoint-online/connect-sposervice) and SharePoint admin center. This role is required for [developer admins](./developer-admin/dev-admin.md) to create new container types through PowerShell cmdlets and also for consuming tenant admins to manage containers created in their tenants. + +The global administrator role already has all the permissions of the SharePoint Embedded administrator role. A global administrator can assign a user the SharePoint Embedded administrator role to act as a consuming tenant admin or a developer administrator for SharePoint Embedded. + +The SharePoint Embedded administrator role is available in Microsoft Entra and Microsoft 365 Admin Center. This role doesn't have access to site management. This means that a SharePoint Embedded administrator can't see 'Active sites' and 'Deleted sites' pages on the SharePoint Admin Center and also can't run site specific PowerShell cmdlets. + +## SharePoint Embedded administrator tasks in the developer tenant + +The following are some of the container-specific commands actions currently supported on PowerShell: + +- Creation of container types + - Creation of a Standard container type with standard billing + - Creation of a Standard container type with direct to customer billing + - Creation of a Trial container type + +- Container type management + - Viewing of container types in the developer tenant + - Editing properties of a container type in the developer tenant + - Configuration properties of a container type in the developer tenant + - Manage billing of applications/ container types for standard billing + +## SharePoint Embedded administrator tasks in consuming tenant + +The following are some of the container-specific commands actions currently supported on PowerShell: + +- Application administration + - Get details of all SharePoint Embedded applications in the tenant + - Get detail of a specific application in the tenant + - Get the permissions of owning applications in the tenant + - Configure External sharing setting of a container of an application in tenant + +- Container administration + - Get details of all containers of an application in the tenant + - Get details of all containers of an application in the tenant sorted by storage + - Get details of a specific container of an application in the tenant + - Set Sensitivity label of a specific container of an application in the tenant + - Soft delete a container of an application in the tenant + - Get details of all soft deleted containers in the tenant + - Restore a soft deleted container of an application in the tenant + - Permanently delete a soft deleted container of an application in the tenant + +The following are some of the actions currently supported on SharePoint Admin Center: + +- View Active container page +- View Deleted container page +- View the detailed information of a container +- Soft delete a container +- Restore a deleted container +- Purge a deleted container + +## Assigning the SharePoint Embedded administrator Role + +The Global admin can assign the SharePoint Embedded Admin role to users through both Entra and Microsoft admin center. + +### Through Entra + +Follow the following steps to assign the role of SharePoint Embedded administrator on Entra: + +1. Sign into Entra as a Global admin +1. Select the **“Users”** tab on the left-hand panel and select **“All users”** +1. Select the user to assign the role of SharePoint Embedded administrator under **“All users”** +1. Select the **“Assigned role”** tab on the left panel +1. Select on **“Add assignments”** button and search for **“SharePoint Embedded”** in the panel that opens +1. Select the 'SharePoint Embedded administrator' option and select on **“Add”** +1. The selected user is assigned the role of SharePoint Embedded administrator + +### Through Microsoft 365 Admin Center + +1. Sign into Microsoft 365 Admin Center as a Global admin +1. Select **“Users”** and select **“Active users”** under it +1. Select the user to assign the role of SharePoint Embedded administrator +1. Select on **“Manage roles”** option under Roles +1. Select **“Admin center access”** and under **“Collaboration”**, select **“SharePoint Embedded administrator”** +1. Select **"Save changes"**. Now the selected user is assigned the role of SharePoint Embedded administrator diff --git a/docs/embedded/administration/billing/billing.md b/docs/embedded/administration/billing/billing.md new file mode 100644 index 000000000..6ef373a92 --- /dev/null +++ b/docs/embedded/administration/billing/billing.md @@ -0,0 +1,125 @@ +--- +title: PAYG billing for SharePoint Embedded +description: This article explains the billing models and how to set up PAYG billing. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded billing + +SharePoint Embedded is a consumption-based Pay-as-you-go (PAYG) offering meaning you pay only for what you use. SharePoint Embedded provides two billing models that the tenant developing the SharePoint Embedded application can select for respective container types, tailoring it to their unique business requirements. The two billing models are Standard and Pass-through billing. + +### Standard + +With the standard billing model, all consumption-based charges are directly billed to the tenant who owns or develops the application. The admin in the developer tenant must establish a valid billing profile when creating a standard container type. + +![Standard](../../images/1bill521.png) + +### Pass-through + +With pass-through billing, consumption-based charges are billed directly to the tenant registered to use the SharePoint Embedded application. Admins in the developer tenant don't need to set up a billing profile when creating a pass-through SharePoint Embedded container type. Once the container type is registered in the consuming tenant, the consuming tenant admin (SharePoint Admin or Global Admin) needs to set up the billing profile in the consuming tenant to use the SharePoint Embedded application. + +![Pass Through](../../images/2bill521.png) + +## Prerequisites to create SharePoint Embedded container type + +A new container type will be created using **SharePoint Online Management Shell**: + +1. Download and install the [latest version of SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588) +1. Open SharePoint Online Management Shell from **Start** screen, type **sharepoint**, and then select **SharePoint Online Management Shell**. +1. Connect to SPO service using `Connect-SPOService` cmdlet by providing admin credentials associated with tenancy. For information on [how to use Connect-SPOService](/powershell/module/sharepoint-online/connect-sposervice), refer the linked documentation. + +### Tenant requirements + +- An active instance of SharePoint is required in your Microsoft 365 tenant. +- Users who will be authenticating into SharePoint Embedded Container Types and Containers must be in Entra ID (Members and Guests) + + > [!NOTE] + > An Office license is not required to collaborate on Microsoft Office documents stored in a container. + +### Roles and Permissions + +- The admin who sets up the billing relationship for SharePoint Embedded needs to have owner or contributor permissions on the Azure subscription. +- Admin needs to have a SharePoint Embedded Administrator or Global Admin role to operate billing cmdlets. + +### Azure Subscription + +For the Standard Billing container type, the developer admin needs to set up: + +- An existing SharePoint tenancy +- An Azure subscription in the tenancy +- A resource group attached to the Azure subscription + +## Set up a Standard Billing container type + +For standard billed container types, developer admins should set up billing in their tenant. The Microsoft 365 SharePoint Embedded Administrator serves as the developer admin. Global Administrators in Microsoft 365 can assign users the SharePoint Embedded Administrator role, which already has all the permissions of the SharePoint Embedded Administrator role. The SharePoint Embedded Admin role is available in Microsoft Entra and Microsoft 365 Admin Center. + +SharePoint Embedded Admin can create a container type using the `New-SPOContainerType` cmdlet by providing an Azure subscription, the resource group associated with the subscription, and a region. + +- If you don't have an Azure subscription, you can create one by following the steps here to [create an Azure subscription in your tenancy](/azure/cloud-adoption-framework/ready/azure-best-practices/initial-subscriptions), +- If you don't have a resource group, you can create one by following the steps here to [create a resource group](/azure/azure-resource-manager/management/manage-resource-groups-portal) + +```powershell +New-SPOContainerType -ContainerTypeName + -OwningApplicationId + -AzureSubscriptionId + -ResourceGroup + -Region +``` + +> [!IMPORTANT] +> Every container type must have an owning application. +> +> A single-owning app can only own one container type at a time. +> +> An Azure subscription can be attached to any number of container types. + +### View & Edit billing properties of Standard container type + +You can view the properties of a container type and associated billing properties by using one of the two PowerShell cmdlets: + +1. See all container types and billing properties except associated region: + + ```powershell + Get-SPOContainerType + ``` + +1. See billing properties associated with a container type including region: + + ```powershell + Get-SPOContainerType -ContainerTypeId + ``` + +1. Update Azure subscription or resource group associated with a container type: + + ```powershell + Set-SPOContainerType -ContainerTypeId [-AzureSubscriptionId ] [-ResourceGroup ] + ``` + + +## Set up a Pass-through Billing container type + +For Pass-through Billing container types, the developer admin doesn't have to set up billing in the developer tenant. SharePoint Embedded Admin can create container type using `New-SPOContainerType` cmdlet with `isPassThroughBilling` specified. + +```powershell +New-SPOContainerType -ContainerTypeName + -OwningApplicationId + -isPassThroughBilling +``` + +### [Set Up Guide in Consuming Tenant Admin Center](../consuming-tenant-admin/cta.md#set-up-billing-for-pass-through-app) + +1. In [Microsoft 365 admin center](https://admin.microsoft.com/), select **Setup**, and the view the **Files and Content** section. Select **Automate Content with Microsoft Syntex.** + + ![Microsoft 365 admin center Files and Content](../../images/DTCBilling1.png) + +1. Select **Go to Syntex settings**. +1. Select **Apps** under **Syntex services for**, select **SharePoint Embedded** + + ![Microsoft 365 admin center SharePoint Embedded Billing setting](../../images/DTCBilling2.png) + +1. Follow the instructions on the **SharePoint Embedded** flyer to turn on SharePoint Embedded apps. + +## SharePoint Embedded meters + +To learn more about the supported pay-as-you-go meters, refer to the [SharePoint Embedded meters](meters.md) article. diff --git a/docs/embedded/administration/billing/billingmanagement.md b/docs/embedded/administration/billing/billingmanagement.md new file mode 100644 index 000000000..b2e03cac5 --- /dev/null +++ b/docs/embedded/administration/billing/billingmanagement.md @@ -0,0 +1,57 @@ +--- +title: SharePoint Embedded Billing Management +description: This article describes how to view SharePoint Embedded application consumption in Azure portal. +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# SharePoint Embedded Billing Management + +The Microsoft Cost Management portal provides a comprehensive overview of your costs, allowing you to track and analyze your spending for SharePoint Embedded application. This guide walks you through the steps to view your billing details and SharePoint Embedded consumption in the Microsoft Cost Management portal. + +## Step-by-Step Guide + +### Sign in to Azure portal + +1. Open your web browser and navigate to the [Azure portal](https://portal.azure.com/). +1. Sign in using your Azure account credentials. + +### Navigate to Cost Management + Billing + +1. Once signed in, locate the left-hand navigation menu. +1. Select on "Cost Management + Billing". If it's not visible, you can search for it using the search bar at the top of the portal. + + ![Cost Management](../../images/billmanag1.png) + +### Select Your Subscription + +1. In the Cost Management + Billing section, you see a list of your subscriptions. +1. Select the subscription for which you want to view the billing details. + +### View Billing Overview + +1. After selecting your subscription, you'll be taken to the Overview page. +1. Here, you can see a summary of your costs, including current spending, forecasted costs, and any spending anomalies. + +### Access Cost Analysis + +1. For a more detailed view, select "Cost analysis" under the Cost Management section. +1. In the Cost Analysis page, you can customize the date range to view costs for specific periods. +1. Use the filters to break down costs by tags - app ID, tenant ID or container type ID. Filters can also set by Meters, Resources etc. Refer to the [SharePoint Embedded meters](meters.md) article to learn more about the pay-as-you-go meters supported. + +![Meters](../../images/billmanag2.png) + +### Download Invoices + +1. To download invoices, go to the "Invoices" section under Billing. +1. Here, you can view and download your billing invoices for any billing period. + +### Set Up Budgets and Alerts + +1. To better manage your spending, you can set up budgets and alerts. +1. Select "Budgets" under the Cost Management section. + + ![Budgets](../../images/billmanag3.png) + +1. Create a new budget by specifying the amount and the time period. +1. Set up alerts to notify you when spending approaches or exceeds your budget. diff --git a/docs/embedded/administration/billing/meters.md b/docs/embedded/administration/billing/meters.md new file mode 100644 index 000000000..a6f770eea --- /dev/null +++ b/docs/embedded/administration/billing/meters.md @@ -0,0 +1,39 @@ +--- +title: SharePoint Embedded Billing Meters +description: This article describes the meters in SharePoint Embedded. +ms.date: 04/30/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded Billing Meters + +SharePoint Embedded employs a pay-as-you-go (PAYG) billing model through an Azure subscription. Billing is determined by how much data in GB you store in SharePoint Embedded, transactions used to access and modify the container and container contents, and data that is egressed from the SharePoint Embedded platform. Each of these factors contributes to the overall cost, ensuring that you only pay for the resources and services you use. You can view this usage and billing details in the [Azure Cost Management](https://ms.portal.azure.com/). Both Standard Billing container type and Pass-through Billing container type will use the same meters. + +SharePoint Embedded has three billing meters as shown. Refer to the [product page](https://adoption.microsoft.com/en-us/sharepoint/embedded/) for pricing details. + + +## Storage + +Storage consumption meters in SharePoint Embedded apply to the storage used by files and documents along with their metadata and versions. Storage consumption also includes all content in the recycle bin and deleted container collection within SharePoint Embedded. + +## API Transactions + +Each Microsoft Graph call made explicitly by the SharePoint Embedded application is counted as one transaction and customers are billed based on the transaction count. See the [examples](/graph/api/resources/filestoragecontainer) of Microsoft Graph calls that can be made by a SharePoint Embedded application. + +However, calls made by internal services to the containers, which the application has no control over, are **not** charged. Some examples of such nonchargeable transactions include: + +1. Queries performed by the eDiscovery service to search through container content for compliance or legal purposes. +1. Admin actions taken by the SharePoint Embedded Admin or Global Admin on containers through SharePoint Admin Center or SPO PowerShell. + +## Egress + +Egress refers to the data downloaded from the SharePoint Embedded platform to the customer's client device such as a desktop or mobile device. + +However, certain types of data transfers are exempt from egress charges. These exemptions ensure that customers aren't billed for data transfers occurring within integrated Microsoft services, promoting seamless usage without extra costs for these specific internal operations. Some examples of these exemptions include: + +1. File downloads from the SharePoint Embedded application server to the customer's Office Desktop client aren't charged. +1. File downloads from the SharePoint Embedded application server to the Web Application Companion (WAC) aren't charged. + +## Pay as you go message (private preview) + +SharePoint Embedded agents use the Copilot Studio meter for $0.01/message (messages are the unit that measures agent usage). Each interaction with SharePoint Embedded agent will use twelve (12) messages - 2 messages for the generative answer feature and 10 messages for the tenant graph grounding feature - so customers are billed at $0.12 per interaction with SharePoint Embedded agents. diff --git a/docs/embedded/administration/consuming-tenant-admin/cta.md b/docs/embedded/administration/consuming-tenant-admin/cta.md new file mode 100644 index 000000000..786aa6acf --- /dev/null +++ b/docs/embedded/administration/consuming-tenant-admin/cta.md @@ -0,0 +1,92 @@ +--- +title: Consuming Tenant Admin +description: This article describes the role and responsibilities of Consuming Tenant Admin in SharePoint Embedded. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# Consuming Tenant Admin + +> [!IMPORTANT] +> Assign the SharePoint Embedded Administrator role available in M365 Admin Center or Microsoft Entra to execute SharePoint Embedded Container cmdlets mentioned in this article. +> +> Global Administrators can continue to execute SharePoint Embedded container cmdlets. +> +> A global administrator can assign a user the SharePoint Embedded administrator role to act as a consuming tenant admin for SharePoint Embedded. + +The organizations that use the SharePoint Embedded applications on their Microsoft 365 (Microsoft 365) tenants are the consuming tenants and the persona that is responsible for managing these applications on their Microsoft 365 tenancy is the consuming tenant administrator. Consuming tenant administrators can perform various administrative actions on the SharePoint Embedded applications registered on their Microsoft 365 tenant and on the containers that hold the content. They can also manage tenant level configurations and ensure that data is stored in a secure, protected way that meets customers’ business and compliance policies. In this article, we describe the enterprise manageability features that are supported and can be performed by the consuming tenant administrator. They can do so either using the PowerShell cmdlets or through the SharePoint Administrator Center (SPAC). + +## Consuming Tenant Admin Role + +Microsoft 365 SharePoint Embedded Administrator serves as the consuming tenant admin. Global Administrators in Microsoft 365 can assign users the SharePoint Embedded Administrator. The Global Administrator role already has all the permissions of the SharePoint Embedded Administrator role. The SharePoint Embedded Role is available in Microsoft Entra and Microsoft 365 Admin Center. +For information on [SharePoint Embedded Admin](../adminrole.md) + +## Administration Tools + +Consuming tenant admins can manage SharePoint Embedded applications with the following options: + +### SharePoint Online Management Shell + +On PowerShell, the SharePoint Embedded Admin can run the following cmdlets: + +1. Enumerate applications in a tenant +1. Enumerate containers of an application in a tenant +1. Enumerate containers of an application sorted basis storage +1. Edit the sensitivity label on a container +1. Set sharing capability configuration on a container + +For information on consuming tenant admin in [PowerShell](../consuming-tenant-admin/ctapowershell.md) + +### SharePoint Administrator Center + +The SharePoint Embedded Admin can access the Active and Deleted containers page on SPAC and perform SharePoint Embedded application level and container level actions. This includes the following: + +1. View the Active container page +1. View the Deleted container page +1. View the detailed information of a container +1. Soft delete, restore, and purge deleted containers + +For information on consuming tenant admin in SharePoint Admin see [container management](ctaUX.md) + +## Security and Compliance Administration + +SharePoint Embedded uses Microsoft’s comprehensive compliance and data governance solutions to help organizations manage risks, protect, and govern sensitive data, and respond to regulatory requirements. Security and compliance solutions work in a similar manner in the SharePoint Embedded platform as they do today in the Microsoft 365 platform so that data is stored in a secure, protected way that meets customers’ business and compliance policies while making it easy for Compliance and SharePoint Administrators to enforce critical security and compliance policies on the content. For information on supported security and compliance capabilities, see [Security and Compliance](../../compliance/security-and-compliance.md). + +## Set Up Billing for Pass-through App + +To use Pass-through SharePoint Embedded App, SharePoint Embedded Admin needs to set up Microsoft Syntex billing in [Microsoft 365 admin center](https://admin.microsoft.com/). No user can access any Pass-through SharePoint Embedded apps before a valid billing is set up for the SharePoint Embedded platform. + +### [Meters](../billing/meters.md) + +SharePoint Embedded employs a pay-as-you-go (PAYG) billing model through an Azure subscription. Billing is determined by how much data in GB you store in SharePoint Embedded, transactions used to access and modify the container and container contents, and data that is egressed from the SharePoint Embedded platform. Each of these factors contributes to the overall cost, ensuring that you only pay for the resources and services you use. You can view this usage and billing details in the [Azure Cost Management](https://ms.portal.azure.com/). + +SharePoint Embedded has three billing meters as shown. Refer to the [product page](https://adoption.microsoft.com/en-us/sharepoint/embedded/) for pricing details + +| SharePoint Embedded Service Meters | Meter Unit | +| :--------------------------------: | :------------: | +| Storage | $/GB | +| API Transactions | $/Transactions | +| Egress | $/GB | + +### Set Up Guide + +1. A valid Azure subscription is required. You can create one by following the steps here to [create an Azure subscription](/azure/cloud-adoption-framework/ready/azure-best-practices/initial-subscriptions). +1. A valid Azure resource group is required. You can create one by following the steps here to [create a resource group](/azure/azure-resource-manager/management/manage-resource-groups-portal). +1. In [Microsoft 365 admin center](https://admin.microsoft.com/), select **Setup**, and the view the **Files and Content** section. Select **Automate Content with Microsoft Syntex.** + + ![Microsoft 365 admin center Files and Content](../../images/DTCBilling1.png) + +1. Select **Go to Syntex settings**. +1. Select **Apps** under **Syntex services for**, select **SharePoint Embedded** + + ![Microsoft 365 admin center SharePoint Embedded Billing setting](../../images/DTCBilling2.png) + +1. Follow the instructions on the **SharePoint Embedded** flyer to turn on SharePoint Embedded apps. + +### [Billing Management](../billing/billingmanagement.md) + +The [Microsoft Cost Management portal](https://portal.azure.com/#view/Microsoft_Azure_CostManagement/Menu/~/overview/openedBy/AzurePortal) provides a comprehensive overview of your costs, allowing you to track and analyze your spending for SharePoint Embedded application. This guide walks you through the steps to view your billing details and SharePoint Embedded consumption in the Microsoft Cost Management portal. + +### Invalid Billing/Turn off SharePoint Embedded + +If you turn off SharePoint Embedded or disconnect the linked Azure subscription, all users will immediately lose access to any application built on the service along with any read and write permissions. diff --git a/docs/embedded/administration/consuming-tenant-admin/ctaUX.md b/docs/embedded/administration/consuming-tenant-admin/ctaUX.md new file mode 100644 index 000000000..052f26f50 --- /dev/null +++ b/docs/embedded/administration/consuming-tenant-admin/ctaUX.md @@ -0,0 +1,218 @@ +--- +title: Manage containers in SharePoint Admin Center +description: This article describes how administrators can manage containers in the SharePoint Admin Center (SPAC). +ms.date: 07/09/2025 +ms.localizationpriority: high +--- +# Manage SharePoint Embedded containers in SharePoint Admin Center + +The organizations that use the SharePoint Embedded applications on their Microsoft 365 tenants are the consuming tenants and the persona that is responsible for managing these applications on their Microsoft 365 tenancy is the consuming tenant administrator (CTA). Consuming tenant administrators can manage containers through a graphical user interface (GUI) using the [SharePoint Administrator Center](https://go.microsoft.com/fwlink/?linkid=2185219). + +To manage SharePoint Embedded containers, the CTA needs to be assigned the SharePoint Embedded Administrator role. + +For information on the SharePoint Embedded Administrator role, see [SharePoint Embedded Admin](../adminrole.md). + +The following actions are supported in SharePoint Admin Center: + +1. View active containers in the tenant +1. View deleted containers in the tenant +1. View detailed information about a container +1. Delete a container +1. Restore a deleted container +1. Permanently deleted a container +2. Sort active containers in the tenant +3. Filter active containers in the tenant +4. Set sensitivity label on active containers +5. Add users to different roles on a container +6. Reassign users from existing roles on a container +7. Remove users from existing roles on a container + +![Active Containers global admin](../../images/ctaux1.png) + +**SharePoint Embedded Administrator** will only see the "Active containers" and "Deleted containers" page when they sign in to SharePoint Admin Center. + +![Active Containers SPE admin](../../images/ctaux2.png) + +## Active Containers + +The Active Containers page displays all the active containers within the tenant, providing a comprehensive overview and management capabilities. This page includes the following metadata for each container: + +1. **Container name:** Name of the container provided by the container owner. +1. **Application name:** Name of the SharePoint Embedded application the container belongs to. +1. **Publisher:** The name of the organization that owns the application. For all publishers other than Microsoft, the value is currently stored as "Other" +1. **Ownership type:** Mentions whether the container is tenant-owned, user-owned, or group-owned. +1. **Principal owner:** The user whose lifecycle impacts the lifecycle of the container. There is no prinicipal owner for a tenant owned container, while it is a user for a user owned container and a group for a group owned containers. +1. **Storage:** The total storage of the files stored in the containers. +1. **Owners:** Users assigned the owner role on the container. +1. **Owner count:** The count of number of owners of the container. +1. **Sensitivity label:** Name of the label assigned to the container. +1. **Created on:** Date and time when the container was created. + +![Active Container Properties](../../images/ctaux3.png) + +### View details of a container + +The detailed container view provides a deeper dive into container-specific metadata, organized under two tabs: + +1. **General:** This panel displays all the general metadata about a container, usage, and configuration settings. + + ![Container Details](../../images/ctaux4.png) + +1. **Membership:** This panel shows the user permissions for different users associated with the container. The admin can manage the membership on a container through this panel. + +> [!IMPORTANT] +> The SharePoint Embedded platform supports four distinct [roles](../../development/sharing-and-perm.md): Owner, Manager, Writer, and Reader. The SharePoint Embedded application on your tenant may not utilize all four roles and might refer to these roles using different names. + +![SharePoint Embedded Membership Roles](../../images/ctaux5.png) + +## Deleted Containers + +The deleted containers page lists all containers in the tenant's deleted container collection. It lists the following metadata: + +1. Container name +1. Application name +1. Publisher +1. Ownership type +1. Principal owner +1. Storage +1. Owners +1. Sensitivity label +1. Created on +1. **Deleted on**: Date and time when the container was deleted. + +![Container Deletion](../../images/ctaux6.png) + +## Delete a container + +> [!WARNING] +> Deleting a container may cause unexpected issues for the SharePoint Embedded application it belongs to and may interrupt the application's usage. This action should only be performed by admins when absolutely necessary. + +Deleting a container can have implications on the functionality of a SharePoint Embedded app Here are some examples of the potential issues that an application can encounter when deleting a container. + +1. **Data Loss:** Deleting a container removes all its content. If the SharePoint Embedded application relies on the data stored within the deleted container, the app might no longer function as expected or might lose access to critical information. +1. **Broken Links:** If the SharePoint Embedded application contains links or references to the deleted container, those links become broken, leading to errors or malfunctioning features within the app. + +A container can be deleted from the Active containers page for any business reason by the CTA. By default, the delete button is deactivated. On selecting a container, the delete button is activated. The CTA can then select the delete button. + +![Container Deletion Process](../../images/ctaux7.png) + +This opens a side panel that warns the user about the effect on the associated SPE application due to the deletion of a container and informs the user about the restoration policy. The CTA can at this stage either cancel the panel and go back to the active containers page or proceed further with the deleting by clicking on “Delete container”. + +![Container deletion selection](../../images/ctaux8.png) + +The selected container is successfully deleted and moved into the deleted containers page. + +![Deleted SPE Container](../../images/ctaux9.png) + +**Deleted containers are permanently purged after 93 days unless there is a retention policy applied to the containers.** + +## Restore a container + +A container in the deleted container collection can be restored on the Deleted containers page by selecting the corresponding containers by selecting the "Restore" link + +![Restore Button SPE Container](../../images/ctaux10.png) + +Restoration of the container happens in the background and the status of the same is displayed on the top-right corner of the page. Upon successful restoration, the container will be available in the Active Containers page. + +![Restored SPE Container](../../images/ctaux11.png) + +## Permanently delete a container + +> [!WARNING] +> Deleting a container may cause unexpected issues for the SharePoint Embedded application it belongs to and may interrupt the application's usage. This action should only be performed by admins when absolutely necessary. + +The CTA can permanently delete a deleted container from the deleted container collection if they decide to. + +The CTA selects the container to be permanently deleted. The “Permanently delete” button is enabled. + +![Permanent SPE Container deletion](../../images/ctaux12.png) + +Upon clicking the button, a pop-up appears. warning the CTA on the action they're performing. If sure, the CTA can proceed and select “Delete”. Otherwise, the CTA can cancel the action. + +![Container Deletion warning](../../images/ctaux13.png) + +Upon clicking Delete, the container is permanently deleted, and the status of the same appears in the top-right corner of the page. Upon successful deletion, the container is permanently removed from the deleted container collection and can't be restored. + +![SPE Container Deleted](../../images/ctaux15-n.png) + +## Sorting on Active containers page + +The CTA can perform their compliance and storage management tasks better through the use of sorting capabilities on the Active containers page. Currently, sorting is supported on the following columns: +1. Storage +1. Created on + +![ SPE Container Sorting](../../images/sorting.png) + +## Filtering on Active containers page + +The CTA can perform their compliance and storage management tasks better through the use of filtering capabilities on the Active containers page. Currently, filtering is supported on the following columns: + +1. Application name: The filter provides the list of all Microsoft SharePoint Embedded applications along with all SharePoint Embedded applications published by other publishers that is registered in the tenant. +1. Publisher: Describes whether the application is Microsoft-owned or published by an "Other" publisher. +1. Ownership type: The filter provides the options of Tenant, User, and Group, irrespective of the type of containers present in the tenant. +1. Principal owner: The filtering experience is a people picker experience. +1. Owner count: This filter provides a range of owner count for the administrator to choose from. +1. Created on: This filter provides a range of dates for the administrator to choose from. + +> [!IMPORTANT] +> The behaviour of the filtering experience on the Active containers page differs from the experience on the Active sites page in SharePoint Admin Center. + +![ SPE Container Filtering](../../images/filter.png) + +## Searching on Active Containers Page + +The search bar on the Active Containers Page can be used to search containers in the active state by their "container name". +![SPE Container Search](../../images/search.png) + +## Editing the sensitivity label of a container on the Active containers page + +The sensitivity label of a container can be set on the Active container page, on the detailed panel of a container. Under the settings panel, the administrator can set the sensitivity label from a list of available sensitivity label. + +![SPE Container Sensitivity](../../images/sensitivity-label.png) + +## Managing user membership of a container + +The administrator can manage the membership of users of a container on the Active container page, on the detailed panel of a container. Under the membership panel, the administrator can view the four roles and the corresponding users in each role. The administrator can: + +**Add a user to a role:** The administrator can navigate to the desired role using the left panel and click on the Add option. This opens up a picker, using which the administrator can select a user from the tenant and assign the role. In case the selected user is already assigned to a different role, the role is displayed when the role is selected and the operation changes from Add to Reassign. + +![SPE Container owner-one](../../images/add-owners-one.png) + +![SPE Container owner-two](../../images/add-owners-two.png) + +**Reassign user to another role:** The administrator can navigate to the desired user under a role using the left panel. On selecting the user, the Reassign option appears. On selecting the option, a drop-dowm menu appears and the administrator can select the role to which the user needs to be reassigned to. + +![ SPE Container reassingn](../../images/reassign-user.png) + +**Remove user from a role:** The administrator can navigate to the desired user under a role using the left panel. On selecting the user, the Remove option appears. On selecting the option, a pop-up screen appears, and the administrator can confirm the removal of the user from the role. + +![SPE Container remove](../../images/remove-user.png) + +## Sorting on the Deleted Containers Page + +Similar to the sorting experience on the Active containers page, the CTA can use sorting capabilities on the Deleted containers page. Currently, sorting is supported on the following columns: + +1. Storage +1. Created on +1. Deleted on + +![ SPE Container Sorting_on_Delete](../../images/sorting-on-deleted.png) + +## Filtering on the Deleted containers page + +The CTA can perform their compliance and storage management tasks better through the use of filtering capabilities on the Deleted containers page, on the following columns: + +1. Application name: The filter provides the list of all Microsoft SharePoint Embedded applications along with all SharePoint Embedded applications published by other publishers that is registered in the tenant. +2. Publisher: Describes whether the application is Microsoft-owned or published by an "Other" publisher. +3. Ownership type: The filter provides the options of Tenant, User, and Group, irrespective of the type of containers present in the tenant. +4. Principal owner: The filtering experience is a people picker experience. +5. Owner count: This filter provides a range of owner counts for the administrator to choose from. +6. Created on: This filter provides a range of dates for the administrator to choose from. +7. Deleted on: This filter provides a range of dates for the administrator to choose from. + +![ SPE Container Filter_on_Delete](../../images/filter-on-delete.png) + +## Upcoming features + +1. Search on the Deleted containers page +1. Sorting and filtering on the Sensitivity Label column diff --git a/docs/embedded/administration/consuming-tenant-admin/ctapowershell.md b/docs/embedded/administration/consuming-tenant-admin/ctapowershell.md new file mode 100644 index 000000000..6a46cc10d --- /dev/null +++ b/docs/embedded/administration/consuming-tenant-admin/ctapowershell.md @@ -0,0 +1,198 @@ +--- +title: Consuming Tenant Admin PowerShell +description: This article describes how an admin can manage containers through SPO PowerShell. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded container management in PowerShell + +The consuming tenant administrator can manage containers using PowerShell commands, designed for container management. To access these commands, they must be assigned the role of Microsoft 365 SharePoint Embedded Administrator. Global Administrators in Microsoft 365 can assign users the SharePoint Embedded Administrator role. The Global Administrator role inherently includes all permissions of the SharePoint Embedded Administrator role. The SharePoint Embedded Administrator role is available in both Microsoft Entra and the Microsoft 365 Admin Center. + +For more information on assigning the SharePoint Embedded admin role, see the [SharePoint Embedded Administrator](../adminrole.md). + +The following are some of the container-specific command actions currently supported on PowerShell: + +### Application administration + +- Get the details of all SharePoint Embedded applications registered in the tenant +- Get the details of all SharePoint Embedded applications in the tenant sorted by storage +- Get the details of a specific SharePoint Embedded application in the tenant +- Get the permissions of the owning applications in the tenant +- Configure the External sharing setting of a container of a SharePoint Embedded application in the tenant + +### Container administration + +- Get details of all containers of a particular SharePoint Embedded application in the tenant +- Get details of a specific container +- Set the Sensitivity label of a specific container +- Soft delete a container +- Get details of all soft deleted containers +- Restore a soft deleted container +- Permanently delete a soft deleted container + +## Administration through SharePoint PowerShell + +Consuming tenant admin can manage SharePoint Embedded applications with PowerShell commands using [SharePoint Online Management Shell](/powershell/sharepoint/sharepoint-online/connect-sharepoint-online). + +To get started using PowerShell to manage SharePoint Embedded, you have to install the [SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588) and [connect to SharePoint Online](/powershell/module/sharepoint-online/connect-sposervice). + +> [!IMPORTANT] +> You must use the latest version of SharePoint PowerShell to use container administration cmdlets. + + +## Application Administration + +With PowerShell cmdlets, tenant admin can get a list of SharePoint Embedded applications registered in their Microsoft 365 tenancy. They can also view all the applications that have "read" and/or "write" access and the level of access to these SharePoint Embedded applications. + +The following commands can be used to manage SharePoint Embedded applications registered on your Microsoft 365 tenants: + +```powershell +Get-SPOApplication +``` + +```powershell +Get-SPOApplication -OwningApplicationId +``` + +For more information, see [Get-SPOApplication cmdlet](/powershell/module/sharepoint-online/get-spoapplication). + +### View guest application permissions + +Admins can view the guest application permissions for any SharePoint Embedded application within their tenant using this command: + +```powershell +Get-SPOApplication -OwningApplicationId -ApplicationId +``` + +`OwningApplicationId` is the ID of the SharePoint Embedded application and ApplicationId is the guest application ID that has access to the SharePoint Embedded application. Application Administration cmdlets don't apply to Microsoft Loop. For more information, see [Get-SPOApplication cmdlet](/powershell/module/sharepoint-online/get-spoapplication). + +### Set sharing capability of applications + +Consuming tenant admins can set the sharing capability at an application level to determine whether files of the containers of the application be shared with external guests or not. + +```powershell +Set-SPOApplication -OwningApplicationId – SharingCapability - OverrideTenantSharingCapability <$ OverrideTenantSharingCapability > +``` + +`SharingCapability` can take the following values: `Disabled`; `ExistingExternalUserSharingOnly`; `ExternalUserSharingOnly`; ExternalUserAndGuestSharing + +`$OverrideTenantSharingCapability` can take the following values: `$true`; `$false` + +## Container Administration + +### View Containers + +Admins can get a list of all the containers for a SharePoint Embedded application using the following commands. This command lists all the active containers within the application: + +```powershell +Get-SPOContainer -OwningApplicationId | FT +``` + +The `OwningApplicationId` is the ID of the SharePoint Embedded application. For more information about using this command, see [Get-SPOContainer cmdlet](/powershell/module/sharepoint-online/get-spocontainer). + +> [!NOTE] +> To enumerate Microsoft Loop containers, use Owning App ID: **a187e399-0c36-4b98-8f04-1edc167a0996** for all the cmdlets of container administration. + +### View containers sorted by storage +Consuming tenant admins can also get a list of all the containers of a SharePoint Embedded application sorted by storage using the following commands. + +```powershell +Get-SPOContainer -OwningApplicationId -SortByStorage | FT +``` + +`` can be `Ascending` or `Descending`. + +### View details of a Container + +Consuming tenant admins can get the details of a container within an application using the following command. This command returns more details of a container including StorageUsed, Ownership details, SiteURL, Label information, Owners count, etc. + +Consuming tenant admins can use the following command: + +```powershell +Get-SPOContainer -Identity +Get-SPOContainer -Identity +``` + +Here, the `containerId` is the ID of the container & `siteURL` is the URL of the SharePoint site that is associated with the container. + +### Sensitivity Label of a container + +Consuming tenant admins can set the sensitivity label of a container of an application using the following: + +```powershell +Set-SPOContainer -Identity -SensitivityLabel +``` + +Consuming tenant admins can remove the sensitivity label of a container of an application using the following: + +```powershell +Set-SPOContainer -Identity -RemoveLabel +``` + +The `ContainerId` is the ID of the container whose sensitivity label is being set. + +### Delete containers + +Deleting a container can have implications on the functionality of a SharePoint Embedded app, Here are some examples of the potential issues that an application can encounter when deleting a container. + +- Data Loss: Deleting a container removes all its content. If the SharePoint Embedded application relies on the data stored within the deleted container, the app might no longer function as expected or might lose access to critical information. +- Broken Links: If the SharePoint Embedded application contains links or references to the deleted container, those links become broken, leading to errors or malfunctioning features within the app. +- Permissions Issues: Deleting a container can affect permissions settings. If the SharePoint Embedded app relies on specific permissions granted to the deleted container, it might encounter permission issues and fail to function properly. + +Therefore, it's essential to carefully consider the consequences of deleting a container and ensure that appropriate measures are taken to mitigate any potential issues. + +### Permanent deletion + +When admins delete a Container, it goes into the Recycle Bin. A deleted container can be restored from the Recycle Bin within 93 days. If a container is deleted from the Recycle Bin, or it exceeds the 93-day retention period, it's permanently deleted. Deleting a container deletes everything within it, including all documents and files. + +Admins should notify the Container owners before they delete a Container so they can move their data to another location, and also inform users when the Container is deleted. + +> [!WARNING] +> Deleting a container may cause unexpected issues for the SharePoint Embedded application the Container belongs to and may interrupt usage of the application. + +```powershell +Remove-SPOContainer -Identity +``` + +The `ContainerId` is the ID of the container that is moved to the deleted container collection. For more information about using this command, see [Remove-SPOContainer cmdlet](/powershell/module/sharepoint-online/remove-spocontainer). + +### View deleted containers + +Admins can get a list of deleted containers on the deleted container collection using the following command. For more information about using this command, see [Get-SPODeletedContainer](/powershell/module/sharepoint-online/get-spodeletedcontainer). + +```powershell +Get-SPODeletedContainer +``` + +### Restore deleted containers + +Admins can restore a deleted container from the deleted container collection using the following command. For more information about using this command, see [Restore-SPODeletedContainer cmdlet](/powershell/module/sharepoint-online/get-spodeletedcontainer). + +```powershell +Restore-SPODeletedContainer -Identity +``` + +### Permanently delete containers + +Admins can permanently delete a container from the deleted container collection if the container has no further retention policies applied to it. For more information about using this command, see [Remove-SPODeletedContainer cmdlet](/powershell/module/sharepoint-online/remove-spodeletedcontainer). + +```powershell +Remove-SPODeletedContainer -Identity +``` + +### Guest application permission management + +If permitted, Admins can add, edit, and remove guest application access to SharePoint Embedded applications. A guest application is defined as any application within the enterprise applications of the owning tenant. For more information about using this command, see [Set-SPOApplicationPermission](/powershell/module/sharepoint-online/set-spoapplicationpermission). + +```powershell +Set-SPOApplicationPermission + [[-OwningApplicationId] ] + [[-ApplicationId] ] + [[-PermissionAppOnly] ] + [[-PermissionDelegated] ] +``` + +## Security and Compliance Administration + +SharePoint Embedded uses Microsoft’s comprehensive compliance and data governance solutions to help organizations manage risks, protect, and govern sensitive data, and respond to regulatory requirements. Security and compliance solutions work similarly in the SharePoint Embedded platform as they do today in the Microsoft 365 platform so that data is stored in a secure, protected way that meets customers’ business and compliance policies while making it easy for Compliance and SharePoint Administrators to enforce critical security and compliance policies on the content. For information on supported security and compliance capabilities, see [Security and Compliance](../../compliance/security-and-compliance.md). diff --git a/docs/embedded/administration/developer-admin/dev-admin.md b/docs/embedded/administration/developer-admin/dev-admin.md new file mode 100644 index 000000000..f9621225e --- /dev/null +++ b/docs/embedded/administration/developer-admin/dev-admin.md @@ -0,0 +1,149 @@ +--- +title: Developer Admin +description: This article describes the role and responsibilities of Developer Tenant Admin in SharePoint Embedded. +ms.date: 03/03/2024 +ms.localizationpriority: high +--- +# Developer Admin + +## Overview + +Organizations that use SharePoint Embedded for file management are included in the Developer Ecosystem, which is overseen by developer administrators. These administrators are responsible for managing applications and the container types that have containers, the foundation of an application that needs to store content. Additionally, they can connect billing profiles to their applications. This article describes the management features available to developer administrators. + +## Developer Admin Role + +> [!IMPORTANT] +> Global Administrators can assign the SharePoint Embedded Administrator role available in M365 Admin Center or Microsoft Entra to execute SharePoint Embedded container commandlets mentioned in this article. +> +> Global Administrators can continue to execute SharePoint Embedded container cmdlets. + +A Microsoft 365 SharePoint Embedded Administrator serves as the developer admin. Global Administrators in Microsoft 365 can assign users the SharePoint Embedded Administrator role. The Global Administrator role already has all the permissions of the SharePoint Embedded Administrator role. The SharePoint Embedded Role is available in Microsoft Entra and Microsoft 365 Admin Center. For information on [SharePoint Embedded Administrator](../adminrole.md) role. + +The following are some of the container-specific commands actions currently supported on PowerShell: + +- Creation of container types + - Creation of Standard container type with standard billing + - Creation of Standard container type with direct to customer billing + - Creation of Trial container type +- Container type management + - Viewing of container types in the tenant + - Editing properties of a container type in the tenant + - Configuration properties of a container type in the tenant + - Manage billing of applications/ container types for standard billing + - Removing a container type in the tenant + +### Billing responsibilities of the developer admin + +There are two types of billing models followed: + +Standard billing: +The developer admin is responsible for the billing of SharePoint Embedded applications. The developer admin needs to establish billing for SharePoint Embedded while creating container types given they have owner or contributor permissions on the Azure subscription that they use to establish the billing relationship on the product. To learn more about how to set up billing and manage cost and invoice, read about [PAYG for SharePoint Embedded](../billing/billing.md). + +Direct to Customer billing: +In this model, the customer, or the consuming tenant admin, is responsible for billing. To ensure the Direct to Customer (DTC) Billing model, the developer admin must set the billing property of Direct to customer to enabled. + +## Administration Tools + +Developer admins are able to manage SharePoint Embedded applications with PowerShell commands using SharePoint Online Management Shell. + +To get started using PowerShell to manage SharePoint Embedded, you have to install the SharePoint Online Management Shell and connect to SharePoint Online. + +> [!IMPORTANT] +> You must use the latest version of SharePoint PowerShell to use container type administration cmdlets. + +## PowerShell cmdlets for admin experience + +### Creation of container types + +The developer administrator can create a container type using PowerShell cmdlets. Each container type is associated to an application ID, a one to one mapping, and an Azure subscription ID. The developer administrator can also create Trial container types that have a validity of 30 days to test out SharePoint Embedded. The following [commands](/powershell/module/sharepoint-online/new-spocontainertype) can be used to create SharePoint Embedded container types on the developer admin’s tenant: + +Standard billing container type: + +```powershell +New-SPOContainerType -ContainerTypeName -OwningApplicationId -AzureSubscriptionId -ResourceGroup -Region ​ +``` +Direct to customer billing container type: + +```powershell +New-SPOContainerType -IsPassThroughBilling -ContainerTypeName -OwningApplicationId +``` + +Trial container type: + +```powershell +New-SPOContainerType –TrialContainerType -ContainerTypeName -OwningApplicationId +``` + +OwningApplicationId is the ID of the SharePoint Embedded application. Azure Subscription ID is the ID of the Microsoft Entra ID profile for billing purposes. + +### Viewing of container types + +The developer administrator can view container types and the corresponding applications created in their tenant using PowerShell commandlets. The following commands can be used to view SharePoint Embedded applications created on the developer admin’s tenant: + +```powershell +Get-SPOContainerType​ +Get-SPOContainerType -ContainerTypeId +``` + +### Manage properties of container types + +Using PowerShell cmdlets, the developer administrator can change the properties of container types, both standard and trial. The following commands can be used to change the properties SharePoint Embedded applications created on the developer admin’s tenant: + +```powershell +Set-SPOContainerType -ContainerTypeId + [-OwningApplicationId ] + [-ContainerTypeName ] + [-WhatIf] [-Confirm] +``` + +### Container type configuration properties + +The developer administrator can change container type configuration settings using PowerShell commandlets. The following container type properties can be set: + +1. Discoverability Disabled: Controls if file items inside the container surface in other Microsoft 365 properties (MRU, etc.). +1. Sharing Restricted: Only manager and owner can share files in the container if restricted sharing is true. + +The following commands can be used to change the configuration settings of SharePoint Embedded applications created on the developer admin’s tenant: + +```powershell +Set-SPOContainertypeConfiguration -ContainerTypeId < ContainerTypeId > -DiscoverabilityDisabled $value +``` + +For `DiscoverabilityDisabled` `$value` can be set to `$true`; `$false` + +The default value `$true` - ensures all content is hidden. + +```powershell +Set-SPOContainertypeConfiguration -ContainerTypeId < ContainerTypeId > -SharingRestricted $value +``` + +For `SharingRestricted` `$value` can be set to `$true`; `$false` + +```powershell +Set-SPOContainertypeConfiguration -ContainerTypeId < ContainerTypeId > - DiscoverabilityDisabled $value -SharingRestriced $value +``` + +The developer admin can view the container type configuration settings using the following cmdlet: + +```powershell +Get-SPOContainertypeConfiguration -ContainerTypeId < ContainerTypeId > +``` + +## Manage billing profile of applications/ container types + +The developer administrator can change the billing profile of container types using PowerShell cmdlets. The following commands can be used to change the properties SharePoint Embedded applications created on the developer admin’s tenant: + +```powershell +Set-SPOContainerType -ContainerTypeId + [-AzureSubscriptionId ] + [-ResourceGroup ]​[-WhatIf] + [-Confirm] +``` + +For more information about billing, see [Billing](../billing/billing.md). + +## Roles and Permissions + +The user or admin who creates the billing relationship for SharePoint Embedded needs to have owner or contributor permissions on an Azure subscription. + +If you don't have an Azure subscription, follow steps here to [create a subscription.](/azure/cloud-adoption-framework/ready/azure-best-practices/initial-subscriptions) diff --git a/docs/embedded/compliance/security-and-compliance.md b/docs/embedded/compliance/security-and-compliance.md new file mode 100644 index 000000000..af95b70a3 --- /dev/null +++ b/docs/embedded/compliance/security-and-compliance.md @@ -0,0 +1,130 @@ +--- +title: Security and Compliance +description: Details Security and Compliance methods provided by SharePoint Embedded +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# Security and Compliance + +Microsoft's SharePoint Embedded provides a faster way to create secure and compliant documents stored in various applications. SharePoint Embedded uses Microsoft’s comprehensive compliance and data governance solutions to help organizations manage risks, protect, and govern sensitive data, and respond to regulatory requirements. Security and compliance solutions work similarly in the SharePoint Embedded platform as they do today on the Microsoft 365 (Microsoft 365) platform so that data is stored in a secure, protected way that meets customers’ business and compliance policies while making it easy for Compliance and SharePoint Administrators to enforce critical security and compliance policies on the content. + +In this article, we describe the security and compliance policies that are supported today on content that resides in the SharePoint Embedded platform, and their capabilities and limitations. + +Since SharePoint Embedded by design doesn’t have any user interface, some Compliance scenarios necessitating user interaction aren't natively supported. The owning application that governs the container can choose to support these scenarios and provide the optimal experience to end users by using the Microsoft Graph. + +## Compliance Policies using Microsoft Purview + +Currently, SharePoint Embedded supports the following Compliance features under Microsoft Purview. You can follow the following steps to retrieve the details of a container that the policy needs to be applied to. + +1. View a list of registered SharePoint Embedded applications registered in the specified tenant: + + ```powershell + Get-SPOApplication + ``` + +1. Retrieve a list of containers in a SharePoint Embedded application by providing the ApplicationID returned in Step #1: + + ```powershell + Get-SPOContainer -OwningApplicationId + ``` + +1. Retrieve the details of a container including the ContainerSiteURL by providing the ContainerID returned in Step #2: + + ```powershell + Get-SPOContainer -OwningApplicationId -Identity + ``` + +For information on how to retrieve the `ContainerSiteURL` to set the various compliance policies described in this article at a container level, see [Get-SPOContainer](/powershell/module/sharepoint-online/get-spocontainer). + +### Audit + +The Audit capabilities provided by SharePoint Embedded mirror the existing Audit functionalities currently supported within SharePoint. All user and admin operations performed in various applications hosted in SharePoint Embedded are captured, recorded, and retained in your organization's unified audit log. For more information on Audit, see [Auditing solutions in Microsoft Purview](/purview/audit-solutions-overview). + +In addition to existing file properties, Audit events related to SharePoint Embedded are logged with the following more data to help filter the Audit search results to isolate the relevant SharePoint Embedded content: + +- `ContainerInstanceId` +- `ContainerTypeId` + +![Audit events](../images/sc1.png) + + +### eDiscovery + +Compliance Admins can use eDiscovery tools in Microsoft Purview to search/hold/export content hosted in the SharePoint Embedded platform. For more information on eDiscovery, see [Microsoft Purview eDiscovery solutions](/purview/ediscovery). + +To perform an eDiscovery Search on all SharePoint Embedded content, Admins should select **All** SharePoint Sites when configuring the eDiscovery Search in Microsoft Purview. This enables the Search for content stored in all SharePoint Sites and all SharePoint Embedded containers. + +![eDiscovery search](../images/sc2.png) + +To limit the eDiscovery Search to one/few SharePoint Embedded containers, Admins can **Choose sites** under the **SharePoint sites** workload and provide the desired container URL. + +![choose sites in eDiscovery search](../images/sc3.png) + +### Data Lifecycle Management (DLM) + +SharePoint Embedded supports retention and holds policies on content stored in its applications using the Microsoft Purview compliance portal. For more information on DLM, see [Learn about Microsoft Purview Data Lifecycle Management](/purview/data-lifecycle-management). + +The existing retention policy is applied to all SharePoint Embedded containers if the policy is configured for **All sites**. Similarly, creating a new retention/hold policy on *all* SharePoint Sites workload automatically enforces the policy on all SharePoint Sites and all containers within SharePoint Embedded. + +![retention policy](../images/sc4.png) + +To selectively enforce the policy on one or more SharePoint Embedded containers, copy the container URL and configure the policy to be selectively enforced only on those containers. + +![enforce retention policy](../images/sc5.png) + +Since SharePoint Embedded doesn't have a built-in user interface, DLM scenarios requiring user interaction aren't natively supported. For instance, if an end user attempts to apply a retention label on a container using a SharePoint Embedded application (app), the app governing the access to the container must furnish that functionality. In such cases, Graph APIs for DLM functionalities can be used. + +### Data Loss Protection (DLP) + +Using Microsoft Purview, Admins can identify, monitor, and automatically protect sensitive items stored in applications using SharePoint Embedded. For more information on DLP, see  [Learn about data loss prevention](/purview/dlp-learn-about-dlp). + +Like retention policies, DLP policies can be enforced on all SharePoint Sites and SharePoint Embedded containers by choosing to configure the policy on ‘All sites’. + +![DLP Policy](../images/sc6.png) + +Admins can also restrict the enforcement of a DLP policy to specific SharePoint Embedded containers by specifying the relevant container URLs during policy configuration. + +![Configure DLP Policy](../images/sc7.png) + +Several scenarios supported by DLP today need user interaction that isn’t natively supported by SharePoint Embedded. For instance, based on its configuration, a DLP policy that prevents external sharing might allow end users to provide a business justification to override the policy. The client app that renders this DLP-flagged file item needs to support such user interactions. + +Policy tips are shown today for files hosted in SharePoint so that users are kept informed about DLP-flagged file items and corresponding restrictions. Similarly, for policy tips to be displayed for files hosted in SharePoint Embedded, the client app can choose to provide more support by utilizing the Microsoft Graph for this purpose. + +## Security features + +### Sensitivity labels on containers + +Global Administrators and SharePoint Administrators can set and remove sensitivity labels on a SharePoint Embedded container by using the newly created SharePoint PowerShell cmdlet: + +```powershell +Set-SPOContainer -Identity -SensitivityLabel +``` + +To learn more about setting sensitivity labels, see [Learn about sensitivity labels](/purview/sensitivity-labels). + +### Block Download policy + +Block Download policy allows SharePoint Administrator or Global Administrator to block the download of files from SharePoint Embedded containers using the following SharePoint PowerShell cmdlet. + +```powershell +Set-SPOSite -Identity -BlockDownloadPolicy $true +``` + +A SharePoint Advanced Management (SAM) license is needed to enforce this policy. Read the full documentation for advanced capabilities at [Block download policy for SharePoint sites and OneDrive](/sharepoint/block-download-from-sites). + +### Conditional Access policy + +SharePoint Embedded supports basic Conditional Access policy configurations such as: + +- `AllowFullAccess`: Allows full access from desktop apps, mobile apps, and the web +- `AllowLimitedAccess`: Allows limited, web-only access +- `BlockAccess`: Blocks Access + +These settings are available with the following PowerShell cmdlet. The `AuthorizationContext` will also be supported soon. + +```powershell +Set-SPOContainer -Identity -ConditionalAccessPolicy +``` + +To learn more about conditional access policies, see [Control access from unmanaged devices](/sharepoint/control-access-from-unmanaged-devices). diff --git a/docs/embedded/development/app-architecture.md b/docs/embedded/development/app-architecture.md new file mode 100644 index 000000000..d3eb1d73c --- /dev/null +++ b/docs/embedded/development/app-architecture.md @@ -0,0 +1,50 @@ +--- +title: App Architecture +description: Anatomy of a SharePoint Embedded application +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# SharePoint Embedded app architecture + +All files and documents in SharePoint Embedded are stored in containers, with all containers and container content created and stored within a Microsoft 365 Tenant. All containers and container content are created, managed, and interacted via the SharePoint Embedded application using Microsoft Graph. + +![SharePoint Embedded Architecture](../images/SPEArch.png) + +## SharePoint Embedded application + +A Microsoft Entra ID application registration. As an owning or guest application to a container type, it has access to containers of that container type. + +## Owning tenant and consuming tenant + +SharePoint Embedded introduces the concepts of owning tenant and consuming tenant. Owning tenant is a Microsoft Entra ID tenant where a container type is created. This is often also the tenant where your SharePoint Embedded application is registered. Consuming tenant is a Microsoft Entra ID tenant where a container type is used. Only a consuming tenant may have containers of such container type. All container and content created via the application is stored within the consuming tenant's Microsoft 365 tenant boundary. + +The same Microsoft Entra ID tenant can be both owning and consuming tenant of a given container type in the SharePoint Embedded ecosystem. + +## Container, container type, and owning application + +A container is the basic storage unit in SharePoint Embedded. Also, a container defines a security and compliance boundary. + +A container type is a SharePoint Embedded resource that defines the relationship, access privileges, and billing accountability between an application and a set of containers. Also, the container type defines behaviors on the set of containers. Learn more about [container types](../getting-started/containertypes.md). + +The container type is represented on each container as an immutable property and is used across the entire SharePoint Embedded ecosystem. Each container type is strongly coupled with one SharePoint Embedded application, which is referred to as the owning application. The owning application developer (the owning tenant) is responsible for creating and managing their container types. SharePoint Embedded mandates a 1:1 relationship between owning application and container type. + +## Access Model + +An application's access to containers and container content is determined by a set of permissions configured between the application and the container type it attempts to access. This set of permission is determined at container Type creation time for owning application. The SharePoint Embedded ecosystem allows applications to access containers of container types it doesn't own. + +In this illustration, multiple applications are deployed in the tenancy, including two apps developed by ISVs (App 1 and 2) and a LOB app (App 3). Each application can access only to the stack of containers of the container type they own. + +![SPE multi app architecture](../images/SPECTDedicated.png) + +In this illustration, both App 1 and App 2 in the tenancy have access to the same container type. Both apps can access the stack of the containers of that type. + +![SPE multi app architecture sharing Container Types](../images/SPECTShared.png) + +#### Example + +Contoso is an ISV and built a human resource management application on SharePoint Embedded. The application is registered and deployed in Fabrikam, an auditing firm. Fabrikam also developed an LOB auditing application on SharePoint Embedded that is used internally. + +In this scenario, both the human resource management application developed by Contoso and the auditing application developed by Fabrikam have their own container type. Contoso is the owning tenant of the human resource management application; and the application is the owning app for its container Type. Likewise, Fabrikam is the owning tenant the auditing application; and the application is the owning app for its container type. In addition, Fabrikam is the consuming tenant for both applications. + +![Example](../images/apparchexample.png) diff --git a/docs/embedded/development/auth.md b/docs/embedded/development/auth.md new file mode 100644 index 000000000..6e20ceb95 --- /dev/null +++ b/docs/embedded/development/auth.md @@ -0,0 +1,164 @@ +--- +title: SharePoint Embedded Authentication and Authorization +description: This article describes the authentication and authorization model for SharePoint Embedded applications. +ms.date: 06/24/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded authentication and authorization + +To use SharePoint Embedded, your application needs to use Microsoft Graph. Learn more about [Microsoft Graph authentication and authorization](/graph/auth/auth-concepts). Learn more about the [SharePoint Embedded architecture](./app-architecture.md). + +## Overview + +Here are some key principles of SharePoint Embedded authentication and authorization: + +- Applications interact with SharePoint Embedded via Microsoft Graph. +- Applications need container type application permissions to access containers of that container type. +- Applications can only access containers that the user is a member of when using access on behalf of a user. +- Applications can access all containers enabled by their container type application permissions when using access without a user. +- Applications use access on behalf of users whenever possible to enhance security and accountability + +## Pre-Requisites + +- A Microsoft Entra ID application registration. See [register an application](/graph/auth-register-app-v2). +- Your Microsoft Entra ID tenant has a Microsoft 365 subscription + +## Authorization + +SharePoint Embedded operations are exposed via Microsoft Graph. SharePoint Embedded supports [access on behalf of a user](/graph/auth-v2-user) and also [access without a user](/graph/auth-v2-service). + +> [!IMPORTANT] +> Microsoft Graph permissions granted to your application allow it to call SharePoint Embedded endpoints. However, your application must be granted [permission to a container type](#container-type-application-permissions) before it gets access to containers of that type. + +### Access on behalf of a user + +SharePoint Embedded operations [on behalf of a user](/graph/auth-v2-user) require applications to receive consent for Microsoft Graph [`FileStorageContainer.Selected`](/graph/permissions-reference#filestoragecontainerselected) delegated permission. This permission requires admin consent on the consuming tenant before any user from the tenant can consent to it. + +In addition to your application receiving consent for `FileStorageContainer.Selected` on a consuming tenant, the user that it's acting on behalf of is required to have [container permissions](#container-permissions). The effective permissions that the application has are the intersection of the application permissions and the user permissions when acting on behalf of a user. + +> [!IMPORTANT] +> Using SharePoint Embedded on behalf of a user is the recommended approach. This type of access enhances the security of your application. It also improves the auditability of actions performed by your application. + +### Access without a user + +SharePoint Embedded operations [without a user](/graph/auth-v2-service) require applications to receive consent for Microsoft Graph [`FileStorageContainer.Selected`](/graph/permissions-reference#filestoragecontainerselected) application permission. This permission requires admin consent on the consuming tenant. + +> [!NOTE] +> An administrator on the consuming tenant must consent to your application's request for permissions. Learn more [here](/entra/identity/enterprise-apps/grant-admin-consent?pivots=portal). + +### Exceptional access patterns + +Currently, there are two types of operations with exceptional access patterns: + +- [Operations not exposed via Microsoft Graph](#operations-not-exposed-via-microsoft-graph) +- [Operations involving searching SharePoint Embedded content](#operations-involving-searching-sharepoint-embedded-content) +- [Operations that require a user license](#operations-that-require-a-user-license) + +> [!IMPORTANT] +> Consider the repercussions of these exceptional access patterns on how your application and other applications can access SharePoint Embedded content in your container type. + +#### Operations not exposed via Microsoft Graph + +There are two types of operations that aren't accessible via Microsoft Graph today: + +- [Container type management](../getting-started/containertypes.md) on owning tenants, which are performed via PowerShell cmdlets. +- [Container type registration](../getting-started/register-api-documentation.md) on consuming tenants, exposed via SharePoint REST API v2. +- [SharePoint Embedded agent](./declarative-agent/spe-da.md) exposed via SharePoint REST API v2 permissions. + +To perform [container type management](../getting-started/containertypes.md) operations, you must be a [SharePoint Embedded Administrator](/entra/identity/role-based-access-control/permissions-reference#sharepoint-embedded-administrator) or [Global Administrator](/entra/identity/role-based-access-control/permissions-reference#global-administrator). + +To [register a container type](../getting-started/register-api-documentation.md), you must request the `Container.Selected` permission on the `Office 365 SharePoint Online` resource. + +| Scope name | Scope ID | Type | Operation | +| :-------------------: | :----------------------------------: | :---------: | :-----------------------------------------------------------------------------------------------: | +| Container.Selected | 19766c1b-905b-43af-8756-06526ab42875 | Application | In the context of SharePoint Embedded, enables container type registration on a consuming tenant. | + +> [!NOTE] +> Container type management on owning tenants and registration on consuming tenants will become Microsoft Graph operations soon, and this permission will no longer be needed. Stay tuned. + +To use the [SharePoint Embedded agent](./declarative-agent/spe-da.md) experience (in the Preview stage) in your application, you also need the `Container.Selected` permission on the `Office 365 SharePoint Online` resource. + +#### Operations involving searching SharePoint Embedded content + +This section refers only to the search scenarios in [Search Content](./content-experiences/search-content.md), and not the enumeration scenarios. + +To use [Microsoft Search](/microsoftsearch/overview-microsoft-search) on SharePoint Embedded content, you must request the Delegated [`Files.Read.All`](/graph/permissions-reference#filesreadall) Microsoft Graph permission on top of `FileStorageContainer.Selected`, normally used for SharePoint Embedded access. During the Preview stage of this feature, the `Files.Read.All` application permission grants applications access to search capabilities on all SharePoint Embedded content. + +> [!NOTE] +> Microsoft Search support for SharePoint Embedded content is in Preview and is subject to change. The access requirements for Microsoft Search on SharePoint Embedded content will align with the SharePoint Embedded authorization model in the future. Stay tuned. + +#### Operations that require a user license + +SharePoint Embedded is designed to work without the need for end users to have any kind of Microsoft 365 product licenses assigned to them. However, there are certain operations that don't abide by this principle yet. + +##### List containers + +The [List containers](/graph/api/filestorage-list-containers?tabs=http) operation returns a `403 Forbidden` response code if called on behalf of a user that doesn't have a OneDrive. There are plans to remove this dependency soon. This dependency doesn't apply to the List containers operation when called without a user context (app-only mode). + +##### Mention users in Office documents + +The common [Office experience](./content-experiences/office-experience.md) includes reviewing documents and adding comments to those documents. For users to show up in the @mentions people picker, they need to have a Microsoft 365 license assigned to them. + +### Container type application permissions + +SharePoint Embedded applications need to be granted container type application permissions by the owner application before they can access containers of the given container type. Container type application permissions are granted to applications via [container type registration](../getting-started/register-api-documentation.md). + +| Permission | Description | +| -------------------- | ------------------------------------------------------------------------------------------------------------------ | +| None | Has no permissions to any containers or content of this container type. | +| ReadContent | Can read the content of containers of this container type. | +| WriteContent | Can write content to containers for this container type. This can't be granted without the ReadContent permission. | +| Create | Can create containers of this container type. | +| Delete | Can delete containers of this container type. | +| Read | Can read the metadata of containers of this container type. | +| Write | Can update the metadata of containers of this container type. | +| EnumeratePermissions | Can enumerate the members of a container and their roles for containers of this container type. | +| AddPermissions | Can add members to the container for containers of this container type. | +| UpdatePermissions | Can update (change roles of) existing memberships in the container for containers of this container type. | +| DeletePermissions | Can delete other members (but not self) from the container for containers of this container type. | +| DeleteOwnPermissions | Can remove own membership from the container for containers of this container type. | +| ManagePermissions | Can add, remove (including self), or update members in the container roles for containers of this container type. | +| ManageContent | Can manage the content of the container | +| Full | Has all permissions for containers of this container type. | + +> [!NOTE] +> The combination of Microsoft Graph permissions and container type application permissions encompasses the client authorization for applications. + +### Container permissions + +Any user accessing a container must be a member of the container. Membership to a container [grants users container permissions](/graph/api/filestoragecontainer-post-permissions). These permissions define the access level that users have on a given container. Container permissions only apply to access on behalf of a user and not to access without a user. A SharePoint Embedded application accessing containers without a user gets the full access defined in its [container type application permissions](#container-type-application-permissions) instead. + +> [!IMPORTANT] +> The calling user creating a new container via delegated calls is automatically assigned the Owner role. + +| Permission | Description | +| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Reader | This role allows the user to read the properties and the contents of the container. | +| Writer | This role has all the permissions a Reader has, plus the permission to create, update, and delete content inside the container, and to update applicable container properties. | +| Manager | This role has all the permissions a Writer has, plus the permission to manage membership of the container. | +| Owner | This role has all the permissions a Manager has, plus the permission to delete containers. | + +## What's next + +Here are some actions you can take next: + +1. Configure your SharePoint Embedded [application manifest](/entra/identity-platform/reference-app-manifest#requiredresourceaccess-attribute) (you can use [Microsoft Entra PowerShell](/powershell/entra-powershell/manage-apps#assign-permissions-to-an-app) or the [Azure CLI](/cli/azure/ad/app/permission#az-ad-app-permission-add)) to request the required permissions: + + - Microsoft Graph (resourceAppId: `00000003-0000-0000-c000-000000000000`) + - `FileStorageContainer.Selected` (type: `Scope`, ID: `085ca537-6565-41c2-aca7-db852babc212`) to access containers on consuming tenants + - Office 365 SharePoint Online (resourceAppId: `00000003-0000-0ff1-ce00-000000000000`) + - `Container.Selected` (type: `Role`, ID: `19766c1b-905b-43af-8756-06526ab42875`) to register a container on consuming tenants + +1. [Grant admin consent](/entra/identity-platform/v2-admin-consent) to your application on both owning and consuming tenants (which can be the same tenant). + + > [!NOTE] + > The `Container.Selected` application permission is hidden, which can cause issues with granting admin consent using the Enterprise apps pane in the Azure portal. Instead, [construct the admin consent URL](/entra/identity-platform/v2-admin-consent#request-the-permissions-from-a-directory-admin) and provide it to your Microsoft Entra directory administrator. For example: + > + > `https://login.microsoftonline.com/{tenant}/v2.0/adminconsent?client_id={client_id}` + > + > Make sure the Microsoft Entra directory administrator [confirms a successful response](/entra/identity-platform/v2-admin-consent#successful-response). + +1. [Create a new container type](../getting-started/containertypes.md) on the owning tenant. +1. [Register a container type](../getting-started/register-api-documentation.md) on the consuming tenant. +1. [Create a container](/graph/api/filestoragecontainer-post) diff --git a/docs/embedded/development/content-experiences/office-experience.md b/docs/embedded/development/content-experiences/office-experience.md new file mode 100644 index 000000000..4add48ca4 --- /dev/null +++ b/docs/embedded/development/content-experiences/office-experience.md @@ -0,0 +1,77 @@ +--- +title: Office Experiences +description: Overview of Office experiences with SharePoint Embedded content +ms.date: 06/18/2025 +ms.localizationpriority: high +--- + +# Office file experiences for SharePoint Embedded + +Office file experiences for SharePoint Embedded platform will work in a similar manner to Microsoft 365 platform. + +## Opening Office documents from SharePoint Embedded + +Office documents from SharePoint Embedded apps can be opened for viewing and editing in Office web or in the Office application for a richer viewing and editing experience. AutoSave feature saves your files automatically as your user's work and is enabled for each Word, Excel, and PowerPoint file stored in your SharePoint Embedded Application Apps. + +## View or restore a previous version of an Office document from SharePoint Embedded + +Versioning is automatically enabled on each Word, Excel, and PowerPoint file stored in your SharePoint Embedded Apps, that helps your users to see what changes have been made in a file, compare different versions, or restore the version you want. This is incredibly important to your users if a mistake was made, a previous version is preferred, or in multi-user coauthoring scenarios when your users are collaborating with others and someone makes changes your users didn't want in a file. + +## Collaborating on Office documents from SharePoint Embedded + +It's simple for your users to collaborate on your SharePoint Embedded Application's Office documents – they can **Share documents** with specific peers or with people outside your organization by Creating a shareable link to use wherever needed, Send an email invitation or @mention in comments to tag someone for feedback and, **Collaborate in real time** by co-authoring in Office with SharePoint Embedded Applications. + +> [!NOTE] +> Mentions require target users to [have an Microsoft 365 license assigned to them](../auth.md#mention-users-in-office-documents). +> +> Mentions are restricted to people inside the consuming tenant's organization. Mentions exclude guests and users from other tenants in a multitenant setting. + +### Share your documents + +#### Send an email invite + +Share your SharePoint Embedded documents by sending an email invitation to specific people: + +- Select Share, start typing the email addresses or contact names of people you want to share with. When you begin to enter info in the box, you can also choose a contact from the list that appears. +- Include a message if you want and hit Send. + +#### Create a shareable link + +Creating a shareable link makes it simple to share your SharePoint Embedded document in an email, document, or IM. + +- Select Share, Copy Link, and Paste the link wherever you want +- Change any permissions of the link if needed + +#### Co-Author + +If you want others to edit with you, you can easily share files and collaborate with trusted peers for a fresh perspective. When you need help with a presentation, you can invite trusted peers to help you get it into shape. This means that when you work on a file, they can as well. You’ll see their changes and they’ll see yours—as you make them! Use @mentions in comments to get someone's attention. + +- See who else is in the document and where they're working. +- A presence indicator shows where someone is making changes. See any changes right as they're being made. +- See changes made by others and see what's happened while you were away. + +#### Levels of sharing access + +There are different options for sharing SharePoint Embedded Application Office Documents from: + +| If you want to … | Sharing Setting to Set | +| ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Allow Anyone who receives the link access to SharePoint Embedded Application File | **Anyone**  gives access to anyone who receives this link, whether they receive it directly from you or are forwarded from someone else. This might include people outside of your organization. | +| Allow anyone in your organization to access to your SharePoint Embedded Application File | **People in \** gives anyone in your organization who has the link access to the file, whether they receive it directly from you or forwarded from someone else. | +| Secure your SharePoint Embedded Application docs only to specific people. | When you need to prevent recipients from forwarding a shared link, use the **Specific People**  permission. **Specific people**  gives access only to the people you specify, although other people might already have access. If people forward the sharing invitation, only people who already have access to the item will be able to use the link. | +| Reshare the link with specific people | **People with existing access**  can be used by people who already have access to the document or folder. It doesn't change the permissions on the item. Use this if you just want to send a link to somebody who already has access. | + +## Breadcrumb properties on Office documents from SharePoint Embedded + +Breadcrumb properties are used by Office clients to display breadcrumb-style elements within Office client UI that aid your users in associating Office files with your Application. + +> [!NOTE] +> We recommend specifying 'Current Channel' to take advantage of Breadcrumb patterns and future enhancements to Office Apps. Learn more about [specifying update channels for Office Apps](/deployoffice/updates/overview-update-channels). + +Breadcrumb patterns for SharePoint Embedded Application Apps are constructed from container properties configured for your Apps. The following diagram maps the container properties to breadcrumb presentation in Office clients: + +![Screenshot of breadcrumb pattern in SharePoint Embedded Applications](../../images/office2.png) + +Here are few examples of SharePoint Embedded Application breadcrumb display within Office client experiences. + +![Screenshot of breadcrumb options in SharePoint Embedded Applications.](../../images/office1.png) diff --git a/docs/embedded/development/content-experiences/search-content.md b/docs/embedded/development/content-experiences/search-content.md new file mode 100644 index 000000000..98afb1bd1 --- /dev/null +++ b/docs/embedded/development/content-experiences/search-content.md @@ -0,0 +1,832 @@ +--- +title: Search SharePoint Embedded containers and content +description: Overview on how to search SharePoint Embedded containers and content +ms.date: 03/28/2025 +ms.localizationpriority: high +--- + +# Search SharePoint Embedded content + +Use the [Microsoft Search](/microsoftsearch/overview-microsoft-search) API in Microsoft Graph to search SharePoint Embedded containers and content. The Search API lets you scope the container type and file type for your queries by specifying the corresponding parameter in the request body. This article describes some examples. + +> [!NOTE] +> +> 1. Searching SharePoint Embedded content is in Preview stage and is subject to change. Please refer to the [exceptional access pattern](../auth.md#operations-involving-searching-sharepoint-embedded-content) that describes its current permission requirements. +> 1. Search API only supports Delegated permissions. +> 1. Your search requests must specify and set the `includeHiddenContent` parameter if your application has opted out of content discoverability in Microsoft 365. Learn more about [SharePoint Embedded content discoverability](./user-experiences-overview.md). + +## Example 1: Search containers by container type + +This example queries all containers by the specified container type with the SharePoint Embedded application opted out from content discoverability on Microsoft 365. The response includes all container instances (`drive`) of the specified container type in the tenant: + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "drive" + ], + "query": { + "queryString": "ContainerTypeId:498c6855-8f0e-0de7-142e-4e9ff86af9ae" + }, + "sharePointOneDriveOptions": { + "includeHiddenContent": true + } + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)", + "value": [ + { + "searchTerms": [], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "rank": 1, + "summary": "Everything about Contoso", + "resource": { + "@odata.type": "#microsoft.graph.drive", + "id": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "createdBy": { + "user": { + "displayName": "Dylan Williams" + } + }, + "lastModifiedDateTime": "2024-01-18T19:45:25Z", + "name": "AllItems.aspx", + "parentReference": { + "sharepointIds": { + "listId": "26d6a67d-bd07-4646-9c5b-85b0e519d6f4" + }, + "siteId": "contoso.sharepoint.com,05031a50-e9c7-474c-889e-7cf44659a5b2,e00b849e-3cec-4ade-8f7b-96d1f0f598fa" + }, + "webUrl": "https://contoso.sharepoint.com/contentstorage/CSP_05031a50-e9c7-474c-889e-7cf44659a5b2/Document Library/Forms/AllItems.aspx" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` + +## Example 2: Search containers by title + +This example queries all containers by a specified container display name and the SharePoint Embedded application didn't opt out from content discoverability on Microsoft 365. The response includes all container instances in the tenant that match the criteria: + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "drive" + ], + "query": { + "queryString": "Title:'contoso' AND ContainerTypeId:498c6855-8f0e-0de7-142e-4e9ff86af9ae" + } + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)", + "value": [ + { + "searchTerms": [ + "contoso" + ], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "rank": 1, + "summary": "Everything about Contoso", + "resource": { + "@odata.type": "#microsoft.graph.drive", + "id": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "createdBy": { + "user": { + "displayName": "Dylan Williams" + } + }, + "lastModifiedDateTime": "2024-01-18T19:45:25Z", + "name": "AllItems.aspx", + "parentReference": { + "sharepointIds": { + "listId": "26d6a67d-bd07-4646-9c5b-85b0e519d6f4" + }, + "siteId": "contoso.sharepoint.com,05031a50-e9c7-474c-889e-7cf44659a5b2,e00b849e-3cec-4ade-8f7b-96d1f0f598fa" + }, + "webUrl": "https://contoso.sharepoint.com/contentstorage/CSP_05031a50-e9c7-474c-889e-7cf44659a5b2/Document Library/Forms/AllItems.aspx" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` + +## Example 3: Search containers by container description + +This example queries all containers by the specified container type and container description, with the SharePoint Embedded application opted out from content discoverability on Microsoft 365. The response includes all container instances in the tenant that match the criteria: + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "drive" + ], + "query": { + "queryString": "Description:'Everything' AND ContainerTypeId:498c6855-8f0e-0de7-142e-4e9ff86af9ae" + }, + "sharePointOneDriveOptions": { + "includeHiddenContent": true + } + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)", + "value": [ + { + "searchTerms": [], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "rank": 1, + "summary": "Everything about Contoso", + "resource": { + "@odata.type": "#microsoft.graph.drive", + "id": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "createdBy": { + "user": { + "displayName": "Dylan Williams" + } + }, + "lastModifiedDateTime": "2024-01-18T19:45:25Z", + "name": "AllItems.aspx", + "parentReference": { + "sharepointIds": { + "listId": "26d6a67d-bd07-4646-9c5b-85b0e519d6f4" + }, + "siteId": "contoso.sharepoint.com,05031a50-e9c7-474c-889e-7cf44659a5b2,e00b849e-3cec-4ade-8f7b-96d1f0f598fa" + }, + "webUrl": "https://contoso.sharepoint.com/contentstorage/CSP_05031a50-e9c7-474c-889e-7cf44659a5b2/Document Library/Forms/AllItems.aspx" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` + +## Example 4: Search for content by title in a specific container + +This example queries all the content by a specific title in a specific container instance, with the SharePoint Embedded application opted out from content discoverability on Microsoft 365. The response includes all `driveItems` in the specific container instance that match the criteria: + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "driveItem" + ], + "query": { + "queryString": "Title:'contoso' AND ContainerId:b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0" + }, + "sharePointOneDriveOptions": { + "includeHiddenContent": true + } + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)", + "value": [ + { + "searchTerms": [ + "contoso", + "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0" + ], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "01SHAK4OWIBDXV4NG2JVFLSGUXVKZ5VF5E", + "rank": 1, + "summary": "Contoso Detailed Design Contoso Product Specification", + "resource": { + "@odata.type": "#microsoft.graph.driveItem", + "size": 56, + "fileSystemInfo": { + "createdDateTime": "2024-01-18T19:46:48Z", + "lastModifiedDateTime": "2024-01-18T19:46:48Z" + }, + "listItem": { + "@odata.type": "#microsoft.graph.listItem", + "fields": {}, + "id": "5eef08c8-da34-4a4d-b91a-97aab3da97a4" + }, + "id": "01SHAK4OWIBDXV4NG2JVFLSGUXVKZ5VF5E", + "createdBy": { + "user": { + "displayName": "Dylan Williams", + "email": "dywilliams@contoso.onmicrosoft.com" + } + }, + "createdDateTime": "2024-01-18T19:46:48Z", + "lastModifiedBy": { + "user": { + "displayName": "Dylan Williams", + "email": "dywilliams@contoso.onmicrosoft.com" + } + }, + "lastModifiedDateTime": "2024-01-18T19:46:48Z", + "name": "contoso.txt", + "parentReference": { + "driveId": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "id": "01SHAK4OVPJ5Q5P6YD6VCZHPV7PKILUJ65", + "sharepointIds": { + "listId": "26d6a67d-bd07-4646-9c5b-85b0e519d6f4", + "listItemId": "1", + "listItemUniqueId": "5eef08c8-da34-4a4d-b91a-97aab3da97a4" + }, + "siteId": "contoso.sharepoint.com,05031a50-e9c7-474c-889e-7cf44659a5b2,e00b849e-3cec-4ade-8f7b-96d1f0f598fa" + }, + "webUrl": "https://contoso.sharepoint.com/contentstorage/CSP_05031a50-e9c7-474c-889e-7cf44659a5b2/Document Library/contoso.txt" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` + +## Example 5: Search by content + +This example queries all the content by the specified words across all containers of a specific container type, with the SharePoint Embedded application opted out from content discoverability on Microsoft 365. The response includes all `driveItems` that match the criteria: + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "driveItem" + ], + "query": { + "queryString": "'contoso' AND ContainerTypeId:498c6855-8f0e-0de7-142e-4e9ff86af9ae" + }, + "sharePointOneDriveOptions": { + "includeHiddenContent": true + } + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)" + "value": [ + { + "searchTerms": [ + "contoso" + ], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "01SHAK4OWIBDXV4NG2JVFLSGUXVKZ5VF5E", + "rank": 1, + "summary": "Contoso Detailed Design Contoso Product Specification", + "resource": { + "@odata.type": "#microsoft.graph.driveItem", + "size": 56, + "fileSystemInfo": { + "createdDateTime": "2024-01-18T19:46:48Z", + "lastModifiedDateTime": "2024-01-18T19:46:48Z" + }, + "listItem": { + "@odata.type": "#microsoft.graph.listItem", + "fields": {}, + "id": "5eef08c8-da34-4a4d-b91a-97aab3da97a4" + }, + "id": "01SHAK4OWIBDXV4NG2JVFLSGUXVKZ5VF5E", + "createdBy": { + "user": { + "displayName": "Dylan Williams", + "email": "dywilliams@contoso.onmicrosoft.com" + } + }, + "createdDateTime": "2024-01-18T19:46:48Z", + "lastModifiedBy": { + "user": { + "displayName": "Dylan Williams", + "email": "dywilliams@contoso.onmicrosoft.com" + } + }, + "lastModifiedDateTime": "2024-01-18T19:46:48Z", + "name": "contoso.txt", + "parentReference": { + "driveId": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "id": "01SHAK4OVPJ5Q5P6YD6VCZHPV7PKILUJ65", + "sharepointIds": { + "listId": "26d6a67d-bd07-4646-9c5b-85b0e519d6f4", + "listItemId": "1", + "listItemUniqueId": "5eef08c8-da34-4a4d-b91a-97aab3da97a4" + }, + "siteId": "contoso.sharepoint.com,05031a50-e9c7-474c-889e-7cf44659a5b2,e00b849e-3cec-4ade-8f7b-96d1f0f598fa" + }, + "webUrl": "https://contoso.sharepoint.com/contentstorage/CSP_05031a50-e9c7-474c-889e-7cf44659a5b2/Document Library/contoso.txt" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` +## Example 6: Search containers by container custom property + +This example queries all containers by the specified custom property key:value pair, with the SharePoint Embedded application that has opted out from content discoverability on Microsoft 365. The response includes all containers that match the criteria: + +> [!NOTE] +> The custom property name must be appended with the text "OWSTEXT" in the query string. + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "drive" + ], + "query": { + "queryString": "customPropertyNametOWSTEXT:customPropertyValue AND ContainerTypeId:498c6855-8f0e-0de7-142e-4e9ff86af9ae" + }, + "sharePointOneDriveOptions": { + "includeHiddenContent": true + } + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)", + "value": [ + { + "searchTerms": [], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "b!C4Psl-ZZZkaZINVay8RKt2fqu3agJbVNlIUjNuIzqlPhOJMrr7ThS4aR8L8XdZu4", + "rank": 1, + "summary": "Everything about Contoso", + "resource": { + "@odata.type": "#microsoft.graph.drive", + "id": "b!UBoDBcfpTEeInnz0Rlmlsp6EC-DsPN5Kj3uW0fD1mPp9ptYmB71GRpxbhbDlGdb0", + "createdBy": { + "user": { + "displayName": "Dylan Williams" + } + }, + "lastModifiedDateTime": "2024-08-02T17:31:06Z", + "name": "AllItems.aspx", + "parentReference": { + "sharepointIds": { + "listId": "2b9338e1-b4af-4be1-8691-f0bf17759bb8" + }, + "siteId": "contoso.sharepoint.com,97ec830b-59e6-4666-9920-d55acbc44ab7,76bbea67-25a0-4db5-9485-2336e233aa53" + }, + "webUrl": "https://contoso.sharepoint.com/contentstorage/CSP_97ec830b-59e6-4666-9920-d55acbc44ab7/Document Library/Forms/AllItems.aspx" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` +## Example 7: Search for content with specific content properties in the response body and sort the results + +This example queries container content by specific words and requires the response to include all specified attributes on the content. Properties that are [sortable](/sharepoint/technical-reference/crawled-and-managed-properties-overview) can be used to sort the results. + +### Request + +```HTTP +POST /search/query +Content-Type: application/json + +{ + "requests": [ + { + "entityTypes": [ + "driveItem" + ], + "query": { + "queryString": "Everything about contoso" + }, + "sharePointOneDriveOptions": { + "includeHiddenContent": true + }, + "fields": [ + "SampleOWSText", + "id", + "name", + "parentReference", + "file", + "folder", + "webUrl", + "createdDateTime", + "lastModifiedDateTime", + "size", + "fileSystemInfo", + "createdBy", + "lastModifiedBy", + "fileSystemInfo", + "fileSystemInfo" + ], + "sortProperties": [ + { + "name": "Created", + "isDescending": false + } + ] + } + ] +} +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json + +{ + "@odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.searchResponse)", + "value": [ + { + "searchTerms": [ + "everything", + "about", + "contoso" + ], + "hitsContainers": [ + { + "hits": [ + { + "hitId": "017JL52SWZQ2M5MULUKFBIL7SZ56EB4V2Z", + "rank": 1, + "summary": "Everything about Contoso", + "resource": { + "@odata.type": "#microsoft.graph.driveItem", + "size": 17363, + "fileSystemInfo": { + "createdDateTime": "2024-06-20T21:49:03Z", + "lastModifiedDateTime": "2024-04-01T16:57:00Z" + }, + "listItem": { + "@odata.type": "#microsoft.graph.listItem", + "id": "d69986d9-7451-4251-85fe-59ef881e5759", + "fields": { + "sampleOWSText": "Sample Value", + "id": "AAAAAH_MwHAjYctMtjgTN1cWJnYHAApvY20ubJFGtzLui9sETKcAAAAAASsAAApvY20ubJFGtzLui9sETKcAAAAAJqsAAA2", + "size": 17363, + "createdBy": "Dylan Williams" + } + }, + "id": "017JL52SWZQ2M5MULUKFBIL7SZ56EB4V2Z", + "createdBy": { + "user": { + "displayName": "Dylan Williams", + "email": "dywilliams@contoso.onmicrosoft.com" + } + }, + "createdDateTime": "2024-06-20T21:49:03Z", + "lastModifiedBy": { + "user": { + "displayName": "Dylan Williams", + "email": "dywilliams@contoso.onmicrosoft.com" + } + }, + "lastModifiedDateTime": "2024-04-01T16:57:00Z", + "name": "Constoso Details.docx", + "parentReference": { + "driveId": "b!rWzsZXXFWEOeeP31bSE5BTjn_6qC3dFNloUBMv62EMilewHuRwQrQau-zcJu2BT0", + "id": "017JL52SXQSKBKPB7VKZCJE5ZSWUN4LZDZ", + "sharepointIds": { + "listId": "ee017ba5-0447-412b-abbe-cdc26ed814f4", + "listItemId": "1", + "listItemUniqueId": "d69986d9-7451-4251-85fe-59ef881e5759" + }, + "siteId": "contoso.sharepoint.com,65ec6cad-c575-4358-9e78-fdf56d213905,aaffe738-dd82-4dd1-9685-0132feb610c8" + }, + "webUrl": "https://contoso.sharepointt.com/contentstorage/CSP_65ec6cad-c575-4358-9e78-fdf56d213905/Document Library/Constoso Details.docx" + } + } + ], + "total": 1, + "moreResultsAvailable": false + } + ] + } + ] +} +``` + +## Known Limitations + +- Search requests run in the context of the signed-in user. Search results are only scoped to enforce any access control applied to the items by the user. For example, search results will include all container or container content matching the search criteria and accessible by the user regardless of whether the SharePoint Embedded application is authorized to access. You should specify the desired container type by including the ContainerTypeId as part of your **queryString** when searching for containers or container content to ensure search results are properly scoped. +- For your application to access the containers or container content in search results, it must have access permissions to the corresponding container types. + +## Enumerate (filter) SharePoint Embedded content + +Content can also be enumerated using URL parameters to return specific content in SharePoint Embedded containers. This does not use the search API to retrieve items. See the [enumerate query parameter](/graph/filter-query-parameter?tabs=http) for reference. + +## Example 1: enumerate content by a specific column property and view the results + +This example enumerates the specified container content by the column property that is on the item: + +### Request + +```HTTP +GET https://graph.microsoft.com/v1.0/drives/{{ContainerID}}/items?$filter=startswith(listitem/fields/{{ColumnProperty}}, '{{Value}}')&$expand=listitem($expand=fields) +``` + +### Response + +```HTTP +HTTP/1.1 200 OK +Content-type: application/json +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives('b%21CORq-a8orUGIrd3_z9t1_vjCBSeqM3JKhDglEU3DIDvEl-Hms0qoQ7QCWYNQfGOF')/items(listItem(fields()))", + "value": [ + { + "@odata.etag": "\"{B8051D89-836E-4B8E-BD2B-7634BAC92825},21\"", + "@microsoft.graph.downloadUrl": "https://.sharepoint.com/contentstorage/CSP_f96ae408-28af-41ad-88ad-ddffcfdb75fe/_layouts/15/download.aspx?UniqueId=b8051d89-836e-4b8e-bd2b-7634bac92825&Translate=false&tempauth=v1.eyJzaXRlaWQiOiJmOTZhZTQwOC0yOGFmLTQxYWQtODhhZC1kZGZmY2ZkYjc1ZmUiLCJhcHBfZGlzcGxheW5hbWUiOiJTUEUtQmFzZWJhbGwiLCJhcHBpZCI6ImZiN2NmNTIwLWNiMzMtNDViZi1hMjM4LWFlNTFkMzE2NjY1ZiIsImF1ZCI6IjAwMDAwMDAzLTAwMDAtMGZmMS1jZTAwLTAwMDAwMDAwMDAwMC9wdWNlbGlrZW50ZXJwcmlzZS5zaGFyZXBvaW50LmNvbUAxNTNhNmViZS1mZjYyLTRiY2UtYjFiYy1hMWVkYTNiYzY2NDUiLCJleHAiOiIxNzMxNjE3MDE3In0.CgoKBHNuaWQSAjY5EgsIzpKzp9W7wj0QBRoNMjAuMTkwLjEzNS40MioscW54cjFGalBneHh2N1lGTkp1dUpxTFZWdFFIS1hOQ2RlQ3EvUUk2aHhlcz0wuAE4AUIQoWPmC1YwAABF4iHcgCWrfkoQaGFzaGVkcHJvb2Z0b2tlbnIpMGguZnxtZW1iZXJzaGlwfDEwMDM3ZmZlOWE5NDg5ZGRAbGl2ZS5jb216ATKCARIJvm46FWL_zksRsbyh7aO8ZkWSAQVTdGV2ZZoBB1B1Y2VsaWuiASdzdGV2ZUBwdWNlbGlrZW50ZXJwcmlzZS5vbm1pY3Jvc29mdC5jb22qARAxMDAzN0ZGRTlBOTQ4OUREsgFyY29udGFpbmVyLnNlbGVjdGVkIGFsbGZpbGVzLnJlYWQgYWxsZmlsZXMud3JpdGUgY29udGFpbmVyLnNlbGVjdGVkIGFsbHNpdGVzLnJlYWQgYWxscHJvZmlsZXMucmVhZCBhbGxwcm9maWxlcy5yZWFkyAEB.tfaYgtjhQxMctJeHUWb9RU7CChHXqFHT0FaM9Dt7J9I&ApiVersion=2.1", + "createdDateTime": "2024-09-20T16:46:00Z", + "eTag": "\"{B8051D89-836E-4B8E-BD2B-7634BAC92825},21\"", + "id": "01UELPCREJDUC3Q3UDRZF32K3WGS5MSKBF", + "lastModifiedDateTime": "2024-11-01T08:14:28Z", + "name": "ClaimExample-1.docx", + "size": 2299607, + "webUrl": "https://.sharepoint.com/contentstorage/CSP_f96ae408-28af-41ad-88ad-ddffcfdb75fe/_layouts/15/Doc.aspx?sourcedoc=%7BB8051D89-836E-4B8E-BD2B-7634BAC92825%7D&file=ClaimExample-1.docx&action=default&mobileredirect=true", + "cTag": "\"c:{B8051D89-836E-4B8E-BD2B-7634BAC92825},5\"", + "commentSettings": { + "commentingDisabled": { + "isDisabled": false + } + }, + "createdBy": { + "application": { + "displayName": "SPEContainerType", + "id": "fb7cf520-cb33-45bf-a238-ae51d316665f" + }, + "user": { + "displayName": "SharePoint App" + } + }, + "lastModifiedBy": { + "application": { + "displayName": "SPEContainerType", + "id": "fb7cf520-cb33-45bf-a238-ae51d316665f" + }, + "user": { + "displayName": "Steve Pucelik", + "email": "Steve@.onmicrosoft.com" + } + }, + "parentReference": { + "driveId": "b!CORq-a8orUGIrd3_z9t1_vjCBSeqM3JKhDglEU3DIDvEl-Hms0qoQ7QCWYNQfGOF", + "driveType": "other", + "id": "01UELPCRF6Y2GOVW7725BZO354PWSELRRZ", + "path": "/drives/b!CORq-a8orUGIrd3_z9t1_vjCBSeqM3JKhDglEU3DIDvEl-Hms0qoQ7QCWYNQfGOF/root:", + "sharepointIds": { + "listId": "e6e197c4-4ab3-43a8-b402-5983507c6385", + "listItemUniqueId": "c4782251-bdd3-4766-a747-b2a2f51c3a00", + "siteId": "f96ae408-28af-41ad-88ad-ddffcfdb75fe", + "siteUrl": "https://.sharepoint.com/contentstorage/CSP_f96ae408-28af-41ad-88ad-ddffcfdb75fe", + "tenantId": "153a6ebe-ff62-4bce-b1bc-a1eda3bc6645", + "webId": "2705c2f8-33aa-4a72-8438-25114dc3203b" + } + }, + "file": { + "mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "hashes": { + "quickXorHash": "DMzi0kCsuukcHlMXiPX9tmTCXtA=" + } + }, + "fileSystemInfo": { + "createdDateTime": "2024-09-20T16:46:00Z", + "lastModifiedDateTime": "2024-11-01T08:14:28Z" + }, + "shared": { + "scope": "unknown" + }, + "listItem@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives('b%21CORq-a8orUGIrd3_z9t1_vjCBSeqM3JKhDglEU3DIDvEl-Hms0qoQ7QCWYNQfGOF')/items('01UELPCREJDUC3Q3UDRZF32K3WGS5MSKBF')/listItem(fields())/$entity", + "listItem": { + "@odata.etag": "\"{B8051D89-836E-4B8E-BD2B-7634BAC92825},21\"", + "createdDateTime": "2024-09-20T16:46:00Z", + "eTag": "\"{B8051D89-836E-4B8E-BD2B-7634BAC92825},21\"", + "id": "23", + "lastModifiedDateTime": "2024-11-01T08:14:28Z", + "webUrl": "https://.sharepoint.com/contentstorage/CSP_f96ae408-28af-41ad-88ad-ddffcfdb75fe/_layouts/15/Doc.aspx?sourcedoc=%7BB8051D89-836E-4B8E-BD2B-7634BAC92825%7D&file=ClaimExample-1.docx&action=default&mobileredirect=true", + "createdBy": { + "application": { + "displayName": "SPEContainerType", + "id": "fb7cf520-cb33-45bf-a238-ae51d316665f" + }, + "user": { + "displayName": "SharePoint App" + } + }, + "lastModifiedBy": { + "application": { + "displayName": "SPEContainerType", + "id": "fb7cf520-cb33-45bf-a238-ae51d316665f" + }, + "user": { + "displayName": "Steve Pucelik", + "email": "Steve@M.onmicrosoft.com" + } + }, + "parentReference": { + "id": "0", + "path": "Document Library", + "siteId": "f96ae408-28af-41ad-88ad-ddffcfdb75fe" + }, + "contentType": { + "id": "0x0101004368E78BC3115C4CAD94FEA35E0F9D90", + "name": "Document" + }, + "fields@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives('b%21CORq-a8orUGIrd3_z9t1_vjCBSeqM3JKhDglEU3DIDvEl-Hms0qoQ7QCWYNQfGOF')/items('01UELPCREJDUC3Q3UDRZF32K3WGS5MSKBF')/listItem/fields/$entity", + "fields": { + "@odata.etag": "\"{B8051D89-836E-4B8E-BD2B-7634BAC92825},21\"", + "id": "23", + "FileLeafRef": "ClaimExample-1.docx", + "": "", + "ContentType": "Document", + "Created": "2024-09-20T16:46:00Z", + "AuthorLookupId": "1073741822", + "Modified": "2024-11-01T08:14:28Z", + "EditorLookupId": "7", + "_CheckinComment": "", + "LinkFilenameNoMenu": "ClaimExample-1.docx", + "LinkFilename": "ClaimExample-1.docx", + "DocIcon": "docx", + "FileSizeDisplay": "2299607", + "ItemChildCount": "0", + "FolderChildCount": "0", + "_ComplianceFlags": "", + "_ComplianceTag": "", + "_ComplianceTagWrittenTime": "", + "_ComplianceTagUserId": "", + "_CommentCount": "", + "_LikeCount": "", + "_DisplayName": "Confidential \\ Internal only", + "AppAuthorLookupId": "1", + "AppEditorLookupId": "1", + "Edit": "0", + "_UIVersionString": "19.0", + "MediaServiceImageTags@odata.type": "#Collection(microsoft.graph.Json)", + "MediaServiceImageTags": [] + } + } + } + ] +} +``` + +## Example 2: Enumerate content by a specific column property and Order the results + +This example enumerates the specified container content by the column property that is on the item and will order the results by the column specified: + +### Request + +```HTTP +GET https://graph.microsoft.com/v1.0/drives/{{ContainerID}}/items?$filter=listitem/fields/{{ColumnProperty}} eq '{{Value}}'&$select=id,name,lastModifiedDateTime,size&$expand=listitem($expand=fields)&$orderby=createdDateTime desc +Headers: +Content-Type: application/json +Prefer: HonorNonIndexedQueriesWarningMayFailRandomly +``` + +> [!NOTE] +> +> When a container has more than 5,000 items and you are using the enumerate method with the OrderBy clause, you must include the following in the header of your request. +> +> `Content-Type: application/json` +> `Prefer: HonorNonIndexedQueriesWarningMayFailRandomly` +## Example 3: Enumerate content by mulitple column properties and Order the results + +This example enumerates the specified container content by the column property you specify and the name of the document (listitem/fields/FileLeafRef) that is on the item and will order the results by the column specified: + +### Request + +```HTTP +GET https://graph.microsoft.com/v1.0/drives/{{ContainerID}}/items?$filter=listitem/fields/{{ColumnProperty1}} eq '{{Value}}' AND listitem/fields/FileLeafRef eq '{{Value}}' &$select=id,name,lastModifiedDateTime,size&$expand=listitem($expand=fields)&$orderby=createdDateTime desc +Headers: +Content-Type: application/json +Prefer: HonorNonIndexedQueriesWarningMayFailRandomly +``` \ No newline at end of file diff --git a/docs/embedded/development/content-experiences/user-experiences-overview.md b/docs/embedded/development/content-experiences/user-experiences-overview.md new file mode 100644 index 000000000..2cf79b470 --- /dev/null +++ b/docs/embedded/development/content-experiences/user-experiences-overview.md @@ -0,0 +1,61 @@ +--- +title: Content Experiences Overview +description: Experiences with SharePoint Embedded content +ms.date: 07/30/2024 +ms.localizationpriority: high +--- + +# User experiences overview + +SharePoint Embedded provides a comprehensive set of user experience features like open and editing Office files, file preview, or in-app search that you can use to build the right user experiences for your applications. + +## Open & edit using Office + +Office documents from SharePoint Embedded applications can be opened for viewing, editing, and collaborating using either the web or Office applications for a richer viewing and editing experience. Learn more about [Office experiences available on SharePoint Embedded](./office-experience.md). + +You can set up your applications to launch Office when a user selects an Office document within your application. This includes options to directly launch an Office application or to open it in a specific mode, such as view (for read-only content) or edit (for editing mode). Learn how to [configure the right Office Experience for your Office Documents](../tutorials/launch-experience.md) + +## Preview content + +Integrate your application with SharePoint Embedded player plugin to offer file preview experiences on a wide range of supported file types. You can embed the file preview experiences either in an iFrame or open a new page. Learn how to [offer File Preview experiences for content on your applications](../tutorials/using-file-preview.md) + +## Download + +You can use [Microsoft Graph's Download DriveItem API](/graph/api/driveitem-get-content) to offer download file user experiences for your applications. This will generate a short-lived, pre-authenticated URL that allows users to download files from your applications. + +> [!NOTE] +> A direct link to the file lacks the appropriate authorization from your application. If used directly in a browser, this would yield an access denied. + +## Content discovery in Microsoft 365 + +You can control how your content appears in the Microsoft 365 experience. The default behavior is SharePoint Embedded application content will be hidden in Microsoft 365 environments including office.com, oneDrive.com, or other Microsoft intelligent file discovery features. The default behavior also excludes Copilot for Microsoft 365 from grounding with your SharePoint Embedded application content. + +If you want to opt into the Microsoft 365 experience, during container type creation, you can change the default settings using cmdlet [Set-SPOContainerTypeConfiguration](../../administration/developer-admin/dev-admin.md#container-type-configuration-properties) as per this example: + +```powershell +Set-SPOContainerTypeConfiguration + -ContainerTypeID + -discoverabilityDisabled $False +``` + +In this way, your files will be integrated into the Microsoft 365 environment, participating in intelligent file discovery. + +> [!NOTE] +> +> 1. If you modify the settings after creating some content, it may take up to 30 days for these changes to achieve full consistency across all consuming tenants. +> 1. To enable the sharing user experience for your content in Office.com, additional application permissions **must** be added at the time of the container type registration process. To add more permission to enable sharing dialog, refer to the following code: + +```http +PUT /storageContainerTypes/{containerTypeId}/applicationPermissions +Content-Type: application/json + +{ + "appId": "4765445b-32c6-49b0-83e6-1d93765276ca", + "delegated": ["readContent","writeContent"], + "appOnly": ["none"] +} +``` + +## Recycle bin + +You can use Microsoft Graph to either delete or permanently delete items in containers. Deleted items are moved to the container’s recycle bin and retained for 93 days. During this period, the items can be restored or permanently deleted using Microsoft Graph. An item in the recycle bin is permanently deleted when it exceeds the 93-day retention period. Permanently deleted items can't be restored. diff --git a/docs/embedded/development/declarative-agent/spe-da-adv.md b/docs/embedded/development/declarative-agent/spe-da-adv.md new file mode 100644 index 000000000..54b6c5c3a --- /dev/null +++ b/docs/embedded/development/declarative-agent/spe-da-adv.md @@ -0,0 +1,315 @@ +--- +title: SharePoint Embedded agent Advanced Topics +description: Learn how the semantic index powers Retrieval-Augmented Generation (RAG) to provide accurate, context-aware AI responses in SharePoint Embedded agent. +ms.date: 06/10/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded agent Advanced Topics Overview + +This advanced guide covers how the semantic index powers Retrieval-Augmented Generation (RAG) to provide accurate, context-aware AI responses. We explore how these concepts work together to ensure your agent retrieves relevant information from your data and returns grounded answers. + +## Caveats + +### Configuration + +#### Required Container Type Configuration + +##### DiscoverabilityDisabled + +The [`discoverabilityDisabled`](../../administration/developer-admin/dev-admin.md#container-type-configuration-properties) property controls whether Microsoft 365 can discover [drive items](/graph/api/resources/driveitem) within a specific container type. + +If you’re updating an existing container type to set this property to `false`, allow up to **24 hours** for the configuration change to fully propagate before: + +- Creating new containers, +- Uploading files to containers, or +- Using SPE agent to interact with folders or files. + +This ensures the agent can correctly access and surface the content. + +Here is an example of how to set `discoverabilityDisabled` to `false` with [Set-SPOContainerTypeConfiguration](/powershell/module/SharePoint-online/set-spocontainertypeconfiguration#examples) + +```powershell +Set-SPOContainerTypeConfiguration -ContainerTypeId 4f0af585-8dcc-0000-223d-661eb2c604e4 -DiscoverabilityDisabled $false +``` + +Discoverability can also be disabled using the Visual Studio Code SharePoint Embedded extension + +![Using the VS Code extension for SPE to set DiscoverabilityDisabled to false](../../images/speco-vscodeextensiondisablediscovery.png) + +##### CSP Policies + +The Content-Security-Policy (CSP) for embedded chat hosts ensures that only specified hosts can load the chat component. Specifically, the `CopilotEmbeddedChatHosts` setting is used in a [Content-Security-Policy](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy) header as a `frame-ancestors` value. This helps in securing the application by restricting which domains can embed the chat component. + +The SPE Administrator on the owning tenant can set this setting by using the `Set-SPOContainerTypeConfiguration` cmdlet: + +```powershell +# Note this MUST be run in Windows PowerShell. It will not work in PowerShell. +Import-Module -Name "Microsoft.Online.SharePoint.PowerShell" +Connect-SPOService "https://-admin.sharepoint.com" +# Login with your admin account. +# ... + +Set-SPOContainerTypeConfiguration -ContainerTypeId XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX -CopilotEmbeddedChatHosts @("http://localhost:3000", "https://contoso.sharepoint.com", "https://fabrikam.com") + +# This will set the container type configuration “CopilotEmbeddedChatHosts” accordingly. +# Replication of this configuration on consuming tenants can take up to 24 hours +# ... + +# Confirm setting value +Get-SPOContainerTypeConfiguration -ContainerTypeId XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + +# On a consuming tenant, you may confirm the setting value as follows +Get-SPOApplication -OwningApplicationId | Select-Object CopilotEmbeddedChatHosts + +OwningApplicationId : +OwningApplicationName : SharePoint Embedded App +Applications : {} +CopilotEmbeddedChatHosts : {http://localhost:3000, https://contoso.sharepoint.com, https://fabrikam.com} +``` + +> [!NOTE] +> +> If this configuration isn't set, the [Content-Security-Policy](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy) is by default set to +> [frame-ancestors](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors): "none", which means no one can embed the agent. + +A SharePoint Embedded Administrator on a consuming tenant may override the values specified by the owning application, by using the consuming tenant cmdlets: + +- [Set-SPOApplication](/powershell/module/SharePoint-online/set-spoapplication) to set the `CopilotEmbeddedChatHosts` property. +- [Get-SPOApplication](/powershell/module/SharePoint-online/get-spoapplication) to get the `CopilotEmbeddedChatHosts` property. + +> [!NOTE] +> +> A consuming tenant override must be a subset of what the owning tenant configured for `CopilotEmbeddedChatHosts`. An administrator +> in a consuming tenant cannot set values that the application owner has not specified for the container type. The override capabilities +> is intended for consuming tenant administrators to enable the agent in only a subset of hosts that the owning application has defined. + +Here's an example of how a consuming tenant can override the setting: + +```powershell +# Note this MUST be run in Windows PowerShell. It will not work in PowerShell. +Import-Module -Name "Microsoft.Online.SharePoint.PowerShell" +Connect-SPOService "https://-admin.sharepoint.com" +# Login with your admin account. +# ... + +Set-SPOApplication -OwningApplicationId XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX -CopilotEmbeddedChatHosts @("https://contoso.sharepoint.com", "https://fabrikam.com") + +# This will set the container type configuration “CopilotEmbeddedChatHosts” accordingly +# Note that @("https://contoso.sharepoint.com", "https://fabrikam.com") is a subset of what we defined in the owning tenant +# Those values were @("http://localhost:3000", "https://contoso.sharepoint.com", "https://fabrikam.com") + +# Confirm the configuration + +Get-SPOApplication -OwningApplicationId | Select-Object CopilotEmbeddedChatHosts + +OwningApplicationId : +OwningApplicationName : SharePoint Embedded App +Applications : {} +CopilotEmbeddedChatHosts : {https://contoso.sharepoint.com, https://fabrikam.com} +``` + +#### Optional Configuration + +##### Authentication and 3P Cookies + +The `iframe` used by SharePoint Embedded agent authenticates users using third-party cookies. If third-party cookies are disabled in the user's browser, the iframe can't authenticate automatically. In this case, a popup prompts the user to sign in manually, ensuring that authentication can still be completed. + +## Advanced Topics + +### Application Scoping + +Application scoping in SharePoint Embedded agent (SPE agent) involves defining the boundaries and context within which the tool operates, ensuring its features and capabilities are tailored to meet the specific needs of different applications. This process helps customize the agent's functionality, making it more effective and relevant for various use cases. + +When SPE agent users query the LLM, it will only have access to files that the **User+Application** have access to. The effective permissions for the agent session will be the intersection of your SharePoint Embedded application's permissions and the user's permissions. + +![Venn Diagram with SPE application access on left, SPE agent in middle and consuming tenant user on right, overlapped area is what agent can access](../../images/speco-appscopingvenn.png) + +### Information Architecture + +Files in SharePoint Embedded are naturally [semantic indexed](spe-da-adv.md#semantic-index). This semantic index underpins retrieval augmented generation [(RAG)](spe-da-adv.md#retrieval-augmented-generation-rag) workflows by providing relevant context from your stored content at query time. In essence, it [grounds](spe-da-adv.md#grounding) the AI responses, ensuring they directly reference accurate information in your containers rather than relying on general knowledge alone. + +![How RAG works in SPE](../../images/speco-ragm365.png) + +With SharePoint Embedded agent, you can further ground the large language models (LLM) response on [specific files or drive items.](spe-da-adv.md#scoping-your-agent-to-specific-content). + +### Semantic index + +[Learn more about semantic index for Microsoft 365 Copilot here](/microsoftsearch/semantic-index-for-copilot) + +The semantic index allows for quick and accurate searches based on data similarity. This means it can find the most relevant information not just by exact matches, but also by understanding the context and meaning. + +### Retrieval-Augmented Generation (RAG) + +RAG enables you to reference relevant source materials stored in a repository at runtime. The data is retrieved from the index and is used to augment the prompt sent to the large language model (LLM). Some benefits of RAG​: + +- Treat data sources as knowledge without having to train your model​ +- Uses search (retrieval) results as additional context in your prompt​ +- Generates the output using the prompt and the supplied context + +The LLM uses the data to inform and construct the response. + +​![The flow of a RAG query](../../images/speco-ragquery.png) + +### Grounding + +Grounding in the context of SPE agent refers to the process of providing input sources to the large language model (LLM) related to the user's prompt. This helps improve the specificity of the prompt and ensures that the responses are relevant and actionable to the user's specific task. The data the agent is grounded on will be the contents of the container type in the agent application. Behind the scenes, SPE agent uses Microsoft 365 Copilot. [Learn more about Microsoft 365 Copilot architecture](/copilot/microsoft-365/microsoft-365-copilot-architecture). + +### Scoping your agent to specific content + +SharePoint Embedded (SPE) agent has the ability to restrict the data sources it has access to. The sample code below shows the available data source types. [This example](https://github.com/microsoft/SharePoint-Embedded-Samples/blob/main/Samples/spe-typescript-react-azurefunction/react-client/src/providers/ChatController.ts#L15) shows how to configure the SDK. + +```typescript +export type IDataSourcesProps = + | IFileDataSource + | IFolderDataSource + | IDocumentLibraryDataSource + | ISiteDataSource + | IWorkingSetDataSource + | IMeetingDataSource; + +export enum DataSourceType { + File = 'File', + Folder = 'Folder', + DocumentLibrary = 'DocumentLibrary', + Site = 'Site', + WorkingSet = 'WorkingSet', + Meeting = 'Meeting' +} +``` + +#### Supported document types for scoping + +[Reference - File Formats Support By copilot](https://support.microsoft.com/topic/file-formats-supported-by-copilot-1afb9a70-2232-4753-85c2-602c422af3a8) + +**Documents**: PDF, DOCX, XLSX, PPTX + +**Text-based Files**: RTF, TXT, CSV, LOG, INI, CONFIG + +**Audio**: WAV + +**Programming Languages**: PY, JS, JSX, JAVA, PHP, CS, C, CPP, CXX, H, HPP, M, COFFEE, DART, LUA, PL, PM, RB, RS, SWIFT, GO, KT, KTS, R, SCALA, T, TS, TSX + +**Shell Scripts**: BASH, SH, ZSH + +**Markup and Documentation**: HTML, CSS, MD, RMD, TEX, LATEX + +**Database Languages**: SQL + +**Data Serialization Formats**: IPYNB, JSON, TOML, YAML, YML + +##### Language/Locale + +The agent `iframe` dynamically loads localization settings to ensure that the chat interface is displayed in the appropriate language. These settings are derived from SharePoint, which provides a comprehensive set of localization options. + +When the agent iframe is initialized, it retrieves the current localization settings from SharePoint. These settings dictate the language and regional preferences for the chat interface, ensuring that all UI elements, messages, and interactions are presented in the user's preferred language. + +You can have this localized by setting your language options in the SharePoint account settings: [Change your personal language and region settings - Microsoft Support](https://support.microsoft.com/office/change-your-personal-language-and-region-settings-caa1fccc-bcdb-42f3-9e5b-45957647ffd7). + +> [!NOTE] +> +> If your M365 language setting is different from your SharePoint account language setting, your M365 language setting takes precedence. You can change your M365 language setting here: [Change your display language in Microsoft 365](https://support.microsoft.com/topic/change-your-display-language-and-time-zone-in-microsoft-365-for-business-6f238bff-5252-441e-b32b-655d5d85d15b). + +An additional locale option can be passed in through the `ChatLaunchConfig` to further set the language the agent responds in: + +```typescript + const [chatConfig] = React.useState({ + header: ChatController.instance.header, + theme: ChatController.instance.theme, + zeroQueryPrompts: ChatController.instance.zeroQueryPrompts, + suggestedPrompts: ChatController.instance.suggestedPrompts, + instruction: ChatController.instance.pirateMetaPrompt, + locale: "en", + }); +``` + +###### Locale Options + +Here are some examples of locale options you can use: + +| Locale Code | Common Name | +|--------------|------------------------------------------| +| af | Afrikaans | +| en-gb | English (UK) | +| he | Hebrew | +| kok | Konkani | +| nn-no | Norwegian (Nynorsk) | +| sr-latn-rs | Serbian (Latin, Serbia) | +| am-et | Amharic | +| es | Spanish | +| hi | Hindi | +| lb-lu | Luxembourgish | +| or-in | Odia (India) | +| sv | Swedish | +| ar | Arabic | +| es-mx | Spanish (Mexico) | +| hr | Croatian | +| lo | Lao | +| pa | Punjabi | +| ta | Tamil | +| as-in | Assamese | +| et | Estonian | +| hu | Hungarian | +| lt | Lithuanian | +| pl | Polish | +| te | Telugu | +| az-latn-az | Azerbaijani (Latin, Azerbaijan) | +| eu | Basque | +| hy | Armenian | +| lv | Latvian | +| pt-br | Portuguese (Brazil) | +| th | Thai | +| bg | Bulgarian | +| fa | Persian | +| id | Indonesian | +| mi-nz | Maori (New Zealand) | +| pt-pt | Portuguese (Portugal) | +| tr | Turkish | +| bs-latn-ba | Bosnian (Latin, Bosnia and Herzegovina) | +| fi | Finnish | +| is | Icelandic | +| mk | Macedonian | +| quz-pe | Quechua (Peru) | +| tt | Tatar | +| ca-es-valencia | Catalan (Valencian) | +| fil-ph | Filipino (Philippines) | +| it | Italian | +| ml | Malayalam | +| ro | Romanian | +| ug | Uyghur | +| ca | Catalan | +| fr-ca | French (Canada) | +| ja | Japanese | +| mr | Marathi | +| ru | Russian | +| uk | Ukrainian | +| cs | Czech | +| fr | French | +| ka | Georgian | +| ms | Malay | +| sk | Slovak | +| ur | Urdu | +| cy-gb | Welsh (UK) | +| ga-ie | Irish (Ireland) | +| kk | Kazakh | +| mt-mt | Maltese (Malta) | +| sl | Slovenian | +| uz-latn-uz | Uzbek (Latin, Uzbekistan) | +| da | Danish | +| gd | Scottish Gaelic | +| km-kh | Khmer (Cambodia) | +| nb-no | Norwegian (Bokmål) | +| sq | Albanian | +| vi | Vietnamese | +| de | German | +| gl | Galician | +| kn | Kannada | +| ne-np | Nepali (Nepal) | +| sr-cyrl-ba | Serbian (Cyrillic, Bosnia and Herzegovina)| +| zh-cn | Chinese (Simplified) | +| el | Greek | +| gu | Gujarati | +| ko | Korean | +| nl | Dutch | +| sr-cyrl-rs | Serbian (Cyrillic, Serbia) | +| zh-tw | Chinese (Traditional) | diff --git a/docs/embedded/development/declarative-agent/spe-da.md b/docs/embedded/development/declarative-agent/spe-da.md new file mode 100644 index 000000000..3e7026291 --- /dev/null +++ b/docs/embedded/development/declarative-agent/spe-da.md @@ -0,0 +1,72 @@ +--- +title: SharePoint Embedded agent +description: Details usage and billing for SharePoint Embedded agents +ms.date: 05/12/2025 +ms.localizationpriority: high +--- + +# Overview + +> [!NOTE] +> +> SharePoint Embedded agent is currently in private preview. Stay tuned for latest API and SDK changes on this page. +> +> SPE agent consumption-based model will be available in May 2025! Starting May 1st, standard billing model will be available to all private preview customers and this rollout is expected to complete by May 15th. This means that starting May 15th, to use SPE agent within an SPE application, you will need to use standard Container Type. SPE Agent interactions, including those from Microsoft 365 Copilot license users, will be billed to the Azure subscription associated with your Container Type. Learn more about [SharePoint Embedded billing management](/sharepoint/dev/embedded/administration/billing/billingmanagement). +> +> We are actively working on enabling Direct-to-Customer billing model for SPE agent. Stay tuned for more announcements. + +SharePoint Embedded agent enables you to add AI capabilities into your application through a simple SDK. This chat control offers the following features: + +- Reason over documents in SharePoint Embedded containers using RAG. +- Developers can configure the application code to limit the search scope to files, folders, and containers. +- Developers can customize and configure chat control including starter prompts, suggested prompts, colors and more. + +Watch this demo to learn more about how to configure this functionality. + +> [!VIDEO https://www.youtube.com/embed/30i7q09EtQo?si=MwLtbrGKnzv7a6My] + +## Why use SharePoint Embedded agent + +SharePoint Embedded agent harness a semantic index to power Retrieval-Augmented Generation (RAG), securely referencing your data within the Microsoft 365 boundary at query time. This ensures accurate, grounded AI responses while reducing reliance on broad knowledge models. A pay-as-you-go billing model is on the horizon, aligning costs with actual usage. + +![Diagram illustrating SPE agent is AI ready](../../images/speco-apparch.png) + +## How to use SharePoint Embedded agent + +### How to build your agent + +Currently, you can use the React SDK library written in TypeScript to build your application. Plans to support additional frameworks and environments will be announced. The SDK is configured with the containerId instance of your containerType, as well as the authorization and authentication token logic you provide through a callback. It will embed itself as an iFrame into your host application. By default, the iFrame is given a `frame-ancestors` property that prevents it from being embedded by any host until configured. Details are provided below. + +#### SPE TypeScript React Application + +Follow the [quick start guide](../tutorials/spe-da-vscode.md) to get started with a prebuilt sample application. + +### API Documentation + +The SharePoint Embedded React TypeScript NPM Package, available at [here](https://github.com/microsoft/SharePoint-Embedded-Samples/tree/feature/copilot-react-sdk/sharepointembedded-chatembedded-react/docs/index.md), provides the SDK for integrating SharePoint Embedded agent into your client applications. + +## Frequently Asked Questions + +### Is consumption-based billing available for SPE agent? + +Yes, starting May 15th you will need to use standard Container Type to use SPE agent within an SPE application. SharePoint Embedded agent interactions, including those from Microsoft 365 Copilot license users, will be billed to the Azure subscription associated with your Container Type. Learn more about [SharePoint Embedded billing management](/sharepoint/dev/embedded/administration/billing/billingmanagement) + +***Trial Container Types expire after 30 days, for this reason we recommend starting off with Standard Container types. There is no upgrade path from Trial to Standard container types.*** + +### Should I use a standard or trial Container Type? + +Once consumption-based billing is enabled, we will be disabling the use of this feature with Trial Container Types and it will only be enabled on Standard Container Types going forward. Please follow this [guide](../../getting-started/containertypes.md) to get started on creating your Standard Container Type. + +## SharePoint Embedded agent Support + +### Chat Control Feedback Dialog + +If you encounter any issues with the chat control, please use the thumbs up or down feedback buttons to report the problem. This method is preferred for sending feedback because it provides us with telemetry data that helps us diagnose and troubleshoot the issue more effectively. + +When you click the thumbs down button, a feedback dialog will appear. Please include any relevant information in this dialog. + +![SPE agent Feedback Modal preview](../../images/speco-feedbackcombined.png) + +## Advanced Topics Overview + +The [advanced topics](spe-da-adv.md) delve into how SharePoint Embedded agent use a semantic index to facilitate Retrieval-Augmented Generation (RAG), ensuring responses are accurately grounded in your stored content. You’ll also learn how to scope your agent to specific data sources, set up various file formats, and configure locale options to tailor the agent experience. By exploring concepts like grounding, semantic indexing, and RAG workflows, you can optimize your agent’s effectiveness and maintain security within the Microsoft 365 boundary. diff --git a/docs/embedded/development/fluid.md b/docs/embedded/development/fluid.md new file mode 100644 index 000000000..84d879d7f --- /dev/null +++ b/docs/embedded/development/fluid.md @@ -0,0 +1,77 @@ +--- +title: Fluid Framework in SharePoint Embedded Applications +description: Details Fluid Integration with SharePoint Embedded Applications +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# Fluid Framework in SharePoint Embedded Applications + +Integrate Fluid Framework and [SharePoint Embedded](../overview.md) to seamlessly and efficiently incorporate document collaboration into your applications. + +## Background + +[Fluid Framework](https://fluidframework.com/) is a collection of client libraries for distributing, synchronizing, and saving shared data. These libraries allow multiple clients to simultaneously create and operate on shared data structures in real-time. Fluid Framework allows developers to use the same practices with shared data as with local data--for example, a Fluid object works in the same way as a local TypeScript object. + +## Quickstart + +Start [building](https://github.com/microsoft/FluidExamples/) in the Fluid [Sample Apps Directory](https://github.com/microsoft/FluidExamples/tree/main/item-counter-spe). You need to [create](#get-started-with-sharepoint-embedded) a SharePoint Embedded application first. + +### Get started with SharePoint Embedded + +Try SharePoint Embedded for free by creating a container type for [trial purposes](../getting-started/containertypes.md). + +1. Set up a free trial [Microsoft 365 tenant](https://www.microsoft.com/microsoft-365/enterprise/microsoft365-plans-and-pricing). Alternatively, you can use an existing tenant if you have admin credentials. +1. Sign into the [SharePoint Embedded Visual Studio Code Extension](../getting-started/spembedded-for-vscode.md) and follow the steps to create an application and container type for trial purposes. + +## Prerequisites + +To get started building with Fluid Framework, you need: + +1. **Admin Credentials**: You need administrative credentials for a [Microsoft 365](https://www.microsoft.com/microsoft-365/enterprise/microsoft365-plans-and-pricing) tenant. +1. **SharePoint Embedded Application**: Ensure that you register your application in [Microsoft Entra ID](https://entra.microsoft.com/). If you don't have a SharePoint Embedded application, refer to the [earlier section](#get-started-with-sharepoint-embedded). +1. **Application (Client) ID**: Obtain the `ClientID` for your SharePoint Embedded Application. +1. **Container Type Information**: + - Identify the `ContainerTypeId` associated with your app’s container type. +1. **Containers**: + - Make sure you have *at least* one container created of the same container type linked to your SharePoint Embedded Application. + +## Get started with Fluid + +### Access App information + +You need the `ClientID` from your application and the `ContainerTypeId` associated with the containers created on that application. + +The `ClientID` is essential for acquiring the correct access tokens when working with Fluid Framework and documents. The `ContainerTypeId` is necessary for accessing containers associated with your SharePoint Embedded application. + +If you used the [Visual Studio Code Extension](../getting-started/spembedded-for-vscode.md), you can [export](/sharepoint/dev/embedded/getting-started/spembedded-for-vscode#export-postman-environment) your Postman Environment to easily view your both your `ContainerTypeId` and `ClientID`. + +Otherwise, you can access your `ContainerTypeId` by using the [`Get-SPOContainerType`](/sharepoint/dev/embedded/concepts/admin-exp/dev-admin#viewing-of-container-types) PowerShell cmdlet. Your `ClientID` is available in [Microsoft Entra ID](https://entra.microsoft.com/) by navigating to **Identity** > **App Registrations** > **Applications** > **All applications** to view your application overview. + +## Run Fluid Sample App: Item Counter + +Now you can test out and start building with the [Fluid Sample App](https://github.com/microsoft/FluidExamples/tree/main/item-counter-spe) Item Counter. + +**Steps:** + +1. Gather your `ClientID` and `ContainerTypeId` of your SharePoint Embedded Application and tenant admin credentials +1. Change to the directory where you'd like to clone the [Fluid Examples repo](https://github.com/microsoft/FluidExamples) +1. Clone the repository by executing the command: `git clone https://github.com/microsoft/FluidExamples.git` +1. Navigate to the **Item Counter** directory `cd .\FluidExamples\item-counter-spe\` +1. Create an empty **.env** file and input your `ClientID` and `ContainerTypeId` with no spaces like so: + + ```text + SPE_CLIENT_ID=YOUR_CLIENTID + + SPE_CONTAINER_TYPE_ID=YOUR_CONTAINERTYPE_ID + ``` + +1. `npm install` +1. `npm run dev` +1. Once Webpack is completed, go to `https://localhost:8080` +1. Sign in with the Admin credentials for your tenant +1. Grant admin consent for your app in the pop-up window +1. Copy the full URL to another browser tab or send it to someone who has credentials to the same tenant. These can be user credentials as long as they are on the same tenant. The live changes to the Item Counter on both browsers show that the data is synced between clients. +1. Congrats on getting your first Fluid App to run! More details can be found in the Item Counter [README](https://github.com/microsoft/FluidExamples/tree/main/item-counter-spe). + + ![Item Counter Sample App](../images/itemcount.png) diff --git a/docs/embedded/development/limits-calling.md b/docs/embedded/development/limits-calling.md new file mode 100644 index 000000000..feb4fd012 --- /dev/null +++ b/docs/embedded/development/limits-calling.md @@ -0,0 +1,73 @@ +--- +title: Limits and Calling Patterns +description: This article explains the limits of SharePoint Embedded. +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# Limits and Calling Patterns + +This document explains the limits of SharePoint Embedded during public preview. + +> [!NOTE] +> These are preview limits that are subject to change. + +## Size limits + +The following table defines the size limits of containers: + +| Resource | Limit | +| --------------------------------------------------------- | ------------------------------------------------------ | +| Container types that a partner tenant can create | 25* | +| Container types that an app can own | 1 | +| Containers of a container type per consuming tenant | 100k* | +| Storage per container type per consuming tenant | 100 TB* | +| Files and folders per container | 30M | +| Storage per container | 25 TB | +| Files and folders with additive permissions per container | 5k | +| File size | 250 GB | +| Version count per file | 500 (Automatic Version History Limits Default Setting) | +| Number of users shared per folder or file | 5k | + +> [!NOTE] +> Limit can be increased per request. + +## Throttling + +### Patterns and best practices + +When applications hit service limits, you receive an HTTP status code 429 ("Too many requests"). You might also receive an HTTP status code 503 ("Server Too Busy"). + +In general, the following are the best practices to handle throttling: + +- Reduce the number of concurrent requests. +- Avoid request spikes. +- Honor the `Retry-After` HTTP header. + +In both cases, a `Retry-After` header is included in the response, indicating how long the calling application should wait before retrying or making a new request. Throttled requests count towards usage limits, so failure to honor `Retry-After` might result in more throttling. + +## API rate limits + +SharePoint Embedded provides various APIs. Different APIs have different costs depending on the functionality and complexity of the API. The cost of APIs is normalized and expressed by resource units. API rate limits are also defined using resource units. + +| Resource units per request | Operations | +| -------------------------- | -------------------------------------------------------------------------- | +| 1 | Single item query, such as get item | +| 2 | Multi-item query, such as list children, create, update, delete, and upload | +| 5 | All permission resource operations, including $expand=permissions | + +> [!NOTE] +> We reserve the right to change the API resource unit cost. + +The following table lists the API rate limits for applications and containers. + +| Resource | Limits | +| --------------------------- | --------------------------- | +| Requests per container | 3k resource units per min | +| Requests per app per tenant | 12k resource units per min* | +| Requests per user | 600 resource units per min | + +> [!NOTE] +> \* Limit can be increased per request. + +Application limits are defined in resource units, and the actual request rate, such as requests per minute, varies based on the chosen API and its corresponding resource unit cost. As a general rule, you can estimate the request rate by averaging about two resource units per request and dividing application resource unit limits by 2. Reducing the usage of permission operations can notably improve the call rate since these operations have the most significant impact on overall resource consumption. diff --git a/docs/embedded/development/sharing-and-perm.md b/docs/embedded/development/sharing-and-perm.md new file mode 100644 index 000000000..4c63f4843 --- /dev/null +++ b/docs/embedded/development/sharing-and-perm.md @@ -0,0 +1,55 @@ +--- +title: Sharing and Permissions +description: Outlines Permission Model for SharePoint Embedded +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# Sharing and permissions in SharePoint Embedded + +## Additive permissions + +In SharePoint Embedded, content always inherits permissions from its parent hierarchy. While you can't alter this inherited permission structure, you can extend access within a container by applying "additive permissions" to specific files and folders. For instance, if _UserA_ belongs to the Reader role, you can grant the user edit permission to a particular document in that container using Microsoft Graph: + +| Scenario | Microsoft Graph API(s) | Notes | +| :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Grant an additive permission | [POST /drives/{drive-id}/items/{item-id}/invite](/graph/api/driveitem-invite) | The sendInvitation property must always be false. You can't grant additive permissions to the root folder in a container as this is essentially the same as adding a User to a role. You can't use AppOnly permissions. | +| Retrieve permissions | [GET /drives/{drive-id}/items/{item-id}/permissions](/graph/api/permission-get) & [GET /drives/{drive-id}/items/{item-id}/permissions/{perm-id}](/graph/api/permission-get), | | +| Delete additive permissions | [DELETE /drives/{drive-id}/items/{item-id}/permissions/{perm-id}](/graph/api/permission-delete) | You can only delete the additive permission on the drive item where it was originally added. | + +## Role-based sharing setting + +SharePoint Embedded offers a role-based sharing model that allows developers to configure file-sharing permissions based on container permission roles, offering a choice between restrictive and open sharing models. By default, the sharing setting is configured to the open model, permitting unrestricted content sharing by all users. This sharing setting is part of [container type configuration](../getting-started/containertypes.md#configuring-container-types). This configuration can only be set by the application owner's developers. To learn more about container permission roles, refer to [Authentication and Authorization with SharePoint Embedded](auth.md#container-permissions). + +### Restrictive sharing model + +Only container members who are either the Owner or Manager roles are permitted to add new permissions to files. + +### Open sharing model + +Any container members and guests with edit permissions can add new permissions to this file. + +This can be configured using the PowerShell cmdlet [Set-SPOcontainerTypeConfiguration](../administration/developer-admin/dev-admin.md#container-type-configuration-properties) as per this example: + +```powershell +Set-SPOcontainerTypeConfiguration + -containerTypeID + -sharingRestricted $false +``` + +## Sharing configuration setting + +By default, SharePoint Embedded application sharing configuration is the same as the consuming tenant-sharing configuration. For example, if the consuming tenant is configured to disable sharing for guests, then the SharePoint Embedded application is unable to add guests to container roles or grant them additive permissions. + +### Application external sharing override + +For SharePoint Embedded applications, sharing configurations can be adjusted at the application level. Consuming tenant admin can configure permissions that are different than tenant-level sharing settings. For example, if a tenant's sharing setting prohibits sharing with guests, SharePoint Embedded applications can be configured to allow guest sharing. So, all containers within that SharePoint Embedded application would have the ability to include guests or extend another permission, while other SharePoint Embedded applications and SharePoint maintain restricted sharing permissions. + +This setting can only be set by consuming tenant SharePoint Embedded admin, and can be configured using the latest PowerShell cmdlet [Set-SPOApplication](../administration/consuming-tenant-admin/ctapowershell.md#set-sharing-capability-of-applications) as shown in this example: + +```powershell +Set-SPOApplication + -OwningApplicationID + -OverrideTenantSharingCapability $true + -SharingCapability +``` diff --git a/docs/embedded/development/tutorials/doc-processing-acs.md b/docs/embedded/development/tutorials/doc-processing-acs.md new file mode 100644 index 000000000..2d450bf9e --- /dev/null +++ b/docs/embedded/development/tutorials/doc-processing-acs.md @@ -0,0 +1,179 @@ +--- +title: Document Processing with Azure Cognitive Services +description: Enabling document processing with Azure Cognitive Services. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# Enabling Document Processing with Azure Cognitive Services + +## Utilizing Azure Cognitive Services + +Azure Cognitive Services is a set of cloud-based APIs that you can use in AI applications and data flows. It provides pre-trained models that are ready to use in your applications, requiring no data and no model training on your part. They can be easily integrated into applications via HTTP REST interfaces. + +You have already learned how to use webhooks with [the application](/training/modules/sharepoint-embedded-create-app/) to get a notification whenever an existing file is updated, or a new file is uploaded in the [Using Webhooks tutorial](./using-webhooks.md). This tutorial will cover connecting it with Azure Cognitive Services to extract data from invoices. + +To set up automatic AI processing with your current SharePoint application upon a change in your container, you need to follow [Using Webhooks](./using-webhooks.md) and then: + +1. Get the delta changes of the container. You're currently able to get the notification whenever there's any change in our container and will now get the files that are added or updated. +1. Call Azure Cognitive Services’s Document Intelligence service API. You'll need to create an Azure AI resource to use the API to extract the fields from an image and get the extracted files. You might store them as shown in this tutorial or you might process them as you like. +![document processing schema](../../images/Document-Processing.png) + +> [!TIP] +> To learn more about the Microsoft Graph APIs used in this tutorial, see [Track changes for a Drive](/graph/api/driveitem-delta), [Get a DriveItem resource](/graph/api/driveitem-get), and [Upload or replace the contents of a DriveItem](/graph/api/driveitem-put-content). + +## Get the delta changes of a container + +Open **GraphProvider.ts** and implement the method `getDriveChanges` to get the list of changed items: + +```typescript +public static async getDriveChanges(driveId: string): Promise { + let changedItems: any[] = []; + const driveDeltaBasePath: string = `/drives/${driveId}/items/root/delta`; + let driveDeltaTokenParams: string = ""; + let hasMoreChanges: boolean = true; + try{ + do { + if (this.changeTokens.has(driveId)) { + driveDeltaTokenParams = `?token=${this.changeTokens.get(driveId)}` + } + const response = await this.graphClient.api(driveDeltaBasePath + driveDeltaTokenParams).get(); + changedItems.push(...response.value); + if (response['@odata.nextLink']) { + const token = new URL(response['@odata.nextLink']).searchParams.get('token'); + this.changeTokens.set(driveId, token); + } else { + hasMoreChanges = false; + const token = new URL(response['@odata.deltaLink']).searchParams.get('token'); + this.changeTokens.set(driveId, token); + } + console.log(this.changeTokens.get(driveId)); + } while (hasMoreChanges); + } + catch(err){ + console.log(err); + } + return changedItems; +} +``` + +Implement the method `getDriveItem` to fetch a file from a container: + +```typescript +public static async getDriveItem(driveId: string, itemId: string): Promise { + return await this.graphClient.api(`/drives/${driveId}/items/${itemId}`).get(); +} +``` + +Create a new file **ReceiptProcessor.ts** and implement a method `processDrive`: + +```typescript +export abstract class ReceiptProcessor { + + public static async processDrive(driveId: string): Promise { + const changedItems = await GraphProvider.getDriveChanges(driveId); + for (const changedItem of changedItems) { + try { + const item = await GraphProvider.getDriveItem(driveId, changedItem.id); + const extension = this.getFileExtension(item.name); + if (this.SUPPORTED_FILE_EXTENSIONS.includes(extension.toLowerCase())) { + console.log(item.name); + const url = item["@microsoft.graph.downloadUrl"]; + const receipt = await this.analyzeReceiptStream(await this.getDriveItemStream(url)); + const receiptString = JSON.stringify(receipt, null, 2) + const fileName = this.getFileDisplayName(item.name) + "-extracted-fields.json"; + const parentId = item.parentReference.id; + await GraphProvider.addDriveItem(driveId, parentId, fileName, receiptString); + } + } catch (error) { + console.log(error); + } + } + } +} +``` + +At this point if you restart the app along with tunneling and subscription, you should see the recently added/updated files listed in the console. + +## Call Azure Cognitive Services' Document Intelligence service API + +To use the Azure Cognitive Services Document Intelligence APIs, you need to create a Multi-Service or Document Intelligence resource for Azure AI Service. Refer to the following tutorials to create the resource: + +- [Quickstart: Create a multi-service resource for Azure AI services](/azure/ai-services/multi-service-resource?tabs=windows&pivots=azportal) +- [Get started with Document Intelligence](/azure/ai-services/document-intelligence/quickstarts/get-started-sdks-rest-api?view=doc-intel-3.1.0&viewFallbackFrom=form-recog-3.0.0&preserve-view=true&pivots=programming-language-javascript) + +After this step, you should have an endpoint and a key ready to use. + +Now open **ReceiptProcessor.ts** to create method `dac` to store the Azure Cognitive Services credentials: + +```typescript +private static dac = new DocumentAnalysisClient( + `${process.env["DAC_RESOURCE_ENDPOINT"]}`, + new AzureKeyCredential(`${process.env["DAC_RESOURCE_KEY"]}`) +); +``` + +Create method `getDriveItemStream`. + +```typescript +private static async getDriveItemStream(url: string): Promise { + const token = GraphProvider.graphAccessToken; + const config: AxiosRequestConfig = { + method: "get", + url: url, + headers: { + "Authorization": `Bearer ${token}` + }, + responseType: 'stream' + }; + const response = await axios.get(url, config); + return response.data; +} +``` + +Create method `analyzeReceiptStream` to get the OCR fields through Azure Cognitive Services processing. Here we're taking the `prebuilt-invoice` model, but other models can be chosen: + +```typescript +private static async analyzeReceiptStream(stream: Readable): Promise { + const poller = await this.dac.beginAnalyzeDocument("prebuilt-invoice", stream, { + onProgress: ({ status }) => { + console.log(`status: ${status}`); + }, + }); + + const { + documents: [result] = [], + } = await poller.pollUntilDone(); + + const fields = result?.fields; + this.removeUnwantedFields(fields); + return fields; +} +``` + +Create a method `removeUnwantedFields` to remove the undesirable fields in Azure Cognitive Services’s response: + +```typescript +private static removeUnwantedFields(fields: any) { + for (const prop in fields) { + if (prop === 'boundingRegions' || prop === 'content' || prop === 'spans') { + delete fields[prop]; + } + if (typeof fields[prop] === 'object') { + this.removeUnwantedFields(fields[prop]); + } + } +} +``` + +Finally, open **GraphProvider.ts** to add the `addDriveItem` method at the end of the `GraphProvider` class. + +```typescript +public static async addDriveItem(driveId: string, parentId: any, fileName: string, receiptString: string) { + await this.graphClient.api(`/drives/${driveId}/items/${parentId}:/${fileName}:/content`).put(receiptString); +} +``` + +Now, restart the demo app and set up the tunneling using ngrok and delta change subscription on the container again. + +If you add/update any file (supported formats: JPEG, JPG, PNG, BMP, TIFF, PDF) in this container, you should see a new JSON file created and containing the fields extracted from the file. diff --git a/docs/embedded/development/tutorials/launch-experience.md b/docs/embedded/development/tutorials/launch-experience.md new file mode 100644 index 000000000..e0b92344d --- /dev/null +++ b/docs/embedded/development/tutorials/launch-experience.md @@ -0,0 +1,90 @@ +--- +title: Configure Default Launch Experience for your Office Files +description: Configure Default Launch Experience for your Office Files +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# Configure Default Launch Experience for your Office Files + +## Configure the Launch mode of Office Clients + +When retrieving a `DriveItem` from the Microsoft Graph API with: + +```http +/graph/api/driveitem-get?view=graph-rest-1.0 +``` + +The `webUrl` property in the response can be a link to Web Application Open Platform Interface (WOPI) for rendering supported office file types. The URL will look like: + +```http +https://host/:w:r/contentstorage/sitecollection/_layouts/15/doc2.aspx?sourcedoc=guid&file=filename.docx&action=default&mobileredirect=true +``` + +This `webUrl` will open WOPI in the default mode (`action=default`). If you wish to override the default mode to force a specific mode (for example, View for read-only and Edit for editor), you can augment the `webUrl` like this: + +```csharp +string webUrl = https://host/:w:r/contentstorage/sitecollection/_layouts/15/doc2.aspx?sourcedoc=guid&file=filename.docx&action=default&mobileredirect=true; + +System.UriBuilder builder = new System.UriBuilder(webUrl); +System.Collections.Specialized.NameValueCollection queryDictionary = System.Web.HttpUtility.ParseQueryString(builder.Query); +queryDictionary["action"] = "view"; +//queryDictionary["action"] = "edit"; +builder.Query = queryDictionary.ToString(); +string modifiedWebUrl = builder.ToString(); +``` + +> [!TIP] +> To learn more about WOPI Actions, see: [WOPI Discovery - WOPI Actions](/microsoft-365/cloud-storage-partner-program/online/discovery#wopi-actions). + +### Open Office files directly in Desktop clients + +To open your files directly in the Office desktop clients, you need to create an Office URI scheme. The format is as follows: + +```xml +:"|""|" +``` + +Use the following table to replace the preceding segments: + +- **scheme-name**: the name of the application, for example: *ms-excel* +- **command-name**: + - `ofv` for Open File View + - `ofe` for Open File Edit + - `nft` for New From Template +- **command-argument-descriptor** and **command-argument**: + - `|u|{file url}` + - `|s|{save location}` + - *only for New From Template* + +> [!NOTE] +> The **New From Template** may not work as you would expect for save location since the permissions schema is different from SharePoint Sites. + +The following contains an example usage of the Office URI scheme: + +```text +ms-word:ofv|u|https://contoso.com/document.docx +ms-powerpoint:ofe|u|https://contoso.com/presentation.pptx +``` + +Because the `webUrl` property points to Office Online for Office documents, you must get the actual link in two steps: + +1. Getting the WebUrl of the parent folder +1. Appending the name of the file + +For example, the following scheme: + +```text +ms-word:ofe|u|{folder.WebUrl]/{item.Name} +``` + +... will result in the following scheme: + +```text +ms-word:ofe|u|https://contoso.sharepoint.com/contentstorage/CSP_1234765465/Document%20Library/MyDocument.docx +``` + +To learn more about Office URI schemes, see [Office URI Schemes](/office/client-developer/office-uri-schemes). + +> [!NOTE] +> The Uri must be opened in a blank window or new tab. diff --git a/docs/embedded/development/tutorials/metadata.md b/docs/embedded/development/tutorials/metadata.md new file mode 100644 index 000000000..1973c22b9 --- /dev/null +++ b/docs/embedded/development/tutorials/metadata.md @@ -0,0 +1,474 @@ +--- +title: SharePoint Embedded Container Metadata +description: Add metadata in Containers and Files. +ms.date: 3/22/2024 +ms.localizationpriority: high +--- + +# Using Metadata with SharePoint Embedded Containers + +In SharePoint Embedded, columns can be added to [Containers](../../getting-started/containertypes.md) to address scenarios requiring custom metadata via Microsoft Graph APIs. Content in the container can then set desired values for corresponding metadata. Metadata is schematized and can be queried. Note the APIs to create and manage columns are on the container instances level – an application is responsible for defining and managing the columns across its containers. + +## Authorization and Authentication + +App+User (Delegated) or App-only (Application) Bearer {token} is required in the Authorization header. + +> [!NOTE] +> Container owners can Create, Update, and Delete Container columns +> All Container members can Read and List Container columns + +### `microsoft.graph.fileStorageContainer` properties + +| Property | Type | Description | Key | Required | ReadOnly | +| -------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------- | --- | -------- | -------- | +| `id` | `Edm.String` | unique stable identifier of the storage container instance | Yes | Yes | Yes | +| `displayName` | `Edm.String` | display name of the container | No | Yes | No | +| `description` | `Edm.String` | description of the container | No | No | No | +| `containerTypeId` | `Edm.Guid` | container type ID | No | Yes | Yes | +| `containerTypeDisplayName` | `Edm.String` | display name of the container type | No | No | Yes | +| `externalGroupId` | `Edm.Guid` | external group ID | No | No | No | +| `permissions` | `Collection` | permissions of users / groups in the container | No | No | No | +| `customProperties` | `microsoft.graph.fileStorageContainerCustomPropertyDictionary` | custom properties | No | No | No | +| `viewpoint` | `microsoft.graph.fileStorageContainerViewpoint` | data that is specific to the current user | No | No | No | +| `drive` | `microsoft.graph.drive` | storage container's drive resource | No | No | Yes | +| `recycleBin` | `microsoft.graph.recycleBin` | storage container's recycleBin resource | No | No | Yes | +| `status` | `microsoft.graph.fileStorageContainerStatus` | an enum value representing the status of the container | No | No | Yes | +| `createdDateTime` | `microsoft.graph.dateTimeOffset` | createdDateTime | No | No | Yes | +| `storageUsedInBytes` | `Edm.Int64` | storage used in bytes | No | No | Yes | +| `assignedSensitivityLabel` | `microsoft.graph.assignedLabel` | the sensitivity label assigned to the container | No | No | No | +| `owners` | `Collection` | The list of users who own the container | No | No | Yes | +| `columns` | `Collection` | the collection of custom metadata fields in the container | No | No | No | + + + +## Limitations + +The following are the properties that SharePoint Embedded Metadata supports: + +| Property name | Type | +| ---------------------- | ------------------------- | +| boolean | booleanColumn | +| choice | choiceColumn | +| currency | currencyColumn | +| dateTime | dateTimeColumn | +| hyperlinkOrPicture | hyperlinkOrPictureColumn | +| isDeletable | Boolean | +| ID | string | +| indexed | Boolean | +| isSealed | Boolean | +| name | string | +| number | numberColumn | +| personOrGroup | personOrGroupColumn | +| readOnly | Boolean | +| text | textColumn | +| type | columnTypes | + +> [!NOTE] +> Please name columns according to the appropriate column naming convention + +### Column Naming Conventions + +Column Names must adhere to the following rules: +- Can't contain "!". +- Can't start with a digit, period, minus sign, or question mark. +- Can't contain any space or any nonalphanumeric characters except "_" or "\". +- Can't look like either type of cell reference. + - A1 mode cell reference with 1 to 3 characters followed by 1 to 5 digits (for example, A3 F02563, ZZZ12). + - R1C1 mode cell references that look like r, or c, or r[#], c[#] or r[#]c[#]. +- Can't be any localized word for "true" or "false". +- Can't be specific names, including "Author", "Created", "Description", etc. + + + +## Create a column in a fileStorageContainer + +This API lets callers create a new column instance in a fileStorageContainer. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: create a column in a fileStorageContainer + +##### Request + +```http +POST https://graph.microsoft.com/beta/storage/fileStorage/containers/{container-id}/columns +Content-Type: application/json + +{ + "description": "test", + "displayName": "Title", + "enforceUniqueValues": false, + "hidden": false, + "indexed": false, + "name": "Title", + "text": { + "allowMultipleLines": false, + "appendChangesToExistingText": false, + "linesForEditing": 0, + "maxLength": 255 + } +} +``` + +> [!NOTE] +> Note Type is not supported. `maxLength` should =< 255. + +##### Response + +```http +HTTP/1.1 201 Created +Content-type: application/json + +{ + "description": "test", + "displayName": "Title", + "enforceUniqueValues": false, + "hidden": false, + "id": "99ddcf45-e2f7-4f17-82b0-6fba34445103", + "indexed": false, + "name": "Title", + "text": { + "allowMultipleLines": false, + "appendChangesToExistingText": false, + "linesForEditing": 0, + "maxLength": 255 + } +} +``` + +## Get a column in a fileStorageContainer by ID + +This API lets callers get a fileStorageContainer column instance by ID. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: get a column in a fileStorageContainer by ID + +##### Request + +```http +GET https://graph.microsoft.com/beta/storage/fileStorage/containers/{container-id}/columns/{column-id} +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "description": "test", + "displayName": "Title", + "enforceUniqueValues": false, + "hidden": false, + "id": "99ddcf45-e2f7-4f17-82b0-6fba34445103", + "indexed": false, + "name": "Title", + "text": { + "allowMultipleLines": false, + "appendChangesToExistingText": false, + "linesForEditing": 0, + "maxLength": 255 + } +} +``` + +## Update a column in a fileStorageContainer by ID + +This API lets callers update a fileStorageContainer column instance by ID. +You can update any property of the column other than the **id** property. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: update a column in a fileStorageContainer by ID + +##### Request + +```http +PATCH https://graph.microsoft.com/beta/storage/fileStorage/containers/{container-id}/columns/{column-id} +Content-Type: application/json + +{ + "required": true, + "hidden": false, + "description": "This is my new column description" +} +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "description": "", + "displayName": "Custom Column", + "enforceUniqueValues": false, + "hidden": false, + "id": "11dfef35-e2f7-4f17-82b0-6fba34445103", + "indexed": false, + "name": "Custom Column", + "readOnly": false, + "required": true, + "text": { + "allowMultipleLines": false, + "appendChangesToExistingText": false, + "linesForEditing": 0, + "maxLength": 255 + } +} +``` + +## Delete a column from a fileStorageContainer + +This API lets callers delete a fileStorageContainer column instance by ID. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: delete a column from a fileStorageContainer + +##### Request + +```http +DELETE https://graph.microsoft.com/beta/storage/fileStorage/containers/{container-id}/columns/{column-id} +``` + +##### Response + +```http +HTTP/1.1 204 No Content +``` + +## List columns in a fileStorageContainer + +This API lets callers enumerate the columns in a fileStorageContainer. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: List columns in a fileStorageContainer + +##### Request + +```http +GET https://graph.microsoft.com/beta/storage/fileStorage/containers/{container-id}/columns +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "value": [ + { + "description": "", + "displayName": "Title", + "hidden": false, + "id": "99ddcf45-e2f7-4f17-82b0-6fba34445103", + "indexed": false, + "name": "Title", + "readOnly": false, + "required": false, + "text": { + "allowMultipleLines": false, + "appendChangesToExistingText": false, + "linesForEditing": 0, + "maxLength": 255 + } + }, + { + "description": "", + "displayName": "Address", + "id": "11dfef35-e2f7-4f17-82b0-6fba34445103", + "indexed": false, + "name": "Address", + "readOnly": false, + "required": false, + "text": { + "allowMultipleLines": false, + "appendChangesToExistingText": false, + "linesForEditing": 0, + "maxLength": 255 + } + } + ] +} +``` + +## Get column values of an item in a fileStorageContainer's drive + +This is an existing API used to showcase our new feature of getting the column values of an item in a fileStorageContainer's drive. +This API supports OData $select features for `column`. + + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: Get column values of an item in a fileStorageContainer's drive + +##### Request + +```http +GET https://graph.microsoft.com/beta/drives/{drive-id}/items/{item-id}/listitem/fields +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "Name": "Widget", + "Color": "Blue", + "Quantity": 2357 +} +``` + +##### Request + +```http +GET https://graph.microsoft.com/beta/drives/{drive-id}/items/{item-id}/listitem/fields?$select=Name,Color +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "Name": "Widget", + "Color": "Blue" +} +``` + +## Patch column values of an item in a fileStorageContainer's drive + +This is an existing API used to showcase our new feature of updating and deleting the column values of an item in a fileStorageContainer's drive. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: update column values of an item in a fileStorageContainer's drive + +##### Request + +```http +PATCH https://graph.microsoft.com/beta/drives/{drive-id}/items/{item-id}/listitem/fields + +Content-Type: application/json + +{ + "Color": "Fuchsia", + "Quantity": 934 +} +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "Name": "Widget", + "Color": "Fuchsia", + "Quantity": 934 +} +``` + +#### REST Operation example: delete column values of an item in a fileStorageContainer's drive + +##### Request + +```http +PATCH https://graph.microsoft.com/beta/drives/{drive-id}/items/{item-id}/listitem/fields + +Content-Type: application/json + +{ + "Color": null +} +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "Name": "Widget", + "Quantity": 934 +} +``` + +## Query a fileStorageContainer's driveitems with Odata query options on custom columns + +This API lets users query drive items in a fileStorageContainer with `$expand`, `$filter`, and `$orderby` Odata query options on their custom columns. + +##### Required permissions (at least one of) + +| ScopeName | Type | +| ----------------------------- | ----------- | +| FileStorageContainer.Selected | Application | +| FileStorageContainer.Selected | Delegated | + +#### REST Operation example: filter fileStorageContainer's driveitems by their custom columns 'TestField' and order the results by 'TestField' + +##### Request + +```http +GET https://graph.microsoft.com/beta/drives/{drive-id}/items?$orderby=listitem/fields/TestField asc&$filter=startswith(listitem/fields/TestField, '3')&$expand=listitem($expand=fields) +``` + +##### Response + +```http +HTTP/1.1 200 OK +Content-type: application/json + +{ + "value": [ + {"name": "a.jpg", "size": 2048, "listitem/fields/TestField": "31" }, + {"name": "b.xlsx", "size": 197, "listitem/fields/TestField": "32" }, + {"name": "c.docx", "size": 391, "listitem/fields/TestField": "33" } + ] +} +``` \ No newline at end of file diff --git a/docs/embedded/development/tutorials/migrate-abs-to-spe.md b/docs/embedded/development/tutorials/migrate-abs-to-spe.md new file mode 100644 index 000000000..d9994ba3d --- /dev/null +++ b/docs/embedded/development/tutorials/migrate-abs-to-spe.md @@ -0,0 +1,374 @@ +--- +title: Tutorial to Migrate from Azure Blob Storage container to SharePoint Embedded container +description: Tutorial in how to migrate from Azure Blob Storage container to SharePoint Embedded container Using C# +ms.date: 07/31/2024 +ms.localizationpriority: high +--- + +# Tutorial For Migrating Content From Azure Blob Storage Container To SharePoint Embedded Container + +## Purpose + +This tutorial will guide you through migrating content from Azure Blob Storage (ABS) to SharePoint Embedded (SPE) using C#. This is useful for customers who have 500 docs in the blob storage container. + +### Prerequisites + +1. A Microsoft Entra ID application registration. See [register an application](/graph/auth-register-app-v2). +1. Your Microsoft Entra ID tenant has a [Microsoft 365 subscription](/training/m365/). +1. A Microsoft Entra ID tenant. If you don't have a tenant, create a [free Azure account to get a free subscription](https://azure.microsoft.com/free/). +1. An account with at least the Global Administrator or SharePoint Embedded Administrator role. +1. .NET Core SDK [version 8.0.303](https://dotnet.microsoft.com/download/dotnet/8.0) +1. Dotnet environment to run the sample app + + - It can be run on Windows, Linux and macOS + +1. SharePoint Embedded container + + - For more information on how to set up a [SPE container](https://aka.ms/start-spe) + +1. Azure Blob Storage container + + - For more information on how to set up an [ABS container](/azure/storage/blobs/storage-blobs-introduction) + +## Authentication + +### Azure Blob Storage + +1. Credentials - Container-level Shared Access Signature (SAS) URL. +1. Permission - Read and List + +### SharePoint Embedded + +1. An [Azure account](https://portal.azure.com) +1. A SharePoint Tenant where you'll create your containers and its Tenant ID +1. An onboarded application ID (sometimes called client ID) and its corresponding ContainerTypeId +1. Create a new App Registration in [Microsoft Entra ID portal](https://entra.microsoft.com). +1. In the App Registration, add a new Mobile & Console application platform in [Microsoft Entra ID App Registration Authenticate portal](https://entra.microsoft.com) + + ![Screenshot of Microsoft Entra ID application configuration](../../images/app-registration-console-platform.png) + +1. A ContainerType +1. A Container +1. Having the application registered in the consuming tenant (even if the owner of the application is the same as the consuming) +1. Having the containerType registered in the consuming tenant (even if the owner of the CT is the same as the consuming) +1. Consuming tenant user name and password credentials - will be required to authenticate the Microsoft Graph client +1. Permission - "User.Read", "FileStorageContainer.Selected" + +## Migrating Data from Azure Blob Storage container to SharePoint Embedded container + +### Description + +This section provides code snippets on how to accomplish the migration. All the validation has been removed for readability. + +### Connecting to Azure Blob Storage Container + +```c# +_containerClient = new BlobContainerClient(new Uri(_containerLevelSASUrl)); +``` + +### Connecting to SharePoint Embedded + +```c# +string[] _scopes = { "User.Read", "FileStorageContainer.Selected" }; +InteractiveBrowserCredentialOptions interactiveBrowserCredentialOptions = new InteractiveBrowserCredentialOptions() + { + ClientId = clientId, + RedirectUri = new Uri("http://localhost"), + }; +InteractiveBrowserCredential interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveBrowserCredentialOptions); + +_graphClient = new GraphServiceClient(interactiveBrowserCredential, scopes, null); + +// Will open up a browser to provide your consuming tenant admin credentials +var user = await _graphClient.Me.GetAsync(); +``` + +### Getting the blob list + +```c# +var blobs = new List(); +await foreach (var blobItem in _containerClient.GetBlobsAsync()) +{ + blobs.Add(blobItem.Name); +} +return blobs; +``` + +### Thread pooling + +```c# +private CountdownEvent _countdown; + +// This is how the thread pool knows how many files are being migrated +_countdown = new CountdownEvent(blobs.Count); +``` + +### FileStructure + +```c# +public class FileStructure +{ + public string blobName { get; set; } + public string parentFolderId { get; set; } +} +``` + +### Traverse blob list + +```c# +// It creates a new folder in the destination. The name of the folder is the blob's container name. +// root means it is the root of the document library. +// If you want to copy it to another drive item, you can put the drive item ID here. +containerFolder = await _graphClient.CreateFolder(_containerName, "root"); + +// Traverse the blob list +foreach (var blobName in fileList) +{ + FileStructure fs = new FileStructure() { blobName = blobName }; + + // This function parses the flat file into the folder hierarchy and creates the folder structure in the destination. It will retrieve the parentFolderId that the file should be copied to. + // If you are going to copy it to root you can comment this line out. The parentFolderId will be containerFolder.Id + fs.parentFolderId = TraverseBlobName(fs, containerFolder.Id) + + // This is where the thread pool happens. + // It takes in a callback function and an Object parameter. + ThreadPool.QueueUserWorkItem(MigrateFile, fs); +} + +// Call so the program doesn't end, it waits for all the files to be processed +_countdown.Wait(); +``` + +### Traverse blob name + +```c# +// Parse for folder path not including the file name and put it in an array +var pathSegments = filePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); +string[] directoriesParts = pathSegments.Take(pathSegments.Length - 1).ToArray(); + +// Traverse the folder listing and create 1 folder at a time +string relativePath = _containerName; +string newFolderId = parentFolderId; +foreach (string folderName in directoriesParts) +{ + string newPath = relativePath + _separator + folderName; + ... + + DriveItem subFolder = await _graphClient.CheckIfItemExists(folderName, newFolderId); + if (subFolder == null) + { + subFolder = await _graphClient.CreateFolder(folderName, newFolderId); + ... + } + newFolderId = subFolder.Id; + + relativePath = newPath; +} + +return newFolderId; +``` + +### Check if the item exists + +```c# +var item = await _graphClient.Drives[_containerId].Items[parentFolderId].ItemWithPath(itemPath).GetAsync(); +``` + +### Create folder + +```c# +var folder = new DriveItem +{ + Name = folderName, + Folder = new Folder(), + AdditionalData = new Dictionary() + { + { "@microsoft.graph.conflictBehavior", "fail" } + } +}; +var createdFolder = await _graphClient.Drives[_containerId].Items[parentFolderId].Children.PostAsync(folder); +``` + +### Migrate File + +```c# +// The parameter must be of type Object. +internal async void MigrateFile(Object stateInfo) +{ + var fileStructure = (FileStructure)stateInfo; + + // Check if the file exists in the destination. If it exists + // - don't upload + // - check if the file is newer in the source than the destination - then upload + ... + + // Migrate the file + // This is where you download the blob as a stream from abs (code below) + ... + + // Then upload the stream to SPE (code below) + ... + + // Signal the countdown event that a file has been migrated + _countdown.Signal(); + + return; +} +``` + +### Downloading From The Blob From ABS As A Stream + +```c# +BlobClient blobClient = _containerClient.GetBlobClient(blobName); + +MemoryStream memoryStream = new MemoryStream(); +await blobClient.DownloadToAsync(memoryStream); +memoryStream.Position = 0; // Reset the stream position to the beginning +``` + +### Uploading The Stream To SPE + +```c# +int _maxChunkSize = 320 * 1024; + +var uploadSessionRequestBody = new CreateUploadSessionPostRequestBody() +{ + AdditionalData = new Dictionary + { + // Fail is set here, so it doesn't get upload again if it already exist + { "@microsoft.graph.conflictBehavior", "fail" } + } +}; + +var uploadSession = await _graphClient.Drives[_containerId] + .Items[parentFolderId] + .ItemWithPath(fileName) + .CreateUploadSession + .PostAsync(uploadSessionRequestBody); + +// The stream is the same stream from the downloading the blob +var fileUploadTask = new LargeFileUploadTask(uploadSession, memoryStream, _maxChunkSize, _graphClient.RequestAdapter); +IProgress progress = new Progress(prog => Console.WriteLine($"Uploaded {fileName} {prog} bytes")); + +// Check uploadResult.UploadSucceeded to see if it is successful +var uploadResult = await fileUploadTask.UploadAsync(progress); +``` + +## Overview Of The Sample App + +### Description + +A sample app called **MigrateABStoSPE** that is designed to migrate files from an Azure Blob Storage (ABS) container to a SharePoint Embedded (SPE) container. The code snippets provided in the **Migrating Data from Azure Blob Storage container to SharePoint Embedded container** are from the sample app. + +It uses Azure.Storage.Blobs and Newtonsoft.Json libraries for working with ABS and JSON data respectively. The app authenticates with both ABS and SPE using client credentials and performs the migration of files. + +### Packages + +1. Microsoft Graph SDK (version 5.56.0) +1. Azure.Identity (version 1.12.0) +1. Azure.Storage.Blobs (version 12.21.0) +1. CommandLineParser (version 2.9.1) +1. Newtonsoft.Json (13.0.3) + +### Out Of Scope + +1. How to deal with files that already exist in the destination - it fails, it doesn't overwrite or rename +1. How to deal with ABS version newer than the destination - it fails because the file already exists in the destination + +### Running The Sample App + +1. Open a terminal or command prompt. +1. Navigate to the directory where the Program.cs file is located. +1. Make sure you have the .NET Core SDK installed on your machine. You can check this by running the command dotnet --version in the terminal. If the command isn't recognized, you can download and install the .NET Core SDK from the official Microsoft website. +1. Once you have confirmed that the .NET Core SDK is installed, you can build the application by running the command `dotnet build`. This will compile the code and generate the necessary binaries. +1. After the build process is complete, you can run the application by executing the command dotnet run followed by the required arguments. The required arguments are: + + - The container-level SAS URL: This is an Azure Blob container level SAS URL. It provides access to the container and its blobs. + - The SPE tenant ID: This is the tenant you're authenticating against in the SPE. + - The SPE client ID: This is the client you're authenticating against in the SPE. + - The SPE container ID: This is the container you're migrating content to in the SPE. For more information on how to get the [container ID](/graph/api/filestorage-list-containers) + - (optional) File name with full path that contains the blob list. + - (optional) File name with full path where to output failed blobs. + +For example, the command to run the application with the required arguments would look like this: + +`dotnet run Program.cs -- --sasurl "" --tenantid "" --clientid "" --containerid "" [ --blobfile "" --outputfile "" ]` + +### Blob and SPE Item Structure + +ABS container doesn't adhere to a folder structure, all the blobs are stored in a flat listing structure. When migrating to SPE, the sample app parses the blob name and creates the folder structure in the container ID provided, with the container name as the top folder. If you're migrating to the root folder, you can ignore this section. + +**Source** + +- Container Name: Container1 + - Blob name: FolderA/blob1.txt + - Blob name: FolderA/FolderB/blob2.txt + - Blob name: FolderA/FolderB/FolderC/blob3.txt + +**Destination** + +- Drive Item folder + - Container1 + - FolderA + - blob1.txt + - FolderB + - blob2.txt + - FolderC + - blob3.txt + +## Handling Errors and Exceptions + +### Common Issues + +1. File already exists in the destination + + - This app checks to see if the file name exists in the destination before it uploads. If there's a file with the exact same name, it will not do the upload again. It will print to stdout a message that the file already exists. To fix it, you can either delete the file from the destination or change the conflictBehavior to replace and not call `CheckIfItemExists` on upload. + +1. The file for the list of blobs isn't found +1. The format for the list of blobs - one blob per line, without quotes around the blob name +1. Not giving enough permission to access the ABS container + + - The minimum permissions are Read and List + +1. Not giving enough permissions to the SPE container + + - The required scope is "User.Read" and "FileStorageContainer.Selected" + - Remember to grant admin consent + - Remember to create the mobile & console platform app + +## Testing the Migration + +### Verification + +1. When the file is queued, it will print to stdout +1. It will print the stats of the total blobs that were processed: total, success, exists in destination, and failed. +1. If there are errors, it will send the failed blob list to a file. The file name will be printed to stdout. It will also, print a command for an incremental re-run. + +## Conclusion + +### Summary + +In this tutorial, we explored how to migrate content from ABS container to SPE container. By following the steps outlined, writing your own app to migrate content should be easy. + +To recap, we: + +1. Authenticated with ABS and Graph +1. How to use a thread pool to queue migration of blob +1. Check if the item exists in destination +1. Retrieved the blob list from ABS container +1. Uploaded the blob to the SPE container + +Understanding these steps is crucial for migrating content from ABS container to SPE container. Now, try implementing these steps in your own projects and see the difference it makes! + +Happy coding! + +### Next Steps + +- For more information about Blob Storage, see [Blob Storage documentation](/azure/storage/blobs/storage-blobs-introduction). +- For more information about SPE, see [SharePoint Embedded documentation](https://aka.ms/start-spe). + +## Appendix + +### Code Repository + +The sample app can be found in the [SharePoint Embedded Samples repository](https://github.com/microsoft/SharePoint-Embedded-Samples/tree/main/Samples/migrate-abs-to-spe). diff --git a/docs/embedded/development/tutorials/spe-da-vscode.md b/docs/embedded/development/tutorials/spe-da-vscode.md new file mode 100644 index 000000000..1a75bcce5 --- /dev/null +++ b/docs/embedded/development/tutorials/spe-da-vscode.md @@ -0,0 +1,355 @@ +--- +title: SharePoint Embedded agent Tutorial +description: Sharepoint Embedded agent tutorial with the SDK and the VS Code SharePoint Embedded Extension +ms.date: 06/10/2025 +ms.localizationpriority: high +--- + +# Tutorial for getting started with SharePoint Embedded agent + +## Prerequisites + +> [!NOTE] +> +> 1. You will need to create a SharePoint Embedded application. If you don't have one, you can easily build a sample application using the instructions [here](#getting-started-using-the-sharepoint-embedded-visual-studio-code-extension). +> 1. You must specify a standard container type at creation time. Depending on the purpose, you may or may not need to provide your Azure Subscription ID. A container type set for trial purposes can't be converted for production, or vice versa. +> 1. You must use the latest version of SharePoint PowerShell to configure a container type. For permissions and the most current information about Windows PowerShell for SharePoint Embedded, see the documentation at [Intro to SharePoint Embedded Management Shell](/powershell/SharePoint/SharePoint-online/introduction-SharePoint-online-management-shell). +> +> - Set the **CopilotChatEmbeddedHosts** property of your container type configuration to `http://localhost:8080` to be able to work through the quick start below, refer to [the CSP section above for more information](../declarative-agent/spe-da-adv.md#csp-policies). +> - Set the **DiscoverabilityDisabled** property of your container type configuration to `false` so that the agent can find the files in your created container. Refer to the [Discoverability Disabled section above for more information](../declarative-agent/spe-da-adv.md#discoverabilitydisabled). +> - Ensure that Copilot for Microsoft 365 is available for your organization. You have two ways to get a developer environment for Copilot: +> - A sandbox Microsoft 365 tenant with M365 Copilot (available in limited preview through [TAP membership](https://developer.microsoft.com/microsoft-365/tap)). +> - An [eligible Microsoft 365 or Office 365 production environment](/microsoft-365-copilot/extensibility/prerequisites#customers-with-existing-microsoft-365-and-copilot-licenses) with a M365 Copilot license. + +## Getting started using the SharePoint Embedded SDK + +### 1. Install the SDK into your React repo + +```console +# Install the SDK with npm + +npm install "https://download.microsoft.com/download/970802a5-2a7e-44ed-b17d-ad7dc99be312/microsoft-sharepointembedded-copilotchat-react-1.0.9.tgz" +``` + +#### If you want to verify checksums + +In MacOS/Linux + +```console +version="1.0.9"; + +url="https://download.microsoft.com/download/970802a5-2a7e-44ed-b17d-ad7dc99be312/microsoft-sharepointembedded-copilotchat-react-1.0.9.tgz"; + +expected_checksum="3bdf19830ffc098b253cc809f969f50fba236ad95fe85123e7b15c7cf58ecf6b"; + +package_path="microsoft-sharepointembedded-copilotchat-react-$version.tgz"; + +curl -o $package_path $url && [ "$(sha256sum $package_path | awk '{ print $1 }')" == "$expected_checksum" ] && npm install $package_path || { echo "Checksum does not match. Aborting installation."; rm $package_path; } +``` + +In Windows: + +```powershell +$version = "1.0.9" +$url = "https://download.microsoft.com/download/970802a5-2a7e-44ed-b17d-ad7dc99be312/microsoft-sharepointembedded-copilotchat-react-1.0.9.tgz" +$expected_checksum = "3BDF19830FFC098B253CC809F969F50FBA236AD95FE85123E7B15C7CF58ECF6B" +$package_path = "microsoft-sharepointembedded-copilotchat-react-$version.tgz" + +Invoke-WebRequest -Uri $url -OutFile $package_path + +$calculated_checksum = Get-FileHash -Path $package_path -Algorithm SHA256 | Select-Object -ExpandProperty Hash + +if ($calculated_checksum -eq $expected_checksum) { + Write-Output "Checksum matches. Installing the package..." + npm install $package_path +} else { + Write-Output "Checksum does not match. Aborting installation." +} +Remove-Item $package_path +``` + +### 2. Create an `authProvider` object + +This is an object that matches this interface: + +```typescript +export interface IChatEmbeddedApiAuthProvider { + // The hostname for your tenant. Example: https://m365x10735106.sharepoint.com + hostname: string; + // This function will be called when an SPO token is required + // Scope needed: ${hostname}/Container.Selected + getToken(): Promise; +} +``` + +Example usage in app: + +```typescript +// In your app: +import { IChatEmbeddedApiAuthProvider } from '@microsoft/sharepointembedded-copilotchat-react'; + +const authProvider: IChatEmbeddedApiAuthProvider = { + hostname: 'https://m365x10735106.sharepoint.com', + getToken: requestSPOAccessToken, +}; +``` + +Example implementation of `getToken` (you need to customize it): + +```typescript +// +async function requestSPOAccessToken() { + // Use your app's actual msalConfig + const msalConfig = { + auth: { + clientId: "{Your Entra client ID}", // this can likely point to process.env.REACT_APP_CLIENT_ID if you have set it in your .env file + }, + cache: { + // https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/caching.md + /* + Cache Location | Cleared on | Shared between windows/tabs | Redirect flow supported + ----------------- ---------- ------------------------- ------------------------ + sessionStorage | window/tab close | No | Yes + localStorage | browser close | Yes | Yes + memoryStorage | page | refresh/navigation | No | No + */ + cacheLocation: 'localStorage', + storeAuthStateInCookie: false, + }, + }; + + const containerScopes = { + scopes: [`${authProvider.hostname}/Container.Selected`], + redirectUri: '/' + }; + + const pca = new msal.PublicClientApplication(msalConfig); + let containerTokenResponse; + + // Consent FileStorageContainer.Selected scope + try { + // attempt silent acquisition first + containerTokenResponse = await pca.acquireTokenSilent(containerScopes); + return containerTokenResponse.accessToken; + } catch (error) { + if (error instanceof InteractionRequiredAuthError) { + // fallback to interaction when silent call fails + containerTokenResponse = await pca.acquireTokenPopup(containerScopes); + return containerTokenResponse.accessToken; + } + else { + console.log(error); + } + } +} +``` + +### 3. Create a React state to store your `chatApi` in + +```typescript +const [chatApi, setChatApi] = React.useState(null); +``` + +Example: + +```typescript +import React from 'react'; +import { ChatEmbedded, ChatEmbeddedAPI, IChatEmbeddedApiAuthProvider } from '@microsoft/sharepointembedded-copilotchat-react'; + +//... +async function requestSPOAccessToken() { + //... +} + +const authProvider: IChatEmbeddedApiAuthProvider = { + hostname: 'https://m365x10735106.sharepoint.com', + getToken: requestSPOAccessToken, +}; + +function App() { + const [chatApi, setChatApi] = React.useState(null); + + return ( + //... + ); +} +``` + +### 4. Add the `ChatEmbedded` component into your react app + +```typescript +import React from 'react'; +import { ChatEmbedded, ChatEmbeddedAPI, IChatEmbeddedApiAuthProvider } from '@microsoft/sharepointembedded-copilotchat-react'; + +//... +async function requestSPOAccessToken() { + //... +} + +const authProvider: IChatEmbeddedApiAuthProvider = { + hostname: 'https://m365x10735106.sharepoint.com', + getToken: requestSPOAccessToken, +}; + +function App() { + const [chatApi, setChatApi] = React.useState(null); + + return ( + //... + + //... + ); +} +``` + +### 5. Use the `chatApi` object in your state to open the chat and run it + +In the example above, call it this way to open the chat. + +```typescript +await chatApi.openChat(); +``` + +You may choose to pass in launch configurations + +```typescript +import { IconName, IconStyle } from './sdk/types'; + +//... +const zeroQueryPrompts = { + headerText: "This is my Starter Prompt", + promptSuggestionList: [{ + suggestionText: 'Hello', + iconRegular: { name: IconName.ChatBubblesQuestion, style: IconStyle.Regular }, + iconHover: { name: IconName.ChatBubblesQuestion, style: IconStyle.Filled }, + }] +}; + +const launchConfig: ChatLaunchConfig = { + header: 'My Awesome Chat', + zeroQueryPrompts, + suggestedPrompts: ["What are my files?",], + instruction: "Response must be in the tone of a pirate", + locale: "en", +}; + +await chatApi.openChat(launchConfig); +``` + +Full example: + +```typescript +import React from 'react'; +import { ChatEmbedded, ChatEmbeddedAPI, IChatEmbeddedApiAuthProvider } from '@microsoft/sharepointembedded-copilotchat-react'; + +//... +async function requestSPOAccessToken() { + //... +} + +const authProvider: IChatEmbeddedApiAuthProvider = { + hostname: 'https://m365x10735106.sharepoint.com', + getToken: requestSPOAccessToken, +}; + +function App() { + const [chatApi, setChatApi] = React.useState(null); + + React.useEffect(() => { + const openChat = async () => { + if (!chatApi) { + return; + } + + await chatApi.openChat(); + }; + + openChat(); + }, [chatApi]); + + + return ( + //... + setChatApi(api)} + authProvider={authProvider} + containerId={container.id} + style={{ width: 'calc(100% - 4px)', height: 'calc(100vh - 8px)' }} + /> + //... + ); +} +``` + +### 6. Your AI chat should be loaded successfully + +## Getting started using the SharePoint Embedded Visual Studio Code Extension + +### Quick Start + +> [!NOTE] +> When using standard container types with the VS Code extension, [DisableDiscoverability](../declarative-agent/spe-da-adv.md#discoverabilitydisabled) and [Grant admin consent](/entra/identity/enterprise-apps/grant-admin-consent?pivots=portal) features are currently not supported. This will need to be done using the [SPO Admin Powershell](/powershell/sharepoint/sharepoint-online/connect-sharepoint-online). + +1. Follow this guide up to the [Load Sample App section](../../getting-started/spembedded-for-vscode.md#load-sample-app) with the Visual Studio Code Extension +1. Within the extension, right click on the owning application, and select `Run sample apps -> Typescript + React + Azure Functions` + + ![Using the SPE VS Code extension to create a TypeScript React Azure Functions project](../../images/speco-runsampleapp.png) + +1. Allow for the extension to copy and create client secrets + + > [!CAUTION] + > Caution for production environments, storing secrets in plain text poses a security risk. + + ![SPE VS Code notification alerting it will copy app secrets in plain text on local machine](../../images/speco-createappsecret.png) + + If the application does not already have a client secret, the extension will ask to create one for you. + + ![SPE VS Code notification prompting user to allow it to create a secret for the application if it does not exist.](../../images/speco-createclientsecret.png) + +1. Select a folder to host the application, this will clone the following [repository for SharePoint Embedded Samples](https://github.com/microsoft/SharePoint-Embedded-Samples/tree/main/Samples/spe-typescript-react-azurefunction) into the folder + + ![windows File Explorer folder to save project on local machine](../../images/speco-cloneproject.png) + + Next, when prompted, open the folder + + ![VS Code extension with the SPE React Typescript + Azure Functions sample application cloned on local machine and open in VS Code](../../images/speco-vscodeclonedproject.png) + +1. Navigate to `react-client\src\components\ChatSideBar.tsx` and uncomment this section + + ![VS Code file explorer with ChatSideBar.tsx in open window with relevant code to uncomment highlighted](../../images/speco-uncommentchatsidebar.png) + +1. Navigate to `react-client\src\routes\App.tsx` and set the React state of the `showSidebar` variable to `true` + + ![VS Code file explorer with App.tsx open with line of showSidebar variable useState function input changed from false to true to enable showing chat side bar](../../images/speco-setshowsidebartrue.png) + +1. You can follow the instructions of the `README.md` file in the root of the project for further npm commands. Run `npm run start` in the root of the project to start your application with the SPE agent functionality enabled. + + > [!NOTE] + > `npm run start` Should be done in the root folder of the sample project. `\SharePoint-Embedded-Samples\Samples\spe-typescript-react-azurefunction` + + ![VS Code terminal in root folder of SPE Typescript project cloned earlier and npm run start command typed in](../../images/speco-runnpmrunstart.png) + +1. Sign in with a user who has a Microsoft 365 Copilot license enabled. + + ![SPE Typescript App running in Edge with sign in buttons](../../images/speco-reacttypescripthomepage.png) + +1. Navigate to the `containers` page, create one if you do not have any yet + + ![SPE Typescript App running in edge in /containers sub page with modal of user c reatign a container called ContosoCompanyContainer](../../images/speco-createcontosocontainer2.png) + + After it has been created, you will see it here: + + ![SPE Typescript App running in edge with a created container from above ContosoCompanyContainer](../../images/speco-createdcontainer.png) + +1. Click the container and upload your files. Once a container has been created and you have navigated inside it, your agent chat experience will become enabled. + + ![SPE Typescript App running in edge inside a created container page of ContosoCompanyContainer](../../images/speco-spechatenabled.png) + +### Examples + +The [SharePoint Embedded Samples](https://github.com/microsoft/SharePoint-Embedded-Samples/tree/main/Samples/spe-typescript-react-azurefunction) repository has examples for how to use SharePoint Embedded in your custom applications. diff --git a/docs/embedded/development/tutorials/using-file-preview.md b/docs/embedded/development/tutorials/using-file-preview.md new file mode 100644 index 000000000..08c9602a2 --- /dev/null +++ b/docs/embedded/development/tutorials/using-file-preview.md @@ -0,0 +1,103 @@ +--- +title: File Previews +description: Preview SharePoint Embedded content +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# Using File Previews + +## Embedding a file preview in an iFrame + +It's possible to preview a [wide range](https://support.microsoft.com/office/file-types-supported-for-previewing-files-in-onedrive-sharepoint-and-teams-e054cd0f-8ef2-4ccb-937e-26e37419c5e4) of files in your browser without using a special application. Among the files supported, you can view PDF, JPG, MP4, etc. + +In order to preview a file in an `iframe`, you need to + +1. Call Graph's driveItem preview endpoint and obtain the GetUrl +1. Use the URL in an iFrame (or even open it in a new page) + +## Get the preview url using Graph + +Microsoft Graph offers the following endpoint to [preview a file](/graph/api/driveitem-preview): + +```javascript +POST https://graph.microsoft.com/{version}/drives/{driveId}/items/{itemId}/preview +``` + +- `Version` is Graph's version. For example "v1.0" +- The `driveId` is Container ID (starts with "b!") +- The `itemId`, which is the drive item ID. + +If you're using the Microsoft Graph C# SDK, the code would be similar to the following: + +```csharp +ItemPreviewInfo preview = await graphServiceClient.Drives[driveId].Items[itemId] + .Preview() + .Request() + .PostAsync(); +``` + +The JSON response includes the preview URLs for each document. Use the one obtained in `getUrl`: + +```javascript +{ + "getUrl": "https://www.onedrive.com/embed?foo=bar&bar=baz", + "postParameters": "param1=value¶m2=another%20value", + "postUrl": "https://www.onedrive.com/embed_by_post" +} +``` + +> [!TIP] +> It is possible to remove the banner at the top by adding the parameter `nb=true` to the obtained URL. E.g. +> `https://contoso.sharepoint.com/restOfUrl/embed.aspx?param1=value&nb=true` + +> [!CAUTION] +> Currently **getUrl** contains a parameter with an encrypted token that can only be used with your application. However, this may change in the near future and you may be asked to add an auth header as you do with other requests. + +## Use the URL in an `iframe` + +The next step is simply to use the URL obtained in the previous step in a new page. You could have an endpoint in your application that serves a new page as similar to this one: + +```html + + + +

Preview

+

Preview of {file name}:

+ + + + +``` + +## Load the document preview dynamically + +If you intend to dynamically load the preview in the same page without leaving it, you might get a CORS error if you attempt to access the Microsoft Graph endpoint directly from a script from your page. + +One way to solve this problem is to create an endpoint in your application that makes the request and returns the url. + +For example, your server-side code should first obtain the document's preview url: + +```csharp +[HttpGet] +[AuthorizeForScopes(Scopes = new string[] { "Files.Read.All" })] +public async Task> GetPreviewUrl(string driveId, string itemId) +{ + // Obtain tokens for the the request + // Use the function created in the first step + return url + "&nb=true"; //Use nb=true to suppress banner +} +``` + +The client-side application can then use the browser's `fetch` API to request and inject the url into the `iframe`: + +```javascript +async function preview(driveId, itemId) { + const url = `/GetPreviewUrl?driveId=${driveId}&itemId=${itemId}`; + const response = await fetch(url, { + credentials: 'include', + }).then(response => response.text()); + + document.getElementById('preview').src = response + "&nb=true"; //Use nb=true to suppress banner +} +``` diff --git a/docs/embedded/development/tutorials/using-webhooks.md b/docs/embedded/development/tutorials/using-webhooks.md new file mode 100644 index 000000000..b0511b294 --- /dev/null +++ b/docs/embedded/development/tutorials/using-webhooks.md @@ -0,0 +1,113 @@ +--- +title: Using Webhooks +description: Use webhooks with SharePoint Embedded. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# Using Webhooks + +## Set Up Webhooks with SharePoint Embedded + +Webhooks are automated messages that are transmitted by an application when a trigger is activated. They can be used in SPE to enable the automation of workflows, the integration of systems, and to respond to events in real-time. + +You'll use webhooks to invoke the Azure Cognitive Services APIs from the application whenever an existing file is updated, or a new file is uploaded. + +To set up webhooks with your [current SharePoint Embedded application](/training/modules/sharepoint-embedded-create-app/), you need to: + +1. Create and register a webhook endpoint to get notifications whenever there's a change in your container. This will be done using REST APIs. +1. Connect to Graph and subscribe to changes. You can expose your application to the internet by either running it locally or deploying it on the cloud. For this tutorial, you'll be employing the former by utilizing ngrok and then subscribing to the changes by making a POST call. +1. Perform any desired action by handling the webhook data. One such use case is covered in [Enabling document processing with Azure Cognitive Services tutorial](./doc-processing-acs.md). + +![using webhooks schema](../../images/Using-Webhooks.png) + +> [!TIP] +> To learn more about the Microsoft Graph APIs used in this tutorial, see [Create subscription](/graph/api/subscription-post-subscriptions). + +## Create and register a webhook + +Open the **index.ts** file and add an endpoint `onReceiptAdded`: + +```typescript +server.post('/api/onReceiptAdded', async (req, res, next) => { + try { + const response = await onReceiptAdded(req, res); + res.send(200, response) + } catch (error: any) { + res.send(500, { message: `Error in API server: ${error.message}` }); + } + next(); +}); +``` + +You also need to add the query parser plugin at the top of this file so that it runs at server startup: + +```typescript +server.use(restify.plugins.bodyParser(), restify.plugins.queryParser()); +``` + +Create **onReceiptAdded.ts** and implement the method `onReceiptAdded` to read `validationToken` and `driveId`. `validationToken` is required when Microsoft Graph makes a one-time call to verify the endpoint upon creation of the webhook subscription. `driveId` is the container-id for which the subscription is created. + +```typescript +require('isomorphic-fetch'); + +export const onReceiptAdded = async (req: Request, res: Response) => { + + const validationToken = req.query['validationToken']; + if (validationToken) { + res.send(200, validationToken, {"Content-Type":"text/plain"}); + return; + } + + const driveId = req.query['driveId']; + if (!driveId) { + res.send(200, "Notification received without driveId, ignoring", {"Content-Type":"text/plain"}); + return; + } + + console.log(`Received driveId: ${driveId}`); + + res.send(200, ""); + return; +} +``` + +## Connect to Graph and subscribe to changes + +Follow the [documentation](https://ngrok.com/docs/getting-started/) to create a tunnel for your backend server using ngrok. + +After starting the app, run the following command in a terminal: + +```powershell +ngrok http 3001 +``` + +On successful completion, you should get the following output. The public-facing endpoint for the app is highlighted in the red rectangle: + +![ngrok registration](../../images/ngrok-registration.png) + +Once the tunneling is active, you can subscribe to delta changes in the container by adding the webhook URL. To do that, open Postman and make the following `POST` request with the appropriate graph access token and `notificationUrl` with the `driveId` appended as a query parameter to ensure that you get notifications for changes only in the desired container. + +```json +POST https://graph.microsoft.com/v1.0/subscriptions +{ + "changeType": "updated", + "notificationUrl":"https://5ac2-2404-f801-8028-3-691a-87b2-d309-545b.ngrok-free.app/api/onReceiptAdded?driveId={{ContainerId}}", + "resource": "drives/{{ContainerId}}/root", + "expirationDateTime": "2024-01-20T03:58:34.088Z", + "clientState": "" +} +``` + +You can use the following code snippet for setting the max possible expiration time of 4230 minutes from the current time by adding this to the "Pre-request Script" section. It will set an environment variable that can be used in the request body. + +```javascript +var now = new Date() +var duration = 1000 * 60 * 4230; // max lifespan of driveItem subscription is 4230 minutes +var expiry = new Date(now.getTime() + duration); +var expiryDateTime = expiry.toISOString(); + +pm.environment.set("ContainerSubscriptionExpiry", expiryDateTime); +``` + +At this point, if you add/update any file in the container, you'll get a notification at the previously added endpoint (`/api/onReceiptAdded`) and a log message at the console: `Received driveId: ` diff --git a/docs/embedded/getting-started/containertypes.md b/docs/embedded/getting-started/containertypes.md new file mode 100644 index 000000000..f21edc78f --- /dev/null +++ b/docs/embedded/getting-started/containertypes.md @@ -0,0 +1,207 @@ +--- +title: Create New SharePoint Embedded Container Types +description: This article explains how Container Types work and the steps to create new Container Types. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded Container Types + +A container type is a SharePoint Embedded resource that defines the relationship, access privileges, and billing accountability between a SharePoint Embedded application and a set of containers. Also, the container type defines behaviors on the set of containers. + +Each container type is strongly coupled with one SharePoint Embedded application, which is referred to as the owning application. The owning application developer is responsible for creating and managing their container types. SharePoint Embedded mandates a 1:1 relationship between owning application and a container type. + +Container type is represented on each container instance as an immutable property (ContainerTypeID) and is used across the entire SharePoint Embedded ecosystem, including: + +- **Access authorization**: A SharePoint Embedded application must be associated with a container type to get access to container instances of that type. Once associated, the application has access to all container instances of that type. The actual access privilege is determined by the application-ContainerTypeID permission setting. The owning application by default has full access privilege to all container instances of the container type it's strongly coupled with. Learn more about [SharePoint Embedded Authorization](../development/auth.md). +- **Easy exploration**: Container type can be created for trial purposes, allowing developers to explore SharePoint Embedded application development and assess its features for free. +- **Billing**: Container types for non-trial purposes are billable and must be created with an Azure Subscription. The usage of containers is metered and charged. Learn more about [metering](../administration/billing/meters.md) and the [SharePoint Embedded billing experience](../administration/billing/billingmanagement.md). +- **Configurable behaviors**: Container type defines selected behaviors for all container instances of that type. Learn more about setting [Container type configuration](../getting-started/containertypes.md#configuring-container-types). + +> [!NOTE] +> +> 1. You must specify the purpose of the container type you're creating at creation time. Depending on the purpose, you may or may not need to provide your Azure Subscription ID. A container type set for trial purposes can't be converted for production; or vice versa. +> 1. Standard and pass through container types can't be converted once created. If you want to convert a standard container type to pass through billing or vice versa, you must delete and re-create the container type. +> 1. You must use the latest version of SharePoint PowerShell to configure a container type. For permissions and the most current information about Windows PowerShell for SharePoint Embedded, see the documentation at [Intro to SharePoint Embedded Management Shell](/powershell/sharepoint/sharepoint-online/introduction-sharepoint-online-management-shell). + +## Creating Container Types + +SharePoint Embedded has 2 different Container Types you can create. + +1. [Trial Container Type](#trial-container-type) +1. [Standard Container Type](#standard-container-types-non-trial) + +### Prerequisites to create SharePoint Embedded container type + +A new container type will be created using **SharePoint Online Management Shell**: + +1. Download and install the [latest version of SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588) +1. Open SharePoint Online Management Shell from **Start** screen, type **sharepoint**, and then select **SharePoint Online Management Shell**. +1. Connect to SPO service using `Connect-SPOService` cmdlet by providing admin credentials associated with tenancy. For information on [how to use Connect-SPOService](/powershell/module/sharepoint-online/connect-sposervice), refer the linked documentation. + +### Tenant requirements + +- An active instance of SharePoint is required in your Microsoft 365 tenant. +- Users who will be authenticating into SharePoint Embedded Container Types and Containers must be in Entra ID (Members and Guests) + + > [!NOTE] + > An Office license is not required to collaborate on Microsoft Office documents stored in a container. + +### Roles and Permissions + +- The admin who sets up the billing relationship for SharePoint Embedded needs to have owner or contributor permissions on the Azure subscription. +- Admin needs to have a SharePoint Embedded Administrator or Global Admin role to operate billing cmdlets. + +### Azure Subscription + +For the standard billing container type, the global administrator or SharePoint Embedded Administrator needs to set up: + +- An existing SharePoint tenancy +- An Azure subscription in the tenancy +- A resource group attached to the Azure subscription + +## Trial Container Type + +A container type can be created for trial/development purposes and isn't linked to any Azure billing profile. This enables developers to explore SharePoint Embedded application development and assess its features for free. For trial container types, the developer tenant is the same as the consuming tenant. +Each developer can have only one container type in the trial status in their tenant at a time. The trial container type is valid for up to 30 days but can be removed at any time within this period. + +To create a container type for trial purposes, you can: + +- Use SharePoint Embedded Visual Studio Code Extension to create the container type in just a few steps. The Visual Studio Code extension registers your container type and creates containers for you. +- Use SharePoint PowerShell. You must be a SharePoint Embedded Administrator or Global Administrator to run the following cmdlet. If you're a SharePoint Administrator, grant yourself the SharePoint Embedded Admin role as well to execute these cmdlets. + + ```powershell + New-SPOContainerType [–TrialContainerType] [-ContainerTypeName] [-OwningApplicationId] [-ApplicationRedirectUrl] [] + ``` + +The following restrictions are applied to trial container types: + +- Up to five containers of the container type can be created. This includes active containers and those in the recycle bin. +- Each container has up to 1 GB of storage space. +- The container type expires after 30 days and access to any existing containers of that container type will be removed. +- The developer must permanently delete all containers of an existing container type in trial status to create a new container type for trial. This includes containers in the deleted container collection. +- The container type is restricted to work in the developer tenant. It can't be deployed in other consuming tenants. + +## Standard Container Types (non-trial) + +A standard container type in SharePoint Embedded defines the relationship, access privileges, and billing profile between an application and its containers. It establishes how the application interacts with the containers, including access permissions, and is associated with a billing profile for non-trial purposes. Each tenant can have 25 container types at a time. + +### Billing profile + +SharePoint Embedded is a consumption-based Pay-as-you-go (PAYG) offering meaning you pay only for what you use. SharePoint Embedded provides two billing models that the tenant developing the SharePoint Embedded application can select for respective container types, tailoring it to their unique business requirements. The two billing models are Standard and Pass-through billing. + +### Standard Container Type - with billing profile + +With the standard billing profile, all consumption-based charges are directly billed to the tenant who owns or develops the application. The admin in the developer tenant must establish a valid billing profile when creating a standard container type. + +![Standard](../images/1bill521.png) + +Each developer tenant can create up to five container types consisting of 1 trial container type and 4 standard container types or 5 standard container types. +Standard container types are created using the [New-SPOContainerType](/powershell/module/sharepoint-online/new-spocontainertype) cmdlet. + +You need the following to create a standard container type: + +- Use SharePoint PowerShell. You must be a SharePoint Embedded Administrator or Global Administrator to run this cmdlet. If you're a SharePoint Administrator, grant yourself the SharePoint Embedded Admin role as well to execute these cmdlets. +- An Azure subscription and a resource group must be present in the Azure portal for regular billing. +- An App registration must be created in Microsoft Entra ID. + +To create a standard container type using an Azure billing profile, use the following cmdlets: + +```powershell +New-SPOContainerType [-ContainerTypeName] [-OwningApplicationId] [-ApplicationRedirectUrl] [] +``` + +Once the container type is created, add the Azure billing profile. + +```powershell +Add-SPOContainerTypeBilling –ContainerTypeId -AzureSubscriptionId -ResourceGroup -Region +``` + +> [!NOTE] +> The user or admin who sets up a billing relationship for SharePoint Embedded must have owner or contributor permissions on the Azure subscription. +> +> Every container type must have an owning application. +> +> A single-owning app can only own one container type at a time. +> +> An Azure subscription can be attached to any number of container types. +> +> If the cmdlet above fails with a SubscriptionNotRegistered error, it is because **Microsoft.Syntex** is not registered as a resource provider in the subscription. The cmdlet will send a resource provider registration request on your behalf but it will take a few minutes to be completed. Please wait 5-10 minutes and try again until the cmdlet succeeds. + +### Standard Container Type - pass-through billing + +With pass-through billing, consumption-based charges are billed directly to the tenant registered to use the SharePoint Embedded application (consuming tenant). Admins in the developer tenant don't need to set up an Azure billing profile when creating a pass-through SharePoint Embedded container type. + +![Pass Through](../images/2bill521.png) + +For container types intended to be directly billed to a customer use the flag `-IsPassThroughBilling`. For the direct to customer billed container type, there's no need to attach a billing profile. + +To create a pass through billing, standard container type, use the following cmdlet: + +```powershell +New-SPOContainerType [-ContainerTypeName] [-OwningApplicationId] [-ApplicationRedirectUrl] [-IsPassThroughBilling] [] +``` + +Once the container type is [registered](../getting-started/register-api-documentation.md) in the consuming tenant, the consuming tenant admin (SharePoint Admin or Global Admin) needs to set up the billing profile in the consuming tenant to use the SharePoint Embedded application. + +#### Set Up Billing Profile in Consuming Tenant + +1. In [Microsoft 365 admin center](https://admin.microsoft.com/), select **Setup**, and the view the **Billing and licenses** section. Select **Activate pay-as-you-go services.** + + ![Microsoft 365 admin center Files and Content](../images/SyntexActivatePAYGSetup.png) + +1. Select **Go to Pay as you go services**. +1. Select **Apps** under **Syntex services for**, select **Apps** and **SharePoint Embedded** + + ![Microsoft 365 admin center SharePoint Embedded Billing setting](../images/SyntexPAYGActivateSPE.png) + + > [NOTE] + The subscription configured in the Syntex services will reflect the consuming charges in the Azure billing portal. + +1. [Register the container type](#registering-container-types) using the App only authentication token. + +## Configuring Container Types + +The Developer Admin can set selected settings on the SharePoint Embedded container types created by using this PowerShell cmdlet. + +This cmdlet allows admins to set [Microsoft 365 content discoverability](../development/content-experiences/user-experiences-overview.md) and [sharing](../development/sharing-and-perm.md) settings on container types. The setting applies to all container instances of the container type: + +```powershell +Set-SPOContainerTypeConfiguration -ContainerTypeId 4f0af585-8dcc-0000-223d-661eb2c604e4 -DiscoverabilityDisabled $False +``` + +## Viewing Container Types + +The Developer Admin can view all the SharePoint Embedded container types they created on their tenant using `Get-SPOContainerType`. This cmdlet retrieves and returns the list of container types created for a SharePoint Embedded Application in the tenant. + +```powershell +Get-SPOContainerType [] +``` + +Example output of the `Get-SPOContainerType` cmdlet + +```powershell +ContainerTypeId : 4f0af585-8dcc-0000-223d-661eb2c604e4 +ContainerTypeName : ContosoLegal +OwningApplicationId : a735e4af-b86e-0000-93ba-1faded6c39e1 +Classification : Standard +AzureSubscriptionId : 564e9025-f7f5-xxx9-9ddd-4cdxxxx1755 +ResourceGroup : prod-resources +Region : EastUS +``` + +## Registering Container Types + +To create and interact with containers, you must [register](../getting-started/register-api-documentation.md) the container type within the Consuming Tenant. The owning application defines the permissions for the container type by invoking the [registration API](../getting-started/register-api-documentation.md). + +## Deleting Container Types + +Developer admins can delete both trial and standard container types. To delete a container type, you must first remove all containers of that container type, including from the deleted container collection. To remove containers, refer to [Consuming Tenant Admin](../administration/consuming-tenant-admin/cta.md). +Once all the containers are deleted, Developer admins can delete the container type using `Remove-SPOContainerType`. + +```powershell +Remove-SPOContainerType [-ContainerTypeId ] +``` +## SharePoint Embedded meters + +To learn more about the supported pay-as-you-go meters, refer to the [SharePoint Embedded meters](../administration/billing/meters.md) article. diff --git a/docs/embedded/getting-started/register-api-documentation.md b/docs/embedded/getting-started/register-api-documentation.md new file mode 100644 index 000000000..320893e72 --- /dev/null +++ b/docs/embedded/getting-started/register-api-documentation.md @@ -0,0 +1,175 @@ +--- +title: Register File Storage container Type Application Permissions +description: Register the container type. +ms.date: 03/03/2025 +ms.localizationpriority: high +--- + +# Register file storage container type application permissions + +In order for a SharePoint Embedded application to interact with containers in a consuming tenant, the container type must first be registered in the consuming tenant. Container type registration happens when the owning application invokes the registration API to specify what permissions can be performed against its container type. The registration API also grants access to other Guest Apps to interact with the owning application's containers. For example, a SharePoint Embedded application can grant permissions to another application--a Guest App so that the Guest App can perform backup operations against its containers. + +Since the registration API controls the permissions that a SharePoint Embedded application can perform against the container in the consuming tenant, this call should be one of the first APIs invoked. Failure to do so results in access denied errors when invoking other APIs against the container and/or the content in the containers. + +There are no restrictions on how many times the registration API can be invoked. How often the registration API is invoked and when it's invoked is dependent on the SharePoint Embedded application. However, the last successful call to the registration API determines the settings used in the consuming tenant. + +## Authentication and authorization requirements + +For the container type's owning application to act on a consuming tenant, some pre-requisites must be completed: + +- the owning app must have a service principal installed on the consuming tenant; and +- the owning app must be granted admin consent to perform container type registration in the consuming tenant. + +> [!NOTE] +> Only the owning application of the container type can invoke the registration API in the consuming tenant. + +Both requirements can be satisfied by having a tenant administrator of the consuming tenant [grant admin consent](/entra/identity/enterprise-apps/grant-admin-consent?pivots=portal) to the container type's owning application. + +The container type registration API requires the `Container.Selected` app-only permission for SharePoint (see [Exceptional access patterns](../development/auth.md#exceptional-access-patterns)). You will need to use the [client credentials grant flow](/entra/identity-platform/v2-oauth2-client-creds-grant-flow) and [request a token with a certificate](/entra/identity-platform/v2-oauth2-client-creds-grant-flow#second-case-access-token-request-with-a-certificate) to use the registration API. + +> [!NOTE] +> The registration API is **NOT** a Microsoft Graph API but a SharePoint API. This API will be ported to Microsoft Graph in the future. + +To request admin consent from a tenant administrator in the consuming tenant, you may direct them to the [admin consent endpoint](/entra/identity-platform/v2-admin-consent). For the right endpoints on national clouds, see [Microsoft identity platform endpoints on national clouds](/entra/identity-platform/authentication-national-cloud#microsoft-entra-authentication-endpoints): + +```http +https://login.microsoftonline.com//adminconsent?client_id= +``` + +You may configure the admin consent endpoint to fit your needs, including handling errors and successful grants. For more information, see [Admin consent URI](/entra/identity-platform/v2-admin-consent). + + +## Container type Permissions + +The registration API determines what permissions a SharePoint Embedded application can perform against containers and content in containers for the specified container type. + +| Permission | Description | +| -------------------- | ------------------------------------------------------------------------------------------------------------------ | +| None | Has no permissions to any containers or content of this container type. | +| ReadContent | Can read content of containers of this container type. | +| WriteContent | Can write content to containers for this container type. This permission can't be granted without the ReadContent permission. | +| Create | Can create containers of this container type. | +| Delete | Can delete containers of this container type. | +| Read | Can read the metadata of containers of this container type. | +| Write | Can update the metadata of containers of this container type. | +| EnumeratePermissions | Can enumerate the members of a container and their roles for containers of this container type. | +| AddPermissions | Can add members to the container for containers of this container type. | +| UpdatePermissions | Can update (change roles of) existing memberships in the container for containers of this container type. | +| DeletePermissions | Can delete other members (but not self) from the container for containers of this container type. | +| DeleteOwnPermissions | Can remove own membership from the container for containers of this container type. | +| ManagePermissions | Can add, remove (including self) or update members in the container roles for containers of this container type. | +| Full | Has all permissions for containers of this container type. | + +## HTTP request + +```http +PUT {RootSiteUrl}/_api/v2.1/storageContainerTypes/{containerTypeId}/applicationPermissions +``` + +> [!NOTE] +> This is NOT a Graph API +> +> `{RootSiteURL}` is the SharePoint URL of the consuming tenant. For example, https://contoso.sharepoint.com. + +### Request body + +In the request body, supply a JSON representation of the container type permissions for the SharePoint Embedded applications. + +### Response + +If successful, this method returns a `200 OK` response code and the container type permissions configured for the SharePoint Embedded applications in the response body. + +| HTTP Code | Description | +| :--------: | ----------- | +| 400 | Bad request. | +| 401 | Request lacks valid authentication credentials. | +| 403 | Provided authentication credentials are valid but insufficient to perform the requested operation. Examples: the calling app isn't the owning app of the container type. | +| 404 | Container type doesn't exist. | + +## Examples + +### Register the container type in a consuming tenant with permissions only for the Owning App + +Register the container type in the consuming tenant and grant full permissions to the Owning Application (AppId 71392b2f-1765-406e-86af-5907d9bdb2ab) for Delegated and AppOnly calls. + +#### Request + +```json +PUT {RootSiteUrl}/_api/v2.1/storageContainerTypes/{containerTypeId}/applicationPermissions +Content-Type: application/json + +{ + "value": [ + { + "appId": "71392b2f-1765-406e-86af-5907d9bdb2ab", + "delegated": ["full"], + "appOnly": ["full"] + } + ] +} +``` + +#### Response + +```json +HTTP/1.1 200 OK +Content-type: application/json + +{ + "value": [ + { + "appId": "71392b2f-1765-406e-86af-5907d9bdb2ab", + "delegated": ["full"], + "appOnly": ["full"] + } + ] +} +``` + +### Register the container type in a consuming tenant with permissions for a Guest App + +Register the container type in the consuming tenant and grant full permissions to the Owning Application (AppId 71392b2f-1765-406e-86af-5907d9bdb2ab) for Delegated and AppOnly calls. In addition, grant a Guest App (AppId 89ea5c94-7736-4e25-95ad-3fa95f62b6) read and write permissions only for Delegated calls. + +#### Request + +```json +PUT /storagecontainerTypes/{containerTypeId}/applicationPermissions +Content-Type: application/json + +{ + "value": [ + { + "appId": "71392b2f-1765-406e-86af-5907d9bdb2ab", + "delegated": ["full"], + "appOnly": ["full"] + }, + { + "appId": "89ea5c94-7736-4e25-95ad-3fa95f62b6", + "delegated": ["read", "write"], + "appOnly": ["none"] + } + ] +} +``` + +#### Response + +```json +HTTP/1.1 200 OK +Content-type: application/json + +{ + "value": [ + { + "appId": "71392b2f-1765-406e-86af-5907d9bdb2ab", + "delegated": ["full"], + "appOnly": ["read"] + }, + { + "appId": "89ea5c94-7736-4e25-95ad-3fa95f62b6", + "delegated": ["read", "write"], + "appOnly": ["none"] + } + ] +} +``` diff --git a/docs/embedded/getting-started/spembedded-for-vscode.md b/docs/embedded/getting-started/spembedded-for-vscode.md new file mode 100644 index 000000000..343a842f5 --- /dev/null +++ b/docs/embedded/getting-started/spembedded-for-vscode.md @@ -0,0 +1,176 @@ +--- +title: SharePoint Embedded for Visual Studio Code +description: Installation and getting started with SharePoint Embedded for Visual Studio Code +ms.date: 07/16/2025 +ms.localizationpriority: high +--- + +# SharePoint Embedded for Visual Studio Code + +The SharePoint Embedded Visual Studio Code extension helps developers get started for free with SharePoint Embedded application development. + +> [!IMPORTANT] +> To start building with SharePoint Embedded, you'll need administrative access to a Microsoft 365 tenant. +> If you don't already have a tenant, you can get your own tenant with the [Microsoft 365 Developer Program](https://developer.microsoft.com/microsoft-365/dev-program), [Microsoft Customer Digital Experience](https://cdx.transform.microsoft.com/), or create a free trial of a [Microsoft 365 E3 license](https://www.microsoft.com/microsoft-365/enterprise/microsoft365-plans-and-pricing). + +## Install SharePoint Embedded for Visual Studio Code + +1. Open a new window in [Visual Studio Code](https://code.visualstudio.com/) and navigate to "**Extensions**" on the activity bar. +1. Search "SharePoint Embedded" in the Extensions view. You can also view the extension in [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=SharepointEmbedded.ms-sharepoint-embedded-vscode-extension). +1. Select **"Install"** and the SharePoint Embedded icon will appear on the activity bar. +1. If already installed, please update to the latest version if one is available. +1. Select the icon to open the SharePoint Embedded view and create a container type with trial configuration. + +![SharePoint Embedded VS Extensions](../images/vsx-images/n1downloadvsx.png) + +### Sign in with admin credentials + +To use the extension, you must sign in to a Microsoft 365 tenant with an administrator account. + +![Install](../images/vsx-images/n2vsx-signin.png) + +- Authentication opens a new tab in an external browser to grant permissions + + ![authorize and authenticate the extension to your M365 Entra tenant](../images/vsx-images/auth-allow-extension-uri.png) + +- Review the requested permissions carefully, then select **Accept** on the pop-up window prompting admin consent + + ![review before consenting to the permissions the extension is asking for](../images/vsx-images/n3vsx-grant-admin-consent.png) + +After successful authorization, select open on the dialog to be redirected to VSCode: + +![authorization completed in browser now redirecting to visual studio code](../images/vsx-images/auth-redirect.png) + +## Create a container type with a trial configuration + +Once signed in, you're prompted to create a [container type with trial configuration](./containertypes.md#trial-container-type). A container type lets you get started calling SharePoint Embedded APIs and building a proof-of-concept application using SharePoint Embedded. Learn more about [container types](containertypes.md). + +![home screen](../images/vsx-images/n4vsx-home-screen.png) + +- Select **Create Trial Container Type** +- Follow the prompts to name your container type. You can change your container type name later on. + +![create container type](../images/vsx-images/n5a-name-ct.png) + +> [!NOTE] +> SharePoint Embedded for Visual Studio Code only supports container types with trial configuration at this time. Other container types with standard or pass-through billing configurations must be created using the SharePoint Online PowerShell Module. + +## Create a Microsoft Entra ID App + +Every container type is owned by a Microsoft Entra ID application. The first step when creating a free trial container type is to create a new or select an existing Microsoft Entra ID application as the owning application. You can either specify the name of your new application or pick one of your existing applications. Learn more about SharePoint Embedded [app architecture](../development/app-architecture.md) + +- Follow the prompts to name your new Entra application or select an existing application ID: + +![Create App](../images/vsx-images/n6aname-app.png) + +> [!NOTE] +> If you choose an existing application, the extension will update that app's configuration settings for it to work with both SharePoint Embedded and this extension. Doing this is NOT recommended on production applications. + +After your container type is created and your application is configured, you'll be able to view your local tenant registration as a tree in the left nav-bar. + +## Register your container type + +After creating your container type, you'll need to register that container type on your local tenant. Learn more about container type [registration](./register-api-documentation.md). + +- Follow the prompts and select **Register on local tenant** on the lower right corner of the VS Code window + + ![local tenant registration popup](../images/vsx-images/local-tenant-registration-popup.png) + +- If you don't see the prompt, you can right-click on your `` and select **Register** from the menu + + ![register](../images/vsx-images/n7aregister-ct.png) + +### Grant permissions + +Review permissions and follow the prompt to grant admin consent + +![grant admin consent popup](../images/vsx-images/auth-grant-admin-consent-popup.png) + +An external browser window will pop open for you to sign-in and grant admin consent + +![login permissions](../images/vsx-images/n9alogin-grant-permissions.png) + +## Create your first container + +With your container type registered, you can now create your first container. Only five containers of container type can be created to upload and manage content. + +- Right-click on the **Containers** drop-down from the tree in the left nav-bar and select **Create container** +- Enter a name for the container you would like to create + +![create container](../images/vsx-images/n10acreate-container.png) +![name container](../images/vsx-images/n11aname-first-cont.png) + +## Recycling Containers + +You can also recycle and recover containers within the extension. + +![recycle containers](../images/vsx-images/n12arecycle-cont.png) + +![final home page](../images/vsx-images/n13a-final-home-page.png) + +## Load Sample App + +With your free trial container type created, you can use the extension to load one of the SharePoint Embedded sample apps and automatically populate the runtime configuration file with the details of your Microsoft Entra ID app and container type. + +![Load Sample App](../images/vsx-images/n15vsxsa-c.png) + +When loading the sample application, you'll be notified that it will create plain text secrets to authenticate on your local machine. + +![sample app plain text secrets notice](../images/vsx-images/sample-app-app-secrets-notice.png) + +If no client secret is found on your application, it will ask if you would like to create one. Press OK to proceed. + +![sample app creating client secret](../images/vsx-images/sample-app-create-client-secret.png) + +> [!IMPORTANT] +> This isn't intended for production environments. [Find out more on how to setup Application Registration for production environments here.](/entra/identity-platform/quickstart-register-app) + +## Using Sample App + +In your terminal, run the following command, this will start the sample application, which consists of 2 parts: + +1. **React Client Application** - The frontend user interface running on port 8080 +1. **Azure Function Application Server** - The backend API server that handles SharePoint Embedded operations + +```console +# Navigate to your sample application directory +cd [your-path]\SharePoint-Embedded-Samples\Samples\spe-typescript-react-azurefunction + +# Install dependencies and start the application +npm run start +``` + +> [!NOTE] +> The initial startup may take a few minutes as dependencies are installed and both applications are built. Wait for both console outputs to appear before navigating to the application. + +This will install the dependencies and run the server and client application, once running, you'll see the following in the terminal, after which you can navigate to http://localhost:8080 to access the application. + +![function api console logs](../images/vsx-images/fn-api-logs.png) + +![client app console logs](../images/vsx-images/client-app-logs.png) + +Once both applications are running successfully: + +1. Open your web browser and navigate to **http://localhost:8080** +1. Sign in using your Microsoft 365 administrator account (the same account used in the VS Code extension) +1. On the home page, select **"Containers"** to begin creating containers and uploading files +1. Follow the on-screen prompts to interact with your SharePoint Embedded containers + +![home-page-for-spe-sample-app](../images/vsx-images/spe-sample-app-home.png) + +> [!IMPORTANT] +> This sample application stores authentication secrets in plain text for development purposes only. Never use this configuration in a production environment. + +### Troubleshooting + +If you encounter issues: + +- **Port already in use**: If port 8080 is already in use, the application will automatically try the next available port +- **Dependencies not installing**: Try running `npm install` manually before `npm run start` +- **Authentication errors**: Ensure your Microsoft Entra ID app is properly configured with the correct redirect URIs + +## Export Postman Environment + +The [SharePoint Embedded Postman Collection](https://github.com/microsoft/SharePoint-Embedded-Samples/tree/main/Postman) allows you to explore and call the SharePoint Embedded APIs. The Collection requires an environment file with variables used for authentication and various identifiers. This extension automates the generation of this populated environment file so you can import it into Postal worker and immediately call the SharePoint Embedded APIs. + +![Export Postman Environment](../images/vsx-images/n14postman-c.png) diff --git a/docs/embedded/images/1bill521.png b/docs/embedded/images/1bill521.png new file mode 100644 index 000000000..6528d71c3 Binary files /dev/null and b/docs/embedded/images/1bill521.png differ diff --git a/docs/embedded/images/2bill521.png b/docs/embedded/images/2bill521.png new file mode 100644 index 000000000..d4dfc162b Binary files /dev/null and b/docs/embedded/images/2bill521.png differ diff --git a/docs/embedded/images/DTCBilling1.png b/docs/embedded/images/DTCBilling1.png new file mode 100644 index 000000000..6a24fa4b5 Binary files /dev/null and b/docs/embedded/images/DTCBilling1.png differ diff --git a/docs/embedded/images/DTCBilling2.png b/docs/embedded/images/DTCBilling2.png new file mode 100644 index 000000000..b4c7318b9 Binary files /dev/null and b/docs/embedded/images/DTCBilling2.png differ diff --git a/docs/embedded/images/Document-Processing.png b/docs/embedded/images/Document-Processing.png new file mode 100644 index 000000000..7982dba53 Binary files /dev/null and b/docs/embedded/images/Document-Processing.png differ diff --git a/docs/embedded/images/SPEAdmin1.png b/docs/embedded/images/SPEAdmin1.png new file mode 100644 index 000000000..87c3a1fa8 Binary files /dev/null and b/docs/embedded/images/SPEAdmin1.png differ diff --git a/docs/embedded/images/SPEAdmin10.png b/docs/embedded/images/SPEAdmin10.png new file mode 100644 index 000000000..9f5feab08 Binary files /dev/null and b/docs/embedded/images/SPEAdmin10.png differ diff --git a/docs/embedded/images/SPEAdmin11.png b/docs/embedded/images/SPEAdmin11.png new file mode 100644 index 000000000..1027fc70a Binary files /dev/null and b/docs/embedded/images/SPEAdmin11.png differ diff --git a/docs/embedded/images/SPEAdmin12.png b/docs/embedded/images/SPEAdmin12.png new file mode 100644 index 000000000..102e0dacf Binary files /dev/null and b/docs/embedded/images/SPEAdmin12.png differ diff --git a/docs/embedded/images/SPEAdmin13.png b/docs/embedded/images/SPEAdmin13.png new file mode 100644 index 000000000..83d556813 Binary files /dev/null and b/docs/embedded/images/SPEAdmin13.png differ diff --git a/docs/embedded/images/SPEAdmin14.png b/docs/embedded/images/SPEAdmin14.png new file mode 100644 index 000000000..dc66703b5 Binary files /dev/null and b/docs/embedded/images/SPEAdmin14.png differ diff --git a/docs/embedded/images/SPEAdmin15.png b/docs/embedded/images/SPEAdmin15.png new file mode 100644 index 000000000..4a3f80cdb Binary files /dev/null and b/docs/embedded/images/SPEAdmin15.png differ diff --git a/docs/embedded/images/SPEAdmin16.png b/docs/embedded/images/SPEAdmin16.png new file mode 100644 index 000000000..03568e615 Binary files /dev/null and b/docs/embedded/images/SPEAdmin16.png differ diff --git a/docs/embedded/images/SPEAdmin2.png b/docs/embedded/images/SPEAdmin2.png new file mode 100644 index 000000000..8be14b0b4 Binary files /dev/null and b/docs/embedded/images/SPEAdmin2.png differ diff --git a/docs/embedded/images/SPEAdmin3.png b/docs/embedded/images/SPEAdmin3.png new file mode 100644 index 000000000..010bf998b Binary files /dev/null and b/docs/embedded/images/SPEAdmin3.png differ diff --git a/docs/embedded/images/SPEAdmin4.png b/docs/embedded/images/SPEAdmin4.png new file mode 100644 index 000000000..26b05d149 Binary files /dev/null and b/docs/embedded/images/SPEAdmin4.png differ diff --git a/docs/embedded/images/SPEAdmin5.png b/docs/embedded/images/SPEAdmin5.png new file mode 100644 index 000000000..b82c2bbfc Binary files /dev/null and b/docs/embedded/images/SPEAdmin5.png differ diff --git a/docs/embedded/images/SPEAdmin6.png b/docs/embedded/images/SPEAdmin6.png new file mode 100644 index 000000000..e80422388 Binary files /dev/null and b/docs/embedded/images/SPEAdmin6.png differ diff --git a/docs/embedded/images/SPEAdmin7.png b/docs/embedded/images/SPEAdmin7.png new file mode 100644 index 000000000..1b97c3acb Binary files /dev/null and b/docs/embedded/images/SPEAdmin7.png differ diff --git a/docs/embedded/images/SPEAdmin8.png b/docs/embedded/images/SPEAdmin8.png new file mode 100644 index 000000000..62cd5b268 Binary files /dev/null and b/docs/embedded/images/SPEAdmin8.png differ diff --git a/docs/embedded/images/SPEAdmin9.png b/docs/embedded/images/SPEAdmin9.png new file mode 100644 index 000000000..08a6f7120 Binary files /dev/null and b/docs/embedded/images/SPEAdmin9.png differ diff --git a/docs/embedded/images/SPEArch.png b/docs/embedded/images/SPEArch.png new file mode 100644 index 000000000..cb0818e3f Binary files /dev/null and b/docs/embedded/images/SPEArch.png differ diff --git a/docs/embedded/images/SPECTDedicated.png b/docs/embedded/images/SPECTDedicated.png new file mode 100644 index 000000000..67b94e68c Binary files /dev/null and b/docs/embedded/images/SPECTDedicated.png differ diff --git a/docs/embedded/images/SPECTShared.png b/docs/embedded/images/SPECTShared.png new file mode 100644 index 000000000..bcc4de7e8 Binary files /dev/null and b/docs/embedded/images/SPECTShared.png differ diff --git a/docs/embedded/images/SharePointEmbeddedToS-1.jpg b/docs/embedded/images/SharePointEmbeddedToS-1.jpg new file mode 100644 index 000000000..03777613c Binary files /dev/null and b/docs/embedded/images/SharePointEmbeddedToS-1.jpg differ diff --git a/docs/embedded/images/SharePointEmbeddedToS-2.jpg b/docs/embedded/images/SharePointEmbeddedToS-2.jpg new file mode 100644 index 000000000..c7196e505 Binary files /dev/null and b/docs/embedded/images/SharePointEmbeddedToS-2.jpg differ diff --git a/docs/embedded/images/SharePointEmbeddedToS-3.jpg b/docs/embedded/images/SharePointEmbeddedToS-3.jpg new file mode 100644 index 000000000..e7fb61050 Binary files /dev/null and b/docs/embedded/images/SharePointEmbeddedToS-3.jpg differ diff --git a/docs/embedded/images/SharePointEmbeddedToS-4.jpg b/docs/embedded/images/SharePointEmbeddedToS-4.jpg new file mode 100644 index 000000000..0d29fbfd4 Binary files /dev/null and b/docs/embedded/images/SharePointEmbeddedToS-4.jpg differ diff --git a/docs/embedded/images/SharePointEmbeddedToS-5.jpg b/docs/embedded/images/SharePointEmbeddedToS-5.jpg new file mode 100644 index 000000000..e09f5cd1c Binary files /dev/null and b/docs/embedded/images/SharePointEmbeddedToS-5.jpg differ diff --git a/docs/embedded/images/SharingPartitions.png b/docs/embedded/images/SharingPartitions.png new file mode 100644 index 000000000..5b3b4bd66 Binary files /dev/null and b/docs/embedded/images/SharingPartitions.png differ diff --git a/docs/embedded/images/SyntexActivatePAYGSetup.png b/docs/embedded/images/SyntexActivatePAYGSetup.png new file mode 100644 index 000000000..00147f57b Binary files /dev/null and b/docs/embedded/images/SyntexActivatePAYGSetup.png differ diff --git a/docs/embedded/images/SyntexPAYGActivateSPE.png b/docs/embedded/images/SyntexPAYGActivateSPE.png new file mode 100644 index 000000000..739a58a47 Binary files /dev/null and b/docs/embedded/images/SyntexPAYGActivateSPE.png differ diff --git a/docs/embedded/images/Using-Webhooks.png b/docs/embedded/images/Using-Webhooks.png new file mode 100644 index 000000000..5d98224cf Binary files /dev/null and b/docs/embedded/images/Using-Webhooks.png differ diff --git a/docs/embedded/images/add-owners-one.png b/docs/embedded/images/add-owners-one.png new file mode 100644 index 000000000..bba134252 Binary files /dev/null and b/docs/embedded/images/add-owners-one.png differ diff --git a/docs/embedded/images/add-owners-two.png b/docs/embedded/images/add-owners-two.png new file mode 100644 index 000000000..fe7af04ed Binary files /dev/null and b/docs/embedded/images/add-owners-two.png differ diff --git a/docs/embedded/images/app-arch.png b/docs/embedded/images/app-arch.png new file mode 100644 index 000000000..0129f6719 Binary files /dev/null and b/docs/embedded/images/app-arch.png differ diff --git a/docs/embedded/images/app-flow7.jpg b/docs/embedded/images/app-flow7.jpg new file mode 100644 index 000000000..cbf6f4801 Binary files /dev/null and b/docs/embedded/images/app-flow7.jpg differ diff --git a/docs/embedded/images/app-registration-console-platform.png b/docs/embedded/images/app-registration-console-platform.png new file mode 100644 index 000000000..177c0bc5a Binary files /dev/null and b/docs/embedded/images/app-registration-console-platform.png differ diff --git a/docs/embedded/images/apparc-1.png b/docs/embedded/images/apparc-1.png new file mode 100644 index 000000000..082e51788 Binary files /dev/null and b/docs/embedded/images/apparc-1.png differ diff --git a/docs/embedded/images/apparc-2.png b/docs/embedded/images/apparc-2.png new file mode 100644 index 000000000..7f8a72df8 Binary files /dev/null and b/docs/embedded/images/apparc-2.png differ diff --git a/docs/embedded/images/apparchexample.png b/docs/embedded/images/apparchexample.png new file mode 100644 index 000000000..f862809ad Binary files /dev/null and b/docs/embedded/images/apparchexample.png differ diff --git a/docs/embedded/images/architecture-overview.png b/docs/embedded/images/architecture-overview.png new file mode 100644 index 000000000..b815cb4cd Binary files /dev/null and b/docs/embedded/images/architecture-overview.png differ diff --git a/docs/embedded/images/billing-1.png b/docs/embedded/images/billing-1.png new file mode 100644 index 000000000..14eb0f29a Binary files /dev/null and b/docs/embedded/images/billing-1.png differ diff --git a/docs/embedded/images/billing-2.png b/docs/embedded/images/billing-2.png new file mode 100644 index 000000000..669b0642a Binary files /dev/null and b/docs/embedded/images/billing-2.png differ diff --git a/docs/embedded/images/billing-manage.png b/docs/embedded/images/billing-manage.png new file mode 100644 index 000000000..014db7f05 Binary files /dev/null and b/docs/embedded/images/billing-manage.png differ diff --git a/docs/embedded/images/billmanag1.png b/docs/embedded/images/billmanag1.png new file mode 100644 index 000000000..bebe7f8b9 Binary files /dev/null and b/docs/embedded/images/billmanag1.png differ diff --git a/docs/embedded/images/billmanag2.png b/docs/embedded/images/billmanag2.png new file mode 100644 index 000000000..1bca53b4f Binary files /dev/null and b/docs/embedded/images/billmanag2.png differ diff --git a/docs/embedded/images/billmanag3.png b/docs/embedded/images/billmanag3.png new file mode 100644 index 000000000..2ac8dd97b Binary files /dev/null and b/docs/embedded/images/billmanag3.png differ diff --git a/docs/embedded/images/ctaux1.png b/docs/embedded/images/ctaux1.png new file mode 100644 index 000000000..c5ff77540 Binary files /dev/null and b/docs/embedded/images/ctaux1.png differ diff --git a/docs/embedded/images/ctaux10.png b/docs/embedded/images/ctaux10.png new file mode 100644 index 000000000..d60b84e5d Binary files /dev/null and b/docs/embedded/images/ctaux10.png differ diff --git a/docs/embedded/images/ctaux11.png b/docs/embedded/images/ctaux11.png new file mode 100644 index 000000000..01dc83bc0 Binary files /dev/null and b/docs/embedded/images/ctaux11.png differ diff --git a/docs/embedded/images/ctaux12.png b/docs/embedded/images/ctaux12.png new file mode 100644 index 000000000..b7f53ffed Binary files /dev/null and b/docs/embedded/images/ctaux12.png differ diff --git a/docs/embedded/images/ctaux13.png b/docs/embedded/images/ctaux13.png new file mode 100644 index 000000000..e77fd7b11 Binary files /dev/null and b/docs/embedded/images/ctaux13.png differ diff --git a/docs/embedded/images/ctaux14.png b/docs/embedded/images/ctaux14.png new file mode 100644 index 000000000..b62786140 Binary files /dev/null and b/docs/embedded/images/ctaux14.png differ diff --git a/docs/embedded/images/ctaux15-n.png b/docs/embedded/images/ctaux15-n.png new file mode 100644 index 000000000..c534fae69 Binary files /dev/null and b/docs/embedded/images/ctaux15-n.png differ diff --git a/docs/embedded/images/ctaux2.png b/docs/embedded/images/ctaux2.png new file mode 100644 index 000000000..3c5dac782 Binary files /dev/null and b/docs/embedded/images/ctaux2.png differ diff --git a/docs/embedded/images/ctaux3.png b/docs/embedded/images/ctaux3.png new file mode 100644 index 000000000..88728dc03 Binary files /dev/null and b/docs/embedded/images/ctaux3.png differ diff --git a/docs/embedded/images/ctaux4.png b/docs/embedded/images/ctaux4.png new file mode 100644 index 000000000..5c06e1b4f Binary files /dev/null and b/docs/embedded/images/ctaux4.png differ diff --git a/docs/embedded/images/ctaux5.png b/docs/embedded/images/ctaux5.png new file mode 100644 index 000000000..4ca1d7238 Binary files /dev/null and b/docs/embedded/images/ctaux5.png differ diff --git a/docs/embedded/images/ctaux6.png b/docs/embedded/images/ctaux6.png new file mode 100644 index 000000000..ab0b73ff8 Binary files /dev/null and b/docs/embedded/images/ctaux6.png differ diff --git a/docs/embedded/images/ctaux7.png b/docs/embedded/images/ctaux7.png new file mode 100644 index 000000000..d5f841cc6 Binary files /dev/null and b/docs/embedded/images/ctaux7.png differ diff --git a/docs/embedded/images/ctaux8.png b/docs/embedded/images/ctaux8.png new file mode 100644 index 000000000..48e3c9b4e Binary files /dev/null and b/docs/embedded/images/ctaux8.png differ diff --git a/docs/embedded/images/ctaux9.png b/docs/embedded/images/ctaux9.png new file mode 100644 index 000000000..233cded62 Binary files /dev/null and b/docs/embedded/images/ctaux9.png differ diff --git a/docs/embedded/images/enable1.png b/docs/embedded/images/enable1.png new file mode 100644 index 000000000..e6f7a30d3 Binary files /dev/null and b/docs/embedded/images/enable1.png differ diff --git a/docs/embedded/images/enable2.png b/docs/embedded/images/enable2.png new file mode 100644 index 000000000..d3bcbbfa2 Binary files /dev/null and b/docs/embedded/images/enable2.png differ diff --git a/docs/embedded/images/enable3.png b/docs/embedded/images/enable3.png new file mode 100644 index 000000000..52f0cd78e Binary files /dev/null and b/docs/embedded/images/enable3.png differ diff --git a/docs/embedded/images/enable4.png b/docs/embedded/images/enable4.png new file mode 100644 index 000000000..3bd2d76ee Binary files /dev/null and b/docs/embedded/images/enable4.png differ diff --git a/docs/embedded/images/enable5.png b/docs/embedded/images/enable5.png new file mode 100644 index 000000000..ec852a6ce Binary files /dev/null and b/docs/embedded/images/enable5.png differ diff --git a/docs/embedded/images/featuretbl.png b/docs/embedded/images/featuretbl.png new file mode 100644 index 000000000..e2cf7c5df Binary files /dev/null and b/docs/embedded/images/featuretbl.png differ diff --git a/docs/embedded/images/filter-on-delete.png b/docs/embedded/images/filter-on-delete.png new file mode 100644 index 000000000..87599873d Binary files /dev/null and b/docs/embedded/images/filter-on-delete.png differ diff --git a/docs/embedded/images/filter.png b/docs/embedded/images/filter.png new file mode 100644 index 000000000..6f1eacbeb Binary files /dev/null and b/docs/embedded/images/filter.png differ diff --git a/docs/embedded/images/itemcount.png b/docs/embedded/images/itemcount.png new file mode 100644 index 000000000..5ceb712fe Binary files /dev/null and b/docs/embedded/images/itemcount.png differ diff --git a/docs/embedded/images/ngrok-registration.png b/docs/embedded/images/ngrok-registration.png new file mode 100644 index 000000000..86c133609 Binary files /dev/null and b/docs/embedded/images/ngrok-registration.png differ diff --git a/docs/embedded/images/office1.png b/docs/embedded/images/office1.png new file mode 100644 index 000000000..8ff7d3ba9 Binary files /dev/null and b/docs/embedded/images/office1.png differ diff --git a/docs/embedded/images/office2.png b/docs/embedded/images/office2.png new file mode 100644 index 000000000..3753f7c67 Binary files /dev/null and b/docs/embedded/images/office2.png differ diff --git a/docs/embedded/images/raasflow.png b/docs/embedded/images/raasflow.png new file mode 100644 index 000000000..a23fd1eff Binary files /dev/null and b/docs/embedded/images/raasflow.png differ diff --git a/docs/embedded/images/raaspic2.png b/docs/embedded/images/raaspic2.png new file mode 100644 index 000000000..bd77feabc Binary files /dev/null and b/docs/embedded/images/raaspic2.png differ diff --git a/docs/embedded/images/reassign-user.png b/docs/embedded/images/reassign-user.png new file mode 100644 index 000000000..5ae1447ed Binary files /dev/null and b/docs/embedded/images/reassign-user.png differ diff --git a/docs/embedded/images/remove-user.png b/docs/embedded/images/remove-user.png new file mode 100644 index 000000000..ffa8d357a Binary files /dev/null and b/docs/embedded/images/remove-user.png differ diff --git a/docs/embedded/images/sc1.png b/docs/embedded/images/sc1.png new file mode 100644 index 000000000..7e284f0a5 Binary files /dev/null and b/docs/embedded/images/sc1.png differ diff --git a/docs/embedded/images/sc2.png b/docs/embedded/images/sc2.png new file mode 100644 index 000000000..f621f6df3 Binary files /dev/null and b/docs/embedded/images/sc2.png differ diff --git a/docs/embedded/images/sc3.png b/docs/embedded/images/sc3.png new file mode 100644 index 000000000..62e1623f4 Binary files /dev/null and b/docs/embedded/images/sc3.png differ diff --git a/docs/embedded/images/sc4.png b/docs/embedded/images/sc4.png new file mode 100644 index 000000000..285aa9dad Binary files /dev/null and b/docs/embedded/images/sc4.png differ diff --git a/docs/embedded/images/sc5.png b/docs/embedded/images/sc5.png new file mode 100644 index 000000000..5fb5d3ae5 Binary files /dev/null and b/docs/embedded/images/sc5.png differ diff --git a/docs/embedded/images/sc6.png b/docs/embedded/images/sc6.png new file mode 100644 index 000000000..98fc406ed Binary files /dev/null and b/docs/embedded/images/sc6.png differ diff --git a/docs/embedded/images/sc7.png b/docs/embedded/images/sc7.png new file mode 100644 index 000000000..fb4038ad6 Binary files /dev/null and b/docs/embedded/images/sc7.png differ diff --git a/docs/embedded/images/search.png b/docs/embedded/images/search.png new file mode 100644 index 000000000..02c1c3ffc Binary files /dev/null and b/docs/embedded/images/search.png differ diff --git a/docs/embedded/images/sensitivity-label.png b/docs/embedded/images/sensitivity-label.png new file mode 100644 index 000000000..5180a30a0 Binary files /dev/null and b/docs/embedded/images/sensitivity-label.png differ diff --git a/docs/embedded/images/sorting-on-deleted.png b/docs/embedded/images/sorting-on-deleted.png new file mode 100644 index 000000000..961e81d55 Binary files /dev/null and b/docs/embedded/images/sorting-on-deleted.png differ diff --git a/docs/embedded/images/sorting.png b/docs/embedded/images/sorting.png new file mode 100644 index 000000000..3f495f85c Binary files /dev/null and b/docs/embedded/images/sorting.png differ diff --git a/docs/embedded/images/spe-vscode-marketplace.png b/docs/embedded/images/spe-vscode-marketplace.png new file mode 100644 index 000000000..ac9a383b6 Binary files /dev/null and b/docs/embedded/images/spe-vscode-marketplace.png differ diff --git a/docs/embedded/images/speco-apparch.png b/docs/embedded/images/speco-apparch.png new file mode 100644 index 000000000..ec05874da Binary files /dev/null and b/docs/embedded/images/speco-apparch.png differ diff --git a/docs/embedded/images/speco-appscopingvenn.png b/docs/embedded/images/speco-appscopingvenn.png new file mode 100644 index 000000000..d5727486a Binary files /dev/null and b/docs/embedded/images/speco-appscopingvenn.png differ diff --git a/docs/embedded/images/speco-bound.png b/docs/embedded/images/speco-bound.png new file mode 100644 index 000000000..8f3cff455 Binary files /dev/null and b/docs/embedded/images/speco-bound.png differ diff --git a/docs/embedded/images/speco-cloneproject.png b/docs/embedded/images/speco-cloneproject.png new file mode 100644 index 000000000..4573bdc74 Binary files /dev/null and b/docs/embedded/images/speco-cloneproject.png differ diff --git a/docs/embedded/images/speco-createappsecret.png b/docs/embedded/images/speco-createappsecret.png new file mode 100644 index 000000000..b283b8259 Binary files /dev/null and b/docs/embedded/images/speco-createappsecret.png differ diff --git a/docs/embedded/images/speco-createclientsecret.png b/docs/embedded/images/speco-createclientsecret.png new file mode 100644 index 000000000..37cf20e57 Binary files /dev/null and b/docs/embedded/images/speco-createclientsecret.png differ diff --git a/docs/embedded/images/speco-createcontosocontainer2.png b/docs/embedded/images/speco-createcontosocontainer2.png new file mode 100644 index 000000000..995cd7f88 Binary files /dev/null and b/docs/embedded/images/speco-createcontosocontainer2.png differ diff --git a/docs/embedded/images/speco-createdcontainer.png b/docs/embedded/images/speco-createdcontainer.png new file mode 100644 index 000000000..e429321c4 Binary files /dev/null and b/docs/embedded/images/speco-createdcontainer.png differ diff --git a/docs/embedded/images/speco-feedbackcombined.png b/docs/embedded/images/speco-feedbackcombined.png new file mode 100644 index 000000000..c3d95ef63 Binary files /dev/null and b/docs/embedded/images/speco-feedbackcombined.png differ diff --git a/docs/embedded/images/speco-feedbackmodal.png b/docs/embedded/images/speco-feedbackmodal.png new file mode 100644 index 000000000..ef3b9ab51 Binary files /dev/null and b/docs/embedded/images/speco-feedbackmodal.png differ diff --git a/docs/embedded/images/speco-feedbackthumbsdown.png b/docs/embedded/images/speco-feedbackthumbsdown.png new file mode 100644 index 000000000..d9e3bd0f5 Binary files /dev/null and b/docs/embedded/images/speco-feedbackthumbsdown.png differ diff --git a/docs/embedded/images/speco-ragai.png b/docs/embedded/images/speco-ragai.png new file mode 100644 index 000000000..28b3f3eac Binary files /dev/null and b/docs/embedded/images/speco-ragai.png differ diff --git a/docs/embedded/images/speco-ragm365.png b/docs/embedded/images/speco-ragm365.png new file mode 100644 index 000000000..17a016ff8 Binary files /dev/null and b/docs/embedded/images/speco-ragm365.png differ diff --git a/docs/embedded/images/speco-ragquery.png b/docs/embedded/images/speco-ragquery.png new file mode 100644 index 000000000..b8a52311b Binary files /dev/null and b/docs/embedded/images/speco-ragquery.png differ diff --git a/docs/embedded/images/speco-reacttypescripthomepage.png b/docs/embedded/images/speco-reacttypescripthomepage.png new file mode 100644 index 000000000..b25861791 Binary files /dev/null and b/docs/embedded/images/speco-reacttypescripthomepage.png differ diff --git a/docs/embedded/images/speco-runnpmrunstart.png b/docs/embedded/images/speco-runnpmrunstart.png new file mode 100644 index 000000000..1f26f6395 Binary files /dev/null and b/docs/embedded/images/speco-runnpmrunstart.png differ diff --git a/docs/embedded/images/speco-runsampleapp.png b/docs/embedded/images/speco-runsampleapp.png new file mode 100644 index 000000000..3d3341eaf Binary files /dev/null and b/docs/embedded/images/speco-runsampleapp.png differ diff --git a/docs/embedded/images/speco-setshowsidebartrue.png b/docs/embedded/images/speco-setshowsidebartrue.png new file mode 100644 index 000000000..2b73eac96 Binary files /dev/null and b/docs/embedded/images/speco-setshowsidebartrue.png differ diff --git a/docs/embedded/images/speco-spechatenabled.png b/docs/embedded/images/speco-spechatenabled.png new file mode 100644 index 000000000..87f35bb1b Binary files /dev/null and b/docs/embedded/images/speco-spechatenabled.png differ diff --git a/docs/embedded/images/speco-uncommentchatsidebar.png b/docs/embedded/images/speco-uncommentchatsidebar.png new file mode 100644 index 000000000..ccc7cfd46 Binary files /dev/null and b/docs/embedded/images/speco-uncommentchatsidebar.png differ diff --git a/docs/embedded/images/speco-vscodeclonedproject.png b/docs/embedded/images/speco-vscodeclonedproject.png new file mode 100644 index 000000000..c88e78db4 Binary files /dev/null and b/docs/embedded/images/speco-vscodeclonedproject.png differ diff --git a/docs/embedded/images/speco-vscodeextensiondisablediscovery.png b/docs/embedded/images/speco-vscodeextensiondisablediscovery.png new file mode 100644 index 000000000..d1c9d63d2 Binary files /dev/null and b/docs/embedded/images/speco-vscodeextensiondisablediscovery.png differ diff --git a/docs/embedded/images/vscodeconsentperms.png b/docs/embedded/images/vscodeconsentperms.png new file mode 100644 index 000000000..05d708775 Binary files /dev/null and b/docs/embedded/images/vscodeconsentperms.png differ diff --git a/docs/embedded/images/vscodecontcreate.png b/docs/embedded/images/vscodecontcreate.png new file mode 100644 index 000000000..df87b340f Binary files /dev/null and b/docs/embedded/images/vscodecontcreate.png differ diff --git a/docs/embedded/images/vscodecontname.png b/docs/embedded/images/vscodecontname.png new file mode 100644 index 000000000..9b2c6d17a Binary files /dev/null and b/docs/embedded/images/vscodecontname.png differ diff --git a/docs/embedded/images/vscodeinstall.png b/docs/embedded/images/vscodeinstall.png new file mode 100644 index 000000000..68ea5d36c Binary files /dev/null and b/docs/embedded/images/vscodeinstall.png differ diff --git a/docs/embedded/images/vscodelaunch.png b/docs/embedded/images/vscodelaunch.png new file mode 100644 index 000000000..50ada3175 Binary files /dev/null and b/docs/embedded/images/vscodelaunch.png differ diff --git a/docs/embedded/images/vscodelogin.png b/docs/embedded/images/vscodelogin.png new file mode 100644 index 000000000..b6921c523 Binary files /dev/null and b/docs/embedded/images/vscodelogin.png differ diff --git a/docs/embedded/images/vscoderegister.png b/docs/embedded/images/vscoderegister.png new file mode 100644 index 000000000..5cfb6fb43 Binary files /dev/null and b/docs/embedded/images/vscoderegister.png differ diff --git a/docs/embedded/images/vscodetree.png b/docs/embedded/images/vscodetree.png new file mode 100644 index 000000000..3d7337b18 Binary files /dev/null and b/docs/embedded/images/vscodetree.png differ diff --git a/docs/embedded/images/vsx-images/auth-allow-extension-uri.png b/docs/embedded/images/vsx-images/auth-allow-extension-uri.png new file mode 100644 index 000000000..f71029396 Binary files /dev/null and b/docs/embedded/images/vsx-images/auth-allow-extension-uri.png differ diff --git a/docs/embedded/images/vsx-images/auth-grant-admin-consent-popup.png b/docs/embedded/images/vsx-images/auth-grant-admin-consent-popup.png new file mode 100644 index 000000000..a8b8485e7 Binary files /dev/null and b/docs/embedded/images/vsx-images/auth-grant-admin-consent-popup.png differ diff --git a/docs/embedded/images/vsx-images/auth-redirect.png b/docs/embedded/images/vsx-images/auth-redirect.png new file mode 100644 index 000000000..ee09cc6bb Binary files /dev/null and b/docs/embedded/images/vsx-images/auth-redirect.png differ diff --git a/docs/embedded/images/vsx-images/client-app-logs.png b/docs/embedded/images/vsx-images/client-app-logs.png new file mode 100644 index 000000000..61c81ce0f Binary files /dev/null and b/docs/embedded/images/vsx-images/client-app-logs.png differ diff --git a/docs/embedded/images/vsx-images/fn-api-logs.png b/docs/embedded/images/vsx-images/fn-api-logs.png new file mode 100644 index 000000000..dc0263c40 Binary files /dev/null and b/docs/embedded/images/vsx-images/fn-api-logs.png differ diff --git a/docs/embedded/images/vsx-images/local-tenant-registration-popup.png b/docs/embedded/images/vsx-images/local-tenant-registration-popup.png new file mode 100644 index 000000000..e233afcf7 Binary files /dev/null and b/docs/embedded/images/vsx-images/local-tenant-registration-popup.png differ diff --git a/docs/embedded/images/vsx-images/n10acreate-container.png b/docs/embedded/images/vsx-images/n10acreate-container.png new file mode 100644 index 000000000..6be23f1cc Binary files /dev/null and b/docs/embedded/images/vsx-images/n10acreate-container.png differ diff --git a/docs/embedded/images/vsx-images/n11aname-first-cont.png b/docs/embedded/images/vsx-images/n11aname-first-cont.png new file mode 100644 index 000000000..3a184eb9c Binary files /dev/null and b/docs/embedded/images/vsx-images/n11aname-first-cont.png differ diff --git a/docs/embedded/images/vsx-images/n12arecycle-cont.png b/docs/embedded/images/vsx-images/n12arecycle-cont.png new file mode 100644 index 000000000..6c26b1b20 Binary files /dev/null and b/docs/embedded/images/vsx-images/n12arecycle-cont.png differ diff --git a/docs/embedded/images/vsx-images/n13a-final-home-page.png b/docs/embedded/images/vsx-images/n13a-final-home-page.png new file mode 100644 index 000000000..bb77e35ed Binary files /dev/null and b/docs/embedded/images/vsx-images/n13a-final-home-page.png differ diff --git a/docs/embedded/images/vsx-images/n14postman-c.png b/docs/embedded/images/vsx-images/n14postman-c.png new file mode 100644 index 000000000..86d9b8a80 Binary files /dev/null and b/docs/embedded/images/vsx-images/n14postman-c.png differ diff --git a/docs/embedded/images/vsx-images/n15vsxsa-c.png b/docs/embedded/images/vsx-images/n15vsxsa-c.png new file mode 100644 index 000000000..6391443a2 Binary files /dev/null and b/docs/embedded/images/vsx-images/n15vsxsa-c.png differ diff --git a/docs/embedded/images/vsx-images/n1downloadvsx.png b/docs/embedded/images/vsx-images/n1downloadvsx.png new file mode 100644 index 000000000..94229faf7 Binary files /dev/null and b/docs/embedded/images/vsx-images/n1downloadvsx.png differ diff --git a/docs/embedded/images/vsx-images/n2vsx-signin.png b/docs/embedded/images/vsx-images/n2vsx-signin.png new file mode 100644 index 000000000..fa78d61e6 Binary files /dev/null and b/docs/embedded/images/vsx-images/n2vsx-signin.png differ diff --git a/docs/embedded/images/vsx-images/n3vsx-grant-admin-consent.png b/docs/embedded/images/vsx-images/n3vsx-grant-admin-consent.png new file mode 100644 index 000000000..c6cfd5cdc Binary files /dev/null and b/docs/embedded/images/vsx-images/n3vsx-grant-admin-consent.png differ diff --git a/docs/embedded/images/vsx-images/n4vsx-home-screen.png b/docs/embedded/images/vsx-images/n4vsx-home-screen.png new file mode 100644 index 000000000..6b9a85cae Binary files /dev/null and b/docs/embedded/images/vsx-images/n4vsx-home-screen.png differ diff --git a/docs/embedded/images/vsx-images/n5a-name-ct.png b/docs/embedded/images/vsx-images/n5a-name-ct.png new file mode 100644 index 000000000..aca25d3a8 Binary files /dev/null and b/docs/embedded/images/vsx-images/n5a-name-ct.png differ diff --git a/docs/embedded/images/vsx-images/n6aname-app.png b/docs/embedded/images/vsx-images/n6aname-app.png new file mode 100644 index 000000000..d58360b2a Binary files /dev/null and b/docs/embedded/images/vsx-images/n6aname-app.png differ diff --git a/docs/embedded/images/vsx-images/n7aregister-ct.png b/docs/embedded/images/vsx-images/n7aregister-ct.png new file mode 100644 index 000000000..9ae83ca19 Binary files /dev/null and b/docs/embedded/images/vsx-images/n7aregister-ct.png differ diff --git a/docs/embedded/images/vsx-images/n9alogin-grant-permissions.png b/docs/embedded/images/vsx-images/n9alogin-grant-permissions.png new file mode 100644 index 000000000..a5cdd7fe2 Binary files /dev/null and b/docs/embedded/images/vsx-images/n9alogin-grant-permissions.png differ diff --git a/docs/embedded/images/vsx-images/sample-app-app-secrets-notice.png b/docs/embedded/images/vsx-images/sample-app-app-secrets-notice.png new file mode 100644 index 000000000..1ade7d0fb Binary files /dev/null and b/docs/embedded/images/vsx-images/sample-app-app-secrets-notice.png differ diff --git a/docs/embedded/images/vsx-images/sample-app-create-client-secret.png b/docs/embedded/images/vsx-images/sample-app-create-client-secret.png new file mode 100644 index 000000000..2bddaef4f Binary files /dev/null and b/docs/embedded/images/vsx-images/sample-app-create-client-secret.png differ diff --git a/docs/embedded/images/vsx-images/spe-sample-app-home.png b/docs/embedded/images/vsx-images/spe-sample-app-home.png new file mode 100644 index 000000000..575c8da11 Binary files /dev/null and b/docs/embedded/images/vsx-images/spe-sample-app-home.png differ diff --git a/docs/embedded/overview.md b/docs/embedded/overview.md new file mode 100644 index 000000000..9f707d52e --- /dev/null +++ b/docs/embedded/overview.md @@ -0,0 +1,72 @@ +--- +title: SharePoint Embedded Overview +description: Microsoft SharePoint Embedded is a cloud-based file and document management system suitable for use in any application. SharePoint Embedded is a new API-only solution that enables app developers to harness the power of the Microsoft 365 file and document storage platform for any app, and is suitable for enterprises building line-of-business applications and ISVs building multitenant applications. +ms.date: 08/17/2024 +ms.localizationpriority: high +--- + +# Overview of SharePoint Embedded + +Microsoft SharePoint Embedded is a cloud-based file and document management system suitable for use in any application. SharePoint Embedded is a new API-only solution that enables app developers to harness the power of the Microsoft 365 file and document storage platform for any app, and is suitable for enterprises building line-of-business applications and ISVs building multitenant applications. + +SharePoint Embedded allows you to integrate advanced Microsoft 365 features into your apps including full-featured collaborative functions from Office, Purview's security and compliance tools, and Copilot capabilities. + +> [!IMPORTANT] +> Help us shape the future of SharePoint Embedded! +> Take our [quick survey](https://forms.microsoft.com/r/1YpGd2pAUS) and share your experience! + +## App documents stay in their Microsoft 365 tenant + +When a consumer uses a SharePoint Embedded application in their Microsoft 365 tenant, SharePoint Embedded creates another partition within their tenant. This storage partition doesn't have a user experience and the documents in the partition are only accessible via APIs. This means that all documents will be accessible to the developer’s application, but the documents will only reside in the consumer’s Microsoft 365 tenant. Within this new storage partition inside of a Microsoft 365 tenant, a SharePoint Embedded application can create many "File Storage Containers" for storing content. + +## Introducing File Storage Containers + +SharePoint Embedded applications use Microsoft Graph APIs to store files and documents in a new entity called a "File Storage Container” or Container for short.  If you’re an ISV, your app will create these containers in your customer’s Microsoft 365 tenant, and if you’re an enterprise, your app will create these containers in your own tenant. Each container provides a place to store files - you can think of them as similar to an API-only Document Library in SharePoint, but with some slight differences. Your app can create many of these containers inside each tenant that uses your app, and each container can be granted permissions separately storing many files with multiple terabytes of content. + +SharePoint Embedded containers are dedicated to and accessible by just your app, so the files and documents your app depends on are isolated and secure within that tenant boundary. + +## App-managed content experiences + +By default, the content stored within a Microsoft 365 tenant by a SharePoint Embedded application is only accessible through that owning application. Applications using SharePoint Embedded also provide the user experience layer for accessing and managing content, using some of the rich content capabilities that Microsoft 365 offers such as: + +- Core content management features like support for any file type and folder structure, searching, sharing, automatic versioning, recycle-bin, and more +- Collaboration features like view, edit, and co-authoring Office Word, Excel, and PowerPoint documents in Office Web and Desktop + +SharePoint Embedded is used by several types of applications: + +- Certain Microsoft products use SharePoint Embedded to manage customer content, such as Loop and Designer. +- ISVs can use SharePoint Embedded in their apps to manage content within their customer’s Microsoft 365 tenant +- Enterprises can use SharePoint Embedded to manage and store content within their own Microsoft 365 tenant, but outside of regular Microsoft 365 entitlements + +## Consumer Microsoft 365 settings apply to app documents + +All documents stored in the SharePoint partition created by the SharePoint Embedded app are in the consumer’s Microsoft 365 tenant and therefore are subject to the consumer’s Microsoft 365 tenant settings. + +This includes settings from Microsoft Purview compliance, risk, and security settings, documents can be opened from Office clients, and customers can use the Office web clients to view and collaborate on the documents. Choosing applications that are built on SharePoint Embedded provides the app consumer Microsoft Purview security and compliance capabilities on that app content, such as: + +- eDiscovery +- Auditing +- Data loss prevention (DLP) +- Retention policies, sensitivity labels, conditional access + +## Understanding the costs and billing for SharePoint Embedded content + +Microsoft 365 customers have different entitlements related to storage, usage, and features depending on the licenses the customer has purchased. + +The partition created in the consumer’s Microsoft 365 tenant by a SharePoint Embedded app doesn’t count towards other Microsoft 365 entitlements including the total amount of Microsoft SharePoint storage that can be used by your organization. Instead, the partition in the consumer’s Microsoft 365 tenant by the SharePoint Embedded app are billed separately through an Azure subscription on a pay-as-you-go metered consumption model that’s based on total storage and the number of API calls. + +> [!NOTE] +> Learn more about billing for SharePoint Embedded, see [Billing Meters](./administration/billing/meters.md). + +## Get Started with SharePoint Embedded + +[Review the prerequisites](./administration/billing/billing.md) + +Create a "File Storage Container" in 15 minutes or less: + +- [Free trial: SharePoint Embedded for Visual Studio Code](./getting-started/spembedded-for-vscode.md) + +Follow manual set-up on SharePoint Embedded from the following Microsoft Learning modules: + +- [Microsoft Learning: SharePoint Embedded - overview & configuration](/training/modules/sharepoint-embedded-setup) +- [Microsoft Learning: SharePoint Embedded - building applications](/training/modules/sharepoint-embedded-create-app) diff --git a/docs/embedded/scenarios-and-use-cases.md b/docs/embedded/scenarios-and-use-cases.md new file mode 100644 index 000000000..2c199f287 --- /dev/null +++ b/docs/embedded/scenarios-and-use-cases.md @@ -0,0 +1,71 @@ +--- +title: Scenarios and Use Cases +description: Scenarios and Use Cases for SharePoint Embedded +ms.date: 05/21/2024 +ms.localizationpriority: high +--- + +# Scenarios and use cases for SharePoint Embedded + +Use these example scenarios to prompt ideas about how custom applications can use SharePoint Embedded. + +> [!NOTE] +> This article is not intended to be an exhaustive list of all SharePoint Embedded features and scenarios. The intention is that these scenarios are contextualized examples of how combinations of features can be used. + +## Scenario: Structured user experience + +### Description + +Where your application requires a guided user experience to make users work in a structured way, rather than the flexible experience of SharePoint. + +Where your application is enabling a business-critical or time sensitive process, use the dedicated resource allocation of SharePoint Embedded to simplify management of throttling. + +### Examples + +- Extended Relationship Management (XRM) applications +- Engagement-based applications +- Workflow-based collaboration, with defined state + +### Why use SharePoint Embedded instead of SharePoint? + +- Your application is the only user interface, allowing you to create a prescriptive user experience +- Resources are separate from your Microsoft 365 entitlements– allowing for simpler resource management. + +## Scenario: Highly controlled collaboration + +### Description + +When building applications on top of SharePoint, it will still be possible for a user with permissions to navigate to the underlying site. Based on their permission level, a user might complete actions in the SharePoint interface that weren't intended by your application, for example changing site settings. These actions might have unintended consequences for your application or content. + +Because SharePoint Embedded is headless, there's no user interface other than what is provided by your custom application. If you don't supply a method to change content or settings through your application, then it won’t be possible for a user to circumvent this through SharePoint. You have the choice for which collaborative features are available in your application, for example sharing. + +### Examples + +- Deal room applications +- Shared research environments + +### Why use SharePoint Embedded instead of SharePoint? + +- You need the collaborative capabilities of SharePoint, only via a highly customized user interface +- You're handling high-value content, where you want to manage risk by removing abilities for a user to discover or alter the content repository +- All containers for the application can share default sharing settings that are separate from your OneDrive and SharePoint settings +- Content is logically separated from other Microsoft 365 content + +## Scenario: Customer facing document upload + +### Description + +Your application is aimed at an end customer, either within your organization or externally, who needs to upload a file as part of their interaction. You require a simplified end-user experience in your custom application, along with the Microsoft 365 capabilities of document storage and compliance. + +Using SharePoint Embedded will support this scenario, while not requiring the users of your application to have access or entitlement to your Microsoft 365 tenant. + +### Examples + +- Applying evidence to mortgage application +- Identity document verification + +### Why use SharePoint Embedded instead of SharePoint? + +- It's critical to segregate this data from the rest of your Microsoft 365 storage, while still being in scope for compliance tools like eDiscovery +- No Microsoft 365 licensing is required for users, or the use of external users in SharePoint +- Containers offer a simple, flexible unit of data storage diff --git a/docs/embedded/whats-new.md b/docs/embedded/whats-new.md new file mode 100644 index 000000000..4a0ba7af0 --- /dev/null +++ b/docs/embedded/whats-new.md @@ -0,0 +1,19 @@ +--- +title: What's new in SharePoint Embedded? +description: Updates about Microsoft SharePoint Embedded. +ms.date: 06/23/2025 +ms.localizationpriority: medium +--- + +# What's new in SharePoint Embedded + +## June 2025 + +- The `CopilotEmbeddedChatHosts` container type setting is now required to use [SharePoint Embedded agent](./development/declarative-agent/spe-da-adv.md#csp-policies). It must be set by the application owner via [`Set-SPOContainerTypeConfiguration`](/powershell/module/sharepoint-online/set-spocontainertypeconfiguration) and can optionally be overridden by consuming tenant administrators via [`Set-SPOApplication`](/powershell/module/SharePoint-online/set-spoapplication). + +## May 2025 + +- The limit of container types that a partner tenant can create has been increased to 25 by default. See [Limits and Calling Patterns](./development/limits-calling.md#size-limits). +- SharePoint Embedded agent switched to a consumption-based model for all users regardless of whether they have a Copilot license or not. See [SharePoint Embedded agent](./development/declarative-agent/spe-da.md). +- The guidance on how to grant admin consent to a SharePoint Embedded application has been updated to use URL-based admin consent. See [Authentication and authorization](./development/auth.md#whats-next). +- Documented an exceptional access pattern for operations that may require a user license. See [Authentication and authorization](./development/auth.md#operations-that-require-a-user-license). diff --git a/docs/features/embed-pages-to-teams.md b/docs/features/embed-pages-to-teams.md index baf3df80c..a4085809f 100644 --- a/docs/features/embed-pages-to-teams.md +++ b/docs/features/embed-pages-to-teams.md @@ -1,13 +1,13 @@ --- -title: Embedding modern SharePoint pages in Microsoft Teams as personal apps (preview) +title: Embedding modern SharePoint pages in Microsoft Teams as personal apps description: SharePoint pages can be embedded as personal apps in the Microsoft Teams. ms.date: 06/28/2022 ms.localizationpriority: high --- -# Embedding modern SharePoint pages in Microsoft Teams as personal apps (preview) +# Embedding modern SharePoint pages in Microsoft Teams as personal apps _**Applies to:** Microsoft 365_ > [!Important] -> When you are planning to embed SharePoint sites in Microsoft Teams, please use the [Viva Connections Desktop model](/sharepoint/guide-to-setting-up-viva-connections) for the optimal experience. +> When you are planning to embed SharePoint sites in Microsoft Teams, please use the [Viva Connections model](/sharepoint/guide-to-setting-up-viva-connections) for the supported experience. diff --git a/docs/features/hub-site/REST-getbyid-method.md b/docs/features/hub-site/REST-getbyid-method.md index 5672130d0..b06971eba 100644 --- a/docs/features/hub-site/REST-getbyid-method.md +++ b/docs/features/hub-site/REST-getbyid-method.md @@ -1,7 +1,7 @@ --- title: GetById REST method description: Gets or updates information about a hub site. -ms.date: 06/28/2022 +ms.date: 03/17/2023 ms.localizationpriority: medium --- @@ -30,8 +30,6 @@ POST /_api/HubSites/GetById |Content-Type|application/json;odata=verbose;charset=utf-8| |x-requestdigest|The appropriate digest for current site.| -
- When using POST to update a hub site with new information, use the following additional header values: | Header | Value | @@ -63,8 +61,7 @@ For GET, no request body is needed. When using POST to update a hub site with ne #### Sample request ```HTTP -GET -https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-499c-92db-38800eefbe44' +GET https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-499c-92db-38800eefbe44' ``` #### Sample response @@ -73,19 +70,19 @@ https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-49 ```JSON { - "@odata.context": "https://contoso.sharepoint.com/_api/$metadata#hubsites/$entity", - "@odata.type": "#SP.HubSite", - "@odata.id": "https://contoso.sharepoint.com/_api/HubSites/GetById", - "@odata.etag": "\"3\"", - "@odata.editLink": "HubSites/GetById", - "Description": null, - "ID": "f93eff08-5806-499c-92db-38800eefbe44", - "LogoUrl": "https://contoso.sharepoint.com/sites/marketing/SiteAssets/__hubLogo____hubLogo__.png", - "SiteId": "f93eff08-5806-499c-92db-38800eefbe44", - "SiteUrl": "https://contoso.sharepoint.com/sites/marketing", - "Targets": "", - "TenantInstanceId": "00000000-0000-0000-0000-000000000000", - "Title": "" + "@odata.context": "https://contoso.sharepoint.com/_api/$metadata#hubsites/$entity", + "@odata.type": "#SP.HubSite", + "@odata.id": "https://contoso.sharepoint.com/_api/HubSites/GetById", + "@odata.etag": "\"3\"", + "@odata.editLink": "HubSites/GetById", + "Description": null, + "ID": "f93eff08-5806-499c-92db-38800eefbe44", + "LogoUrl": "https://contoso.sharepoint.com/sites/marketing/SiteAssets/__hubLogo____hubLogo__.png", + "SiteId": "f93eff08-5806-499c-92db-38800eefbe44", + "SiteUrl": "https://contoso.sharepoint.com/sites/marketing", + "Targets": "", + "TenantInstanceId": "00000000-0000-0000-0000-000000000000", + "Title": "" } ``` @@ -94,8 +91,7 @@ https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-49 #### Sample request ```HTTP -POST -https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-499c-92db-38800eefbe44' +POST https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-499c-92db-38800eefbe44' ``` #### Sample response @@ -110,6 +106,28 @@ https://contoso.sharepoint.com/_api/HubSites/GetById?hubSiteId='f93eff08-5806-49 } ``` +### Associate a hub with another hub (parent hub association) + +#### Sample request + +```HTTP +POST https://contoso.sharepoint.com/_api/HubSites/GetById('f93eff08-5806-499c-92db-38800eefbe44') +``` + +```JSON +{ + "__metadata": { "type": "SP.HubSite" }, + "Title":"Marketing hub site", + "LogoUrl": "https://contoso.sharepoint.com/sites/marketing/SiteAssets/__hubLogo____hubLogo__.png", + "Description": "Hub site for marketing coordination", + "ParentHubSiteId":"269da5d4-6a9e-45a5-9502-a74d14977293" +} +``` + +#### Sample response + +**Status code:** 204 + ## See also - [Hub site REST API](hub-site-rest-api.md) diff --git a/docs/features/hub-site/create-hub-site-with-powershell.md b/docs/features/hub-site/create-hub-site-with-powershell.md index a89bd0578..16c183783 100644 --- a/docs/features/hub-site/create-hub-site-with-powershell.md +++ b/docs/features/hub-site/create-hub-site-with-powershell.md @@ -1,13 +1,14 @@ --- title: Create SharePoint hub sites using PowerShell description: Example code for creating a SharePoint hub site by using PowerShell. -ms.date: 08/24/2022 +ms.date: 04/23/2025 ms.localizationpriority: high --- # Create SharePoint hub sites by using PowerShell If you're a global or SharePoint admin in Office 365, you can convert any existing site to a hub site by using Microsoft PowerShell. In this example, you'll learn how to create a SharePoint hub site and to associate another site with it. In this scenario, you are setting up sites for the Contoso marketing department: + - You will create a hub site that all other marketing sites will be associated with. - You will then specify settings and permissions for the hub site. - Finally, you will create a second site and associate it with the hub site. @@ -28,29 +29,29 @@ The samples below can be performed using [PnP PowerShell](https://www.powershell First, we will create the marketing site that will serve as a hub site that other sites can associate with. The intent is that any sites that are marketing-oriented will be part of the hub site. This applies common navigation and branding across the associated sites, enables team members to search across all the sites associated with the single hub site, and takes advantage of other hub site features. -1. Connect to the SharePoint Online Admin center using: +1. Connect to the SharePoint Online Admin center using interactive login and [registered Azure AD (Entra ID)](https://pnp.github.io/powershell/articles/registerapplication.html) application: - ```powershell - Connect-PnPOnline -Url https://contoso-admin.sharepoint.com -UseWebLogin - ``` + ```powershell + Connect-PnPOnline -Url https://contoso-admin.sharepoint.com -Interactive -ClientId + ``` -2. Create the site to be used as a hub site using the [New-PnPSite](https://pnp.github.io/powershell/cmdlets/New-PnPSite.html) cmdlet: +1. Create the site to be used as a hub site using the [New-PnPSite](https://pnp.github.io/powershell/cmdlets/New-PnPSite.html) cmdlet: - ```powershell - New-PnPSite -Type TeamSite -Title "Contoso marketing division" -Alias "marketing" -Description "Main site for collaboration for marketing teams at Contoso" - ``` + ```powershell + New-PnPSite -Type TeamSite -Title "Contoso marketing division" -Alias "marketing" -Description "Main site for collaboration for marketing teams at Contoso" + ``` - The cmdlet returns the URL of the new site similar to the following: + The cmdlet returns the URL of the new site similar to the following: - ``` - https://contoso.sharepoint.com/sites/marketing - ``` + ```http + https://contoso.sharepoint.com/sites/marketing + ``` -3. Register the new marketing site as a hub site by using the [Register-PnPHubSite](https://pnp.github.io/powershell/cmdlets/Register-PnPHubSite.html) cmdlet: +1. Register the new marketing site as a hub site by using the [Register-PnPHubSite](https://pnp.github.io/powershell/cmdlets/Register-PnPHubSite.html) cmdlet: - ```powershell - Register-PnPHubSite -Site https://contoso.sharepoint.com/sites/marketing - ``` + ```powershell + Register-PnPHubSite -Site https://contoso.sharepoint.com/sites/marketing + ``` ## Set properties and permissions on the hub site @@ -59,15 +60,14 @@ The hub site doesn't have a logo or description yet. We also want to constrain i ### Set properties 1. Upload a logo image for the site by going to `https://contoso.sharepoint.com/sites/marketing/SiteAssets` and uploading any image you like. Make a note of the image file name. +1. Use the [Set-PnPHubSite](https://pnp.github.io/powershell/cmdlets/Set-PnPHubSite.html) cmdlet to set the logo and description. In place of `mylogo.jpg`, specify the name of the image that you uploaded: -2. Use the [Set-PnPHubSite](https://pnp.github.io/powershell/cmdlets/Set-PnPHubSite.html) cmdlet to set the logo and description. In place of `mylogo.jpg`, specify the name of the image that you uploaded: - - ```powershell + ```powershell Set-PnPHubSite - -Identity https://contoso.sharepoint.com/sites/marketing - -LogoUrl https://contoso.sharepoint.com/sites/marketing/SiteAssets/mylogo.jpg - -Description "Main hub site for collaboration on marketing activities across Contoso" - ``` + -Identity https://contoso.sharepoint.com/sites/marketing + -LogoUrl https://contoso.sharepoint.com/sites/marketing/SiteAssets/mylogo.jpg + -Description "Main hub site for collaboration on marketing activities across Contoso" + ``` ### Set permissions @@ -75,9 +75,9 @@ Now we will restrict access so that only the user `nestorw@contoso.com` can make - Run the [Grant-PnPHubSiteRights](https://pnp.github.io/powershell/cmdlets/Grant-PnPHubSiteRights.html) cmdlet to grant a user rights to the marketing hub site. We'll use `nestorw@contoso` in this example, but you can use any valid user on your tenant (you can specify multiple users by separating them with a comma): - ```powershell + ```powershell Grant-PnPHubSiteRights -Identity https://contoso.sharepoint.com/sites/marketing -Principals "nestorw@contoso" - ``` + ``` ## Create and associate a new site @@ -85,30 +85,29 @@ The final step is to create the site we want to associate with the hub. You can 1. Provision the site by using the [New-PnPSite](https://pnp.github.io/powershell/cmdlets/New-PnPSite.html) cmdlet: - ```powershell - New-PnPSite -Type TeamSite -Title "Online advertising team" -Alias "online-advertising" -Description "For collaboration on online advertising resources" - ``` + ```powershell + New-PnPSite -Type TeamSite -Title "Online advertising team" -Alias "online-advertising" -Description "For collaboration on online advertising resources" + ``` - The cmdlet returns the URL of the new site similar to the following: + The cmdlet returns the URL of the new site similar to the following: - ``` + ```http: https://contoso.sharepoint.com/sites/online-advertising - ``` + ``` -2. Associate this site with the hub site by using the [Add-PnPHubSiteAssociation](https://pnp.github.io/powershell/cmdlets/Add-PnPHubSiteAssociation.html) cmdlet: +1. Associate this site with the hub site by using the [Add-PnPHubSiteAssociation](https://pnp.github.io/powershell/cmdlets/Add-PnPHubSiteAssociation.html) cmdlet: - ```powershell + ```powershell Add-PnPHubSiteAssociation - -Site https://contoso.sharepoint.com/sites/online-advertising - -HubSite https://contoso.sharepoint.com/sites/marketing - ``` + -Site https://contoso.sharepoint.com/sites/online-advertising + -HubSite https://contoso.sharepoint.com/sites/marketing + ``` ## Confirm the hub site is working To confirm, you can either: - Run the [Get-PnPHubSite](https://pnp.github.io/powershell/cmdlets/Get-PnPHubSite.html) cmdlet. - - Sign in to SharePoint Online and view the hub site directly at `https://contoso.sharepoint.com/sites/marketing`. The hub site navigation appears at the top of the site. If you go to the `https://contoso.sharepoint.com/sites/online-advertising` site, it shows the same hub site navigation at the top. diff --git a/docs/features/hub-site/hub-site-o365cli.md b/docs/features/hub-site/hub-site-o365cli.md index 822f4c372..2ecea1787 100644 --- a/docs/features/hub-site/hub-site-o365cli.md +++ b/docs/features/hub-site/hub-site-o365cli.md @@ -1,7 +1,7 @@ --- title: CLI for Microsoft 365 commands for SharePoint hub sites description: Use CLI for Microsoft 365 to create and manage SharePoint hub sites. -ms.date: 06/28/2022 +ms.date: 06/27/2024 ms.localizationpriority: high --- @@ -16,10 +16,8 @@ Use the CLI for Microsoft 365 commands to create and manage SharePoint hub sites To run the CLI for Microsoft 365 commands, you'll need to do the following: 1. Download and install [NodeJS LTS version](https://nodejs.org/en/) - -2. Follow the instructions at [Installing the CLI](https://pnp.github.io/cli-microsoft365/user-guide/installing-cli/) to install the CLI for Microsoft 365 on your machine - -3. Follow the instructions at [Logging in to Office 365](https://pnp.github.io/cli-microsoft365/user-guide/connecting-office-365/) to connect to your SharePoint tenant. +1. Follow the instructions at [Installing the CLI](https://pnp.github.io/cli-microsoft365/user-guide/installing-cli/) to install the CLI for Microsoft 365 on your machine +1. Follow the instructions at [Logging in to Office 365](https://pnp.github.io/cli-microsoft365/user-guide/connecting-microsoft-365) to connect to your SharePoint tenant. To verify your setup and connection, try using the [hubsite list](https://pnp.github.io/cli-microsoft365/cmd/spo/hubsite/hubsite-list/) command to list the current hub sites. If the cmdlet runs and returns with no errors, you're ready to proceed. @@ -38,7 +36,7 @@ The following commands are available for managing hub sites: |[hubsite rights grant](https://pnp.github.io/cli-microsoft365/cmd/spo/hubsite/hubsite-rights-grant)| Grants permissions to join the hub site for one or more principals | |[hubsite rights revoke](https://pnp.github.io/cli-microsoft365/cmd/spo/hubsite/hubsite-rights-revoke)| Revokes rights to join sites to the specified hub site for one or more principals | |[hubsite set](https://pnp.github.io/cli-microsoft365/cmd/spo/hubsite/hubsite-set)| Updates properties of the specified hub site | -|[hubsite theme sync](https://pnp.github.io/cli-microsoft365/cmd/spo/hubsite/hubsite-theme-sync)| Applies any theme updates from the parent hub site. | +|[hubsite theme sync](https://pnp.github.io/cli-microsoft365/cmd/spo/site/site-hubsite-theme-sync)| Applies any theme updates from the parent hub site. | |[hubsite unregister](https://pnp.github.io/cli-microsoft365/cmd/spo/hubsite/hubsite-unregister)| Unregisters the specifies site collection as a hub site | ## See also diff --git a/docs/features/hub-site/hub-site-powershell.md b/docs/features/hub-site/hub-site-powershell.md index e315f4c0c..58fa78c4d 100644 --- a/docs/features/hub-site/hub-site-powershell.md +++ b/docs/features/hub-site/hub-site-powershell.md @@ -14,8 +14,7 @@ Use PowerShell cmdlets to create and manage SharePoint hub sites. To run the PowerShell cmdlets: 1. Download and install the [SharePoint Online Management Shell](https://www.microsoft.com/download/details.aspx?id=35588). If you already have a previous version of the shell installed, uninstall it first, and then install the latest version. - -2. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. +1. Follow the instructions at [Connect to SharePoint Online PowerShell](https://technet.microsoft.com/library/fp161372.aspx) to connect to your SharePoint tenant. To verify your setup, try using the **Get-SPOHubSite** cmdlet to read the current list of hub sites. If the cmdlet runs and returns with no errors, you're ready to proceed. diff --git a/docs/features/site-footer.md b/docs/features/site-footer.md index 80bec7f03..eb1d37583 100644 --- a/docs/features/site-footer.md +++ b/docs/features/site-footer.md @@ -1,7 +1,7 @@ --- title: Overview of the SharePoint Site footer description: SharePoint Site footers can be used to show a logo or set of links/labels in a modern SharePoint site. They can be configured using the UI settings or by using APIs. -ms.date: 07/14/2022 +ms.date: 09/24/2023 ms.localizationpriority: high --- @@ -35,7 +35,7 @@ Set-PnPFooter -Enabled:$true # for enabling the footer ``` > [!NOTE] -> Above PowerShell scripts assumes that you have already installed PnP PowerShell cmdlets for your environment and you are not using multi-factor authentication. You can install PnP PowerShell cmdlets to your computer by opening PowerShell console in administrative mode and executing following command: `Install-Module SharePointPnPPowerShellOnline`. If you are using multi-factor authentication, you can enable MFA login by updating the `Connect-PnPOnline` line as follows: `Connect-PnPOnline -Url "" -UseWebLogin`. +> Above PowerShell scripts assumes that you have already installed PnP PowerShell cmdlets for your environment and you are not using multi-factor authentication. You can install PnP PowerShell cmdlets to your computer by opening PowerShell console in administrative mode and executing following command: `Install-Module PnP.PowerShell -Scope CurrentUser`. If you are using multi-factor authentication, you can enable MFA login by updating the `Connect-PnPOnline` line as follows: `Connect-PnPOnline -Url "" -Interactive`. [!INCLUDE [pnp-powershell](../../includes/snippets/open-source/pnp-powershell.md)] diff --git a/docs/general-development/access-sharepoint-from-mobile-and-native-device-apps.md b/docs/general-development/access-sharepoint-from-mobile-and-native-device-apps.md index 5b13bd2af..bc4e82403 100644 --- a/docs/general-development/access-sharepoint-from-mobile-and-native-device-apps.md +++ b/docs/general-development/access-sharepoint-from-mobile-and-native-device-apps.md @@ -76,5 +76,4 @@ You can build these apps on the ASP.NET platform or a non-Microsoft stack. If yo These apps **gain authorized access to SharePoint data by using access tokens** that are issued by the Azure Control Service (ACS) in compliance with the OAuth Authentication Code flow. For more, see [Authorization Code OAuth flow for SharePoint Add-ins](https://msdn.microsoft.com/library/e89e91c7-ea39-49b9-af5a-7f047a7e2ab7%28Office.15%29.aspx). -> [!IMPORTANT] -> Azure Access Control (ACS), a service of Azure Active Directory (Azure AD), will be retired on November 7, 2018. This retirement does not impact the SharePoint Add-in model, which uses the `https://accounts.accesscontrol.windows.net` hostname (which is not impacted by this retirement). For more information, see [Impact of Azure Access Control retirement for SharePoint Add-ins](https://developer.microsoft.com/office/blogs/impact-of-azure-access-control-deprecation-for-sharepoint-add-ins). +[!INCLUDE [azure-acs-retirement](../../includes/snippets/azure-acs-deprecation.md)] diff --git a/docs/general-development/basic-uri-structure-and-path.md b/docs/general-development/basic-uri-structure-and-path.md index c311b5a05..86c10a404 100644 --- a/docs/general-development/basic-uri-structure-and-path.md +++ b/docs/general-development/basic-uri-structure-and-path.md @@ -10,170 +10,83 @@ ms.localizationpriority: high # Basic URI Structure and Path This topic explains how to construct the URI structure and path for REST service commands in Excel Services. - + > [!NOTE] -> -> The Excel Services REST API applies to SharePoint and SharePoint 2016 on-premises. For Office 365 Education, Business, and Enterprise accounts, use the Excel REST APIs that are part of the [Microsoft Graph](http://graph.microsoft.io/docs/api-reference/v1.0/resources/excel +> +> The Excel Services REST API applies to SharePoint and SharePoint 2016 on-premises. For Office 365 Education, Business, and Enterprise accounts, use the Excel REST APIs that are part of the [Microsoft Graph](https://graph.microsoft.io/docs/api-reference/v1.0/resources/excel ) endpoint. - - - - ## Basic URL Structure and Path -The REST API in Excel Services gives you the ability to access resources like charts, PivotTables, tables, and named ranges in a workbook directly through a URL. Each REST URL in Excel Services is built of three parts. Following is the basic structure of the URL to access the resources in a workbook: - - - +The REST API in Excel Services gives you the ability to access resources like charts, PivotTables, tables, and named ranges in a workbook directly through a URL. Each REST URL in Excel Services is built of three parts. Following is the basic structure of the URL to access the resources in a workbook: 1. **REST aspx Page URI** The entry point to an .aspx page - - -2. **Workbook Location** The path to the workbook - - -3. **Resource Location** The path to the requested resource inside the workbook - - -Following is the construct for the REST URL to a specific element in a workbook: - - - - +1. **Workbook Location** The path to the workbook +1. **Resource Location** The path to the requested resource inside the workbook +Following is the construct for the REST URL to a specific element in a workbook: -``` - +```http http:///_vti_bin/ExcelRest.aspx/// ``` Following is an example of how a REST URL in Excel Services looks with all three parts combined. In this example, the REST URL is accessing a workbook called "sampleWorkbook.xlsx" that contains a chart called "SampleChart": - - - - - -``` +```http http:///_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model/Charts('SampleChart') ``` The workbook is stored in a document library. The full path to the workbook is `http://` _\_ `/Docs/Documents/sampleWorkbook.xlsx`. - - - + The three parts of the REST URL are: - - - 1. **REST aspx Page URI**: `http://` _\_ `/_vti_bin/ExcelRest.aspx` - - -2. **Workbook Location**: `/Docs/Documents/sampleWorkbook.xlsx` - - -3. **Resource Location**: `/model/Ranges('nameOfTheNamedRange')` - - +1. **Workbook Location**: `/Docs/Documents/sampleWorkbook.xlsx` +1. **Resource Location**: `/model/Ranges('nameOfTheNamedRange')` ### Accessing by Using the Discovery User Interface You can also access the chart by using the discovery user interface. To learn how access resources like charts, tables, PivotTables, and ranges by using the discovery mechanism shown in the following screen shot, see [Discovery in Excel Services REST API](discovery-in-excel-services-rest-api.md). - - - - - - ![Excel Services REST model URL](../images/SharePointServer14Con_XLSvcs_RESTModel.gif) - - - - - - - - - - - - - - - ### Marker Path Following is the aspx page for the REST service in Excel Services: - - - -``` +```http http:///_vti_bin/ExcelRest.aspx ``` To access the REST service in Excel Services, you must preface the URL with `http://` _\_ `/_vti_bin/ExcelRest.aspx`. - - - ### Workbook Location -The workbook location is the relative path to the workbook that has resources that you are interested in accessing. For example, assume that you have a workbook named sampleWorkbook.xlsx, saved to a trusted SharePoint document library. In this example, following is the path to the location of sampleWorkbook.xlsx: - - - +The workbook location is the relative path to the workbook that has resources that you are interested in accessing. For example, assume that you have a workbook named sampleWorkbook.xlsx, saved to a trusted SharePoint document library. In this example, following is the path to the location of sampleWorkbook.xlsx: -``` +```http http:///Docs/Documents/sampleWorkbook.xlsx ``` You take the relative path to the workbook ( `Docs/Documents/sampleWorkbook.xlsx`) and append it to the marker path. Following is the URL with the marker path and workbook location appended: - - - - - -``` +```http http:///_vti_bin/ExcelRest.aspx ``` - ### Resource Location The resource location is the path inside the workbook to the element that you request. For example, if you want to get a chart, the resource location would be similar to `/model/Charts('Chart 1')`. - - - -For the full URL, you append this to the marker path and the relative path to the workbook. Following is the full example URL: - - - - +For the full URL, you append this to the marker path and the relative path to the workbook. Following is the full example URL: -``` +```http http:///_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model/Charts('Chart 1') - ``` - ## See also +### Concepts -#### Concepts - - - - - - [Resources URI for Excel Services REST API](resources-uri-for-excel-services-rest-api.md) - - - - [Discovery in Excel Services REST API](discovery-in-excel-services-rest-api.md) +- [Resources URI for Excel Services REST API](resources-uri-for-excel-services-rest-api.md) +- [Discovery in Excel Services REST API](discovery-in-excel-services-rest-api.md) diff --git a/docs/general-development/build-windows-phone-apps-that-access-sharepoint.md b/docs/general-development/build-windows-phone-apps-that-access-sharepoint.md index 0d74d8b71..0bcd5d7b8 100644 --- a/docs/general-development/build-windows-phone-apps-that-access-sharepoint.md +++ b/docs/general-development/build-windows-phone-apps-that-access-sharepoint.md @@ -5,33 +5,24 @@ ms.assetid: 36681335-f772-4499-8445-f94481bc18e7 description: Create SharePoint Add-ins that integrate SharePoint and mobile devices such as Windows Phone 8 and Windows Phone 7. ms.localizationpriority: medium --- - # Build Windows Phone apps that access SharePoint SharePoint provides an exciting opportunity for developers to build mobile apps that travel with users, are interactive and attractive, and are available whenever and wherever users want to work with them. You can combine Windows Phone 8 and Windows Phone 7 applications with on-premises SharePoint services and applications, or with remote SharePoint services and applications that run in the cloud (such as those that use SharePoint Online) to create powerful applications that extend the functionality beyond the traditional desktop or laptop and into a truly portable and much more accessible environment. - + The new mobility features offered by SharePoint are built on existing Microsoft tools and technologies, such as SharePoint, Windows Phone, Visual Studio, and Silverlight. Developers who are already familiar with those technologies and their related tools will be able to create SharePoint-powered mobile apps for Windows Phone without a steep learning curve. In this section, we explore some of the types of SharePoint-powered mobile apps you can build for Windows Phone 8 and Windows Phone 7 and the most common ways to customize those applications. SharePoint provides a framework and tools for developers, including Visual Studio 2010 project templates, to create mobile solutions that interact with SharePoint data both in on-premises SharePoint installations and in the cloud by using SharePoint Online. Figure 1 shows how a simple list application could look on Windows Phone. - - + **Figure 1. SharePoint list items in a Windows Phone app** ![SharePoint list items in a Windows Phone app](../images/9159345c-ce12-41a6-8994-fc2e9aa26fd6.gif) - - ## What skills do you need to create mobile apps? In this section, we assume that you're familiar with SharePoint, the .NET Framework, the Visual Studio development system, and Visual C#. It's also good to have some experience with Windows Phone 8 or Windows Phone 7 application development using Silverlight, and it helps to be familiar with XAML, the StackPanel and Pivot controls for Windows Phone, and concepts such as tombstoning, Silverlight data binding, and so on. If you are new to Windows Phone application development using Silverlight, we recommend that you check out the following resources. -- [Developing a Windows Phone Application from Start to Finish](https://msdn.microsoft.com/library/gg680270%28v=pandp.11%29.aspx) - -- [User interface for Windows Phone](https://msdn.microsoft.com/library/windowsphone/develop/ff967556%28v=vs.105%29.aspx) - -- [Quickstart: Creating a user interface with XAML for Windows Phone](https://msdn.microsoft.com/library/windowsphone/develop/jj207025%28v=vs.105%29.aspx) - -- [Pivot control architecture for Windows Phone](https://msdn.microsoft.com/library/windowsphone/develop/ff941097%28v=vs.105%29.aspx) - - +- [Developing a Windows Phone Application from Start to Finish](https://msdn.microsoft.com/library/gg680270%28v=pandp.11%29.aspx) +- [User interface for Windows Phone](https://msdn.microsoft.com/library/windowsphone/develop/ff967556%28v=vs.105%29.aspx) +- [Quickstart: Creating a user interface with XAML for Windows Phone](https://msdn.microsoft.com/library/windowsphone/develop/jj207025%28v=vs.105%29.aspx) +- [Pivot control architecture for Windows Phone](https://msdn.microsoft.com/library/windowsphone/develop/ff941097%28v=vs.105%29.aspx) ## Development overview for mobile apps using SharePoint @@ -39,34 +30,34 @@ You can build a wide variety of mobile apps using SharePoint. This section descr ### Windows Phone SharePoint Application template -This is the simplest type of mobile app you can build to bring a regular list to the phone. SharePoint offers a Visual Studio template to enable you to quickly and easily create SharePoint list applications for the Windows Phone. For example, you can build a "To Do List"-type Windows Phone application that brings your task list from SharePoint into the Windows Phone and enables the you to use your phone to update the status of a task on the go. Another example is having the product catalog for an inventory list in SharePoint available on the phone for the sales people. +This is the simplest type of mobile app you can build to bring a regular list to the phone. SharePoint offers a Visual Studio template to enable you to quickly and easily create SharePoint list applications for the Windows Phone. For example, you can build a "To Do List"-type Windows Phone application that brings your task list from SharePoint into the Windows Phone and enables the you to use your phone to update the status of a task on the go. Another example is having the product catalog for an inventory list in SharePoint available on the phone for the sales people. -Installing the Windows Phone SharePoint SDK makes two Windows Phone SharePoint Application templates available to you in Visual Studio 2010 or Visual Studio 2010 Express for Windows Phone (see [How to: Set up an environment for developing mobile apps for SharePoint](how-to-set-up-an-environment-for-developing-mobile-apps-for-sharepoint.md)). +Installing the Windows Phone SharePoint SDK makes two Windows Phone SharePoint Application templates available to you in Visual Studio 2010 or Visual Studio 2010 Express for Windows Phone (see [How to: Set up an environment for developing mobile apps for SharePoint](how-to-set-up-an-environment-for-developing-mobile-apps-for-sharepoint.md)). Using the Windows Phone SharePoint List Application template, you can follow the steps of a wizard to create a functional Windows Phone app that can access and manipulate data in a SharePoint list. ### New and enhanced mobility object model in SharePoint SharePoint adds several new classes to both the server and client object models to enable the SharePoint mobility scenarios that we described earlier in this article. - -To enable location-aware apps, there is a new native field type class, **SPFieldGeoLocation**, along with several associated classes for structuring the value of location fields and rendering them. These classes are also callable in the SharePoint client object model for Silverlight. The new field type also has a definition added to the standard SharePoint fldtypes.xml file and new user controls for rendering the field on the Display, Edit, and New forms. For an overview, see [Integrating location and map functionality in SharePoint](integrating-location-and-map-functionality-in-sharepoint.md). + +To enable location-aware apps, there is a new native field type class, **SPFieldGeoLocation**, along with several associated classes for structuring the value of location fields and rendering them. These classes are also callable in the SharePoint client object model for Silverlight. The new field type also has a definition added to the standard SharePoint fldtypes.xml file and new user controls for rendering the field on the Display, Edit, and New forms. For an overview, see [Integrating location and map functionality in SharePoint](integrating-location-and-map-functionality-in-sharepoint.md). To enable SharePoint authentication for Windows Phone users, the client object model includes a new **Authenticator** class and several associated classes. For an overview, see [Overview of the SharePoint mobile client authentication object model](overview-of-the-sharepoint-mobile-client-authentication-object-model.md). - + To enable automatic notifications to Windows Phone users of events on a SharePoint farm, the server object model includes several new classes, each of which is also callable from the client object model. These classes include methods that enable phone apps to register with SharePoint server apps for notifications about specified types of events. There are also methods that the server apps use to send notifications to registered subscribers. For an overview, see [Create a Windows Phone SharePoint list app to receive push notifications](how-to-configure-and-use-push-notifications-in-sharepoint-apps-for-windows.md#create-a-windows-phone-sharepoint-list-app-to-receive-push-notifications). - + With SharePoint, you're not limited to mobile app development just for Windows Phone 8 and Windows Phone 7. With the JavaScript programming interface and the new Representational State Transfer (REST) programming interface provided by SharePoint, you can create applications for non-Windows Phone mobile devices; you can interact with SharePoint sites by using JavaScript that executes as scripts in the browser, or remotely by using any technology that supports standard REST capabilities. The following section provides an overview of the REST and JavaScript programming interfaces. #### ECMAScript (JavaScript, JScript) object model architecture SharePoint Foundation 2010 introduced the client object models, which enabled developers to perform remote communication with SharePoint by using the web programming technology of their choice: the .NET Framework, Silverlight, or JavaScript. - + In SharePoint Foundation 2010, the client object models provide APIs that enable developers to interact with SharePoint sites from script that executes in the browser, from code (based on the .NET Framework 3.5 or later) that executes in a .NET Framework-managed application, or from code that executes in a Silverlight 2.0 application. The proxy .js and managed .dll files that compose the client object models are built on the client.svc web service, and handle the effective batching, serialization of requests, and parsing of replies. Figure 2 shows a high-level view of the SharePoint client object model architecture. **Figure 2. SharePoint client object model architecture** - + ![SharePoint client object model architecture](../images/SP15Con_BuildSharePointAppsForMobileDevices_Fig3.png) - + To learn how to use the JavaScript client object model against SharePoint data, see the [ECMAScript Client Object Model video](https://msdn.microsoft.com/SP2010DevTrainingCourse_ECMAScriptClientObjectModel.aspx). #### REST endpoints in SharePoint @@ -74,65 +65,44 @@ To learn how to use the JavaScript client object model against SharePoint data, To use the REST capabilities that are built into SharePoint, you can construct a RESTful HTTP request using the Open Data Protocol (OData) standard that corresponds to the desired client object model API. The client.svc web service handles the HTTP request and serves the appropriate response, in either Atom or JavaScript Object Notation (JSON) format. The client application must then parse that response. Figure 3 shows a high-level view of the SharePoint REST architecture. **Figure 3. SharePoint REST architecture** - + ![SharePoint REST architecture](../images/SP15Con_BuildSharePointAppsForMobileDevices_Fig2.png) - + Currently, the REST service in SharePoint is read-only. That is, only REST endpoints that represent an HTTP GET operation are available - + By default, the SharePoint REST service responses are formatted using the Atom protocol, according to the OData specification. In addition, the REST service supports HTTP Accept headers that enable developers to specify that the response is returned in JSON format. To learn more about REST services in SharePoint, see [Use OData query operations in SharePoint REST requests](https://msdn.microsoft.com/library/d4b5c277-ed50-420c-8a9b-860342284b72%28Office.15%29.aspx). - + The SharePoint REST service supports the following OData query operators: - Filter - Take - Expand - - ## Start developing mobile apps for SharePoint The following how-tos and overviews delve into the specific information you need to start your mobile app development: -- [How to: Set up an environment for developing mobile apps for SharePoint](how-to-set-up-an-environment-for-developing-mobile-apps-for-sharepoint.md) - -- [Overview of Windows Phone SharePoint application templates in Visual Studio](overview-of-windows-phone-sharepoint-application-templates-in-visual-studio.md) - -- [Architecture of the Windows Phone SharePoint List Application template](architecture-of-the-windows-phone-sharepoint-list-application-template.md) - -- [How to: Create a Windows Phone SharePoint list app](how-to-create-a-windows-phone-sharepoint-list-app.md) - -- [How to: Store and retrieve SharePoint list items on a Windows Phone](how-to-store-and-retrieve-sharepoint-list-items-on-a-windows-phone.md) - -- [How to: Implement business logic and data validation in a Windows Phone app for SharePoint](how-to-implement-business-logic-and-data-validation-in-a-windows-phone-app-for-s.md) - -- [How to: Support and convert SharePoint field types for Windows Phone apps](how-to-support-and-convert-sharepoint-field-types-for-windows-phone-apps.md) +- [How to: Set up an environment for developing mobile apps for SharePoint](how-to-set-up-an-environment-for-developing-mobile-apps-for-sharepoint.md) +- [Overview of Windows Phone SharePoint application templates in Visual Studio](overview-of-windows-phone-sharepoint-application-templates-in-visual-studio.md) +- [Architecture of the Windows Phone SharePoint List Application template](architecture-of-the-windows-phone-sharepoint-list-application-template.md) +- [How to: Create a Windows Phone SharePoint list app](how-to-create-a-windows-phone-sharepoint-list-app.md) +- [How to: Store and retrieve SharePoint list items on a Windows Phone](how-to-store-and-retrieve-sharepoint-list-items-on-a-windows-phone.md) +- [How to: Implement business logic and data validation in a Windows Phone app for SharePoint](how-to-implement-business-logic-and-data-validation-in-a-windows-phone-app-for-s.md) +- [How to: Support and convert SharePoint field types for Windows Phone apps](how-to-support-and-convert-sharepoint-field-types-for-windows-phone-apps.md) +- [How to: Customize list item queries and filter data for Windows Phone apps](how-to-customize-list-item-queries-and-filter-data-for-windows-phone-apps.md) +- [How to: Customize the user interface of a SharePoint list app for Windows Phone](how-to-customize-the-user-interface-of-a-sharepoint-list-app-for-windows-ph.md) +- [How to: Use multiple SharePoint lists in a Windows Phone app](how-to-use-multiple-sharepoint-lists-in-a-windows-phone-app.md) +- [How to: Configure and use push notifications in SharePoint apps for Windows Phone](how-to-configure-and-use-push-notifications-in-sharepoint-apps-for-windows.md) +- [Integrating location and map functionality in SharePoint](integrating-location-and-map-functionality-in-sharepoint.md) +- [How to: Create a mobile app in SharePoint that contains data from an external data source](how-to-create-a-mobile-app-in-sharepoint-that-contains-data-from-an-externa.md) +- [How to: Integrate maps with Windows Phone apps and SharePoint lists](how-to-integrate-maps-with-windows-phone-apps-and-sharepoint-lists.md) +- [How to: Build search-driven mobile apps with the Navigation and Event Logging REST interfaces](how-to-build-search-driven-mobile-apps-with-the-navigation-and-event-logging-res.md) -- [How to: Customize list item queries and filter data for Windows Phone apps](how-to-customize-list-item-queries-and-filter-data-for-windows-phone-apps.md) - -- [How to: Customize the user interface of a SharePoint list app for Windows Phone](how-to-customize-the-user-interface-of-a-sharepoint-list-app-for-windows-ph.md) - -- [How to: Use multiple SharePoint lists in a Windows Phone app](how-to-use-multiple-sharepoint-lists-in-a-windows-phone-app.md) - -- [How to: Configure and use push notifications in SharePoint apps for Windows Phone](how-to-configure-and-use-push-notifications-in-sharepoint-apps-for-windows.md) - -- [Integrating location and map functionality in SharePoint](integrating-location-and-map-functionality-in-sharepoint.md) - -- [How to: Create a mobile app in SharePoint that contains data from an external data source](how-to-create-a-mobile-app-in-sharepoint-that-contains-data-from-an-externa.md) - -- [How to: Integrate maps with Windows Phone apps and SharePoint lists](how-to-integrate-maps-with-windows-phone-apps-and-sharepoint-lists.md) - -- [How to: Build search-driven mobile apps with the Navigation and Event Logging REST interfaces](how-to-build-search-driven-mobile-apps-with-the-navigation-and-event-logging-res.md) - ## See also -- [Programming models in SharePoint](programming-models-in-sharepoint.md) -- [How to: Set up an environment for developing mobile apps for SharePoint](how-to-set-up-an-environment-for-developing-mobile-apps-for-sharepoint.md) -- [Windows Phone SDK 8.0](https://www.microsoft.com/download/details.aspx?id=35471) -- [Microsoft SharePoint SDK for Windows Phone 8](https://www.microsoft.com/download/details.aspx?id=36818) -- [Windows Phone SDK 7.1](https://www.microsoft.com/download/details.aspx?id=29233) -- [Microsoft SharePoint SDK for Windows Phone 7.1](https://www.microsoft.com/download/details.aspx?id=30476) -- [About Expression Blend](https://msdn.microsoft.com/library/cc296376%28Expression.40%29.aspx) - - - +- [Programming models in SharePoint](programming-models-in-sharepoint.md) +- [How to: Set up an environment for developing mobile apps for SharePoint](how-to-set-up-an-environment-for-developing-mobile-apps-for-sharepoint.md) +- [Windows Phone SDK 8.0](https://www.microsoft.com/download/details.aspx?id=35471) +- [Windows Phone SDK 7.1](https://www.microsoft.com/download/details.aspx?id=29233) +- [About Expression Blend](https://msdn.microsoft.com/library/cc296376%28Expression.40%29.aspx) diff --git a/docs/general-development/client-side-web-parts-maintenance-mode.md b/docs/general-development/client-side-web-parts-maintenance-mode.md index 69c50b2c3..7a9543bcd 100644 --- a/docs/general-development/client-side-web-parts-maintenance-mode.md +++ b/docs/general-development/client-side-web-parts-maintenance-mode.md @@ -1,7 +1,7 @@ --- title: Maintenance mode for client-side web parts description: When working with client-side web parts, you can load them in maintenance mode. The maintenance mode can be helpful when trying to debug issues related to web parts placed on the page. -ms.date: 05/25/2021 +ms.date: 04/28/2023 ms.assetid: 3ebd2a11-8291-4228-add0-9e0cd899dd3c ms.localizationpriority: medium --- @@ -78,10 +78,10 @@ If the web part [integrates its properties with SharePoint](../spfx/web-parts/gu ## Disable SPFx web parts and extensions -If you need to troubleshoot a SharePoint page to see if there is a SharePoint Framework extension or web part causing issues you can append **?disable3PCode=1** to the URL to disable loading of SPFx components, for example: +If you need to troubleshoot a SharePoint page to see if there is a SharePoint Framework extension or web part causing issues you can append **?disable3PCode** to the URL to disable loading of SPFx components, for example: ```text -https://contoso.sharepoint.com/sites/team?disable3PCode=1 +https://contoso.sharepoint.com/sites/team?disable3PCode ``` This will prevent loading of any third party SPFx components on the page. diff --git a/docs/general-development/create-a-workflow-with-elevated-permissions-by-using-the-sharepoint-workflo.md b/docs/general-development/create-a-workflow-with-elevated-permissions-by-using-the-sharepoint-workflo.md index 0c628e66b..cf9ffd1c1 100644 --- a/docs/general-development/create-a-workflow-with-elevated-permissions-by-using-the-sharepoint-workflo.md +++ b/docs/general-development/create-a-workflow-with-elevated-permissions-by-using-the-sharepoint-workflo.md @@ -1,42 +1,36 @@ --- title: Create a workflow with elevated permissions by using the SharePoint Workflow platform description: Create SharePoint workflows that access objects in SharePoint that require elevated permissions. These solutions grant permissions to the workflow app and wrap actions with the App Step. -ms.date: 12/29/2017 +ms.date: 05/18/2023 ms.assetid: 4656f6a0-36fd-4b7d-898e-8cd4bdbbda57 ms.localizationpriority: high --- - # Create a workflow with elevated permissions by using the SharePoint Workflow platform - - This article describes how to create SharePoint workflows that access objects in SharePoint that require elevated permissions. These solutions use two features: granting permissions to the workflow app and wrapping actions with the App Step. > [!NOTE] > SharePoint 2010 workflows have been retired since August 1, 2020 for new tenants and removed from existing tenants on November 1, 2020. If you’re using SharePoint 2010 workflows, we recommend migrating to Power Automate or other supported solutions. For more info, see [SharePoint 2010 workflow retirement](https://support.microsoft.com/office/sharepoint-2010-workflow-retirement-1ca3fff8-9985-410a-85aa-8120f626965f). - -> [!IMPORTANT] -> This article assumes that the SharePoint Workflow platform has been installed and configured and that SharePoint has been configured for add-ins. For more information about SharePoint Workflows and SharePoint Add-ins, including installation and configuration, see [Workflows in SharePoint](workflows-in-sharepoint.md) and [Install and manage SharePoint Add-ins](../sp-add-ins/sharepoint-add-ins.md). +> [!IMPORTANT] +> This article assumes that the SharePoint Workflow platform has been installed and configured and that SharePoint has been configured for add-ins. For more information about SharePoint Workflows and SharePoint Add-ins, including installation and configuration, see [Workflows in SharePoint](workflows-in-sharepoint.md) and [Install and manage SharePoint Add-ins](../sp-add-ins/sharepoint-add-ins.md). Imagine that as a SharePoint administrator, you would like to define some processes for managing user requests for purchases of add-ins from the Office Store. In the simplest case, you want to send an acknowledgment email when a user requests an add-in. In addition, you might also want to add structure to the request approval process. - -By default, workflow does not have permissions to access the app catalog. Catalog lists in SharePoint require owner (full control) permissions. Workflows generally run at a permission level equivalent to write. - + +By default, workflow does not have permissions to access the app catalog. Catalog lists in SharePoint require owner (full control) permissions. Workflows generally run at a permission level equivalent to write. + To solve this, you have to create a workflow with elevated permissions by doing the following in the Site Collection site: 1. Allow the workflow to use add-in permissions. - -2. Grant full control permission to the workflow. - -3. Develop the workflow to wrap actions inside an App Step. +1. Grant full control permission to the workflow. +1. Develop the workflow to wrap actions inside an App Step. ## Allow a workflow to use add-in permissions on a SharePoint site The first step is to allow the workflow to use add-in permissions. You configure a workflow to use add-in permissions on the **Site settings** page of the SharePoint site where the workflow runs. The following procedure configures the SharePoint site to allow the workflow to use add-in permissions. - -> [!IMPORTANT] + +> [!IMPORTANT] > The procedure must be completed by a user that has **Site Administrator** permissions. ### To allow workflow to use add-in permissions @@ -45,79 +39,71 @@ The first step is to allow the workflow to use add-in permissions. You configure ![Settings menu](../images/SPD15-WFAppPermissions1.png) -2. Go to **Site settings**. - -3. In the **Site Actions** section, select **Manage site features**. +1. Go to **Site settings**. +1. In the **Site Actions** section, select **Manage site features**. +1. Locate the feature called **Workflows can use app permissions**, as shown in the figure, and then select **Activate**. -4. Locate the feature called **Workflows can use app permissions**, as shown in the figure, and then select **Activate**. - - > [!WARNING] - > This feature will not activate unless you have properly configured the SharePoint Workflow platform and SharePoint Add-ins. + > [!WARNING] + > This feature will not activate unless you have properly configured the SharePoint Workflow platform and SharePoint Add-ins. - ![Workflow can use app permissions feature](../images/SPD15-WFAppPermissions2.png) - + ![Workflow can use app permissions feature](../images/SPD15-WFAppPermissions2.png) ## Grant full control permission to a workflow For the workflow to function properly, it must be granted full control on the site. The following procedure grants full control permission to the workflow. - -> [!IMPORTANT] + +> [!IMPORTANT] > The procedure must be completed by a user that has **Site Owner** permissions. The workflow must already be published to the SharePoint site. ### To grant full control permission to a workflow 1. Select the **Settings** icon. - + ![Settings menu](../images/SPD15-WFAppPermissions1.png) -2. Go to **Site settings**. - -3. In the **Users and Permissions** section, select **Site app permissions**. - -> [!IMPORTANT] -> In SharePoint Online, select **Site collection app permissions**. This option is only visible to **Site Collection Administrators**. - -4. Copy the **client** section of the **App Identifier**. This is the identifier between the last "|" and the "@" sign, as shown in the figure. - - ![Selecting App Identifier](../images/SPD15-WFAppPermissions3.png) - -5. Go to the **Grant permission to an app** page. This must be done by browsing to the appinv.aspx page of the site. - - Example: `http://{hostname}/{the Site Collection}/_layouts/15/appinv.aspx`. - - > [!NOTE] - > The 'app' in this step refers to the workflow add-in in general and not just a specific workflow. Individual workflows cannot be access controlled. When you enable add-in permissions, you are enabling for all workflows within the Site Collection. - - For more information about setting up a workflow, see the [Blog article from Sympraxis Consulting: Looping Through Content in a SharePoint Site Workflow](http://sympmarc.com/series/looping-through-content-in-a-sharepoint-2013-site-workflow/) - - The following figure shows an example. - - ![The appinv.aspx URL example and page.](../images/SPD15-WFAppPermissions4.png) - -6. Paste the client ID in the **App Id** field, and then select **Lookup**, as shown in the previous figure. - -7. Paste the following code in the **Permission Request XML** field to grant full control permission *(note: this code block was updated on 12/29/17 to include the `AllowAppOnlyPolicy`)*. - - ```XML +1. Go to **Site settings**. +1. In the **Users and Permissions** section, select **Site app permissions**. + + > [!IMPORTANT] + > In SharePoint Online, select **Site collection app permissions**. This option is only visible to **Site Collection Administrators**. + +1. Copy the **client** section of the **App Identifier**. This is the identifier between the last "|" and the "@" sign, as shown in the figure. + + ![Selecting App Identifier](../images/SPD15-WFAppPermissions3.png) + +1. Go to the **Grant permission to an app** page. This must be done by browsing to the appinv.aspx page of the site. + + Example: `http://{hostname}/{the Site Collection}/_layouts/15/appinv.aspx`. + + > [!NOTE] + > The 'app' in this step refers to the workflow add-in in general and not just a specific workflow. Individual workflows cannot be access controlled. When you enable add-in permissions, you are enabling for all workflows within the Site Collection. + + For more information about setting up a workflow, see the [Blog article from Sympraxis Consulting: Looping Through Content in a SharePoint Site Workflow](http://sympmarc.com/series/looping-through-content-in-a-sharepoint-2013-site-workflow/) + + The following figure shows an example. + + ![The appinv.aspx URL example and page.](../images/SPD15-WFAppPermissions4.png) + +1. Paste the client ID in the **App Id** field, and then select **Lookup**, as shown in the previous figure. +1. Paste the following code in the **Permission Request XML** field to grant full control permission *(note: this code block was updated on 12/29/17 to include the `AllowAppOnlyPolicy`)*. + + ```XML + ``` + + > [!WARNING] + > There are no placeholders in the **Scope** value. It is a literal value. Enter it exactly as it appears here. - ``` + The following figure shows an example of the completed page _(note that the code in the **Permission Request XML** area does not reflect the recent update to the code in Step 7)_. - > [!WARNING] - > There are no placeholders in the **Scope** value. It is a literal value. Enter it exactly as it appears here. + ![Looking up an App Id.](../images/SPD15-WFAppPermissions5.png) - The following figure shows an example of the completed page _(note that the code in the **Permission Request XML** area does not reflect the recent update to the code in Step 7)_. - - ![Looking up an App Id.](../images/SPD15-WFAppPermissions5.png) +1. Select **Create**. +1. You are then asked to trust the workflow add-in, as shown in the following figure. Select **Trust It**. -8. Select **Create**. - -9. You are then asked to trust the workflow add-in, as shown in the following figure. Select **Trust It**. - - ![Trust the Workflow app.](../images/SPD15-WFAppPermissions6.png) - + ![Trust the Workflow app.](../images/SPD15-WFAppPermissions6.png) ## Wrap actions inside an App Step @@ -125,73 +111,60 @@ Finally, you need to wrap the workflow actions inside an App Step. The following ### To wrap actions inside an App Step -1. Open the app catalog site in SharePoint Designer. - -2. Create a new Custom List on which to run the workflow. In this example, the list name is **App Demo**. - -3. Select **Workflows** in the navigation window. - -4. Create a new **List Workflow** for the **App Demo** list, as shown in the figure. +1. Open the app catalog site in SharePoint Designer. +1. Create a new Custom List on which to run the workflow. In this example, the list name is **App Demo**. +1. Select **Workflows** in the navigation window. +1. Create a new **List Workflow** for the **App Demo** list, as shown in the figure. + + ![Create a new List Workflow.](../images/SPD15-WFAppPermissions7.png) + +1. Insert an **App Step**, as shown in the figure. + + ![Adding an App Step.](../images/SPD15-WFAppPermissions8.png) + +1. Insert a **Send an Email** action in the **App Step**. +1. Select the **Address book** button. In the **To** field, select **Workflow Lookup for a User**, and then select **Add** as shown in the figure. - ![Create a new List Workflow.](../images/SPD15-WFAppPermissions7.png) + ![Select Workflow lookup for a user.](../images/SPD15-WFAppPermissions9.png) -5. Insert an **App Step**, as shown in the figure. - - ![Adding an App Step.](../images/SPD15-WFAppPermissions8.png) +1. Enter the **Created By** field as the lookup value, as shown in the figure. -6. Insert a **Send an Email** action in the **App Step**. - -7. Select the **Address book** button. In the **To** field, select **Workflow Lookup for a User**, and then select **Add** as shown in the figure. + ![Lookup for Person dialog.](../images/SPD15-WFAppPermissions10.png) - ![Select Workflow lookup for a user.](../images/SPD15-WFAppPermissions9.png) - -8. Enter the **Created By** field as the lookup value, as shown in the figure. +1. Enter **Email** from the **App Demo** list in the email message body. +1. Select **OK** to return to the workflow. The completed workflow is shown in the figure. - ![Lookup for Person dialog.](../images/SPD15-WFAppPermissions10.png) - -9. Enter **Email** from the **App Demo** list in the email message body. - -10. Select **OK** to return to the workflow. The completed workflow is shown in the figure. + ![Email action in App Step.](../images/SPD15-WFAppPermissions11.png) - ![Email action in App Step.](../images/SPD15-WFAppPermissions11.png) - -11. Select the **Workflow Settings** icon in the ribbon, as shown in the figure. - - ![Workflow Settings icon in ribbon.](../images/SPD15-WFAppPermissions12.png) +1. Select the **Workflow Settings** icon in the ribbon, as shown in the figure. -12. Clear the check box next to **Automatically update the workflow status to the current stage name**, and then select **Publish**. - - ![Clear automatic updates check mark and publish.](../images/SPD15-WFAppPermissions13.png) - + ![Workflow Settings icon in ribbon.](../images/SPD15-WFAppPermissions12.png) - +1. Clear the check box next to **Automatically update the workflow status to the current stage name**, and then select **Publish**. + + ![Clear automatic updates check mark and publish.](../images/SPD15-WFAppPermissions13.png) ## Understand how it works To understand why elevating permissions for a workflow is required, consider that workflows are fundamentally add-ins for SharePoint, and they follow the same authorization rules of the add-in model. The default configuration for workflow is that the effective permissions of the workflow are an intersection of user permissions and the add-in permissions, as shown in the figure. - + ![Permissions diagram.](../images/SPD15-WFAppPermissions14.png) - + Two reasons why it is necessary to elevate permissions to create a workflow in the App Request list are: - By default, workflow only has write permission. - - The user has no permissions. - -The first step to solve this problem is to allow the application to authorize by using only its identity and ignoring that of the user. This is done by enabling the App Step feature. The second step grants full control permission to the workflow. - + +The first step to solve this problem is to allow the application to authorize by using only its identity and ignoring that of the user. This is done by enabling the App Step feature. The second step grants full control permission to the workflow. + The following diagram illustrates the change in permissions. - + ![Permissions matrix.](../images/SPD15-WFAppPermissions15.png) - - ## See also - [Blog article from the SharePoint Designer team: Workflow package and deploy scenario](https://blogs.msdn.microsoft.com/sharepointdesigner/2012/08/29/packaging-sharepoint-2013-list-site-and-reusable-workflow-and-how-to-deploy-the-package/) - [What's new in workflow in SharePoint](what-s-new-in-workflows-for-sharepoint.md) -- [Getting started with SharePoint workflow](get-started-with-workflows-in-sharepoint.md) +- [Getting started with SharePoint workflow](get-started-with-workflows-in-sharepoint.md) - [Workflow actions and activities reference for SharePoint](workflow-actions-and-activities-reference-for-sharepoint.md) - [Workflow development in SharePoint Designer and Visio](workflow-development-in-sharepoint-designer-and-visio.md) - - diff --git a/docs/general-development/create-hybrid-connectivity-apps-for-sharepoint.md b/docs/general-development/create-hybrid-connectivity-apps-for-sharepoint.md index 144aa4b6d..f88e805a7 100644 --- a/docs/general-development/create-hybrid-connectivity-apps-for-sharepoint.md +++ b/docs/general-development/create-hybrid-connectivity-apps-for-sharepoint.md @@ -1,231 +1,111 @@ --- title: Create hybrid connectivity apps for SharePoint description: This is an article with links to learn about the process of developing and deploying apps for SharePoint hybrid connectivity solutions. -ms.date: 06/07/2022 +ms.date: 05/18/2023 ms.assetid: 311f036e-3442-4497-b35e-442b665462d3 ms.localizationpriority: medium --- - # Create hybrid connectivity apps for SharePoint + Learn about the process of developing and deploying apps for SharePoint hybrid connectivity solutions. + ## Hybrid connectivity in SharePoint and SharePoint Online - As businesses move to using SharePoint Online, they need a way to expose large amounts of proprietary data safely and securely. To help solve this challenge, SharePoint introduced hybrid connectivity. - - - + The Business Connectivity Services (BCS) hybrid connectivity capability lets SharePoint consume data housed on-premises, inside corporate firewalls, and secured by various forms of authentication. With hybrid connectivity functionality, SharePoint Online can access this data securely over the web as if it was on the same internal network. Once hybrid connectivity is configured, users can work with data that is secured within the business' infrastructure. They can access and manipulate the data according to the permissions that they have been granted in SharePoint. - - - + For a complete description of how to configure a working hybrid solution, see [Hybrid for SharePoint](https://technet.microsoft.com/library/jj838715.aspx). This series of articles walks you through all the requirements of configuring data sources, reverse proxies, search, security, networking, and everything else needed to set up the end-to-end scenario. - - - -> **Caution:** -> To configure a hybrid SharePoint environment, you need a combination of expert skills and significant hands-on experience with SharePoint, SharePoint Online, and related products and technologies. We recommend that you engage Microsoft Consulting Services to provide technical guidance and support during the design and deployment of your hybrid environment. > For more information, see [Microsoft Services](https://www.microsoft.com/en-us/microsoft-365/products-apps-services). - - - +> [!CAUTION] +> To configure a hybrid SharePoint environment, you need a combination of expert skills and significant hands-on experience with SharePoint, SharePoint Online, and related products and technologies. We recommend that you engage Microsoft Consulting Services to provide technical guidance and support during the design and deployment of your hybrid environment. > For more information, see [Microsoft Services](https://www.microsoft.com/en-us/microsoft-365/products-apps-services). For you to be able to create an app that consumes data from an internal data source through BCS and the hybrid connection, this article assumes that you have already followed the procedures to configure your hybrid environment. - - - ## Create hybrid connectivity apps - Creating a hybrid SharePoint Add-in is essentially the same as creating any SharePoint Add-in. - - - -Follow these steps to create a hybrid app: - - - - -- [Prepare the data source](#bkmk_PrepareDataSource) - - -- [Create an SharePoint Add-in](#bkmk_CreateAnApp) - - -- [Create an external content type](#bkmk_CreateECT) - - -- [Deploy the hybrid app](#bkmk_DeployHybridApp) - - + +Follow these steps to create a hybrid app + +- [Prepare the data source](#prepare-the-data-source) +- [Create an SharePoint Add-in](#create-an-sharepoint-add-in) +- [To add an external content ty](#to-add-an-external-content-type) +- [Deploy the hybrid app](#deploy-the-hybrid-app) ### Prepare the data source - - -Most of the time, the data source is already in place and is servicing any number of business applications. However, that data may only be available from inside the corporate security infrastructure. If your data does exist on a server located on the inside of a corporate firewall, or is secured by some other means, the next step is to expose that data to BCS, which is also housed inside the firewall. A network device is configured to translate calls from SharePoint Online to the internal SharePoint farm. This device is referred to as a "reverse proxy" and allows the SharePoint Add-in located in the cloud to call into BCS located inside the firewall. BCS handles all the data connectivity from there. - - - -To make this data available to BCS, you should expose it as an OData source. You do this by creating an Internet Information Services (IIS) website that will host the service and allow BCS to talk to the data source through OData and Representational State Transfer (REST) endpoints. - - - -To create an OData endpoint, you will need to follow these steps for creating a Windows Communication Foundation (WCF) data service. - - - -### To create a WCF data service +Most of the time, the data source is already in place and is servicing any number of business applications. However, that data may only be available from inside the corporate security infrastructure. If your data does exist on a server located on the inside of a corporate firewall, or is secured by some other means, the next step is to expose that data to BCS, which is also housed inside the firewall. A network device is configured to translate calls from SharePoint Online to the internal ShePoint farm. This device is referred to as a "reverse proxy" and allows the SharePoint Add-in located in the cloud to call into BCS located inside the firewall. BCS handles all the data connectivity from there. + +To make this data available to BCS, you should expose it as an OData source. You do this by creating an Internet Information Services (IIS) website that will host the service and allow BCS to talk to the data source through OData and Representational State Transfer (REST) endpoints +To create an OData endpoint, you will need to follow these steps for creating a Windows Communication Foundation (WCF) data service. 1. Create an IIS website running at least Microsoft .NET Framework 4. Secure the site using basic authentication. - + > [!NOTE] - > It's not necessary for SharePoint to be installed on this server. In fact, for the sake of simplicity and performance, it's better if SharePoint is not installed on the server that hosts the WCF data service. - -2. Create a new project in Visual Studio 2012 using the **ASP.NET Empty Web Application** template. - - -3. In **Solution Explorer** add a new **ADO.NET Entity Data Model**. - - -4. Choose the **Generate from database** option in the **Entity Data Model Wizard**. - - -5. Select an existing connection, or create a new one. - - -6. Provide the URL and connection security information. - - -7. Select the items that you want to include in the model, and choose **Finish**. - - -8. Again in **Solution Explorer**, add a new **WCF Data Service** using the Visual Studio template. - - -9. Name the data service, and choose **Next**. - + > It's not necessary for SharePoint to be installed on this server. In fact, for the sake of simplicity and performance, it's better if SharePoint is not installed on the server thathosts the WCF data service + +1. Create a new project in Visual Studio 2012 using the **ASP.NET Empty Web Application** template. +1. In **Solution Explorer** add a new **ADO.NET Entity Data Model**. +1. Choose the **Generate from database** option in the **Entity Data Model Wizard**. +1. Select an existing connection, or create a new one. +1. Provide the URL and connection security information. +1. Select the items that you want to include in the model, and choose **Finish**. +1. Again in **Solution Explorer**, add a new **WCF Data Service** using the Visual Studio template. +1. Name the data service, and choose **Next**. + At this point, the entity model will be created and the resulting classes will be included in your project. - - -10. Set the security to the entities created by replacing the `/* TODO: put your data source class name here */` with the class name of the entity model you just created and specifying which entities you want to grant permissions to. - - -For a complete tutorial of how to set this up, see the following: - - - - -- [Getting Started With OData Part 1: Building an OData Service](https://msdn.microsoft.com/data/gg601462) - - -- [Quickstart (WCF Data Services)](https://msdn.microsoft.com/library/cc668796.aspx) - - -### Create an SharePoint Add-in - +1. Set the security to the entities created by replacing the `/* TODO: put your data source class name here */` with the class name of the entity model you just created and specifying which entities you want to grant permissions to. -One of the assumptions we are making here is that you are developing your app inside the corporate firewall. This represents a scenario where a developer working for a company would have a computer located behind the protection of the security infrastructure, developing and testing the app until it is ready to be deployed. This simplifies the process of connecting to the data source from Visual Studio, and uses Office Developer Tools for Visual Studio 2013 to automatically generate the external content type in the next step. - - - +For a complete tutorial of how to set this up, see the following: -### To create a new app +- [Getting Started With OData Part 1: Building an OData Service](https://msdn.microsoft.com/data/gg601462) +- [Quickstart (WCF Data Services)](https://msdn.microsoft.com/library/cc668796.aspx) +### Create an SharePoint Add-in -1. Open Visual Studio 2012 on your development computer that has Office Developer Tools for Visual Studio 2013 and SharePoint installed. - - -2. Create a new app for SharePoint. - - -3. Specify the name of the app, the local SharePoint URL that will host your site for testing, and how you want the app to be hosted. Choose **Finish**. - - +One of the assumptions we are making here is that you are developing your app inside the corporate firewall. This represents a scenario where a developer working for a company would have a computer located behind the protection of the security infrastructure, developing and testing the app until it is ready to be deployed. This simplifies the process of connecting to the data source from Visual Studio, and uses Office Developer Tools for Visual Studio 2013 to automatically generate the external content type in e next step. -### Create an external content type - +### To create a new app + +1. Open Visual Studio 2012 on your development computer that has Office Developer Tools for Visual Studio 2013 and SharePoint stalled. +1. Create a new app for SharePoint. +1. Specify the name of the app, the local SharePoint URL that will host your site for testing, and ### Create an external content type To add a BDC model or external content type to your project, do the following. - - - ### To add an external content type - 1. With your new project still open, open the shortcut menu for the solution, and choose **Add**, **Content types for an External Data source**. - - -2. The first page of the wizard is used to specify the URL of the data service. On the **Specify OData Source** page, enter the URL of the OData service that you want to connect to. The URL should resemble the following: **http://services.odata.org/Northwind/Northwind.svc/**. - - -3. Choose a name for your OData source, and then choose **Next**. - - -4. A list of data entities that are being exposed by the OData service appears. Make sure that the **Create list instances for the selected data entities** check box is selected. - - -5. Select one or more of the entities, and choose **Finish**. - - -6. The last thing you have to do before deployment is modify the URL in your newly created external content type file. - - Open the .ect file in an XML editor. - - -7. Modify the `ODataServiceMetadataUrl` property to point to the URL that allows access through the reverse proxy. - - -8. Modify the `ODataServiceUrl` property with the URL that allows access through the reverse proxy. - - +1. The first page of the wizard is used to specify the URL of the data service. On the **Specify OData Source** page, enter the URL of the OData service that you want to connect to. The URL should resemble the following: `http://services.odata.org/Northwind/Northwind.svc/`. +1. Choose a name for your OData source, and then choose **Next**. +1. A list of data entities that are being exposed by the OData service appears. Make sure that the +1. The last thing you have to do before deployment is modify the URL in your newly created external content type file. + + Open the **\*.ect** file in an XML editor. + +1. Modify the `ODataServiceMetadataUrl` property to point to the URL that allows access through the reverse proxy. +1. Modify the `ODataServiceUrl` property with the URL that allows access through the reverse proxy. + For information about how to add an OData-based external content type, see [How to: Create an external content type from an OData source in SharePoint](how-to-create-an-external-content-type-from-an-odata-source-in-sharepoint.md). - - - ### Deploy the hybrid app - When it is time to deploy your app, you have a couple of choices. You can deploy it directly to a tenancy using F5 deployment, or you can package it using the publishing features of Visual Studio to create an .app file. This file can then be given to the SharePoint Online tenant administrator and uploaded. - - - -For information about deploying SharePoint Add-ins, see the following: - - - - -- [Deploying and installing SharePoint Add-ins: methods and options](https://msdn.microsoft.com/library/d15a74a7-3c10-485a-9885-7ef11aaa0d90%28Office.15%29.aspx) - - -- [Publish SharePoint Add-ins by using Visual Studio](https://msdn.microsoft.com/library/8137d0fa-52e2-4771-8639-60af80f693bb%28Office.15%29.aspx) - - -You can also take the BDCM file created for the external content type and extract that to be used at any level above the app. This is demonstrated in [How to: Convert an add-in-scoped external content type to tenant-scoped](how-to-convert-an-add-in-scoped-external-content-type-to-tenant-scoped.md). - - - + +For information about deploying SharePoint Add-ins, see the following: + +- [Deploying and installing SharePoint Add-ins: methods and options](https://msdn.microsoft.com/library/d15a74a7-3c10-485a-9885-7ef11aaa0d90%28Office.15%29.aspx + +- [Publish SharePoint Add-ins by using Visual Studio](https://msdn.microsoft.com/library/8137d0fa-52e2-4771-8639-60af80f693bb%28Office.15%29.aspx) + +You can also take the BDCM file created for the external content type and extract that to be used at any level above the app. This is demonstrated in [How to: Convert an add-in-scoped external ## See also - - - -- [Hybrid for SharePoint](https://technet.microsoft.com/library/jj838715.aspx) - - -- [Business Connectivity Services in SharePoint](business-connectivity-services-in-sharepoint.md) - - -- [How to: Create an external content type from an OData source in SharePoint](how-to-create-an-external-content-type-from-an-odata-source-in-sharepoint.md) - - -- [Publish SharePoint Add-ins by using Visual Studio](https://msdn.microsoft.com/library/8137d0fa-52e2-4771-8639-60af80f693bb%28Office.15%29.aspx) - - +- [Hybrid for SharePoint](https://technet.microsoft.com/library/jj838715.aspx) +- [Business Connectivity Services in SharePoint](business-connectivity-services-in-sharepoint.md) +- [How to: Create an external content type from an OData source in SharePoint](how-to-create-an-external-content-type-from-an-odata-source-in-sharepoint.md) diff --git a/docs/general-development/creating-a-workflow-by-using-sharepoint-designer-and-the-sharepoint-wo.md b/docs/general-development/creating-a-workflow-by-using-sharepoint-designer-and-the-sharepoint-wo.md index ca3ae4e44..2a41cd9e9 100644 --- a/docs/general-development/creating-a-workflow-by-using-sharepoint-designer-and-the-sharepoint-wo.md +++ b/docs/general-development/creating-a-workflow-by-using-sharepoint-designer-and-the-sharepoint-wo.md @@ -1,212 +1,86 @@ --- title: Creating a workflow by using SharePoint Designer 2013 and the SharePoint Workflow platform description: This is an article with links to learn about creating a workflow by using SharePoint Designer 2013 and the SharePoint Workflow platform. -ms.date: 06/07/2022 +ms.date: 05/09/2023 ms.assetid: c05e0127-c6f5-48b8-b8f2-cbcc30149c8b ms.localizationpriority: high --- +# Creating a workflow by using SharePoint Designer 2013 and the SharePoint Workflow platform +Learn how to install, open, and create a workflow by using SharePoint Designer 2013 and the SharePoint Workflow platform. -# Creating a workflow by using SharePoint Designer 2013 and the SharePoint Workflow platform -Learn how to install, open, and create a workflow by using SharePoint Designer 2013 and the SharePoint Workflow platform. - -> [!NOTE] -> SharePoint 2010 workflows have been retired since August 1, 2020 for new tenants and removed from existing tenants on November 1, 2020. If you’re using SharePoint 2010 workflows, we recommend migrating to Power Automate or other supported solutions. For more info, see [SharePoint 2010 workflow retirement](https://support.microsoft.com/office/sharepoint-2010-workflow-retirement-1ca3fff8-9985-410a-85aa-8120f626965f). +> [!CAUTION] +> SharePoint 2010 workflows have been retired since August 1, 2020 for new tenants and removed from existing tenants on November 1, 2020. If you’re using SharePoint 2010 workflows, we recommend migrating to Power Automate or other supported solutions. For more information, see [SharePoint 2010 workflow retirement](https://support.microsoft.com/office/sharepoint-2010-workflow-retirement-1ca3fff8-9985-410a-85aa-8120f626965f). +> [!CAUTION] +> SharePoint 2013 workflows are scheduled for retirement in April 2024. For more information, see: [SharePoint 2013 workflow retirement](https://support.microsoft.com/office/sharepoint-2013-workflow-retirement-4613d9cf-69aa-40f7-b6bf-6e7831c9691e). ## Install SharePoint Designer 2013 - -SharePoint Designer 2013 is a free download. To download and install SharePoint Designer 2013 follow these steps: - - - +SharePoint Designer 2013 is a free download. To download and install SharePoint Designer 2013 follow these steps: ### To install SharePoint Designer 2013 - -1. Open your web browser and navigate to the Microsoft Download Center: [https://www.microsoft.com/download](https://www.microsoft.com/download). - - -2. Type SharePoint Designer 2013 in the search field. - - -3. Click the link for "SharePoint Designer 2013". - - -4. Read the overview, system requirements, and installation instructions. Make sure your system is compatible. - - -5. Select your platform type: 64-bit ( **x64**) or 32-bit ( **x86**) as shown in the figure. - - -6. Follow the instructions to install SharePoint Designer 2013. - - +1. Open your web browser and navigate to the Microsoft Download Center: [https://www.microsoft.com/download](https://www.microsoft.com/download). +1. Type SharePoint Designer 2013 in the search field. +1. Click the link for "SharePoint Designer 2013". +1. Read the overview, system requirements, and installation instructions. Make sure your system is compatible. +1. Select your platform type: 64-bit ( **x64**) or 32-bit ( **x86**) as shown in the figure. +1. Follow the instructions to install SharePoint Designer 2013. **Figure: SharePoint Designer 2013 download page** - - - - - - - ![The SharePoint Designer 2013 Download page.](../images/SPD15-install-connect-1.png) - - - - - - - - - - - ## Open SharePoint Designer 2013 and connect to a SharePoint site - -SharePoint Designer 2013 installs as an Office 2013 application. To open SharePoint Designer 2013 and connect to a SharePoint site follow these steps: - - - -2013 -### To open SharePoint Designer 2013 and connect to a SharePoint site +SharePoint Designer 2013 installs as an Office 2013 application. To open SharePoint Designer 2013 and connect to a SharePoint site follow these steps: +### To open SharePoint Designer 2013 and connect to a SharePoint site -1. Open SharePoint Designer 2013 by selecting it on the **Start** menu. Click **Start** icon, click **All Programs**, click **Microsoft Office 2013**, and then click **SharePoint Designer 2013**. - - -2. Click **Open Site** on the SharePoint Designer 2013 start page. - - -3. Enter the SharePoint site that you want to connect to. For example, http://www.contoso.com/sites/a-sharepoint-site. - - -4. Click **Open** to open the site. - - -5. Enter your credentials, if prompted. (If security is not integrated with the computer you signed in on then you are prompted to enter your credentials.) Make sure to use credentials that have access to the SharePoint site. - - +1. Open SharePoint Designer 2013 by selecting it on the **Start** menu. Click **Start** icon, click **All Programs**, click **Microsoft Office 2013**, and then click **SharePoint Designer 2013**. +1. Click **Open Site** on the SharePoint Designer 2013 start page. +1. Enter the SharePoint site that you want to connect to. For example, `https://www.contoso.com/sites/a-sharepoint-site`. +1. Click **Open** to open the site. +1. Enter your credentials, if prompted. (If security is not integrated with the computer you signed in on then you are prompted to enter your credentials.) Make sure to use credentials that have access to the SharePoint site. ## Create a List workflow based on the SharePoint Workflow platform - SharePoint Designer 2013 can be used for many important tasks. The navigational pane is used to switch between different aspects of SharePoint Designer 2013. To create a new List workflow based on the SharePoint Workflow platform, follow these steps: - - - ### To create a workflow based on the SharePoint Workflow platform - 1. Click the Workflows node in the Navigation pane. - - -2. Click the **List Workflow** drop-down in the **New** section of the ribbon, as shown in the figure. - - -3. Select the list that you want to associate with the new workflow. - - -4. On the **Create List Workflow** dialog box, enter a name and description for the workflow and then make sure that the **Platform Type** is set to **SharePoint 2013 Workflow**, as shown in the figure. - +1. Click the **List Workflow** drop-down in the **New** section of the ribbon, as shown in the figure. +1. Select the list that you want to associate with the new workflow. +1. On the **Create List Workflow** dialog box, enter a name and description for the workflow and then make sure that the **Platform Type** is set to **SharePoint 2013 Workflow**, as shown in the figure. + > [!NOTE] - > If you do not see SharePoint Workflow as an available platform type then Workflow Manager is not configured to work with the SharePoint farm. See [Configure Workflow Manager to work with the SharePoint Server 2013 Farm](https://technet.microsoft.com/library/jj658588.aspx#section5). + > If you do not see SharePoint Workflow as an available platform type then Workflow Manager is not configured to work with the SharePoint farm. See [Configure Workflow Manager to work with the SharePoint Server 2013 Farm](https://technet.microsoft.com/library/jj658588.aspx#section5). -5. Click **OK** to create the workflow. - - +1. Click **OK** to create the workflow. **Figure: The ribbon button for creating a new list workflow** - - - - - - - ![SharePoint Designer 2013 - New List Workflow](../images/SPD15-install-connect-2.png) - - - - - - - - - - - **Figure: Create List Workflow dialog box** - - - - - - - ![Workflow Creation Dialog](../images/SPD15-install-connect-3.png) - - - - - - - - - - - -Now that the workflow is created, you can add Actions, Conditions, Stages, Steps, and Loops to build your workflow. These workflow components are available in the ribbon of SharePoint Designer 2013, as shown in the figure. - - - -**Figure: Workflow items for the SharePoint Workflow platform** +Now that the workflow is created, you can add Actions, Conditions, Stages, Steps, and Loops to build your workflow. These workflow components are available in the ribbon of SharePoint Designer 2013, as shown in the figure. - - - +**Figure: Workflow items for the SharePoint Workflow platform** - - - ![Workflow items in the ribbon.](../images/SPD15-install-connect-4.png) - + > [!NOTE] > The previous procedure is used to create a List workflow. A Reusable workflow or Site workflow can be created using the same procedure with the following modification. Instead of selecting the List Workflow button in the ribbon select the **Reusable Workflow** or **Site Workflow** button when creating the workflow. - - - To learn more about the available components of workflow development, see [Workflow actions quick reference (SharePoint Workflow platform)](workflow-actions-quick-reference-sharepoint-workflow-platform.md). - - - ## See also - - - -- [What's new in workflow in SharePoint](https://msdn.microsoft.com/library/6ab8a28b-fa2f-4530-8b55-a7f663bf15ea.aspx) - - -- [Getting started with SharePoint workflow](https://msdn.microsoft.com/library/cc73be76-a329-449f-90ab-86822b1c2ee8.aspx) - - -- [Workflow development in SharePoint Designer and Visio](workflow-development-in-sharepoint-designer-and-visio.md) - - - - - - +- [What's new in workflow in SharePoint](https://msdn.microsoft.com/library/6ab8a28b-fa2f-4530-8b55-a7f663bf15ea.aspx) +- [Getting started with SharePoint workflow](https://msdn.microsoft.com/library/cc73be76-a329-449f-90ab-86822b1c2ee8.aspx) +- [Workflow development in SharePoint Designer and Visio](workflow-development-in-sharepoint-designer-and-visio.md) diff --git a/docs/general-development/custom-content-processing-with-the-content-enrichment-web-service-callout.md b/docs/general-development/custom-content-processing-with-the-content-enrichment-web-service-callout.md index 76071461d..7c4275829 100644 --- a/docs/general-development/custom-content-processing-with-the-content-enrichment-web-service-callout.md +++ b/docs/general-development/custom-content-processing-with-the-content-enrichment-web-service-callout.md @@ -1,177 +1,96 @@ --- title: Custom content processing with the Content Enrichment web service callout description: This is an article to learn about custom content processing with the Content Enrichment web service callout. -ms.date: 06/07/2022 +ms.date: 05/18/2023 ms.assetid: bdda92c8-9c8d-416e-9a6b-4a9373686fa0 ms.localizationpriority: medium --- - - # Custom content processing with the Content Enrichment web service callout + Learn about the content enrichment web service callout in SharePoint that enables developers to create an external web service to modify managed properties for crawled items during content processing. + Search in SharePoint enables users to modify the managed properties of crawled items before they are indexed by calling out to an external content enrichment web service. The ability to modify managed properties for items during content processing is helpful when performing tasks such as data cleansing, entity extraction, classification, and tagging. - - - +![Content enrichment within content processing](../images/SP15_Content_Enrichment.gif) **Figure 1. Content enrichment within content processing** - - - - - - - -![Content enrichment within content processing](../images/SP15_Content_Enrichment.gif) - - - -Figure 1 shows a part of the process that takes place in the content processing component. The content enrichment web service is a SOAP-based service that you can create to receive a callout from the web service client inside the content processing component. Based on Figure 1, the web service client refers to the Content Enrichment operator inside the content processing component; theweb service refers to the SOAP web service that you implement.The web service receives a configurable payload from the content processing component. Then, the resulting response from the web service is merged into the crawled item before it is added to the search index. The web service client works with managed properties that you can configure as input properties or as output properties. Input properties are sent to the web service; output properties are returned by the web service. Certain managed properties are hidden or are read-only and can't be sent to the web service or received from the web service. See [How to list all read-only managed properties for the Content Enrichment web service](#SP15contentprocess_read-only_managed_properties) for information about how to verify which managed properties are read-only. - -> **Important:** -> The content enrichment callout step can only be configured with a single web service endpoint. Any kind of fault tolerance, or routing capabilities to support multiple implementations must be handled by the developer implementing the web service. In addition, the developer may have various web service implementations hosted at different endpoints; however, at any given time, only one of these endpoints can be used in the configuration. - - - +Figure 1 shows a part of the process that takes place in the content processing component. The content enrichment web service is a SOAP-based service that you can create to receive a callout from the web service client inside the content processing component. Based on Figure 1, the web service client refers to the Content Enrichment operator inside the content processing component; the web service refers to the SOAP web service that you implement.The web service receives a configurable payload from the content processing component. Then, the resulting response from the web service is merged into the crawled item before it is added to the search index. The web service client works with managed properties that you can configure as input properties or as output properties. Input properties are sent to the web service; output properties are returned by the web service. Certain managed properties are hidden or are read-only and can't be sent to the web service or received from the web service. See [How to list all read-only managed properties for the Content Enrichment web service](#how-to-list-all-read-only-managed-properties-for-the-content-enrichment-web-service) for information about how to verify which managed properties are read-only. +> [!IMPORTANT] +> The content enrichment callout step can only be configured with a single web service endpoint. Any kind of fault tolerance, or routing capabilities to support multiple implementations must be handled by the developer implementing the web service. In addition, the developer may have various web service implementations hosted at different endpoints; however, at any given time, only one of these endpoints can be used in the configuration. ## Content enrichment web service contract - The web service client is a SOAP (version 1.1) RPC client with a predefined behavior. The web service contract has the following characteristics: - - - - The content processing component sends a SOAP RPC call to a configurable endpoint over HTTP. - - - The payload contains an array of property objects. - - - The web service performs some custom logic on the array of property objects, and returns an array of modified or new property objects. - - - The web service must send a response to the web service client within a given timeout. - - - No specific authentication or encryption mechanisms are supported as part of the contract. You can, however, apply your own security on the transport mechanism. - - ## Configuring the Content Enrichment web service client - To configure the web service client, you use the following Windows PowerShell cmdlets: - - - - -- [Get-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219783%28office.15%29.aspx) - - -- [Set-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219659%28office.15%29.aspx) - - -- [Remove-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219742%28office.15%29.aspx) - - -- [New-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219502%28office.15%29.aspx) - - + +- [Get-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219783%28office.15%29.aspx) +- [Set-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219659%28office.15%29.aspx) +- [Remove-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219742%28office.15%29.aspx) +- [New-SPEnterpriseSearchContentEnrichmentConfiguration](https://technet.microsoft.com/library/jj219502%28office.15%29.aspx) + Table 1 lists the properties you can configure through the Windows PowerShell cmdlets mentioned previously. - - - **Table 1. Properties that are configurable for the client by using Windows PowerShell cmdlets** - -|**Configuration property**|**Description**|**Default value**| -|:-----|:-----|:-----| -|**Endpoint**
|Specifies the URL of the external web service.
|Empty.
| -|**InputProperties**
|The managed properties that the external web service receives.
|Empty.
| -|**OutputProperties**
|The managed properties that the external web service returns.
|Empty.
| -|**Timeout**
|The amount of time until the web service times out in milliseconds.
Depending on **FailureMode**, the item fails to be processed or a warning is written to the ULS log.
|5000 milliseconds; Valid range [100, 30000].
| -|**SendRawData**
|Enables or disables sending raw data to the web service.
|False.
| -|**MaxRawDataSize**
|The maximum size of raw data sent to the web service in kilobytes (KB). If the binary data of an item exceeds this limit, the item is not sent. This does not prevent the **InputProperties** from being sent, and the **OutputProperties** from being received.
|5120 kilobytes.
| -|**FailureMode**
|Controls the behavior of the web service client when errors occur. When **FailureMode** is set to **ERROR**, any problems that occur during content enrichment processing send a failed callback for that particular item.
When **FailureMode** is set to **WARNING**, the item is indexed, without any modifications by the web service and a warning is written to the ULS log.
|Error.
| -|**DebugMode**
|A mode that when set to **true** enables the content enrichment client to send all managed properties to the client without expecting any properties in return. Any configured **Trigger** property, **InputProperties** property, and **OutputProperties** property are ignored.
|False.
| -|**Trigger**
|A **Boolean** predicate that is executed on every crawled item. If the predicate evaluates to **true**, the record is sent to the web service. Otherwise, the item is passed through to the search index.
|Empty.
| - +| **Configuration property** | **Description** | **Default value** | +| :------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------- | +| **Endpoint** | Specifies the URL of the external web service. | Empty. | +| **InputProperties** | The managed properties that the external web service receives. | Empty. | +| **OutputProperties** | The managed properties that the external web service returns. | Empty. | +| **Timeout** | The amount of time until the web service times out in milliseconds. Depending on **FailureMode**, the item fails to be processed or a warning is written to the ULS log. | 5000 milliseconds; Valid range [100, 30000]. | +| **SendRawData** | Enables or disables sending raw data to the web service. | False. | +| **MaxRawDataSize** | The maximum size of raw data sent to the web service in kilobytes (KB). If the binary data of an item exceeds this limit, the item is not sent. This does not prevent the **InputProperties** from being sent, and the **OutputProperties** from being received. | 5120 kilobytes. | +| **FailureMode** | Controls the behavior of the web service client when errors occur. When **FailureMode** is set to **ERROR**, any problems that occur during content enrichment processing send a failed callback for that particular item. When **FailureMode** is set to **WARNING**, the item is indexed, without any modifications by the web service and a warning is written to the ULS log. | Error. | +| **DebugMode** | A mode that when set to **true** enables the content enrichment client to send all managed properties to the client without expecting any properties in return. Any configured **Trigger** property, **InputProperties** property, and **OutputProperties** property are ignored. | False. | +| **Trigger** | A **Boolean** predicate that is executed on every crawled item. If the predicate evaluates to **true**, the record is sent to the web service. Otherwise, the item is passed through to the search index. | Empty. | ### How to list all read-only managed properties for the Content Enrichment web service - Certain managed properties are read-only and cannot be output from the web service. These properties can be listed by using the [Get-SPEnterpriseSearchServiceApplication](https://technet.microsoft.com/library/ff608050%28office.15%29.aspx) and [Get-SPEnterpriseSearchMetadataManagedProperty](https://technet.microsoft.com/library/ff607560%28office.15%29.aspx)Windows PowerShell cmdlets, shown in the following example: - - - - -``` +```powershell $ssa = Get-SPEnterpriseSearchServiceApplication Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $ssa | ?{$_.IsReadOnly -or $_.MappingDisallowed -or $_.DeleteDisallowed} - ``` - ## About trigger conditions for configuring the web service callout - A trigger condition is an expression that is used to configure the web service callout. If a trigger condition evaluates to **true**, the web service client performs a callout for that record. If a trigger condition evaluates to **false**, the web service client does not perform a callout and passes the crawled item to the search index. Alternatively, if no trigger condition is configured; all items are sent to the web service. - - - -Trigger conditions use an expression language to refer to the values of managed properties. You can use the operators and functions in the expression language to build simple or complex trigger conditions so you can determine when to perform a web service callout. - - - + +Trigger conditions use an expression language to refer to the values of managed properties. You can use the operators and functions in the expression language to build simple or complex trigger conditions so you can determine when to perform a web service callout. + Table 2 lists examples of trigger conditions. - - - **Table 2. Trigger condition examples for configuring the Content Enrichment web service callout** +| **Expression** | **Description** | **Requirements** | +| :-------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------- | +| MP1 > 2 | Returns **true** if the value of the managed property named MP1 is greater than 2. | MP1 must have a numeric type. | +| IsNull(MP2) | Returns **true** if the managed property named MP2 is not present for the crawled item or is empty/null. | MP2 can be of any type. | +| StartsWith(MP1, "sample") AND MP2 != 18 | Returns **true** if the value in the managed property MP1 starts with "sample" and the value of managed property MP2 is not 18. | MP1 must be of type **string** and MP2 must be a numeric type. | +| IsDay(MP1, 2009, 12, 24) | Checks whether the managed property MP1 contains a **DateTime** that falls on December 24, 2009. | MP1 must be of type **DateTime**. | -|**Expression**|**Description**|**Requirements**| -|:-----|:-----|:-----| -|MP1 > 2
|Returns **true** if the value of the managed property named MP1 is greater than 2.
|MP1 must have a numeric type.
| -|IsNull(MP2)
|Returns **true** if the managed property named MP2 is not present for the crawled item or is empty/null.
|MP2 can be of any type.
| -|StartsWith(MP1, "sample") AND MP2 != 18
|Returns **true** if the value in the managed property MP1 starts with "sample" and the value of managed property MP2 is not 18.
|MP1 must be of type **string** and MP2 must be a numeric type.
| -|IsDay(MP1, 2009, 12, 24)
|Checks whether the managed property MP1 contains a **DateTime** that falls on December 24, 2009.
|MP1 must be of type **DateTime**.
| - -See [Trigger expressions syntax in SharePoint](trigger-expressions-syntax-in-sharepoint.md) for the elements that can be used in a trigger expression and a list of supported functions. - - - +See [Trigger expressions syntax in SharePoint](trigger-expressions-syntax-in-sharepoint.md) for the elements that can be used in a trigger expression and a list of supported functions. ## Implementing the Content Enrichment external web service - -For a basic implementation, do the following: - - - +For a basic implementation, do the following: 1. Include the **Microsoft.Office.Server.Search.ContentProcessingEnrichment.dll** located in `C:\\Program Files\\Microsoft Office Servers\\15.0\\Search\\Applications\\External` in your project as a reference. - - -2. Implement **IContentProcessingEnrichmentService** as a web service. - - +1. Implement **IContentProcessingEnrichmentService** as a web service. ## See also - - - -- [Configure search in SharePoint](configure-search-in-sharepoint.md) - - -- [Custom content processing with the Content Enrichment web service callout](custom-content-processing-with-the-content-enrichment-web-service-callout.md) - - +- [Configure search in SharePoint](configure-search-in-sharepoint.md) +- [Custom content processing with the Content Enrichment web service callout](custom-content-processing-with-the-content-enrichment-web-service-callout.md) diff --git a/docs/general-development/custom-word-breakers-in-sharepoint-server.md b/docs/general-development/custom-word-breakers-in-sharepoint-server.md index 98753b690..c4869dcbb 100644 --- a/docs/general-development/custom-word-breakers-in-sharepoint-server.md +++ b/docs/general-development/custom-word-breakers-in-sharepoint-server.md @@ -1,293 +1,99 @@ --- title: Custom word breakers in SharePoint description: Describes word breaking in SharePoint and provides steps on how to switch to a custom word breaker in SharePoint. -ms.date: 06/09/2022 +ms.date: 05/09/2023 ms.assetid: d18b48d4-987c-4228-9932-30d5b30f86a2 ms.localizationpriority: medium --- - # Custom word breakers in SharePoint -Learn about word breaking in SharePoint. -Word breaking is one of the key Natural Language Processing (NLP) features that enable search and improve search results (or recall). Word breakers split a stream of text into individual words or tokens on which you can base additional language processing. Word breakers are language-specific. In addition to built-in word breakers, Search in SharePoint enables the use of custom word breakers so that users can tune word breaking behavior according to their needs. See [Supported languages for word breaker customizations in SharePoint](#SP15_SupportedLanguages) for a list languages supported for word breaker customization. - - - -For information on how to write a word breaker refer to the following articles -- [Implementing a Word Breaker](https://msdn.microsoft.com/library/ms693186%28v=vs.85%29.aspx) - - -- [IWordBreaker interface](https://msdn.microsoft.com/library/ms691079%28v=vs.85%29.aspx) - - +Word breaking is one of the key Natural Language Processing (NLP) features that enable search and improve search results (or recall). Word breakers split a stream of text into individual words or tokens on which you can base additional language processing. Word breakers are language-specific. In addition to built-in word breakers, Search in SharePoint enables the use of custom word breakers so that users can tune word breaking behavior according to their needs. See [Supported languages for word breaker customizations in SharePoint](#supported-languages-for-word-breaker-customizations-in-sharepoint) for a list languages supported for word breaker customization. -## How to switch to a custom word breaker in SharePoint - +For information on how to write a word breaker refer to the following articles + +- [Implementing a Word Breaker](https://msdn.microsoft.com/library/ms693186%28v=vs.85%29.aspx) +- [IWordBreaker interface](https://msdn.microsoft.com/library/ms691079%28v=vs.85%29.aspx) +## How to switch to a custom word breaker in SharePoint -> **Caution:** -> When you replace existing word breakers, you modify the registry at your own risk. Serious problems might occur if you modify the registry incorrectly by using Registry Editor or by using another method. These problems might require that you reinstall the operating system. Microsoft cannot ensure that these problems can be solved. Switching to a different word breaker might also cause serious problems during indexing and querying. Before you modify the registry, back up the registry and ensure that you know how to restore the registry if a problem occurs. - - - +> [!CAUTION] +> When you replace existing word breakers, you modify the registry at your own risk. Serious problems might occur if you modify the registry incorrectly by using Registry Editor or by using another method. These problems might require that you reinstall the operating system. Microsoft cannot ensure that these problems can be solved. Switching to a different word breaker might also cause serious problems during indexing and querying. Before you modify the registry, back up the registry and ensure that you know how to restore the registry if a problem occurs. Take the following steps to replace the existing word breaker with a custom word breaker or replace the existing word breaker with a word breaker in another language. - - - 1. Open the Registry Editor, as follows: - 1. Choose **Start**, and then choose **Run**. - - -2. In the **Open** dialog box, type **Regedit**, and then choose **OK**. - - -2. In Registry Editor, select the following registry subkey: - +1. In the **Open** dialog box, type **Regedit**, and then choose **OK**. +1. In Registry Editor, select the following registry subkey: + **HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office Server\\15.0\\Search\\Setup\\ContentIndexCommon\\LanguageResources\\Default\\** _language from the list below_ - - -3. In the right pane, open the shortcut menu for the **WBDLLPathOverride** registry value, and then choose **Modify**. - - -4. In the **Edit String** dialog box, in the **Value data** box, type the path to your custom word breaker DLL, and then choose **OK**. The new DLL should be located in the same path as the existing DLL that is being replaced. - - -5. In the right pane, open the shortcut menu for the **WBreakerClass** registry value, and then choose **Modify**. - - -6. In the **Edit String** dialog box, in the **Value data** box, type the class ID of your custom word breaker, and then choose **OK**. - - -7. Restart the SharePoint Search Host Controller and SharePoint. - - -8. Do a full re-crawl. - - + +1. In the right pane, open the shortcut menu for the **WBDLLPathOverride** registry value, and then choose **Modify**. +1. In the **Edit String** dialog box, in the **Value data** box, type the path to your custom word breaker DLL, and then choose **OK**. The new DLL should be located in the same path as the existing DLL that is being replaced. +1. In the right pane, open the shortcut menu for the **WBreakerClass** registry value, and then choose **Modify**. +1. In the **Edit String** dialog box, in the **Value data** box, type the class ID of your custom word breaker, and then choose **OK** + + Restart the SharePoint Search Host Controller and SharePoint. + +1. Do a full re-crawl. ## Supported languages for word breaker customizations in SharePoint - The following languages are supported for word breaker customization: - - - -Arabic - - - -Bengali - - - -Bulgarian - - - -Catalan - - - -Chinese (People's Republic of China) - - - -Chinese (Taiwan) - - - -Croatian - - - -Czech - - - -Danish - - - -Dutch (Dutch) - - - -English (United States) - - - -Estonian - - - -Finnish - - - -French (Standard) - - - -German (Standard) - - - -Greek - - - -Gujarati - - - -Hebrew - - - -Hindi - - - -Hungarian - - - -Icelandic - - - -Indonesian - - - -Italian (Default) - - - -Japanese - - - -Kannada - - - -Kazakh - - - -Korean - - - -Latvian - - - -Lithuanian - - - -Malay - - - -Malayalam - - - -Marathi - - - -Norwegian - - - -Polish - - - -Portuguese (Portuguese) - - - -Punjabi - - - -Romanian - - - -Russian - - - -Serbian (Cyrillic) - - - -Slovak - - - -Slovenian - - - -Spanish (Modern Sort) - - - -Swedish - - - -Tamil - - - -Telugu - - - -Thai - - - -Turkish - - - -Ukrainian - - - -Urdu - - - -Vietnamese - - - -## See also - +- Arabic +- Bengali +- Bulgarian +- Catalan +- Chinese (People's Republic of China) +- Chinese (Taiwan) +- Croatian +- Czech +- Danish +- Dutch (Dutch) +- English (United States) +- Estonian +- Finnish +- French (Standard) +- German (Standard) +- Greek +- Gujarati +- Hebrew +- Hindi +- Hungarian +- Icelandic +- Indonesian +- Italian (Default) +- Japanese +- Kannada +- Kazakh +- Korean +- Latvian +- Lithuanian +- Malay +- Malayalam +- Marathi +- Norwegian +- Polish +- Portuguese (Portuguese) +- Punjabi +- Romanian +- Russian +- Serbian (Cyrillic) +- Slovak +- Slovenian +- Spanish (Modern Sort) +- Swedish +- Tamil +- Telugu +- Thai +- Ukrainian +- Urdu +- Vietnamese +## See also -- [Configure search in SharePoint](configure-search-in-sharepoint.md) - - -- [Implementing a Word Breaker](https://msdn.microsoft.com/library/ms693186%28v=vs.85%29.aspx) - - -- [IWordBreaker interface](https://msdn.microsoft.com/library/ms691079%28v=vs.85%29.aspx) - - - +- [Configure search in SharePoint](configure-search-in-sharepoint.md) +- [Implementing a Word Breaker](https://msdn.microsoft.com/library/ms693186%28v=vs.85%29.aspx) +- [IWordBreaker interface](https://msdn.microsoft.com/library/ms691079%28v=vs.85%29.aspx) diff --git a/docs/general-development/developing-with-duet-enterprise-2-0.md b/docs/general-development/developing-with-duet-enterprise-2-0.md index 3ecdbe31c..1a9d4abed 100644 --- a/docs/general-development/developing-with-duet-enterprise-2-0.md +++ b/docs/general-development/developing-with-duet-enterprise-2-0.md @@ -1,172 +1,89 @@ --- title: Developing with Duet Enterprise 2.0 description: Describes Duet Enterprise 2.0's features and details how to set up the developer environment, how to add an external content type, and more. -ms.date: 06/09/2022 +ms.date: 05/09/2023 ms.assetid: c3ef38aa-559e-4832-95c7-75e222c77624 ms.localizationpriority: medium --- - # Developing with Duet Enterprise 2.0 ## Overview - Duet Enterprise 2.0 is the latest version of a collaborative effort between Microsoft and SAP to give SharePoint users the ability to work with data from SAP systems.It combines components from SAP as well as SharePoint and SharePoint Online. It gives a developer the ability to create components that will allow users to bring data from SAP systems into the familiar SharePoint environment. - - - ## Features of Duet Enterprise 2.0 - When properly installed and configured, Duet Enterprise 2.0 will provide the following features: - - - - You can work with data in SAP systems within SharePoint using Business Data Web parts, External lists and custom components. - - - Use SAP data in SharePoint without code by using built-in components. - - - Use SAP reporting systems inside of an app. - - - Use special web parts installed with Duet Enterprise 2.0 to add SAP information to SharePoint pages - - - Use SAP workflow in an app. - - - Developers can use client-side JavaScript to interact with SAP external data. - - - Secure data using OAuth for authentication. - - ## Setting up the development environment - Developing SharePoint Add-ins using Duet Enterprise 2.0, for the most part, is exactly the same as creating standard SharePoint Add-ins. You can use Visual Studio to extend your apps and work within the robust framework of the Visual Studio integrated development environment. - - - ## Adding external content types - In order to access the external data housed on the SAP system, you will have to add an external content type. Since SAP data is exposed through OData endpoints, the auto-generation tools installed in Visual Studio can be used to [How to: Create an external content type from an OData source in SharePoint](how-to-create-an-external-content-type-from-an-odata-source-in-sharepoint.md) that is scoped at the app level. - - - + Follow these steps to create an external content type: - - - ### Creating an external content type from an SAP OData endpoint 1. In **Solution Explorer**, open the shortcut menu for the project, and choose **Add**, **Content types for External Data source**. - - -2. On the **Specify OData Source** page, enter the URL of the Duet Enterprise Workflow Service. - - -3. Choose a name for your OData source. - - -4. Select the entities that are needed. - - -5. Choose **Finish**. - - +1. On the **Specify OData Source** page, enter the URL of the Duet Enterprise Workflow Service. +1. Choose a name for your OData source. +1. Select the entities that are needed. +1. Choose **Finish**. + Visual Studio will create a new folder named External Content Types where you will find the newly created BDC model. - - - ## Configuring the BDC model - The most important thing to make the project work, is to add the **ODataExtensionProvider** property to the BDC model. This property defines the extension provider that provides BCS with the SAP extensions needed for creating app code. - - - -This sample shows the properties added to the BDC model: - - - - - -```XML +This sample shows the properties added to the BDC model: +```xml - - - https://:443/sap/opu/odata/sap/ - ZANDY_PO_HEADER_SRV/$metadata - 2.0 - - OBA.Server.Canary.ObaOdataServerExtensionProvider, - OBA.Server.SSOProvider, - Version=15.0.0.0, - Culture=neutral, - PublicKeyToken=71e9bce111e9429c - SAP-PASSPORT - - + + + https://:443/sap/opu/odata/sap/ + ZANDY_PO_HEADER_SRV/$metadata + 2.0 + + OBA.Server.Canary.ObaOdataServerExtensionProvider, + OBA.Server.SSOProvider, + Version=15.0.0.0, + Culture=neutral, + PublicKeyToken=71e9bce111e9429c + SAP-PASSPORT + ``` - ## Using Duet starter services to develop custom apps - -Duet Enterprise 2.0 installs several starter services to the file system on the SharePoint server. In a default installation, the files are found at C:\\Program Files\\Duet Enterprise\\2.0\\Solutions\\Starter Services. Among these are: - - - +Duet Enterprise 2.0 installs several starter services to the file system on the SharePoint server. In a default installation, the files are found at **C:\\Program Files\\Duet Enterprise\\2.0\\Solutions\\Starter Services**. Among these are: - OBACustomerWorkspace - - - OBAOrderToCash - - - OBAPortal - - - OBAProductCenter - - + Each of these solutions contains WSP files, solution and other supporting files needed to implement them. - - - + These solutions can be used to see what can be done with Duet Enterprise 2.0 and what the development patterns are, but they are not supported for use in SharePoint Add-ins. - - - ## See also - - - -- [Duet Enterprise for Microsoft SharePoint and SAP Server 2.0](https://technet.microsoft.com/library/ff972436.aspx) - - -- [How to: Create an external content type from an OData source in SharePoint](how-to-create-an-external-content-type-from-an-odata-source-in-sharepoint.md) - - -- [Visual Studio Developer Center](https://msdn.microsoft.com/vstudio/default) - - -- [Office Development with Visual Studio](https://msdn.microsoft.com/office/hh133430) - - +- [Duet Enterprise for Microsoft SharePoint and SAP Server 2.0](https://technet.microsoft.com/library/ff972436.aspx) +- [How to: Create an external content type from an OData source in SharePoint](how-to-create-an-external-content-type-from-an-odata-source-in-sharepoint.md) +- [Visual Studio Developer Center](https://msdn.microsoft.com/vstudio/default) +- [Office Development with Visual Studio](https://msdn.microsoft.com/office/hh133430) diff --git a/docs/general-development/discovery-in-excel-services-rest-api.md b/docs/general-development/discovery-in-excel-services-rest-api.md index c537f0ac6..8e8ef0626 100644 --- a/docs/general-development/discovery-in-excel-services-rest-api.md +++ b/docs/general-development/discovery-in-excel-services-rest-api.md @@ -1,153 +1,86 @@ --- title: Discovery in Excel Services REST API description: Describes the discovery mechanisms built into the Excel Services REST API and provides code examples. -ms.date: 06/09/2022 +ms.date: 05/09/2023 ms.assetid: e3a8e057-f803-446d-81c9-4eb8ef3691e1 ms.localizationpriority: medium --- - # Discovery in Excel Services REST API This topic discusses the discovery mechanisms built into the Excel Services REST API. - -> [!NOTE] -> The Excel Services REST API applies to SharePoint and SharePoint 2016 on-premises. For Office 365 Education, Business, and Enterprise accounts, use the Excel REST APIs that are part of the [Microsoft Graph](http://graph.microsoft.io/docs/api-reference/v1.0/resources/excel -) endpoint. - - - +> [!NOTE] +> The Excel Services REST API applies to SharePoint and SharePoint 2016 on-premises. For Office 365 Education, Business, and Enterprise accounts, use the Excel REST APIs that are part of the [Microsoft Graph](/graph/api/overview) endpoint. ## Discovery Base URL and Discovery Example -Discovery enables developers and users to discover information about and the content of a workbook manually or programmatically. The discovery mechanism supplies the [Atom](http://tools.ietf.org/html/rfc4287) feed that contains information about the resources in a workbook. By using discovery, you can explore and view the resources in the workbook. Resources that you can explore and access are ranges, charts, tables, and PivotTables. - - - -Following is the construct of the REST URL to a specific element in a workbook: - - - - - +Discovery enables developers and users to discover information about and the content of a workbook manually or programmatically. The discovery mechanism supplies the [Atom](http://tools.ietf.org/html/rfc4287) feed that contains information about the resources in a workbook. By using discovery, you can explore and view the resources in the workbook. Resources that you can explore and access are ranges, charts, tables, and PivotTables. -``` +Following is the construct of the REST URL to a specific element in a workbook: +```http http:///_vti_bin/ExcelRest.aspx/// ``` -As described in the [Basic URI Structure and Path](basic-uri-structure-and-path.md) topic, following is the REST URL to access a workbook named **sampleWorkbook.xlsx** and further view the chart called **SampleChart**: - - - +As described in the [Basic URI Structure and Path](basic-uri-structure-and-path.md) topic, following is the REST URL to access a workbook named **sampleWorkbook.xlsx** and further view the chart called **SampleChart**: - - -``` +```http http:///_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model/Charts('SampleChart') ``` To start and explore the resources in the workbook and view the resources by using discovery, go to the model page by using a URI that follows this example: - - - - - -``` +```http http:///_vti_bin/ExcelRest.aspx///model ``` -Using the "sampleWorkbook.xlsx" example, following is the URI: - - - - +Using the **sampleWorkbook.xlsx** example, following is the URI: - -``` +```http http:///_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model ``` Following is a screen shot of the model page. - - - **Excel Services REST model URL** - - - - - - - ![Excel Services REST model URL](../images/SharePointServer14Con_XLSvcs_RESTModel.gif) - - - + The URL to the model page is where you start the discovery. The model page displays four resource collections that the Excel Services REST API currently supports. The resource collections are ranges, charts, tables, or PivotTables. You can explore those resources in a particular workbook by clicking **Ranges**, **Charts**, **Tables**, or **PivotTables** on the model page. - - - -For example, to access the chart in the workbook by using discovery, do the following: - - - - - - - -1. On the model page, click **Charts**. Clicking the **Charts** link brings another Atom feed—this resulting feed lists all the charts that are available in the sampleWorkbook.xlsx workbook. The sampleWorkbook.xlsx workbook contains three charts named **Chart 1**, **Chart 3**, and **SampleChart**. Therefore, three chart names are listed, as seen in the following screen shot. - - **Excel Services REST discovery chart list** +For example, to access the chart in the workbook by using discovery, do the following: - +1. On the model page, click **Charts**. Clicking the **Charts** link brings another Atom feed—this resulting feed lists all the charts that are available in the sampleWorkbook.xlsx workbook. The sampleWorkbook.xlsx workbook contains three charts named **Chart 1**, **Chart 3**, and **SampleChart**. Therefore, three chart names are listed, as seen in the following screen shot. - ![Excel Services REST discovery chart list](../images/19126dce-b896-4623-8686-92f2fa807283.gif) - + **Excel Services REST discovery chart list** - + ![Excel Services REST discovery chart list](../images/19126dce-b896-4623-8686-92f2fa807283.gif) - -2. On the model page, click **SampleChart**. This displays the chart named **SampleChart** that resides in **sampleWorkbook.xlsx**, as shown in the following screen shot. - - **Viewing chart using REST** +1. On the model page, click **SampleChart**. This displays the chart named **SampleChart** that resides in **sampleWorkbook.xlsx**, as shown in the following screen shot. - + **Viewing chart using REST** - ![Viewing chart using REST](../images/11734dcf-1b57-40cc-b1e8-8b10b7e5d5cb.gif) - + ![Viewing chart using REST](../images/11734dcf-1b57-40cc-b1e8-8b10b7e5d5cb.gif) - - - -3. Similarly, clicking **Chart 1** or **Chart 3** displays the chart with the corresponding name. Clicking **SampleChart** navigates to the actual chart URL. Following is the URL to the **SampleChart** image (as can be seen in the screen shot): - -``` - http:///_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model/Charts('SampleChart%20')?$format=image -``` +1. Similarly, clicking **Chart 1** or **Chart 3** displays the chart with the corresponding name. Clicking **SampleChart** navigates to the actual chart URL. Following is the URL to the **SampleChart** image (as can be seen in the screen shot): + ```http + http:///_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model/Charts('SampleChart%20')?$format=image + ``` ## Atom Feed -Using the [Atom](http://tools.ietf.org/html/rfc4287) feed provided by the REST API gives you an easier way of getting to the data that you are interested in. If you view the source of the webpage, you get the XML. An example from the charts in **sampleWorkbook.xlsx** is shown below. - - - -As can be seen in the XML, the feed contains traversable elements that enable code to discover what elements exist in the workbook. Each Atom entry corresponds to a chart that can be accessed. This same mechanism applies to discovering ranges, tables, and PivotTables. - - - - +Using the [Atom](http://tools.ietf.org/html/rfc4287) feed provided by the REST API gives you an easier way of getting to the data that you are interested in. If you view the source of the webpage, you get the XML. An example from the charts in **sampleWorkbook.xlsx** is shown below. +As can be seen in the XML, the feed contains traversable elements that enable code to discover what elements exist in the workbook. Each Atom entry corresponds to a chart that can be accessed. This same mechanism applies to discovering ranges, tables, and PivotTables. -```XML +```xml - + Charts http://ServerName/_vti_bin/ExcelRest.aspx/Docs/Documents/sampleWorkbook.xlsx/model/Charts 2010-01-19T19:32:53Z @@ -191,14 +124,8 @@ As can be seen in the XML, the feed contains traversable elements that enable co ``` - ## See also - #### Concepts - - - - - [Resources URI for Excel Services REST API](resources-uri-for-excel-services-rest-api.md) +- [Resources URI for Excel Services REST API](resources-uri-for-excel-services-rest-api.md) diff --git a/docs/general-development/excel-services-best-practices.md b/docs/general-development/excel-services-best-practices.md index af7fbf707..436f5ccbc 100644 --- a/docs/general-development/excel-services-best-practices.md +++ b/docs/general-development/excel-services-best-practices.md @@ -1,7 +1,7 @@ --- title: Excel Services Best Practices description: Describes the best practices for working with Excel Services and provides general advice and details on mitigating threats. -ms.date: 06/09/2022 +ms.date: 05/09/2023 keywords: guidelines f1_keywords: - guidelines @@ -9,229 +9,116 @@ ms.assetid: 56fa3913-c156-49da-bed0-a6a106fc129f ms.localizationpriority: medium --- - # Excel Services Best Practices This topic contains a list of best-practice recommendations for working with Excel Services. - - - - ## Mitigating Threats - ### Anonymous Access and Information Disclosure The following settings combination gives anonymous users access to any files in the share to which the process account has access. Therefore, the following combination of settings is not recommended, because of the possibility of information disclosure: - - - - Anonymous access to Microsoft SharePoint Foundation is turned on. - - - You have a UNC trusted location and the **Process account** is turned on. - + > [!NOTE] > The **Process account** is a global Excel Services setting that affects all trusted locations. - - - - ### To view the Process account option - 1. On the **Start** menu, click **All Programs**. - - -2. Point to **Microsoft SharePoint 2010 Products**, and then click **SharePoint Central Administration**. - - -3. Under **Application Management**, click **Manage service applications**. - - -4. On the Manage Service Applications page, click **Excel Services Application**. - - -5. On the **Excel Services Application** page, click **Global Settings**. - - -6. In the **Security** section, look under **File Access Method** for the **Process account** option. - - +1. Point to **Microsoft SharePoint 2010 Products**, and then click **SharePoint Central Administration**. +1. Under **Application Management**, click **Manage service applications**. +1. On the Manage Service Applications page, click **Excel Services Application**. +1. On the **Excel Services Application** page, click **Global Settings**. +1. In the **Security** section, look under **File Access Method** for the **Process account** option. ### Denial of Service Attack In a denial of service attack against a Web service, an attacker generates very large, individual requests against the Web service. The purpose is to attempt to exploit the limits of one or more Web service input values. - - - + We recommend that you use the Microsoft Internet Information Services (IIS) setting to set the maximum request size for the Web service. - - - + Use the **maxRequestLength** attribute in the **httpRuntime** element in the **system.web** element to prevent denial of service attacks that are caused by users posting large files to the server. The default size is 4096 KB (4 MB). - - - + For more information, see [\ Element](https://msdn.microsoft.com/library/e9b81350-8aaf-47cc-9843-5f7d0c59f369.aspx) and [\ Element](https://msdn.microsoft.com/library/fd52b2c5-5014-4e6f-b869-4ea666dc83d6.aspx). - - - ### Sniffing Between the Calling Application and the Web Service Computer If the calling application and Excel Web Services are deployed to different computers, an attacker can listen to the network traffic for data transfer between the calling application and the Web service. This threat is also called "sniffing" or "eavesdropping." - - - + To help mitigate this threat, we recommend that you: - - - - Use Secure Sockets Layer (SSL) to set up a secure channel to protect data transfer between the client and the server. The SSL protocol helps to protect data against packet sniffing by anyone with physical access to the network. - - - Physically protect the relevant network if a custom application using Excel Web Services is running in a confined network—for example, if Excel Web Services is deployed on a Web front-end computer within the enterprise. - - -For more information, see [Securing Your Network](https://msdn.microsoft.com/library/af62ece0-0dd7-4b8e-ad12-4d13f2d60816.aspx) and [SOAP Security](https://msdn.microsoft.com/library/aa912494.aspx). - - - + +For more information, see [Securing Your Network](https://msdn.microsoft.com/library/af62ece0-0dd7-4b8e-ad12-4d13f2d60816.aspx) and [SOAP Security](https://msdn.microsoft.com/library/aa912494.aspx). + For information about Excel Services topology, scalability, performance, and security, see the Microsoft SharePoint Server 2010 TechCenter. - - - ### Spoofing We recommend that you use SSL to help mitigate the threats of hijacked Web service Internet Protocol (IP) addresses and ports, and to help prevent attackers from receiving requests and replying on behalf of the Web service. - - - + The SSL certificate is matched against a few properties, one of which is the IP address from which the message is coming. The attacker cannot spoof the IP address if it does not have the Web service SSL certificate. - - - + For more information, see [Securing Your Network](https://msdn.microsoft.com/library/af62ece0-0dd7-4b8e-ad12-4d13f2d60816.aspx). - - - ## Excel Services User-Defined Functions (UDFs) - ### Strong Name Dependencies In some cases, a user-defined function (UDF) assembly depends on other assemblies that are deployed with it. These dependent DLLs load successfully if they are in the global assembly cache, or if they are located in the same folder as the UDF assembly. - - - + In the latter case, however, it is possible for the load to fail if Excel Calculation Services has already loaded another assembly with the same name. (It fails either because the assembly is not strongly named, or because another version with the same name has been deployed and loaded.) - - - + Consider the following scenario, with the following directory structure: - - - -1. C:\\Udfs\\Udf01 - +1. ***C:\\Udfs\\Udf01*** + The Udf01 folder contains: - - - Udf01.dll - - - - dependent.dll (not strongly named) - - + + - Udf01.dll + - dependent.dll (not strongly named) The Udf01.dll file has a dependency on the dependent.dll file. - - -2. C:\\Udfs\\Udf02 - + +1. **C:\\Udfs\\Udf02** + The Udf02 folder contains: - - - Udf02.dll (which depends on Interop.dll) - - - - dependent.dll (which is not strongly named) - - + + - Udf02.dll (which depends on Interop.dll) + - dependent.dll (which is not strongly named) The Udf02.dll file has a dependency on the dependent.dll file. Udf01.dll's dependency and Udf02.dll's dependency share the same name. But Udf02.dll's dependent.dll file is not the same as Udf01.dll's dependent.dll file. - - + Assume the following flow: - - - - -1. Udf01.dll is the first DLL to be loaded. Excel Calculation Services looks for dependent.dll and loads Udf01.dll's dependency, which in this case is dependent.dll. - - -2. Udf02.dll is loaded after Udf01.dll. Excel Calculation Services sees that Udf02.dll depends on dependent.dll. However, a DLL with the name "dependent.dll" is already loaded. Therefore, Udf02.dll's dependent.dll file is not loaded, and the currently loaded dependent.dll file is used as the dependency. - - + +1. Udf01.dll is the first DLL to be loaded. Excel Calculation Services looks for dependent.dll and loads Udf01.dll's dependency, which in this case is dependent.dll. +1. Udf02.dll is loaded after Udf01.dll. Excel Calculation Services sees that Udf02.dll depends on dependent.dll. However, a DLL with the name "dependent.dll" is already loaded. Therefore, Udf02.dll's dependent.dll file is not loaded, and the currently loaded dependent.dll file is used as the dependency. + As a result, the object—in this case, the dependent.dll file that Udf02.dll needs—is not loaded into memory. - - - + To avoid name collision, we recommend that you strongly name your dependencies, and name them uniquely. - - - ## General - ### Naming Managed-Code DLLs To ensure that your assembly names are unique, use the fully qualified class name, following the [Namespace Naming Guidelines](https://msdn.microsoft.com/library/c08bc0d8-9b3a-4564-9af6-71699f62e00d.aspx). - - - -For example, use CompanyName.Hierarchichal.Namespace.ClassName instead ofNamespace.ClassName. - - - -## See also +For example, use `CompanyName.Hierarchichal.Namespace.ClassName` instead of `Namespace.ClassName`. +## See also #### Tasks - - - - - [How to: Trust a Location](how-to-trust-a-location.md) +- [How to: Trust a Location](how-to-trust-a-location.md) #### Concepts - - - - - [Excel Services Architecture](excel-services-architecture.md) - - - - [Accessing the SOAP API](accessing-the-soap-api.md) - - - - [Excel Services Alerts](excel-services-alerts.md) - - - - [Excel Services Known Issues and Tips](excel-services-known-issues-and-tips.md) - - - - [Excel Services Blogs, Forums, and Resources](excel-services-blogs-forums-and-resources.md) +- [Excel Services Architecture](excel-services-architecture.md) +- [Accessing the SOAP API](accessing-the-soap-api.md) +- [Excel Services Alerts](excel-services-alerts.md) +- [Excel Services Known Issues and Tips](excel-services-known-issues-and-tips.md) +- [Excel Services Blogs, Forums, and Resources](excel-services-blogs-forums-and-resources.md) diff --git a/docs/general-development/excel-services-known-issues-and-tips.md b/docs/general-development/excel-services-known-issues-and-tips.md index 535acd48e..66fa55c00 100644 --- a/docs/general-development/excel-services-known-issues-and-tips.md +++ b/docs/general-development/excel-services-known-issues-and-tips.md @@ -1,328 +1,163 @@ --- title: Excel Services Known Issues and Tips description: Describes known issues and tips for working with Excel Services and provides links to related documentation. -ms.date: 06/09/2022 +ms.date: 05/09/2023 ms.assetid: b4a41437-4f00-4f88-8510-627fa0252004 ms.localizationpriority: medium --- - # Excel Services Known Issues and Tips The following are a known issues and tips for working with Excel Services. - - - - ## Excel Web Service - ### Viewing the WSDL Location You can view the Excel Web Services Web Services Description Language (WSDL) page by navigating to the following URL on the server: `http:////_vti_bin/excelservice.asmx?WSDL` - - - -If you do not have a custom site, you can view the WSDL by using the following URL: - - - - `http:///_vti_bin/excelservice.asmx?WSDL` - - - -For more information, see [Accessing the SOAP API](accessing-the-soap-api.md). - - - + +If you do not have a custom site, you can view the WSDL by using the following URL: `http:///_vti_bin/excelservice.asmx?WSDL` + +For more information, see [Accessing the SOAP API](accessing-the-soap-api.md). ### Understanding Excel Web Services and Namespaces The following are Excel web services and namespaces: - - - - The single web service object that contains all the API methods: **ExcelService** - - -- The schema namespace: `http://schemas.microsoft.com/office/excel/server/webservices` - - -- The web service page name: ExcelService.asmx - - +- The schema namespace: `http://schemas.microsoft.com/office/excel/server/webservices` +- The web service page name: **ExcelService.asmx** ### Linking Locally or to a Web Service -In certain scenarios, you should link directly to Microsoft.Office.Excel.Server.WebServices.dll and access it as you would any local assembly, instead of calling it as a web service through SOAP over HTTP. - - - +In certain scenarios, you should link directly to Microsoft.Office.Excel.Server.WebServices.dll and access it as you would any local assembly, instead of calling it as a web service through SOAP over HTTP. + For more information and guidelines on when to use direct linking, see [Loop-Back SOAP Calls and Direct Linking](loop-back-soap-calls-and-direct-linking.md). - - - ### Understanding Invalid Characters The calls to the **GetCell** and **GetRange** methods will fail if the workbook cells contain characters that are invalid in an XML response. - - - + For example, if a cell contains characters with hexadecimal values 0x1, 0x2 ... 0x8, the ASP.NET parser will throw an exception that the value of the character being written to the XML response is invalid: - - - - **System.InvalidOperationException: Client found response content type of 'text/html; charset=utf-8', but expected 'text/xml'. The request failed with the error message: -- \ \ \' ', hexadecimal value 0x01, is an invalid character.** - - - + +**System.InvalidOperationException: Client found response content type of 'text/html; charset=utf-8', but expected 'text/xml'. The request failed with the error message: -- \ \ \' ', hexadecimal value 0x01, is an invalid character.** + This behavior is expected. The XML specification that defines which characters are allowed in a valid XML response specifies that hexadecimal values 0x1, 0x2 ... 0x8 are invalid XML characters: - - - - **Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */** - - - -For more information, see [W3C Extensible Markup Language (XML) Specification](http://www.w3.org/TR/REC-xml) (http://www.w3.org/TR/REC-xml#NT-Char). - - - + +**Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */** + +For more information, see [W3C Extensible Markup Language (XML) Specification](http://www.w3.org/TR/REC-xml#NT-Char). ### Saving a Workbook When you make changes to a workbook—for example, by setting values to a range using Excel Web Services—the changes to the workbook are preserved only for that particular session. The changes are not saved or persisted back to the original workbook. When the current workbook session ends (for example, when you call the **CloseWorkbook** method, or the session times out), changes you made will be lost. - - - + If you want to save changes to a workbook, you can use the **GetWorkbook** method and then save the workbook using the API of the destination file store. For more information, see [How to: Get an Entire Workbook or a Snapshot](how-to-get-an-entire-workbook-or-a-snapshot.md) and [How to: Save a Workbook](https://msdn.microsoft.com/library/feb74f7a-2d8f-4672-911b-de85f8852aea%28Office.15%29.aspx). - - - ### Understanding the Url Property of an Excel Web Services Proxy Class -Do not use the **Url** property of an Excel Web Services proxy for the location of the workbook you want to open. The **Url** property of a web service proxy class generated by Visual Studio gets or sets the base URL of the XML web service the client is requesting. In the case of Excel Web Services, this is usually: - - - - `http:///_vti_bin/ExcelService.asmx` - - - -To specify the location of a workbook, use the **OpenWorkbook** method instead of the **Url** property as shown in the following code example. - - - - +Do not use the **Url** property of an Excel Web Services proxy for the location of the workbook you want to open. The **Url** property of a web service proxy class generated by Visual Studio gets or sets the base URL of the XML web service the client is requesting. In the case of Excel Web Services, this is usually: `http:///_vti_bin/ExcelService.asmx` +To specify the location of a workbook, use the **OpenWorkbook** method instead of the **Url** property as shown in the following code example. -``` - +```csharp //Instantiate the web service and make a status array object. ExcelService xlservice = new ExcelService(); -string sheetName = "Sheet1"; +string sheetName = "Sheet1"; //Set the path to the workbook to open. //TODO: Change the path to the workbook - //to point to a workbook you have access to. +//to point to a workbook you have access to. //The workbook must be in a trusted location. -string targetWorkbookPath = - "http://myserver02/example/Shared%20Documents/Book1.xlsx"; +string targetWorkbookPath = "http://myserver02/example/Shared%20Documents/Book1.xlsx"; //Set credentials for requests. xlservice.Credentials = System.Net.CredentialCache.DefaultCredentials; -//Call the open workbook, and point to the trusted +//Call the open workbook, and point to the trusted //location of the workbook to open. -string sessionId = xlservice.OpenWorkbook(targetWorkbookPath, "en-US", - "en-US", out outStatus); - +string sessionId = xlservice.OpenWorkbook(targetWorkbookPath, "en-US", "en-US", out outStatus); ``` -For more information, see [WebClientProtocol.Url Property](https://go.microsoft.com/fwlink/?LinkId=64908) (https://msdn.microsoft.com/library/default.asp?url=/library/cpref/html/frlrfSystemWebServicesProtocolsWebClientProtocolClassUrlTopic.asp). - - - +For more information, see [WebClientProtocol.Url Property](https://msdn.microsoft.com/library/default.asp?url=/library/cpref/html/frlrfSystemWebServicesProtocolsWebClientProtocolClassUrlTopic.asp). ## Understanding Security - ### Using Workbook Permissions Beware of the following issues regarding workbook permissions: - - - - Excel Web Services uses the Microsoft SharePoint Foundation authorization scheme to verify that the caller has the right to call APIs (that is, make web service calls) on the SharePoint Foundation site (that is, the website where Excel Web Services is located) remotely. If the caller does not have the "Use Remote API" right, the Excel Web Services returns an "HTTP 401 (Unauthorized)" error, and logs an "API authorization failed" event. Excel Web Services performs these authorization checks only for calls that originate as SOAP calls. Calls from applications that link locally to Microsoft.Office.Excel.Server.WebServices.dll are not considered remote calls. Therefore, they are not subject to authorization checks. However, if the application that links locally to Microsoft.Office.Excel.Server.WebServices.dll is itself a SOAP service, and handles the service's SOAP calls, the call to Excel Web Services will seem like a SOAP call (even though the application links directly to Microsoft.Office.Excel.Server.WebServices.dll). In this scenario, Excel Web Services will perform the authorization checks. - - - To get the entire workbook (for example, by calling the **GetWorkbook** method using the `WorkbookType.FullWorkbook` argument), the caller needs "open" permission for the workbook or "read" permission in a file share. - - - To call the **GetApiVersion** method, no permission is necessary. - - - For the rest of the Excel Web Services methods, besides credentials, the caller needs "view" permission (in SharePoint Foundation) or "read" permission (in a file share) for the workbook. - - ### Trusted Location The workbooks you want to open in Excel Services must be placed in a trusted location. If not, the Excel Web Services calls to open the workbook will fail. - - - + For information about how to trust a location, see [How to: Trust a Location](how-to-trust-a-location.md) and [How to: Trust Workbook Locations Using Script](https://msdn.microsoft.com/library/79ab6ced-7a0c-4275-b852-bb246fc6be57%28Office.15%29.aspx). - - - ## Visual Studio - ### Microsoft Visual Studio Proxy Behavior -When Microsoft Visual Studio creates a proxy class for a client project that calls Excel Web Services, it has the following behavior: - - - +When Microsoft Visual Studio creates a proxy class for a client project that calls Excel Web Services, it has the following behavior: + If a method has no return value, and one or more **out** arguments, the first **out** argument is moved to become the return value. That is, the method in the proxy class will have one less **out** argument in the method signature. But the signature will have a return value with the type and content of what used to be the first **out** argument. - - - + The affected Excel Web Services methods are: - - - - **Calculate** - - - **CalculateA1** - - - **CalculateWorkbook** - - - **CancelRequest** - - - **CloseWorkbook** - - - **GetSessionInformation** - - - **Refresh** - - - **SetCell** - - - **SetCellA1** - - - **SetRange** - - - **SetRangeA1** - - ## Excel Services User-Defined Functions - ### Global Assembly Cache is Checked First, Then the Local Folder By design in the Microsoft .NET Framework, an assembly in a global assembly cache will be loaded instead of the same assembly in a local folder. The common language runtime will look for an assembly in the global assembly cache first before searching in the local folders. - - - + Therefore, if an assembly is installed in the global assembly cache and is in the UDF list but disabled (or removed from the UDF list altogether), and an identical assembly is installed in a local folder and enabled, the assembly in the global assembly cache will still get loaded and used instead of the same assembly in the local folder. - - - + This does not affect upgrade scenarios in which the assembly version has been modified, which means the assembly is not the same anymore. - - - ## General - ### Order of Strings in Sharedstring.xml is Not Maintained -Excel Services does not maintain the original order of strings in a workbook shared-string table (the Sharedstrings.xml part within the Microsoft Office Excel XML Format file). For example, execute the following steps: - - - - -1. Open a file using Excel. - - -2. Save the file in .xlsx file format. - - -3. Upload the file to a document library that is a trusted location. - - -4. Open the file in the document library by using Excel Web Access. - - -5. Click **Open in Excel**. - - -6. Save the file in .xlsx file format. - - -If you compare the Sharedstrings.xml file created in Step 2 with the one created in Step 6, you will find the order of the Sharedstrings.xml parts might be different. - - - +Excel Services does not maintain the original order of strings in a workbook shared-string table (the **Sharedstrings.xml** part within the Microsoft Office Excel XML Format file). For example, execute the following steps: + +1. Open a file using Excel. +1. Save the file in .xlsx file format. +1. Upload the file to a document library that is a trusted location. +1. Open the file in the document library by using Excel Web Access. +1. Click **Open in Excel**. +1. Save the file in .xlsx file format. + +If you compare the **Sharedstrings.xml** file created in Step 2 with the one created in Step 6, you will find the order of the **Sharedstrings.xml** parts might be different. + You should not write an application that assumes the order of strings in the shared-string table is fixed. For example, you cannot replace the shared-string table with an existing localized translation table. You must adjust to the new ordering of strings in the shared-string table. - - - ## See also - #### Tasks +- [How to: Trust a Location](how-to-trust-a-location.md) - - - - [How to: Trust a Location](how-to-trust-a-location.md) #### Concepts - - - - - [Excel Services Best Practices](excel-services-best-practices.md) - - - - [Excel Services Alerts](excel-services-alerts.md) - - - - [Excel Services Architecture](excel-services-architecture.md) - - - - [Supported and Unsupported Features](supported-and-unsupported-features.md) - - - - [Accessing the SOAP API](accessing-the-soap-api.md) - - - - [Excel Services Blogs, Forums, and Resources](excel-services-blogs-forums-and-resources.md) +- [Accessing the SOAP API](accessing-the-soap-api.md) +- [Excel Services Alerts](excel-services-alerts.md) +- [Excel Services Architecture](excel-services-architecture.md) +- [Excel Services Best Practices](excel-services-best-practices.md) +- [Excel Services Blogs, Forums, and Resources](excel-services-blogs-forums-and-resources.md) +- [Supported and Unsupported Features](supported-and-unsupported-features.md) diff --git a/docs/general-development/external-events-and-alerts-in-sharepoint.md b/docs/general-development/external-events-and-alerts-in-sharepoint.md index f13fd8e3c..056ad3528 100644 --- a/docs/general-development/external-events-and-alerts-in-sharepoint.md +++ b/docs/general-development/external-events-and-alerts-in-sharepoint.md @@ -1,7 +1,7 @@ --- title: External events and alerts in SharePoint description: Learn the concepts behind creating remote event receivers in SharePoint that can be attached to external lists and execute when the external data that the list represents is updated. -ms.date: 09/25/2017 +ms.date: 05/18/2023 ms.assetid: e48e4812-a185-43c5-b243-04b1d79b88ee ms.localizationpriority: medium --- @@ -10,280 +10,158 @@ ms.localizationpriority: medium Learn the concepts behind creating remote event receivers in SharePoint that can be attached to external lists and execute when the external data that the list represents is updated. ## What are event receivers? - An event receiver is a piece of managed code that responds to SharePoint triggering events such as adding, moving, deleting, checking in, and checking out. When these events occur, and the event receiver's criteria are met, the code that you write to provide additional functionality is executed. When SharePoint objects, such as lists, workflows and features, are configured to wait on these events to occur, they are called event hosts. - - Event receivers let you perform business logic when a specific event occurs. Essentially, these are the hooks where you can create code to handle certain conditions, make notifications, update other systems, and so on. When you create event receivers, a DLL is generated. You can place that DLL into the global assembly cache, so that the event receivers are invoked in response to any changes in an external system. - - The following example contains a simple external event receiver in C# that executes when a new item is added to the list. - - - - - ```csharp - public class EntryContentEventReceiver : SPItemEventReceiver { - public override void ItemAdded(SPItemEventProperties properties) - { - base.ItemAdded(properties); - - // properties.ExternalNotificationMessage holds the message sent by the external - // system. - } + public override void ItemAdded(SPItemEventProperties properties) + { + base.ItemAdded(properties); + // properties.ExternalNotificationMessage holds the message sent by the external system + } +} ``` External event receivers can also be extended to work against an entity event receiver and as remote event receivers deployed as a service on-premises or in Microsoft Azure. - - - ## What are remote event receivers? - Remote event receivers are new for SharePoint. In a traditional SharePoint solution, you use an event receiver to handle events such as users creating or deleting lists or items in lists. In an SharePoint Add-in, you use a remote event receiver to handle similar events. Remote event receivers work similarly to regular event receivers, except that remote event receivers handle events that occur when an SharePoint Add-in is on a different system from its host web application. - - Business Connectivity Services (BCS) uses remote event receivers attached to external lists and entities to allow you to write code that can react to changes in data hosted in the external system. - - To accommodate this, two stereotypes have been added to the schema of the BDC model: **EventSubscriber** and **EventUnsubscriber**. > [!NOTE] > Event receivers are not supported in sandboxed solutions. - - - - ## What features and capabilities does the new external event receiver infrastructure provide? - By using and extending the SharePoint event receiver features, BCS is able to add alerts, external list event receivers, and entity receivers to provide extended functionality. - - - -- **Alerts:** Alerts have been an integral part of SharePoint for several versions, but until SharePoint, they would not work with external lists. Now a user can create alerts on an external list that have the same behavior as alerts on a standard SharePoint list. - - -- **External list event receivers:** Event receivers can now be attached to external lists just like they can for standard lists. This provides an extensibility mechanism that lets you write code that is executed at specific times. - - +- **Alerts:** Alerts have been an integral part of SharePoint for several versions, but until arePoint, they would not work with external lists. Now a user can create alerts on an external list that have the same behavior as alerts on a standard SharePoint list. +- **External list event receivers:** Event receivers can now be attached to external lists just like they can for standard lists. This provides an extensibility mechanism that lets you write de that is executed at specific times. - **Entity event receivers:** Entity event receivers provide flexibility by letting you write more robust code that allows other operations like providing user context for filtering data. This can allow better personalization and customized security. - Remote eventing in SharePoint makes several interesting scenarios possible. For example, you might have a "Sales Lead Tracking" application that lets a sales team be notified when new sales leads are entered into an external lead application. When a new sales lead is entered, SharePoint is notified through the notification system that is part of the lead application. SharePoint receives the notification and then creates new tasks for the specified salespeople to follow up on each new lead. By configuring the sales lead entry application on the external system to send a notification to SharePoint on the creation of each new lead, SharePoint is kept completely up to date. - - - ## Prerequisites for using event receivers for external lists - To use event receivers for external lists, you need the following: - - - - SharePoint - - - Visual Studio 2012 - For more information about setting up a SharePoint development environment, see [Set up a general development environment for SharePoint](set-up-a-general-development-environment-for-sharepoint.md). - - - ## Configure the external system to notify SharePoint of external events - For external events to work, a number of components have to be installed and configured on both the SharePoint host and the external system. - - You have to configure the external system so that it can do the following: - - - - **Determine when underlying data changes.** For the external system to know when changes have been made, you have to create a mechanism for polling for specific changes. You can do this by using a timed service that polls the data source at specific intervals. - - -- **Receive and record requests for subscriptions to change notifications.** The external system has to implement a subscription store so that it can store who should receive change notifications. The simplest solution is probably a database table. The table (or whatever mechanism you choose) should record SubscriptionID, Delivery Address, Event Type, and Entity Name. - - -- **Post notifications to Representational State Transfer (REST) endpoints.** To let SharePoint subscribers know that a change has occurred, the external system application needs to send an HTTP WebRequest to the delivery address recorded in the subscription store. This delivery address is a RESTful endpoint generated by SharePoint during the subscription process. - - +- **Receive and record requests for subscriptions to change notifications.** The external system has to implement a subscription store so that it can store who should receive change notifications. The simplest solution is probably a database table. The table (or whatever anism you choose) should record SubscriptionID, Delivery Address, Event Type, and Entity Name. +- **Post notifications to Representational State Transfer (REST) endpoints.** To let SharePoint subscribers know that a change has occurred, the external system application needs to send an HTTPWebRequest to the delivery address recorded in the subscription store. This delivery address is a RESTful endpoint generated by SharePoint during the subscription process ## Configure SharePoint to allow communication with external systems - To allow communication with the external system, SharePoint must be configured with the following: - - - - A BDC model with **EventSubscriber** and **EventUnsubscriber** stereotypes configured - - - Event receivers - - ### How is external eventing enabled? You can enable external eventing in SharePoint through **Site Settings** or by adding the following custom feature id to your project - - - -```XML - +```xml ``` Eventing for an external system is enabled when SharePoint creates the delivery address and sends it to the external system during the Subscribe process. - - - ## Overall flow of external eventing between SharePoint and external systems - In Figure 1, notice that there are three distinct steps involved when using external event receivers: subscribe, notification, and unsubscribe. - - - **Figure 1 Complete data flow for external notifications** - - - - - - - -![Data flow for external event notifications](../images/ExtEvtsAndAlrts_Figure1.jpg) - - - - - - - - - - - +[Data flow for external event notifications](../images/ExtEvtsAndAlrts_Figure1.jpg) ## EventSubscriber: subscribe to notifications - For a user (SharePoint object) to receive notifications when the underlying data has changed, the user must subscribe to the notifications for an entity. To allow this, the BDC Model schema has been extended to include the **Subscribe** stereotype. The **Subscribe** stereotype is used by SharePoint to let the external system know that the sender is requesting to be notified of changes to the underlying data. - - Figure 2 demonstrates the flow of information between SharePoint and the external system during the Subscribe process. - - - **Figure 2. Subscribe process flow** - - - - - - - ![External eventing Subscribe method process flow](../images/ExtEvtsAndAlerts_Figure2.jpg) - - The following describes the general flow of the subscription process: - - - - - - - 1. **User requests a subscription for notifications.** Using a custom user interface (a button on a page or a ribbon), SharePoint initiates a request to the external system app for notifications. - - -2. **SharePoint generates a delivery address.** As part of the Subscribe process, SharePoint creates a REST endpoint where notifications will be delivered. - - -3. **Subscription request is sent to the external system.** SharePoint then encapsulates the requestor information along with the dynamically generated REST URL, and sends a web request to the external system. - - -4. **External system receives request.** There are different possibilities for implementing a subscription store. In this example, you will use a SQL Server database table. - - -5. **External system generates a subscriptionId.** A new **subscriptionId** is generated using code in the line-of-business (LOB) application. The **subscriptionId** should be a GUID. - - -6. **External system records the subscription.** The external system application records the **subscriptionId**, delivery address, event type, and other information sent from SharePoint into the subscription store. - - -7. **External system sends the subscriptionId back to SharePoint.** For SharePoint to correctly route the updates that are sent by the external system, the **subscriptionId** is sent back to SharePoint and SharePoint records that information in its database. +1. **SharePoint generates a delivery address.** As part of the Subscribe process, SharePoint creates a REST endpoint where notifications will be delivered. +1. **Subscription request is sent to the external system.** SharePoint then encapsulates the requestor information along with the dynamically generated REST URL, and sends a web request to the external system. +1. **External system receives request.** There are different possibilities for implementing a subscription store. In this example, you will use a SQL Server database table. +1. **External system generates a subscriptionId.** A new **subscriptionId** is generated using code in the line-of-business (LOB) application. The **subscriptionId** should be a GUID. +1. **External system records the subscription.** The external system application records the **subscriptionId**, delivery address, event type, and other information sent from SharePoint into the subscription store. +1. **External system sends the subscriptionId back to SharePoint.** For SharePoint to correctly route the updates that are sent by the external system, the **subscriptionId** is sent back to SharePoint and SharePoint records that information in its database. The BDC model is working against a **Subscribe** function import. The metadata for function import is shown in this example. - - -```XML - FunctionImport - +```xml - - - + + + - - - + + + - ``` - ### Code example: BDC model with Subscribe The following is an example of a BDC model with the **Subscribe** method added. - - - -```XML - +```xml /EntitySubscribes @@ -369,147 +247,71 @@ The following is an example of a BDC model with the **Subscribe** method added. Table 1 lists the important attributes of the BDC model that are needed to make the **Subscribe** stereotype work. - - - **Table 1. BDC model attributes** - -|**Attribute**|**Description**| -|:-----|:-----| -|**IsDeliveryAddress**
|A **Boolean** flag used on a **TypeDescriptor** to indicate whether the delivery address provided is to be used to deliver notifications.
| -|**IsEventType**
|A **Boolean** flag used on a **TypeDescriptor** to indicate whether the event type provided is to be used as the event type. Valid event types are **ItemAdded**, **ItemUpdated**, **ItemDeleted**, and so on.
| -|**SubscriptionIdName**
|A string used on a **TypeDescriptor** that represents the name of a **subscriptionId** part.
| - +| **Attribute** | **Description** | +| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **IsDeliveryAddress** | A **Boolean** flag used on a **TypeDescriptor** to indicate whether the delivery address provided is to be used to deliver notifications. | +| **IsEventType** | A **Boolean** flag used on a **TypeDescriptor** to indicate whether the event type provided is to be used as the event type. Valid event types are **ItemAdded**, **ItemUpdated**, **ItemDeleted**, and so on. | +| **SubscriptionIdName** | A string used on a **TypeDescriptor** that represents the name of a **subscriptionId** part. | ## Notifications - In SharePoint, the event-handling infrastructure has been enhanced to allow external data sources to notify SharePoint when information in the external system has been modified. Then, when SharePoint receives a notification, event receivers that are associated with the SharePoint external list or entity can execute code to perform specified actions. - - When a subscription is created, the external system needs a way to tell SharePoint about the changes that have occurred on a particular entity. The external system is expected to deliver notifications to the delivery address as provided by SharePoint to the external system during the Subscribe process using an OData Atom-formatted payload. - - Figure 3 shows the communication flow between the external system and SharePoint when a new record is added to the data in the external system. - - - **Figure 3 Notification process** - - - - - - - ![External event notification process](../images/ExtEvtsAndAlerts_Figure3.jpg) - - - - - - - 1. **New record is added to external system.** In this example, a new record is added to the external system using the application user interface or directly into the database. - - -2. **External system application is notified of the change.** The external system application has to be made aware of the changes that are happening to the underlying data. There are a number of ways to do this. You can use SQL triggers that fire when data changes on specific tables, or you can create a polling mechanism to query the data store for changes. There are other ways to accomplish this, but each will have to be evaluated with performance in mind. - - -3. **External system sends notification request to SharePoint through delivery address.** To communicate the changes, an Atom-formatted request has to be sent to the delivery address that is stored in the LOB application's subscription store. - - +1. **External system application is notified of the change.** The external system application has to be made aware of the changes that are happening to the underlying data. There are a number of ways to do this. You can use SQL triggers that fire when data changes on specific tables, or you can create a polling mechanism to query the data store for changes. There are other ways to accomplish this, but each will have to be evaluated with performance in mind. +1. **External system sends notification request to SharePoint through delivery address.** To communicate the changes, an Atom-formatted request has to be sent to the delivery address that is stored in the LOB application's subscription store. ### Notification payload In constructing the notification, the LOB system has to create an HTTP payload that includes either the full details of the item that changed, or just the identity of the item that changed. - - - - **Identity:** When the payload is sent as an identity, the payload is expected to have only information about the identity of the changed item. For example, for a customer in a Customers entity, the payload would only contain the ID of the customer that has changed. - - - **Full item:** In this case, the payload is an entire record that has changed in the external system. In the customer example, the entire changed customer record is included. > [!NOTE] > The full item is only supported when you use the OData connector. - - - The type of payload that is being sent by the external system must be indicated during the subscription process. - - The following is an example of the BDC model property used for notifications. - - - - - -```XML - +```xml ODataEntryContentNotificationParser - ``` If it is not specified, the default payload is an identity payload. - - - ### Notification delivery address (virtual address) The subscription process initiated from SharePoint results in a virtual address being created by SharePoint, allowing an entry point for the external system to post notifications. The delivery address is used by the external system to post those notifications. The delivery address is also passed to the external system during the subscription request. - - - ## EventUnsubscriber: remove subscription from the notifications list - The **Unsubscribe** operation removes a subscription from the notifications list. - - - Figure 4 shows that the **UnSubscribe** method is much simpler. Because the subscription ID was sent back to SharePoint, and SharePoint recorded it, all that is needed is to send the UnSubscribe request with the correct subscription ID. - - - +Figure 4 shows that the **UnSubscribe** method is much simpler. Because the subscription ID was sent back to SharePoint, and SharePoint recorded it, all that is needed is to send the UnSubscribe request with the correct subscription ID. **Figure 4 Code flow for UnSubscribe method** - - - - - - - ![External notifications unsubscribe process](../images/ExternalEventsAndAlerts_UnsubscribeFlow.jpg) - - - ### BDC model for Unsubscribe The following XML example shows how you can create a BDC model that unsubscribes from the external system event notifications. - - - -```XML - +```xml @@ -554,8 +356,6 @@ The following XML example shows how you can create a BDC model that unsubscribes - - @@ -588,77 +388,46 @@ The following XML example shows how you can create a BDC model that unsubscribes - ``` - ## Code example: Attach an event receiver to an external list - The following code provides an example of how to attach an event receiver to an external list. After it is attached, the event receiver listens for notifications from the external system about updates, additions, and deletions that are performed on the native data. - - - -```XML - +```csharp private static void AddEventReceiver(string siteUrl, string listTitle) { - string assembly = "SampleEventReceiver, Culture=neutral, Version=1.0.0.0, - PublicKeyToken=1bfafa687d2e46a7"; - string className = "SampleEventReceiver.EntryContentEventReceiver"; - - try - { - using (SPSite site = new SPSite(siteUrl)) + string assembly = "SampleEventReceiver, Culture=neutral, Version=1.0.0.0,PublicKeyToken=1bfafa687d2e46a7"; + string className = "SampleEventReceiver.EntryContentEventReceiver"; + try + { + using (SPSite site = new SPSite(siteUrl)) + { + using (SPWeb web = site.OpenWeb()) { - using (SPWeb web = site.OpenWeb()) - { - SPList list = web.Lists[listTitle]; - list.EventReceivers.Add(SPEventReceiverType.ItemAdded, - assembly, className); - } + SPList list = web.Lists[listTitle]; + list.EventReceivers.Add(SPEventReceiverType.ItemAdded, assembly, className); } - } - catch (Exception e) - { - Console.WriteLine(e); - } + } + } + catch (Exception e) + { + Console.WriteLine(e); + } } - ``` - ## Beyond the basics: Learn more about using external event receivers - For more information about external events and alerts, see the following. - - - **Table 2. Advanced concepts for working with external event receivers** +| **Article** | **Description** | +| :----------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [How to: Create an OData data service for use as a BCS external system](how-to-create-an-odata-data-service-for-use-as-a-bcs-external-system.md) | Learn how to create an Internet-addressable Windows Communication Foundation (WCF) service that uses OData to send notifications to SharePoint when the underlying data changes. These notifications are used to tigger events that are attached to external lists. | -|**Article**|**Description**| -|:-----|:-----| -| [How to: Create an OData data service for use as a BCS external system](how-to-create-an-odata-data-service-for-use-as-a-bcs-external-system.md)
|Learn how to create an Internet-addressable Windows Communication Foundation (WCF) service that uses OData to send notifications to SharePoint when the underlying data changes. These notifications are used to trigger events that are attached to external lists.
| - - -## See also - - - -- [What's new in Business Connectivity Services in SharePoint](what-s-new-in-business-connectivity-services-in-sharepoint.md) - - -- [Business Connectivity Services in SharePoint](business-connectivity-services-in-sharepoint.md) - - -- [Business Connectivity Services programmers reference for SharePoint](business-connectivity-services-programmers-reference-for-sharepoint.md) - - -- [How to: Create external event receivers](how-to-create-external-event-receivers.md) - - +## See Also +- [What's new in Business Connectivity Services in SharePoint](what-s-new-in-business-connectivity-services-in-sharepoint.md) +- [Business Connectivity Services in SharePoint](business-connectivity-services-in-sharepoint.md) diff --git a/docs/general-development/get-started-with-workflows-in-sharepoint.md b/docs/general-development/get-started-with-workflows-in-sharepoint.md index 76663f9ea..9a55786ce 100644 --- a/docs/general-development/get-started-with-workflows-in-sharepoint.md +++ b/docs/general-development/get-started-with-workflows-in-sharepoint.md @@ -16,6 +16,7 @@ Learn about the newly engineered Workflow Manager Client 1.0, which provides the > For instructions on setting up and configuring SharePoint and Microsoft Azure, see [Set up and configure SharePoint Workflow Manager](set-up-and-configure-sharepoint-workflow-manager.md). > [!NOTE] +> SharePoint 2013 workflow has been deprecated since April 2023 and will be turned off for new tenants as of April 2, 2024. It will be removed from existing tenants and will be fully retired as of April 2, 2026. If you’re using SharePoint 2013 workflow, we recommend migrating to Power Automate or other supported solutions. For more info, see [SharePoint 2013 workflow retirement in Microsoft 365](https://support.microsoft.com/office/4613d9cf-69aa-40f7-b6bf-6e7831c9691e). > SharePoint 2010 workflows have been retired since August 1, 2020 for new tenants and removed from existing tenants on November 1, 2020. If you’re using SharePoint 2010 workflows, we recommend migrating to Power Automate or other supported solutions. For more info, see [SharePoint 2010 workflow retirement](https://support.microsoft.com/office/sharepoint-2010-workflow-retirement-1ca3fff8-9985-410a-85aa-8120f626965f). diff --git a/docs/general-development/how-to-access-external-data-with-rest-in-sharepoint.md b/docs/general-development/how-to-access-external-data-with-rest-in-sharepoint.md index db33f2e7e..5d9087c9d 100644 --- a/docs/general-development/how-to-access-external-data-with-rest-in-sharepoint.md +++ b/docs/general-development/how-to-access-external-data-with-rest-in-sharepoint.md @@ -1,193 +1,130 @@ --- title: Access external data by using REST in SharePoint description: Describes how to access external data from SharePoint by using REST URLs for BCS and provides an example that sets up an external list. -ms.date: 06/09/2022 +ms.date: 05/18/2023 ms.assetid: 0663cc8c-a736-434d-9858-6ce12ce7f748 ms.localizationpriority: high --- - - # Access external data by using REST in SharePoint Learn how to access external data from SharePoint by using Representational State Transfer (REST) URLs for Business Connectivity Services (BCS). This article shows how to set up an external list that retrieves data from an Open Data protocol (OData) source. - - - - ## Prerequisites for accessing external data using REST - To access external data from SharePoint by using REST, you need the following: - - - - SharePoint - - - Visual Studio 2012 - - - Office Developer Tools for Visual Studio 2012 - - - A functioning SharePoint Add-ins development environment: Follow the instructions in [Set up a general development environment for SharePoint](set-up-a-general-development-environment-for-sharepoint.md). - - - Access to the public OData.org producers - - ### Core concepts to know when accessing external data with REST The SharePoint REST service provides a way to access external data using a specially constructed URL. To understand how it works and how to use it, see the following articles. - - - **Table 1. Core concepts for REST in SharePoint** - -|**Article title**|**Description**| -|:-----|:-----| -| [Use OData query operations in SharePoint REST requests](https://msdn.microsoft.com/library/d4b5c277-ed50-420c-8a9b-860342284b72%28Office.15%29.aspx)
|Learn how to use the SharePoint REST service, which provides a REST programming interface comparable to the existing client object model.
| -| [Get to know the SharePoint REST service](https://msdn.microsoft.com/library/2de035a0-ac75-43bd-9665-5c5a59c4c590%28Office.15%29.aspx)
|Get the basics of using the SharePoint REST service to access and update SharePoint data, using the REST and OData web protocol standards.
| -| [Complete basic operations using SharePoint REST endpoints](/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints)
|Learn how to navigate the SharePoint data structure as it is represented in the REST service, perform common CRUD (create, read, update, and delete) operations on SharePoint items via the REST service, synchronize SharePoint items across applications, and control item concurrency.
| - +| **Article title** | **Description** | +| :---------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Use OData query operations in SharePoint REST requests](https://msdn.microsoft.com/library/d4b5c277-ed50-420c-8a9b-860342284b72%28Office.15%29.aspx) | Learn how to use the SharePoint REST service, which provides a REST programming interface comparable to the existing client object model. | +| [Get to know the SharePoint REST service](https://msdn.microsoft.com/library/2de035a0-ac75-43bd-9665-5c5a59c4c590%28Office.15%29.aspx) | Get the basics of using the SharePoint REST service to access and update SharePoint data, using the REST and OData web protocol standards. | +| [Complete basic operations using SharePoint REST endpoints](/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints) | Learn how to navigate the SharePoint data structure as it is represented in the REST service, perform common CRUD (create, read, update, and delete) operations on SharePoint items via the REST service, synchronize SharePoint items across applications, and control item concurrency. | ## Create an SharePoint Add-in to access external data using REST - The following procedures guide you through setting up an SharePoint Add-in and configuring a webpage to make requests using REST functions to retrieve data from an external data source. - - - ### To create an SharePoint Add-in - 1. Open Visual Studio 2012 or later. - - -2. Create an **App for SharePoint** project. - - -3. Specify the app settings, including app name, the site URL for debugging the app, and how you want to host the app (Autohosted, Provider-hosted, SharePoint-hosted). For more information about hosting options, see [Choose patterns for developing and hosting your SharePoint Add-in](https://msdn.microsoft.com/library/05ce5435-0a03-4ddc-976b-c33b08d03457%28Office.15%29.aspx). - - -4. Choose **Finish** to create the app. - - +1. Create an **App for SharePoint** project. +1. Specify the app settings, including app name, the site URL for debugging the app, and how you want to host the app (Autohosted, Provider-hosted, SharePoint-hosted). For more information about hosting options, see [Choose patterns for developing and hosting your SharePoint Add-in](https://msdn.microsoft.com/library/05ce5435-0a03-4ddc-976b-c33b08d03457%28Office.15%29.aspx). +1. Choose **Finish** to create the app. ### To generate the external content type - 1. In **Solution Explorer**, open the shortcut menu for the project, and choose **Add**, **Content Types for External Data Source**. - - -2. In the **Specify OData Source** page, enter the URL of the OData service you want to connect to. In this case, use the Northwind OData source published at [http://www.odata.org/ecosystem](http://www.odata.org/ecosystem). Set the URL for the OData service to `http://services.odata.org/Northwind/Northwind.svc/`, and provide a name for the data source. - +1. In the **Specify OData Source** page, enter the URL of the OData service you want to connect to. In this case, use the Northwind OData source published at [https://www.odata.org/ecosystem](https://www.odata.org/ecosystem). Set the URL for the OData service to `http://services.odata.org/Northwind/Northwind.svc/`, and provide a name for the data source. + Choose **Next**. - - -3. This displays a list of data entities that are being exposed by the OData Service. Select the **Customers** entity. Ensure that the **Create list instances for the selected data entities (except Service Operations)** check box is selected. - - -4. Choose **Finish**. - - + +1. This displays a list of data entities that are being exposed by the OData Service. Select the **Customers** entity. Ensure that the **Create list instances for the selected data entities (except Service Operations)** check box is selected. +1. Choose **Finish**. ## Code example: Add scripts and HTML to the Home.aspx page - -At this point, you have an external content type and an external list that will display the data from the Northwind OData source. - - - +At this point, you have an external content type and an external list that will display the data from the Northwind OData source. + The next objective is to modify the default.aspx page that was created when you created your app. You will add a container to hold the results of the query that is executed with the page loads. By executing the scripts on the page load event, you ensure that the script is executed every time the page is browsed, and the resulting REST calls are made to the Northwind OData source to add records to the page. - - - ### To add the container to the Default.aspx page - 1. In **Solution Explorer**, open the Default.aspx page in the **Pages** module. - - -2. Add the following **div** element to the page. - -```HTML - -
-``` +1. Add the following **div** element to the page. + + ```html +
+ ``` + +1. Save the page. -3. Save the page. - - Finally, you add code to the App.js file that executes when the page loads. - - - ### To modify the App.js file to make REST calls +1. Open the **App.js** file in the Scripts module of your SharePoint project. +1. Paste the following code at the end of the file. -1. Open the App.js file in the Scripts module of your SharePoint project. - - -2. Paste the following code at the end of the file. - -``` - $(document).ready(function () { +```javascript +$(document).ready(function () { - // Namespace - window.AppLevelECT = window.AppLevelECT || {}; + // Namespace + window.AppLevelECT = window.AppLevelECT || {}; - // Constructor - AppLevelECT.Grid = function (hostElement, surlWeb) { - this.hostElement = hostElement; - if (surlWeb.length > 0 && surlWeb.substring(surlWeb.length - 1, surlWeb.length) != "/") - surlWeb += "/"; - this.surlWeb = surlWeb; - } + // Constructor + AppLevelECT.Grid = function (hostElement, surlWeb) { + this.hostElement = hostElement; + if (surlWeb.length > 0 && surlWeb.substring(surlWeb.length - 1, surlWeb.length) != "/") + surlWeb += "/"; + this.surlWeb = surlWeb; + } - // Prototype - AppLevelECT.Grid.prototype = { + // Prototype + AppLevelECT.Grid.prototype = { - init: function () { + init: function () { - $.ajax({ - url: this.surlWeb + "_api/lists/getbytitle('Customer')/items?$select=BdcIdentity,CustomerID,ContactName", - headers: { - "accept": "application/json", - "X-RequestDigest": $("#__REQUESTDIGEST").val() - }, - success: this.showItems - }); - }, + $.ajax({ + url: this.surlWeb + "_api/lists/getbytitle('Customer')/items?$select=BdcIdentity,CustomerID,ContactName", + headers: { + "accept": "application/json", + "X-RequestDigest": $("#__REQUESTDIGEST").val() + }, + success: this.showItems + }); + }, - showItems: function (data) { - var items = []; + showItems: function (data) { + var items = []; - items.push(""); - items.push(''); + items.push("
Customer IDCustomer Name
"); + items.push(''); - $.each(data.d.results, function (key, val) { - items.push(''); - }); + $.each(data.d.results, function (key, val) { + items.push(''); + }); - items.push("
Customer IDCustomer Name
' + - val.CustomerID + '' + - val.ContactName + '
' + + val.CustomerID + '' + + val.ContactName + '
"); + items.push(""); - $("#displayDiv").html(items.join('')); - } - } + $("#displayDiv").html(items.join('')); + } + } - ExecuteOrDelayUntilScriptLoaded(getCustomers, "sp.js"); + ExecuteOrDelayUntilScriptLoaded(getCustomers, "sp.js"); }); function getCustomers() { @@ -197,28 +134,11 @@ function getCustomers() { ``` Press F5 to deploy the app to SharePoint. Browse to the Default.aspx page in the app, and a list of customers appears on the page. - - - ## See also - - - -- [Business Connectivity Services in SharePoint](business-connectivity-services-in-sharepoint.md) - - -- [Get to know the SharePoint REST service](https://msdn.microsoft.com/library/2de035a0-ac75-43bd-9665-5c5a59c4c590%28Office.15%29.aspx) - - -- [Complete basic operations using SharePoint REST endpoints](/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints) - - -- [Add-in-scoped external content types in SharePoint](add-in-scoped-external-content-types-in-sharepoint.md) - - -- [What's new in Business Connectivity Services in SharePoint](what-s-new-in-business-connectivity-services-in-sharepoint.md) - - - +- [Business Connectivity Services in SharePoint](business-connectivity-services-in-sharepoint.md) +- [Get to know the SharePoint REST service](https://msdn.microsoft.com/library/2de035a0-ac75-43bd-9665-5c5a59c4c590%28Office.15%29.aspx) +- [Complete basic operations using SharePoint REST endpoints](/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints) +- [Add-in-scoped external content types in SharePoint](add-in-scoped-external-content-types-in-sharepoint.md) +- [What's new in Business Connectivity Services in SharePoint](what-s-new-in-business-connectivity-services-in-sharepoint.md) diff --git a/docs/general-development/how-to-add-a-device-channel-panel-snippet-in-sharepoint.md b/docs/general-development/how-to-add-a-device-channel-panel-snippet-in-sharepoint.md index 87d28d5d4..6d119f6d0 100644 --- a/docs/general-development/how-to-add-a-device-channel-panel-snippet-in-sharepoint.md +++ b/docs/general-development/how-to-add-a-device-channel-panel-snippet-in-sharepoint.md @@ -1,156 +1,92 @@ --- title: Add a Device Channel Panel snippet in SharePoint description: Describes how to add a Device Channel Panel that can be added to a master page or page layout to control how content is rendered in created channels. -ms.date: 06/09/2022 +ms.date: 05/18/2023 ms.assetid: 612780a8-6267-49f6-a32d-33600bb5f6b4 ms.localizationpriority: medium --- - # Add a Device Channel Panel snippet in SharePoint A Device Channel Panel is a snippet that you can add to a master page or page layout to control what content is rendered for each channel that you create. The primary purpose of a Device Channel Panel is to selectively display different page fields on different channels from a single page layout. ## Introduction to the Device Channel Panel snippet - A Device Channel Panel is a control that you can add to a master page or page layout to control what content is rendered in each channel that you create. A Device Channel Panel is a container that specifies one or more channels; if one or more of those channels are active when the page is rendered, all of the contents of the Device Channel Panel are also rendered. A Device Channel Panel can include almost any type of content, including a link to a CSS file or a .js file. It is an easy way to include specific content for specific channels. - - - + Perhaps the most common scenario for using Device Channel Panels is to selectively include parts of a page layout for specific channels. For example, you may have a page layout with separate text fields for a long greeting and a short greeting. By placing the page fields inside Device Channel Panels, you can display the short greeting only to phones and the long greeting only to the desktop. The content of a Device Channel Panel is not displayed on non-included channels—in fact, the content is not rendered at all, which prevents bytes from going across the wire. For this reason, using Device Channel Panels is a better way to display content on specific channels than using a CSS class with `Display:None` because Device Channel Panels help to reduce the page weight for a specific channel. - - - + You can also use Device Channel Panels on master pages. For example, if you have a master page that can accommodate two different devices (or two different browsers) with only minimal changes, you can use Device Channel Panels to hold the content on the master page that is specific to either of those devices. - - - + There are two limitations to using a Device Channel Panel: - - - - **Display templates** Because display templates are rendered on the client side and Device Channel Panels run on the server side, you cannot use a Device Channel Panel within a display template. Instead, you should use two different Content Search web parts within Device Channel Panels on your page layout, or use the JavaScript variable to trigger the behavior you want within the display template itself. - - - **Web part zones** You cannot insert a web part zone inside a Device Channel Panel. If you want to allow authors to add web parts to a page, and if you are not concerned about the page weight for mobile devices, you can add a Rich Text Editor page field to a Device Channel Panel, and then instruct authors to add web parts there. You can add web parts directly to a Device Channel Panel (without a web part zone). - - ## Inserting a Device Channel Panel snippet - Like all snippets, you add a Device Channel Panel snippet from the Snippet Gallery. To navigate to the Snippet Gallery, you must first select a master page or page layout to edit. - - - - ### To insert a Device Channel Panel snippet - 1. Browse to your publishing site. - - -2. In the upper-right corner of the page, choose the Settings gear, and then choose **Design Manager**. - - -3. In Design Manager, in the left navigation pane, choose **Edit Master Pages** or **Edit Page Layouts**, depending on what type of file you're editing. - - -4. Select the name of the master page or page layout that you want to add the snippet to. - - -5. To open the Snippet Gallery, choose **Snippets** in the upper-right corner of the server-side preview. - - -6. On the ribbon, on the **Design** tab, choose **Device Channel Panel**. - - -7. On the right side of the Snippet Gallery, under **About this Component**, click or select section headers to expand or collapse groups of properties, and then configure any custom settings that you want. - +1. In the upper-right corner of the page, choose the Settings gear, and then choose **Design Manager**. +1. In Design Manager, in the left navigation pane, choose **Edit Master Pages** or **Edit Page Layouts**, depending on what type of file you're editing. +1. Select the name of the master page or page layout that you want to add the snippet to. +1. To open the Snippet Gallery, choose **Snippets** in the upper-right corner of the server-side preview. +1. On the ribbon, on the **Design** tab, choose **Device Channel Panel**. +1. On the right side of the Snippet Gallery, under **About this Component**, click or select section headers to expand or collapse groups of properties, and then configure any custom settings that you want. + The section named **Important** contains the properties that are key to how this particular snippet works. For a Device Channel Panel, the **IncludedChannels** property is the most important. For this property, enter the alias of each Device Channel that you want to display the content contained in this Device Channel Panel. If you enter more than one alias, separate each with a comma. - + > [!NOTE] > If you edit the alias of a channel in the Device Channels list, you must manually find and update that alias wherever it appears in your design files, including updating the **IncludedChannels** property for every Device Channel Panel that uses that alias. -8. After you configure any other properties, choose **Update**. This updates the HTML snippet on the left side of the page, so that the markup reflects your custom settings. You can always choose **Reset** to return all properties to their default settings. - - -9. On the left side of the Snippet Gallery, under **HTML Snippet**, choose **Copy to Clipboard**. - - -10. In your HTML editor, open the mapped network drive on your computer, and then open the HTML file for the master page or page layout that you're adding the snippet to. - +1. After you configure any other properties, choose **Update**. This updates the HTML snippet on the left side of the page, so that the markup reflects your custom settings. You can always choose **Reset** to return all properties to their default settings. +1. On the left side of the Snippet Gallery, under **HTML Snippet**, choose **Copy to Clipboard**. +1. In your HTML editor, open the mapped network drive on your computer, and then open the HTML file for the master page or page layout that you're adding the snippet to. + For more information, see [How to: Map a network drive to the SharePoint Master Page Gallery](how-to-map-a-network-drive-to-the-sharepoint-master-page-gallery.md). - - -11. In the HTML file, paste the snippet where you want the markup to appear. - + +1. In the HTML file, paste the snippet where you want the markup to appear. + If you are adding the snippet to a page layout, make sure to paste the snippet inside **PlaceHolderMain**. - - -12. Replace the **
** where `class="DefaultContentBlock"` with your own specific content. - - Typically, if you're adding a Device Channel Panel to a page layout, you replace the **
** by copying page fields inside the panel. - - -13. Save the page, and then refresh the server-side preview in Design Manager to make sure the Device Channel Panel appears as expected. - + +1. Replace the `
` where `class="DefaultContentBlock"` with your own specific content. + + Typically, if you're adding a Device Channel Panel to a page layout, you replace the `
` by copying page fields inside the panel. + +1. Save the page, and then refresh the server-side preview in Design Manager to make sure the Device Channel Panel appears as expected. + To preview the panel on different channels, you can add query string parameters to the URL. For example, you can append the query string variable `"DeviceChannel=YourChannelAlias"` to the URL of any page in the server-side preview. - - ## Understanding the snippet markup - -The two most important parts of a Device Channel Panel snippet are the **IncludedChannels** property and the **
** where `class="DefaultContentBlock"`. By default, the **IncludedChannels** property is empty. In the **Important** section of the property grid, you should enter the aliases, separated by commas, of the device channels that you want to display the content in this panel. - +The two most important parts of a Device Channel Panel snippet are the **IncludedChannels** property and the `
` where `class="DefaultContentBlock"`. By default, the **IncludedChannels** property is empty. In the **Important** section of the property grid, you should enter the aliases, separated by commas, of the device channels that you want to display the content in this panel. + > [!NOTE] > If you change an alias in the Device Channels list, you must also change that alias wherever it appears in your markup, including in the **IncludedChannels** property for every Device Channel Panel that uses that alias. - - - - -The **
** where `class="DefaultContentBlock"` should be replaced with whatever specific content you want to display for the included channels. A Device Channel Panel can include almost any type of content, including a link to a CSS file or a .js file. The most common scenario for using Device Channel Panels is to include specific page fields from a page layout for specific channels. In this case, you copy the page field markup where the **
** is positioned inside the Device Channel Panel. - - - +The `
` where `class="DefaultContentBlock"` should be replaced with whatever specific content you want to display for the included channels. A Device Channel Panel can include almost any type of content, including a link to a CSS file or a .js file. The most common scenario for using Device Channel Panels is to include specific page fields from a page layout for specific channels. In this case, you copy the page field markup where the `
` is positioned inside the Device Channel Panel. ```HTML -
- You should replace this div with content that renders based on your Device Channel Panel Properties. + You should replace this div with content that renders based on your Device Channel Panel Properties.
- ``` - ## See also - - - -- [SharePoint Design Manager snippets](sharepoint-design-manager-snippets.md) - - -- [SharePoint Design Manager device channels](sharepoint-design-manager-device-channels.md) - - -- [Build sites for SharePoint](build-sites-for-sharepoint.md) - - -- [Develop the site design in SharePoint](develop-the-site-design-in-sharepoint.md) - - +- [SharePoint Design Manager snippets](sharepoint-design-manager-snippets.md) +- [SharePoint Design Manager device channels](sharepoint-design-manager-device-channels.md) +- [Build sites for SharePoint](build-sites-for-sharepoint.md) +- [Develop the site design in SharePoint](develop-the-site-design-in-sharepoint.md) diff --git a/docs/general-development/how-to-add-a-security-trim-snippet-in-sharepoint.md b/docs/general-development/how-to-add-a-security-trim-snippet-in-sharepoint.md index 166c19a3c..6fde84dc3 100644 --- a/docs/general-development/how-to-add-a-security-trim-snippet-in-sharepoint.md +++ b/docs/general-development/how-to-add-a-security-trim-snippet-in-sharepoint.md @@ -1,152 +1,87 @@ --- title: Add a Security Trim snippet in SharePoint description: Describes how to add a Security Trim snippet in SharePoint to display content only to specific and authenticated users. -ms.date: 06/09/2022 +ms.date: 05/18/2023 ms.assetid: 4beaab08-760b-408a-b768-906312779379 ms.localizationpriority: high --- - # Add a Security Trim snippet in SharePoint You can use a Security Trim snippet to display content only to specific users, based on a specific permission that those users must have and whether the users are authenticated or anonymous. ## Introduction to the Security Trim snippet - You can use a Security Trim snippet to display content only to specific users, based on a specific permission that those users must have, and whether those users are authenticated or anonymous. You can add a Security Trim panel to a master page or page layout. A Security Trim panel is a container that can include other components or snippets, such as web parts, in addition to static content. - - - + For example, you can use a Security Trim panel to display the following content to specific users: - - - - A Content by Search web part that displays which documents an authenticated user is currently working on. - - - A list view of recently modified documents so that authenticated users can see what's new on the site. - - - A Content by Search web part that displays to non-authenticated visitors a list of recommended links based on the current article. Such a list of recommendations might be noise to authenticated content authors working in the site, but it's important for non-authenticated visitors. - - - A sign-in link separate from the ribbon, for non-authenticated users or users who have yet to be authenticated. - + > [!NOTE] - > This sign-in link is inserted automatically into a master page that is created by using Design Manager, but you can delete it if it's not needed. + > This sign-in link is inserted automatically into a master page that is created by using Design Manager, but you can delete it if it's not needed. A Security Trim panel has two important property settings, one for authentication and one for permissions (or authorization). For example, you can use a Security Trim panel to display the following content to specific users: - - - - **AuthenticationRestrictions** With this property, you can restrict the panel to either authenticated or anonymous users, or choose all users (all users is the default setting). - - - **Permissions** With this property, you can select a specific permission that users must have to view the content in the panel. - + > [!NOTE] - > You are selecting an individual permission, not a permission level. (A permission level is a set of granted permissions.) + > You are selecting an individual permission, not a permission level. (A permission level is a set of granted permissions.) + Of course, if you restrict the authentication to only anonymous users, it's typically not necessary to specify a specific permission because anonymous users have usually not been given any SharePoint permissions. It makes sense to use permissions only with all users or with all authenticated users. - - - -The Security Trim panel has three options on the ribbon, listed in the left column of Table 1. Table 1 shows how these settings determine the specific permission that users are required to have, the lowest default permission level that includes that specific permission, and the group that is linked to that permission level by default.) - + +The Security Trim panel has three options on the ribbon, listed in the left column of Table 1. Table 1 shows how these settings determine the specific permission that users are required to have, the lowest default permission level that includes that specific permission, and the group that is linked to that permission level by default. + > [!NOTE] -> These are the default settings, which can be changed for any given scope, such as a site collection, site, list, or item. - - - +> These are the default settings, which can be changed for any given scope, such as a site collection, site, list, or item. For example, if you set a Security Trim panel to **Show to authors**, by default content inside that panel is visible to users in the Members group and the Owners group. - - - **Table 1. Mapping of panel options to default permission levels and groups** - |**Security Trim panel option**|**Permissions property**|**Permission**|**Permission level**|**Group**| |:-----|:-----|:-----|:-----|:-----| -|Show to authors
|**AddAndCustomizePages**
|Add and Customize Pages
|Contribute (or higher)
|Members
| -|Show to Authenticated Users
|**ViewPages**
|View Pages
|Read (or higher)
|Visitors
| -|Show to Administrators
|**FullMask**
|Select All
|Full Control
|Owners
| - +|Show to authors |**AddAndCustomizePages** |Add and Customize Pages |Contribute (or higher) |Members | +|Show to Authenticated Users |**ViewPages** |View Pages |Read (or higher) |Visitors | +|Show to Administrators |**FullMask** |Select All |Full Control |Owners | ### Inserting a Security Trim panel - Like all snippets, you add the Security Trim snippet from the Snippet Gallery. To navigate to the Snippet Gallery, you must first select a master page or page layout to edit. - - - ### To insert a Security Trim panel - 1. Browse to your publishing site. - - -2. In the upper-right corner of the page, choose the Settings gear, and then choose **Design Manager**. - - -3. In Design Manager, in the left navigation pane, choose **Edit Master Pages** or **Edit Page Layouts**, depending on what type of file you're editing. - - -4. Select the name of the master page or page layout that you want to add the snippet to. - - -5. To open the Snippet Gallery, choose **Snippets** in the upper-right corner of the server-side preview. - - -6. On the ribbon, on the **Design** tab, choose **Security Trim**. - +1. In the upper-right corner of the page, choose the Settings gear, and then choose **Design Manager**. +1. In Design Manager, in the left navigation pane, choose **Edit Master Pages** or **Edit Page Layouts**, depending on what type of file you're editing. +1. Select the name of the master page or page layout that you want to add the snippet to. +1. To open the Snippet Gallery, choose **Snippets** in the upper-right corner of the server-side preview. +1. On the ribbon, on the **Design** tab, choose **Security Trim**. + Optionally, in the drop-down list on the **Security Trim** button, you can select the users to whom the panel content will be visible, or you can see more options by configuring the important property values for the panel. - - -7. On the right side of the Snippet Gallery, under **About this Component**, click or select section headers to expand or collapse groups of properties, and then configure any custom settings that you want. - - -8. After you configure any properties, choose **Update**. This updates the HTML snippet on the left side of the page, so that the markup reflects your custom settings. You can always choose **Reset** to return all properties to their default settings. - - -9. On the left side of the Snippet Gallery, under **HTML Snippet**, choose **Copy to Clipboard**. - - -10. In your HTML editor, open the mapped network drive on your computer, and then open the HTML file for the master page or page layout that you're adding the snippet to. - - -11. In the HTML file, paste the snippet where you want the markup to appear. - + +1. On the right side of the Snippet Gallery, under **About this Component**, click or select section headers to expand or collapse groups of properties, and then configure any custom settings that you want. +1. After you configure any properties, choose **Update**. This updates the HTML snippet on the left side of the page, so that the markup reflects your custom settings. You can always choose **Reset** to return all properties to their default settings. +1. On the left side of the Snippet Gallery, under **HTML Snippet**, choose **Copy to Clipboard**. +1. In your HTML editor, open the mapped network drive on your computer, and then open the HTML file for the master page or page layout that you're adding the snippet to. +1. In the HTML file, paste the snippet where you want the markup to appear. + If you are adding the snippet to a page layout, make sure to paste the snippet inside **PlaceHolderMain**. - - -12. Replace the **
** where `class="DefaultContentBlock"` with your own specific content. - - -13. Save the page, and then refresh the server-side preview in Design Manager to make sure the Security Trim panel appears as expected. - - -## Understanding the snippet markup - +1. Replace the `
` where `class="DefaultContentBlock"` with your own specific content. +1. Save the page, and then refresh the server-side preview in Design Manager to make sure the Security Trim panel appears as expected. -The most important parts of a Security Trim snippet are the **AuthenticationRestrictions** property and the **Permissions** property, and the **
** in bold below. **AuthenticationRestrictions** appears in the markup only when changed from **AllUsers**, which is the default. If you choose **Reset** for the snippet in the Snippet Gallery, **AuthenticationRestrictions** is removed from the markup, which means the snippet uses the default value, **AllUsers**. - - - -The **
** where `class="DefaultContentBlock"` is what you replace with your own content, which can include other snippets and controls. - - - +## Understanding the snippet markup +The most important parts of a Security Trim snippet are the **AuthenticationRestrictions** property and the **Permissions** property, and the `
` in bold below. **AuthenticationRestrictions** appears in the markup only when changed from **AllUsers**, which is the default. If you choose **Reset** for the snippet in the Snippet Gallery, **AuthenticationRestrictions** is removed from the markup, which means the snippet uses the default value, **AllUsers**. +The `
` where `class="DefaultContentBlock"` is what you replace with your own content, which can include other snippets and controls. ```HTML -
@@ -161,21 +96,9 @@ The **
** where `class="DefaultContentBlock"` is what you replace with your
``` - ## See also - - - -- [Understanding permission levels](https://support.office.com/article/understanding-permission-levels-in-sharepoint-87ecbb0e-6550-491a-8826-c075e4859848) - - -- [SharePoint Design Manager snippets](sharepoint-design-manager-snippets.md) - - -- [Build sites for SharePoint](build-sites-for-sharepoint.md) - - -- [Develop the site design in SharePoint](develop-the-site-design-in-sharepoint.md) - - +- [Understanding permission levels](https://support.office.com/article/understanding-permission-levels-in-sharepoint-87ecbb0e-6550-491a-8826-c075e4859848) +- [SharePoint Design Manager snippets](sharepoint-design-manager-snippets.md) +- [Build sites for SharePoint](build-sites-for-sharepoint.md) +- [Develop the site design in SharePoint](develop-the-site-design-in-sharepoint.md) diff --git a/docs/general-development/how-to-add-a-web-part-zone-snippet-in-sharepoint.md b/docs/general-development/how-to-add-a-web-part-zone-snippet-in-sharepoint.md index c096a9521..5390f1ed0 100644 --- a/docs/general-development/how-to-add-a-web-part-zone-snippet-in-sharepoint.md +++ b/docs/general-development/how-to-add-a-web-part-zone-snippet-in-sharepoint.md @@ -1,209 +1,116 @@ --- title: Add a web part zone snippet in SharePoint description: Describes how to add a web part zone snippet in SharePoint and provides a list of Web part zone properties used to restrict content authors. -ms.date: 06/09/2022 +ms.date: 05/18/2023 ms.assetid: 7583b217-200c-4569-8f88-fe975c8ebd72 ms.localizationpriority: high --- - # Add a web part zone snippet in SharePoint -> [!IMPORTANT] +> [!IMPORTANT] > This extensibility option is **only** available for classic SharePoint experiences. You cannot use this option with modern experiences in SharePoint Online, like with communication sites. We do not recommend using classic experience or these branding techniques anymore. A web part zone is a snippet that you can add to a page layout so that content authors can add, edit, or delete web parts in that zone. ## Introduction to the web part zone snippet - A web part is a server control that provides a specific piece of SharePoint functionality, and a web part zone is a container that determines the layout, behavior, and other properties of the web parts contained in that zone. For example, a web part zone can specify whether the web parts in the zone: - - - -- Are arranged in a horizontal or vertical layout. - - +- Are arranged in a horizontal or vertical layout. - Display common user interface (UI) elements such as a title bar or border. - - - Can be customized by content authors when they edit a page in the browser. - - - Can be personalized by site visitors who create a personal view of a web part when they view a page in the browser. - - + In a publishing site, content authors with the necessary permissions can create or edit pages that reside in the Pages library. As a designer, you can add a web part zone to a page layout. When a content author creates or edits a page based on that page layout, the author can add, edit, or delete web parts in that zone. For example, you may want to add a web part zone to a page layout so that content authors can: - - - - Display the results of a search query by using a Content Search web part. Authors can update or modify the search query when a search-driven web part resides inside a web part zone. - - - Embed video or audio clips in a webpage by using a Media web part. - - - Create lists of hyperlinks that are easily edited, grouped, or reordered by using a Summary Link web part. - - - Create a site map that lists all pages in a site and that is automatically updated whenever a page is added, deleted, renamed, or moved by using a Table of Contents web part. - - ### When to use web part zones When a page layout includes one or more web part zones, the web part zones are available on all pages that use that layout, which enables authors to insert web parts onto those pages. If you enable authors to insert web parts on pages, you reduce your control over the users' experience of the site. For example, an author could insert a Table of Contents web part onto a page that exposes parts of your site that you don't want visitors to navigate to from the current page. - - - + If you want complete control over how a web part appears on your site, and if you want that web part to appear on all pages of a certain type, add the web part directly to a page layout. If you want a web part to appear on all pages in a site, you can also add a web part directly to a master page. - + > [!NOTE] -> Web part zones are available on page layouts but not on master pages—the purpose of zones is to allow authors to modify web parts, and authors typically don't edit a master page. - - - +> Web part zones are available on page layouts but not on master pages—the purpose of zones is to allow authors to modify web parts, and authors typically don't edit a master page. You can also add web part zones to a page layout but restrict their use. For example, you can add web parts to a zone, and then set a property of that zone so that content authors can edit the properties of existing web parts but not add or remove web parts from the zone. web part zones have a set of properties that serve a dual purpose. You can use one subset of properties to organize the layout and format of web parts on the page. You can use another subset of properties to provide an additional level of protection from modification (or "lock down") of the web parts within the zone. - - - + For varying levels of control over how web parts are presented on your site, you can: - - - - Add web parts directly to a master page or page layout. This means content authors cannot modify the web parts. - - - Add web parts to zones on page layouts, but restrict those zones to only the default web parts that you add. - - - Add web part zones to page layouts, and give content authors complete control over what web parts appear in those zones and how they are configured. - - + The properties of a web part zone can specify whether content authors are allowed to change: - - - - The layout of web parts in the zone by adding, deleting, resizing, or moving the web parts. - - - The web part settings for all users (the shared view of a web part). - - - Their personal web part settings (the personal view of a web part). - - + Table 1 shows important properties to consider when you want to restrict a web part zone. - - - **Table 1. Web part zone properties used to restrict content authors** - |**Property Name**|**Description**| |:-----|:-----| -|**AllowLayoutChange**
|Specifies whether web parts within the zone can be closed, minimized, deleted, or restored.
If set to **False**, users cannot close, minimize, delete, or restore web parts in the zone, drag web parts to a different zone, or rearrange or move web parts within the zone. Users also cannot add web parts from the web part catalog, and several properties that affect the UI of web parts in the zone are disabled. This property does not affect the ability to change the layout programmatically.
If set to **True**, users with appropriate permissions can perform these actions.
| -|**LockLayout**
|Specifies whether web parts within the zone can be added, deleted, resized, or moved. This property works the same whether the web part page is in personal view or shared view.
If set to **True**, the specific web part properties for each web part in the zone that are affected are: **Zone (ZoneID)**, **Part Order (PartOrder)**, **Visible on Page (IsVisible)**, **Height (Height)**, **Width (Width)**, **Allow Close (AllowRemove)**, and **IsIncluded** (the **Close** command on the **web part** menu). Other web part properties are not affected.
If set to **False**, the web part properties determine whether modifications can be made (together with the appropriate site permissions).
| -|**AllowCustomization**
|Specifies whether shared property values of web parts within the zone can be modified.
If set to **True**, users with appropriate permissions can make changes to the web parts in the zone for all users.
If set to **False**, users cannot make changes to the web parts in the zone in the UI in shared view. But, changes can still be made programmatically and by using the web part Maintenance page.
| -|**AllowPersonalization**
|Specifies whether personal property values of web parts within the zone can be modified.
If set to **True**, users with appropriate permissions can make personal changes to the web parts in the zone.
If set to **False**, users cannot make personal changes to the web parts through the UI, unless the web part is a private web part and they have appropriate permissions.
| - -> [!NOTE] -> You cannot insert a web part zone inside a Device Channel Panel. If you want to allow authors to add web parts to a page, and if you are not concerned about the page weight for mobile devices, you can add a Rich Text Editor page field to a Device Channel Panel, and then instruct authors to add web parts there. You can add web parts directly to a Device Channel Panel (without a web part zone). For more information, see [How to: Add a Device Channel Panel snippet in SharePoint](how-to-add-a-device-channel-panel-snippet-in-sharepoint.md). - - - +|**AllowLayoutChange** |Specifies whether web parts within the zone can be closed, minimized, deleted, or restored. If set to **False**, users cannot close, minimize, delete, or restore web parts in the zone, drag web parts to a different zone, or rearrange or move web parts within the zone. Users also cannot add web parts from the web part catalog, and several properties that affect the UI of web parts in the zone are disabled. This property does not affect the ability to change the layout programmatically. If set to **True**, users with appropriate permissions can perform these actions. | +|**LockLayout** |Specifies whether web parts within the zone can be added, deleted, resized, or moved. This property works the same whether the web part page is in personal view or shared view. If set to **True**, the specific web part properties for each web part in the zone that are affected are: **Zone (ZoneID)**, **Part Order (PartOrder)**, **Visible on Page (IsVisible)**, **Height (Height)**, **Width (Width)**, **Allow Close (AllowRemove)**, and **IsIncluded** (the **Close** command on the **web part** menu). Other web part properties are not affected. If set to **False**, the web part properties determine whether modifications can be made (together with the appropriate site permissions). | +|**AllowCustomization** |Specifies whether shared property values of web parts within the zone can be modified. If set to **True**, users with appropriate permissions can make changes to the web parts in the zone for all users. If set to **False**, users cannot make changes to the web parts in the zone in the UI in shared view. But, changes can still be made programmatically and by using the web part Maintenance page. | +|**AllowPersonalization** |Specifies whether personal property values of web parts within the zone can be modified. If set to **True**, users with appropriate permissions can make personal changes to the web parts in the zone. If set to **False**, users cannot make personal changes to the web parts through the UI, unless the web part is a private web part and they have appropriate permissions. | +> [!NOTE] +> You cannot insert a web part zone inside a Device Channel Panel. If you want to allow authors to add web parts to a page, and if you are not concerned about the page weight for mobile devices, you can add a Rich Text Editor page field to a Device Channel Panel, and then instruct authors to add web parts there. You can add web parts directly to a Device Channel Panel (without a web part zone). For more information, see [How to: Add a Device Channel Panel snippet in SharePoint](how-to-add-a-device-channel-panel-snippet-in-sharepoint.md). ## Inserting a web part zone snippet - Like all snippets, you add this snippet from the Snippet Gallery. To navigate to the Snippet Gallery, you must first select a page layout to edit. Web part zones can be added to page layouts but cannot be added to master pages. - - - ### To insert a web part zone snippet - 1. Browse to your publishing site. - - -2. In the upper-right corner of the page, choose the Settings gear, and then choose **Design Manager**. - - -3. In Design Manager, in the left navigation pane, choose **Edit Page Layouts**. - - -4. Select the name of the page layout that you want to add the snippet to. - - -5. To open the Snippet Gallery, choose **Snippets** in the upper-right corner of the server-side preview. - - -6. On the ribbon, on the **Design** tab, choose **web part zone**. - - -7. On the right side of the Snippet Gallery, under **About this Component**, click or select section headers to expand or collapse groups of properties, and then configure any custom settings that you want. - +1. In the upper-right corner of the page, choose the Settings gear, and then choose **Design Manager**. +1. In Design Manager, in the left navigation pane, choose **Edit Page Layouts**. +1. Select the name of the page layout that you want to add the snippet to. +1. To open the Snippet Gallery, choose **Snippets** in the upper-right corner of the server-side preview. +1. On the ribbon, on the **Design** tab, choose **web part zone**. +1. On the right side of the Snippet Gallery, under **About this Component**, click or select section headers to expand or collapse groups of properties, and then configure any custom settings that you want. + The section named **Important** contains the properties that are key to how this particular snippet works. For a web part zone, the snippet has a unique ID. After you copy the snippet into your page layout, you should not reuse this ID. If you want to add another web part zone snippet, choose **Refresh** to generate a new ID for the next snippet. - + For descriptions of properties that are necessary for restricting a web part zone ( **LockLayout**, **AllowCustomization**, and **AllowPersonalization**), see Table 1. - + > [!NOTE] - > You may notice that some property names are bold in the property grid of the Snippet Gallery. These properties have values that have been changed from the default setting for this component, but these properties are not necessarily relevant to a designer scenario. In other words, a property may be bold but not necessarily important for your scenario. - -8. After you configure any properties, choose **Update**. This updates the HTML snippet on the left side of the page, so that the markup reflects your custom settings. You can always choose **Reset** to return all properties to their default settings. - - -9. On the left side of the Snippet Gallery, under **HTML Snippet**, choose **Copy to Clipboard**. - - -10. In your HTML editor, open the mapped network drive on your computer, and then open the HTML file for the master page or page layout that you're adding the snippet to. - + > You may notice that some property names are bold in the property grid of the Snippet Gallery. These properties have values that have been changed from the default setting for this component, but these properties are not necessarily relevant to a designer scenario. In other words, a property may be bold but not necessarily important for your scenario. + +1. After you configure any properties, choose **Update**. This updates the HTML snippet on the left side of the page, so that the markup reflects your custom settings. You can always choose **Reset** to return all properties to their default settings. +1. On the left side of the Snippet Gallery, under **HTML Snippet**, choose **Copy to Clipboard**. +1. In your HTML editor, open the mapped network drive on your computer, and then open the HTML file for the master page or page layout that you're adding the snippet to. + For more information, see [How to: Map a network drive to the SharePoint Master Page Gallery](how-to-map-a-network-drive-to-the-sharepoint-master-page-gallery.md). - - -11. In the HTML file, paste the snippet where you want the markup to appear. - + +1. In the HTML file, paste the snippet where you want the markup to appear. + When you are adding the snippet to a page layout, make sure to paste the snippet inside **PlaceHolderMain**. - - -12. Replace the **
** where `class="DefaultContentBlock"` with your own specific content. - - -13. If you want to prepopulate the zone with web parts—for example, if the zone will restrict content authors to modifying only existing web parts and not adding new ones—insert web part snippets where the **** tag appears. - - -14. Save the page, and then refresh the server-side preview in Design Manager to make sure the page appears as expected. - - + +1. Replace the `
` where `class="DefaultContentBlock"` with your own specific content. +1. If you want to prepopulate the zone with web parts—for example, if the zone will restrict content authors to modifying only existing web parts and not adding new ones—insert web part snippets where the **** tag appears. +1. Save the page, and then refresh the server-side preview in Design Manager to make sure the page appears as expected. ## Understanding the snippet markup - The two most important parts of a web part zone snippet are the **ID** property and the **** comment. Each zone should have a unique ID. If you want to add more than one web part zone to your page layout, make sure to choose **Refresh** in the Snippet Gallery before copying each snippet so that a new ID is generated. The **** comment should be replaced with any web parts that you want to appear in the zone by default. - - - + Additional properties that can be used to restrict how content authors can use zones ( **AllowCustomization**, **AllowPersonalization**, and **LockLayout**) are shown in the following code. - + > [!NOTE] > The **AllowCustomization**, **AllowPersonalization**, and **LockLayout** properties appear in the markup only if you change their default values in the property grid. - - - - - - - -```HTML +```html
@@ -219,24 +126,10 @@ Additional properties that can be used to restrict how content authors can use z ``` - ## See also - - - -- [SharePoint Design Manager snippets](sharepoint-design-manager-snippets.md) - - -- [WebPartZone class](https://msdn.microsoft.com/library/system.web.ui.webcontrols.webparts.webpartzone.aspx) - - -- [WebPartZoneBase properties](https://msdn.microsoft.com/library/335sw9k3.aspx) - - -- [Build sites for SharePoint](build-sites-for-sharepoint.md) - - -- [Develop the site design in SharePoint](develop-the-site-design-in-sharepoint.md) - - +- [SharePoint Design Manager snippets](sharepoint-design-manager-snippets.md) +- [WebPartZone class](https://msdn.microsoft.com/library/system.web.ui.webcontrols.webparts.webpartzone.aspx) +- [WebPartZoneBase properties](https://msdn.microsoft.com/library/335sw9k3.aspx) +- [Build sites for SharePoint](build-sites-for-sharepoint.md) +- [Develop the site design in SharePoint](develop-the-site-design-in-sharepoint.md) diff --git a/docs/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online.md b/docs/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online.md index 566f0a624..f239f0fb8 100644 --- a/docs/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online.md +++ b/docs/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online.md @@ -1,7 +1,7 @@ --- title: Avoid getting throttled or blocked in SharePoint Online -description: Find out about throttling in SharePoint Online and learn how to avoid being throttled or blocked. -ms.date: 01/19/2023 +description: Learn about throttling in SharePoint Online and learn how to avoid being throttled or blocked. +ms.date: 06/12/2025 ms.assetid: 33ed8106-d850-42b1-8d7f-5ba83901149c ms.localizationpriority: high --- @@ -21,7 +21,10 @@ Does this sound familiar? You're running an application - for example, to scan f ## What is throttling? -SharePoint Online uses throttling to maintain optimal performance and reliability of the SharePoint Online service. Throttling limits the number of API calls or operations within a time window to prevent overuse of resources. +SharePoint Online uses throttling to maintain the optimal performance and reliability of the SharePoint Online service. Throttling limits the number of API calls or operations within a time window to prevent the overuse of resources. + +> [!NOTE] +> Recent updates to this article enhance transparency to already existing throttling rules in the system ### What happens when you get throttled in SharePoint Online? @@ -29,72 +32,138 @@ When usage limits are exceeded, SharePoint Online throttles any further requests For requests that a user performs directly in the browser, SharePoint Online redirects you to the throttling information page, and the requests fail. -For requests that an application makes, including [Microsoft Graph](/graph), CSOM or REST calls, SharePoint Online returns HTTP status code 429 ("Too many requests") or 503 ("Server Too Busy") and the requests will fail. +For requests that an application makes, including [Microsoft Graph](/graph), CSOM, or REST calls, SharePoint Online returns HTTP status code 429 ("Too many requests") or 503 ("Server Too Busy"), and the requests will fail. - HTTP 429 indicates the calling application sent too many requests in a time window and exceeded a predetermined limit. -- HTTP 503 indicates the service isn't ready to handle the request. The common cause is that the service is experiencing more temporary load spikes than expected. +- HTTP 503 indicates the service isn't ready to handle the request. The common cause is that the service is experiencing more temporary load spikes. -In both cases, a `Retry-After` header is included in the response indicating how long the calling application should wait before retrying or making a new request. Throttled requests count towards usage limits, so failure to honor `Retry-After` may result in more throttling. +In both cases, a `Retry-After` header is included in the response, indicating how long the calling application should wait before retrying or making a new request. Throttled requests count towards usage limits, so failure to honor `Retry-After` may result in more throttling. If the offending application continues to exceed usage limits, SharePoint Online may completely block the application or specific request patterns from the application; in this case, the application will keep getting HTTP status code 503, and Microsoft will notify the tenant of the block in the Office 365 Message Center. -### User Throttling +### Resource units -Throttling limits the number of calls and operations collectively made by applications on behalf of a user to prevent overuse of resources. +Some limits are measured in terms of API costs. [Microsoft Graph APIs](/graph) have a predetermined resource unit cost per request: -That said, it's rare for a user to get throttled in SharePoint Online. The service is robust, and it's designed to handle high volume. If you do get throttled, 99% of the time it is because of custom code, such as custom web parts, complex list view and queries, or custom apps users run. That doesn’t mean that there aren’t other ways to get throttled, just that they’re less common. For example, one user syncing a large amount of data across 10 machines at the same time could trigger throttling. +| Resource units per request | Operations | +| -------------------------- | -------------------------------------------------------------------------------------------------------------- | +| 1 |
  • Single item query, such as get item
  • Delta with a token
  • Download file from drive item | +| 2 |
  • Multi item query, such as list children, except delta with a token
  • Create, update, delete, and upload | +| 5 |
  • All permission resource operations, including `$expand=permissions` | -### Application Throttling +> [!NOTE] +> We reserve the right to change the API resource unit cost. -In addition to throttling by user account, limits are also applied to applications in a tenant. +### User Throttling -Every application has its own limits in a tenant, which are based on the number of licenses purchased per organization (see the plans listed on [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#limits-by-plan) for licenses included). Every request that an application makes across all API endpoints, including [Microsoft Graph](/graph), CSOM and REST, counts towards the application’s usage. +Throttling limits the number of calls and operations collectively made by applications on behalf of a user to prevent the overuse of resources. -SharePoint provides various APIs. Different APIs have different costs depending on the complexity of the API. The cost of APIs is normalized by SharePoint and expressed by resource units. Application’s limits are also defined using resource units. +That said, it's rare for a user to get throttled in SharePoint Online. The service is robust, and it's designed to handle high volume. If you do get throttled, 99% of the time it is because of custom code, such as custom web parts, complex list views and queries, or custom apps users run. That doesn’t mean that there aren’t other ways to get throttled, just that they’re less common. For example, one user syncing a large amount of data across 10 machines at the same time could trigger throttling. -The table below defines the resource unit limits for an application in a tenant: +| Category | Type of throttling | Time interval | Limit | +|--------------|------------------------------|-------------------|-----------| +| User | Requests | 5 min | 3,000 | +| User | Ingress | 1 H | 50 GB | +| User | Egress | 1 H | 100 GB | +| User | Delegation Token Request | 5 min | 50 | +| User | External sharing emails | 1 H | 200 | -| License count | 0 – 1k | 1k – 5k | 5k - 15k | 15k - 50k | 50k+ | -| --------------- | --------- | --------- | --------- | --------- | --------- | -| App 1 minute | 1,200 | 2,400 | 3,600 | 4,800 | 6,000 | -| App daily | 1,200,000 | 2,400,000 | 3,600,000 | 4,800,000 | 6,000,000 | +> [!NOTE] +> Displayed limits are default values. Microsoft may change these limits at any time. Your experience may vary -> [!NOTE] -> We reserve the right to change the resource unit limits. +### Tenant Throttling -In terms of API costs, [Microsoft Graph APIs](/graph) have a predetermined resource unit cost per request: +Some throttling limits are applied at the Tenant level to ensure the operations collectively made do not overuse resources. -| Resource units per request | Operations | -| -------------------------- | ------------------------------------------------------- | -| 1 |
  • Single item query, such as get item
  • Delta with a token | -| 2 |
  • Multi item query, such as list children, except delta with a token
  • Create, update, delete and upload | -| 5 |
  • All permission resource operations, including $expand=permissions | +When a customer enables Multi-Geo, each geo gets its own limits (usage measurement not shared across geos). For the limits that are dependent on license count, the total tenant user license count is used (total users across all geos). -> [!NOTE] -> We reserve the right to change the API resource unit cost. +| Category | Type of throttling | Time interval | Tenant license count | Limit | +|--------------|--------------------------------------|-------------------|--------------------------|-----------| +| Tenant | [Resource Units](#resource-units) | 5 min | 0 - 1,000 | 18,750 | +| Tenant | [Resource Units](#resource-units) | 5 min | 1,001 - 5,000 | 37,500 | +| Tenant | [Resource Units](#resource-units) | 5 min | 5,001 - 15,000 | 56,250 | +| Tenant | [Resource Units](#resource-units) | 5 min | 15,001 - 50,000 | 75,000 | +| Tenant | [Resource Units](#resource-units) | 5 min | 50,000+ | 93,750 | +| Tenant | Assign Sensitivity Label | 5 min | no license bound | 100 | +| Tenant | PeopleManagerAPIs | 5 min | 0 - 1,000 | 3,000 | +| Tenant | PeopleManagerAPIs | 5 min | 1,001 - 5,000 | 6,000 | +| Tenant | PeopleManagerAPIs | 5 min | 5,001 - 15,000 | 9,000 | +| Tenant | PeopleManagerAPIs | 5 min | 15,001 - 50,000 | 12,000 | +| Tenant | PeopleManagerAPIs | 5 min | 50,000+ | 15,000 | -Delta with a token is the most efficient way to scan content in SharePoint, and we talk more in details at the [best practices for scanning applications](https://aka.ms/ScanGuidance). To help applications that follow the guidance, we lower the resource unit cost of delta requests with a token to 1 resource unit, although it's a multi-item query. The delta request without a token is considered a multi-item query and costs 2 resource units per request. +> [!NOTE] +> Displayed limits are default values. Microsoft may change these limits at any time. Your experience may vary -In [batching](/graph/json-batching), requests in a batch are evaluated individually by resource units. +### Application Throttling + +In addition to throttling by user account, limits are also applied to applications in a tenant. -CSOM and REST don't have a predetermined resource unit cost and they usually consume more resource units than [Microsoft Graph APIs](/graph) to achieve the same functionality. And in addition to resource unit limits, CSOM and REST are also subject to other internal resource limits, so if applications call CSOM and REST, they may experience more throttling than the limits described in this document. We highly recommend you choose [Microsoft Graph APIs](/graph) over CSOM and REST APIs when possible. +Every application has its own limits in a tenant, which are based on the number of licenses purchased per organization (see the plans listed on [SharePoint Limits](/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#limits-by-plan) for licenses included). Every request that an application makes across all API endpoints, including [Microsoft Graph](/graph), CSOM, and REST, counts towards the application’s usage. -Since application limits are in resource units, the actual request rate, such as requests per minute, depends on application’s API choice and the corresponding API resource unit cost. In general, you can estimate the request rate using an average of 2 resource units per request and divide resource unit limits by 2 to get the estimated request rate. +SharePoint provides various APIs. Different APIs have different costs depending on the complexity of the API. The cost of APIs is normalized by SharePoint and expressed by resource units. Application’s limits are also defined using resource units. -Although each application has its own limits within a tenant and we allow tenants to run more than one application, multiple applications running against the same tenant share the same resource bucket, and in rare occurrences can cause rate limiting when too many applications send requests at the time. +For multitenant applications: + +1. Each tenant hosting the application is considered distinct, operating independently from others. Consequently, every application is subject to its own usage limits within each tenant as defined above. +1. The consumption of resource units by the application is to be measured on a per-tenant, per-application basis. This ensures that each tenant-application pair remains within the permissible resource limits specified for that particular tenant. +1. Should the application reach its resource limit within one tenant, this occurrence will not affect other instances of the application operating in different tenants. Each tenant's resource utilization is isolated, preventing cross-tenant impact. + +| Category | Type of throttling | Time interval | Tenant license count | Limit | +|--------------------|--------------------------------------|-------------------|--------------------------|------------| +| Per APP Per Tenant | [Resource Units](#resource-units) | 24 H | 0 - 1,000 | 1,200,000 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 24 H | 1,001 - 5,000 | 2,400,000 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 24 H | 5,001 - 15,000 | 3,600,000 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 24 H | 15,001 - 50,000 | 4,800,000 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 24 H | 50,000+ | 6,000,000 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 1 min | 0 - 1,000 | 1,250 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 1 min | 1,001 - 5,000 | 2,500 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 1 min | 5,001 - 15,000 | 3,750 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 1 min | 15,001 - 50,000 | 5,000 | +| Per APP Per Tenant | [Resource Units](#resource-units) | 1 min | 50,000+ | 6,250 | +| Per APP Per Tenant | Ingress | 1 H | no license bound | 400 GB | +| Per APP Per Tenant | Egress | 1 H | no license bound | 400 GB | +| Per APP Per Tenant | Specific Sharing APIs | 5 min | no license bound | 300 | + +> [!NOTE] +> Displayed limits are default values. Microsoft may change these limits at any time. Your experience may vary + +### Other Limits + +| Category | Type of throttling | Time interval | Limit | +|-------------------------------|--------------------------------------|-------------------|-----------| +| SharePoint Embedded containers| [Resource Units](#resource-units) | 1 min | 3,000 | +| Per Site | Anonymous Link | 5 min | 3,000 | +| Per Site | Anonymous Egress (Download) | 2 H | 100 GB | +| Per Site | External sharing emails | 1 H | 200 | + +> [!NOTE] +> Displayed limits are default values. Microsoft may change these limits at any time. Your experience may vary ## How to handle throttling? Below is a quick summary of the best practices to handle throttling: + - Reduce the number of concurrent requests - Avoid request spikes - Choose [Microsoft Graph APIs](/graph) over CSOM and REST APIs when possible - Use the `Retry-After` and `RateLimit` HTTP headers -- Decorate your traffic so we know who you are (see section on traffic decoration best practice more on that below) +- Decorate your traffic so we know who you are (see section on traffic decoration best practice, more on that below) +- Consider using [Graph Data Connect for SharePoint](https://techcommunity.microsoft.com/blog/microsoft_graph_data_connect_for_sharepo/links-about-microsoft-graph-data-connect-for-sharepoint/4069045) for broad site analytics +- Understand if [service prioritization in SharePoint](https://aka.ms/SharePointPrioritization) is the right fit for your scenario + +As stated earlier, [Microsoft Graph](/graph) is cloud born APIs that have the latest improvements and optimizations. In general, [Microsoft Graph](/graph) consumes fewer resources than CSOM and REST to achieve the same functionality. Hence, adopting [Microsoft Graph](/graph) can improve the application's performance and reduce throttling. + +If you do run into throttling, we require using the `Retry-After` HTTP header to ensure minimum delay until the throttle is removed. The `RateLimit` HTTP headers send you early signals when you're close to limits, and you can proactively reduce requests to avoid hitting the throttle. + +Delta with a token is the most efficient way to scan content in SharePoint, and we talk more in detail at the [best practices for scanning applications](https://aka.ms/ScanGuidance). To help applications that follow the guidance, we lower the resource unit cost of delta requests with a token to 1 resource unit, although it's a multi-item query. The delta request without a token is considered a multi-item query and costs 2 resource units per request. -As stated earlier, [Microsoft Graph](/graph) is cloud born APIs that have the latest improvements and optimizations. In general, [Microsoft Graph](/graph) consumes less resource than CSOM and REST to achieve the same functionality. Hence, adopting [Microsoft Graph](/graph) can improve application's performance and reduce throttling. +In [batching](/graph/json-batching), requests in a batch are evaluated individually by resource units. + +CSOM and REST don't have a predetermined resource unit cost, and they usually consume more resource units than [Microsoft Graph APIs](/graph) to achieve the same functionality. In addition to resource unit limits, CSOM and REST are also subject to other internal resource limits, so if applications call CSOM and REST, they may experience more throttling than the limits described in this document. We highly recommend you choose [Microsoft Graph APIs](/graph) over CSOM and REST APIs when possible. + +Since application limits are in resource units, the actual request rate, such as requests per minute, depends on the application’s API choice and the corresponding API resource unit cost. In general, you can estimate the request rate using an average of 2 resource units per request, and divide resource unit limits by 2 to get the estimated request rate. -If you do run into throttling, we require using the `Retry-After` HTTP header to ensure minimum delay until the throttle is removed. The `RateLimit` HTTP headers send you early signals when you're close to limits and you can proactively reduce requests to avoid hitting the throttle. +Although each application has its limits within a tenant, and we allow tenants to run more than one application, multiple applications running against the same tenant share the same resource bucket, and in rare occurrences can cause rate limiting when too many applications send requests at the time. ### Retry-after header @@ -102,11 +171,12 @@ When applications experience throttling, SharePoint Online returns a `Retry-Afte Honoring the `Retry-After` HTTP header is the fastest way to handle being throttled because SharePoint Online dynamically determines the right time to try again. -Throttled requests count towards usage limits, so failure to honor `Retry-After` may result in more throttling. In other words, aggressive retries work against calling applications because even though the calls fail, they still count towards usage limits. Honoring the `Retry-After` HTTP header will ensure the shortest delay and reduce wasting quotas in throttled requests. +Throttled requests count towards usage limits, so failure to honor `Retry-After` may result in more throttling. In other words, aggressive retries work against calling applications because even though the calls fail, they still count toward usage limits. Honoring the `Retry-After` HTTP header will ensure the shortest delay and reduce wasting quotas in throttled requests. ### RateLimit headers - preview -In addition to the `Retry-After` header in the response of throttled requests, SharePoint Online also returns the [IETF RateLimit headers](https://github.com/ietf-wg-httpapi/ratelimit-headers) for selected limits in certain conditions to help applications manage rate limiting. We recommend applications to take advantage of these headers to avoid hitting throttle. +In addition to the `Retry-After` header in the response to throttled requests, SharePoint Online also returns the [IETF RateLimit headers](https://github.com/ietf-wg-httpapi/ratelimit-headers) for selected limits in certain conditions to help applications manage rate limiting. We recommend applications to take advantage of these headers to avoid hitting the throttle. + - `RateLimit-Limit` contains the limit in the current time window. - `RateLimit-Remaining` indicates the remaining quota in the current window. - `RateLimit-Reset` indicates the number of seconds until the quota is refilled. @@ -118,61 +188,67 @@ The `RateLimit` headers are returned on a **best-efforts** basis, so application Below is the list of limits that we support the `RateLimit` headers for. The policies and values are subject to change: | limit | Condition | limit value | Description | -| -------------------------- | ------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------- | -| App 1 minute resource unit | Usage >= 80% of the limit | Resource unit | When an application consumes 80% or more of its app 1 minute limit, the limit, remaining and reset are returned. | +|----------------------------|---------------------------|---------------|------------------------------------------------------------------------------------------------------------------| +| App 1-minute resource unit | Usage >= 80% of the limit | Resource unit | When an application consumes 80% or more of its app 1-minute limit, the limit, remaining, and reset are returned.| Below are some examples to help you understand the `RateLimit` headers: - An application has consumed 90% of its resource unit quota (1,080 out of 1,200), and its consumption is within all the limits that apply to it. The request succeeds and the `RateLimit` headers are returned. -``` -HTTP/1.1 200 Ok -RateLimit-Limit: 1200 -RateLimit-Remaining: 120 -RateLimit-Reset: 5 -``` - -- An application has consumed 100% of its resource unit quota, so it gets throttled due to this policy. The request is throttled and the `RateLimit` headers are returned. The `Retry-After` matches the `RateLimit-Reset`. -``` -HTTP/1.1 429 Too Many Requests -Retry-After: 31 -RateLimit-Limit: 1200 -RateLimit-Remaining: 0 -RateLimit-Reset: 31 -``` - -- An application has consumed 90% of its resource unit quota but its consumption has already reached other limits that the `RateLimit` headers don't support. In this case, the request is throttled and the `RateLimit` headers aren't returned to avoid confusion although the condition to return the headers is satisfied. -``` -HTTP/1.1 429 Too Many Requests -Retry-After: 9 -``` + + ``` + HTTP/1.1 200 Ok + RateLimit-Limit: 1200 + RateLimit-Remaining: 120 + RateLimit-Reset: 5 + ``` + +- An application has consumed 100% of its resource unit quota, so it gets throttled due to this policy. The request is throttled, and the `RateLimit` headers are returned. The `Retry-After` matches the `RateLimit-Reset`. There are instances where the `Retry-After` returns a smaller value. In such cases, the general rule of thumb is to honor the greater of the two values. + + ``` + HTTP/1.1 429 Too Many Requests + Retry-After: 31 + RateLimit-Limit: 1200 + RateLimit-Remaining: 0 + RateLimit-Reset: 31 + ``` + +- An application has consumed 90% of its resource unit quota, but its consumption has already reached other limits that the `RateLimit` headers don't support. In this case, the request is throttled and the `RateLimit` headers aren't returned to avoid confusion, although the condition to return the headers is satisfied. + + ``` + HTTP/1.1 429 Too Many Requests + Retry-After: 9 + ``` + Additional information can be found in [Prevent throttling in your application by using RateLimit headers in SharePoint Online](https://devblogs.microsoft.com/microsoft365dev/prevent-throttling-in-your-application-by-using-ratelimit-headers-in-sharepoint-online/) -### How to decorate your http traffic? +### How to decorate your HTTP traffic? Well-decorated traffic will be prioritized over traffic that isn't properly decorated. What is the definition of undecorated traffic? -- Traffic is undecorated if there's no AppID/AppTitle and User Agent string in API calls to SharePoint Online. The User Agent string should be in a specific format as described below. +- Traffic is undecorated if there's no AppID/AppTitle and User Agent string in API calls to SharePoint Online. The User-Agent string should be in a specific format as described below. - If you're developing a web application executing in the browser, most modern browsers don't allow overwriting the User Agent string, and you don't need to implement it. What are the recommendations? -- If you've created an application, the recommendation is to register and use AppID and AppTitle – This will ensure the best overall experience and best path for any future issue resolution. Include also the User Agent string information as defined in following step. +- If you've created an application, the recommendation is to register and use AppID and AppTitle – This will ensure the best overall experience and best path for any future issue resolution. Include also the User Agent string information as defined in the following step. + > [!NOTE] > Refer to the [Microsoft identity documentation](/azure/active-directory/develop/), such as the [Quickstart: Register an application with the Microsoft identity platform](/azure/active-directory/develop/quickstart-register-app) page, for information on creating an Azure AD application. -- Make sure to include User Agent string in your API call to SharePoint with following naming convention +- Make sure to include the User-Agent string in your API call to SharePoint with the following naming convention | Type | User Agent | Description | -| ---------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| ISV Application | ISV|CompanyName|AppName/Version | Identify as ISV and include Company Name, App Name separated by a pipe character and then adding Version number separated with a slash character | +|------------------------|----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| ISV Application | ISV|CompanyName|AppName/Version | Identify as ISV and include Company Name, App Name separated by a pipe character and then add Version number separated with a slash character | | Enterprise application | NONISV|CompanyName|AppName/Version | Identify as NONISV and include Company Name, App Name separated by a pipe character and then adding Version number separated with a slash character | -- If you're building your own JavaScript libraries, which are used to call SharePoint Online APIs, make sure that you include the User Agent information to your http request and potentially register your web application also as an Application, where suitable. +- If you're building your own JavaScript libraries, which are used to call SharePoint Online APIs, make sure that you include the User-Agent information to your HTTP request and potentially register your web application also as an Application, where suitable. > [!NOTE] -> Format of the user agent string is expected to follow [RFC2616](http://www.ietf.org/rfc/rfc2616.txt), so please follow up on the above guidance on the right separators. It is also fine to append existing user agent string with the requested information. +> The format of the user agent string is expected to follow [RFC2616](http://www.ietf.org/rfc/rfc2616.txt), so please follow up on the above guidance on the right separators. It is also fine to append the existing user agent string with the requested information. + ## Common throttling scenarios in SharePoint Online @@ -180,52 +256,70 @@ The most common causes of per-user throttling in SharePoint Online are client-si - **Sporadic traffic** - Constant load or repetitive complex queries against SharePoint Online must be optimized for low impact. Failing to follow [best practices for scanning applications](https://aka.ms/ScanGuidance) that process files in bulk will likely result in throttling. These apps include sync engines, backup providers, search indexers, classification engines, data loss prevention tools, and any other tool, which attempts to reason over the entirety of data and apply changes to it. + Constant load or repetitive complex queries against SharePoint Online must be optimized for low impact. Failing to follow [best practices for scanning applications](https://aka.ms/ScanGuidance) that process files in bulk will likely result in throttling. These apps include sync engines, backup providers, search indexers, classification engines, data loss prevention tools, and any other tool, that attempts to reason over the entirety of data and apply changes to it. - **Overwhelming traffic** - A single process dramatically exceeds throttling limits, continually, over a long time period. + A single process dramatically exceeds throttling limits, continually, over a long period. - - You used web services to build a tool to synchronize user profile properties. The tool updates user profile properties based on information from your line-of-business (LOB) human resources (HR) system. The tool makes calls at too high a frequency. - - You're running a load-testing script on SharePoint Online and you get throttled. Load testing isn't allowed on SharePoint Online. - - You customized your team site on SharePoint Online, for example, by adding a status indicator on the Home page. This status indicator updates frequently, which causes the page to make too many calls to the SharePoint Online service - this triggered throttling. - - Running the OneDrive Sync client while also running migration applications or applications that crawl sites and write back data can result in high request volumes that may trigger throttling. + - You used web services to build a tool to synchronize user profile properties. The tool updates user profile properties based on information from your line-of-business (LOB) human resources (HR) system. The tool makes calls at too high a frequency. + - You're running a load-testing script on SharePoint Online and you get throttled. Load testing isn't allowed on SharePoint Online. + - You customized your team site on SharePoint Online, for example, by adding a status indicator on the Home page. This status indicator updates frequently, which causes the page to make too many calls to the SharePoint Online service - this triggered throttling. + - Running the OneDrive Sync client while also running migration applications or applications that crawl sites and write back data can result in high request volumes that may trigger throttling. - **Unsupported use cases** - Unsupported use of SharePoint Online may experience throttling. Using SharePoint and OneDrive as an intermediary service between Microsoft 365 and another repository is an example of an unsupported use case. + Unsupported use of SharePoint Online may result in throttling. Using SharePoint and OneDrive as an intermediary service between Microsoft 365 and another repository is an example of an unsupported use case. - **Creating multiple AppIDs for the same application** - Don't create separate AppIDs where the applications essentially perform the same operations, such as backup or data loss prevention. Applications running against the same tenant ultimately share the same resource of the tenant. Historically some applications have tried this approach to get around the application throttling but ended up exhausting the tenant’s resource and causing multiple applications to be throttled in the tenant. + Don't create separate AppIDs where the applications essentially perform the same operations, such as backup or data loss prevention. Applications running against the same tenant ultimately share the same resources as the tenant. Historically, some applications have tried this approach to get around the application throttling but ended up exhausting the tenant’s resource and causing multiple applications to be throttled in the tenant. + ## Scenario specific limits ### When using app-only authentication with Sites.Read.All permission -When you're using SharePoint Online search APIs with app-only authentication and the app having Sites.Read.All permission (or stronger), the app will be registered with full permissions, and is allowed to query all your SharePoint Online content (including user’s private ODB content). +When you're using SharePoint Online search APIs with app-only authentication and the app has **Sites.Read.All** permission (or stronger), the app will be registered with full permissions, and is allowed to query all your SharePoint Online content (including the user’s private OneDrive for Business content). + +To ensure the service remains fast and reliable, queries using such permission are throttled at 25 requests per second. The search query will return an HTTP 429 response. When waiting for throttling recovery, you should ensure to pause all search query requests you may be making to the service using a similar app-only permission. Making more calls while receiving throttle responses will extend the time it takes for your app to become unthrottled. + +### When searching using delegated user permissions + +Searching with delegated user permissions occurs when an application submits a search query request with the signed-in user's permissions. Examples of delegated requests are as follows: the search box on a SharePoint page, a search-based web part or custom application embedded on a SharePoint page, and a Power Automate workflow querying for item information. -To ensure the service remains fast and reliable, queries using such permission are throttled at 25 requests per second. The search query will return with an http 429 response. When waiting for throttling recovery, you should ensure to pause all search query requests you may be making to the service using similar app-only permission. Making more calls while receiving throttle responses will extend the time it takes for your app to become unthrottled. +To ensure service stability, the service will throttle delegated user requests that exceed 10 requests per second per user. This per-user limit aggregates across all requests from all apps. If a single user sends more than 10 search query requests per second, an HTTP 429 is returned. The requesting application should wait the duration of the timeout specified in the response header before sending subsequent requests. When designing search-based applications, SharePoint pages, and workflows, implementors should make sure the page and application do not exceed 10 requests per second in aggregate and handle 429 throttling responses. For more information and guidance on page design and search optimization, see [Optimize search requests in SharePoint Online modern site pages](/microsoft-365/enterprise/modern-search-optimization) and [Use the Page Diagnostics tool for SharePoint Online](/microsoft-365/enterprise/page-diagnostics-for-spo). ### When searching for people search results -When searching using a result source that requests people results, we may throttle any requests exceeding a limit of 25 requests per second. This limit applies jointly to all requests using the out-of-the-box "Local People Results" result source and all requests using custom people search result sources. +When searching using a result source that requests people results, we may throttle any requests exceeding an organization-wide limit of 25 requests per second. This limit applies to all SharePoint search CSOM and REST requests using either the out-of-the-box "Local People Results" result source or a custom people search result source. + +If you have applications or components that are causing your people search requests to get throttled, we recommend that you: + +1. Consider if the requests are necessary for your application. For example, if you're using a custom search site, that makes many simultaneous queries, check whether some of those requests can be removed without any significant impact on your organization's search experience. Alternatively, consider trying our modern people search experience in [Microsoft Search](/microsoftsearch/get-started-search-in-sharepoint-online) by searching from the [SharePoint](https://sharepoint.com/) start page. People search in Microsoft Search has been optimized for better performance and more relevant results. +1. Avoid making concurrent requests. For example, instead of issuing 10 requests all at once, issue them consecutively - only issue the next query after the previous one has been completed. You may need to consider caching these results if you need them quickly, for example of a page load. +1. Try consolidating the requests into a single query. For example, instead of making 10 simultaneous queries for `WorkEmail:user1@constoso.com`, `WorkEmail:user2@constoso.com`,..., `WorkEmail:user10@contoso.com`, try the single query, `WorkEmail:user1@constoso.com WorkEmail:user2@constoso.com ... WorkEmail:user10@contoso.com`. +1. Consider using the [Microsoft Graph API](/graph/search-concept-person) if a high-request-volume scenario (in excess of 25 requests per second) is truly necessary. + +### When accessing OneDrive sites + +When a client makes excessive attempts to access many OneDrive site collections that do not exist, we may throttle requests from that client's IP address. The client will receive an HTTP 429 response when accessing any OneDrive site collection during the throttling period. + +### Multi-Geo Customers and throttling -If you have applications or components, which are causing your people search requests to get throttled, we recommend that you: -1. Consider if the requests are necessary for your application. For example, if you're using a custom search site, which makes many simultaneous queries, check whether some of those requests can be removed without any significant impact to your organization's search experience. Alternatively, consider trying our modern people search experience in [Microsoft Search](/microsoftsearch/get-started-search-in-sharepoint-online) by searching from the [SharePoint](http://sharepoint.com/) start page. People search in Microsoft Search has been optimized for better performance and more relevant results. -2. Avoid making concurrent requests. For example, instead of issuing 10 requests all at once, issue them consecutively - only issue the next query after the previous one has completed. You may need to consider caching these results if you need them quickly, for example of a page load. -3. Try consolidating the requests into a single query. For example, instead making 10 simultaneous queries for `WorkEmail:user1@constoso.com`, `WorkEmail:user2@constoso.com`,..., `WorkEmail:user10@contoso.com`, try the single query, `WorkEmail:user1@constoso.com WorkEmail:user2@constoso.com ... WorkEmail:user10@contoso.com`. -4. Consider using the [Microsoft Graph API](/graph/people-example#search-people) if a high-request-volume scenario (in excess of 25 requests per second) is truly necessary. +When a customer enables throttling, each gets their own limits (usage measurement not shared across geos). For the limits that are dependant on licenses count, the total tenant user licenses count is used (total users across all geos). ## What should you do if you get blocked in SharePoint Online? -Blocking is the most extreme form of throttling. We rarely ever block a tenant, unless we detect long-term, excessive traffic that may threaten the overall health of the SharePoint Online service. We apply blocks to prevent excessive traffic from degrading the performance and reliability of SharePoint Online. A block - which is placed at the app or user level - prevents the offending process from running until you fix the problem. If we block your subscription, you must take action to modify the offending processes before the block can be removed. +Blocking is the most extreme form of throttling. We rarely ever block a tenant unless we detect long-term, excessive traffic that may threaten the overall health of the SharePoint Online service. We apply blocks to prevent excessive traffic from degrading the performance and reliability of SharePoint Online. A block - which is placed at the app or user level - prevents the offending process from running until you fix the problem. If we block your subscription, you must take action to modify the offending processes before the block can be removed. If we block your subscription, we'll notify you of the block in the Office 365 Message Center. The message describes what caused the block, provides guidance on how to resolve the offending issue, and tells you who to contact to get the block removed. ## See also +- [Service Prioritization in SharePoint](https://aka.ms/SharePointPrioritization) - [Diagnosing performance issues with SharePoint Online](https://support.office.com/article/3c364f9e-b9f6-4da4-a792-c8e8c8cd2e86) - [Capacity planning and load testing SharePoint Online](https://support.office.com/article/capacity-planning-and-load-testing-sharepoint-online-c932bd9b-fb9a-47ab-a330-6979d03688c0) - [Microsoft Graph dev center](/graph) - [Microsoft Graph throttling guidance](/graph/throttling) - [Prevent throttling in your application by using RateLimit headers in SharePoint Online](https://devblogs.microsoft.com/microsoft365dev/prevent-throttling-in-your-application-by-using-ratelimit-headers-in-sharepoint-online/) +- [Four options for site analytics](https://techcommunity.microsoft.com/blog/microsoft_graph_data_connect_for_sharepo/four-options-for-sharepoint-site-analytics/4076416) diff --git a/docs/general-development/how-to-create-a-page-layout-in-sharepoint.md b/docs/general-development/how-to-create-a-page-layout-in-sharepoint.md index b17de39ea..7b226bd53 100644 --- a/docs/general-development/how-to-create-a-page-layout-in-sharepoint.md +++ b/docs/general-development/how-to-create-a-page-layout-in-sharepoint.md @@ -98,7 +98,7 @@ If you're using Design Manager to create page layouts and master pages, the most - **PlaceHolderMain** The master page contains a content placeholder with `ID="PlaceholderMain"`, which contains the **DefaultContentBlock** `
    ` tag with the yellow box that shows **This area will be filled in by content you create in your page layouts.** You should not put any content inside this placeholder on the master page. The page layout contains a content placeholder with the same ID. You should put markup only inside this placeholder, and put no markup outside this placeholder, on a page layout. The IDs for the two placeholders ( **PlaceholderMain**) should match. -- **PlaceHolderAdditionalPageHead** When you work with a page layout, you typically don't insert elements into the **** tag of the page layout. Instead, you add elements to the content placeholder with `id="PlaceHolderAdditionalPageHead"`. When a content page is rendered in the browser, this additional page head gets merged into the end of the head of the master page. +- **PlaceHolderAdditionalPageHead** When you work with a page layout, you typically don't insert elements into the `` tag of the page layout. Instead, you add elements to the content placeholder with `id="PlaceHolderAdditionalPageHead"`. When a content page is rendered in the browser, this additional page head gets merged into the end of the head of the master page. @@ -184,7 +184,7 @@ When you create HTML mockups for your site, you may have HTML files that represe -You can simply put the styles for one or more page layouts into the same style sheet that the master page links to. But, if you want to minimize the weight of the CSS that is loaded per page, you can also use different style sheets for different page layouts. When you do this, it's important to know that a link to a style sheet cannot go in the **** tag of a page layout. Instead, the link must go in the content placeholder named **PlaceHolderAdditionalPageHead**. +You can simply put the styles for one or more page layouts into the same style sheet that the master page links to. But, if you want to minimize the weight of the CSS that is loaded per page, you can also use different style sheets for different page layouts. When you do this, it's important to know that a link to a style sheet cannot go in the `` tag of a page layout. Instead, the link must go in the content placeholder named **PlaceHolderAdditionalPageHead**. > [!NOTE] > In this markup, the attribute `ms-design-css-conversion="no"` excludes the style sheet from theming. Also, the link to the style sheet should appear after the lines commented ** + ``` - ### Create a workflow Now we create a workflow so we can test the custom site column and content type. +1. Add a workflow to our project and configure it to be a list workflow. +1. Create an association with this workflow using the **Announcements** list that we created earlier. +1. Create a new variable of type **DynamicValue** and name it "ItemProperties"; we're going to use this variable to store the item that kicks off the workflow's properties. +1. Create an **Int32** variable and name it "ItemAuthorId", as shown in Figure 15. - - -1. Add a workflow to our project configure it to be a list workflow. - - -2. Create an association with this workflow using the **Announcements** list that we created earlier. - - -3. Create a new variable of type **DynamicValue** and name it "ItemProperties"; we are going to use this variable to store the item that kicks off the workflow's properties. - - -4. Create an **Int32** variable and name it "ItemAuthorId", as shown in Figure 15. - - **Figure 15. Creating a workflow variable** - - - - ![The screenshot shows how to create an Int32 variable and name it "ItemAuthorId".](../images/WorkingWithTasksSharePointWorkflowsFig15.png) - - - - - + **Figure 15. Creating a workflow variable** + ![The screenshot shows how to create an Int32 variable and name it "ItemAuthorId".](../images/WorkingWithTasksSharePointWorkflowsFig15.png) ### Collect the list item properties Now we collect the list item properties. - - - 1. Drop the **LookupSPListItem** activity onto the design surface and set the **ListID** property to _(current list)_ and the **ItemId** property to _(current item)_. +1. Now set the **Result** output to the **ItemProperties** **DynamicValue** variable that we created a moment ago. +1. To get the author of the item from the variable, select the **Get Properties** link in the **LookupSPListItem** activity and add a **GetDynamicValueProperties** activity on the design surface. +1. Set the item's **Source** property to the output of the **LookupSPListItem** activity automatically. +1. Select the **[???]** button on the **Properties** property to display the **Properties** dialog box. +1. Change the **Entity Type** to **List Item of Announcements** to give the dialog box a context and assign the **Created By** path to the variable **ItemAuthorId**, as shown in Figure 16. - -2. Now set the **Result** output to the **ItemProperties** **DynamicValue** variable that we created a moment ago. - - -3. To get the author of the item from the variable, click the **Get Properties** link in the **LookupSPListItem** activity and add a **GetDynamicValueProperties** activity on the design surface. - - -4. Set the item's **Source** property to the output of the **LookupSPListItem** activity automatically. - - -5. Click the **[???]** button on the **Properties** property to display the **Properties** dialog box. - - -6. Change the **Entity Type** to **List Item of Announcements** to give the dialog box a context and assign the **Created By** path to the variable **ItemAuthorId**, as shown in Figure 16. - - **Figure 16. Properties dialog** - - - - ![The screenshot shows how to change the Entity Type to List Item of Announcements](../images/WorkingWithTasksSharePointWorkflowsFig16.png) - - - - - + **Figure 16. Properties dialog** + ![The screenshot shows how to change the Entity Type to List Item of Announcements](../images/WorkingWithTasksSharePointWorkflowsFig16.png) ### Create a single task Now we can create the single task. - - - 1. Add a **SingleTask** activity to the design surface. +1. Select the **Configure** link in the activity to open the **Task Options** dialog box. +1. Set the **Body** field to some string (it doesn't matter what), then set the **Assigned To** property to the variable you're using to store the author identifier (in our case, **ItemAuthorId**). +1. Change the title of the task, as shown in Figure 17. + **Figure 17. Task Title setting** + ![The screenshot shows how to change the title of the task.](../images/WorkingWithTasksSharePointWorkflowsFig17.png) -2. Click the **Configure** link in the activity to open the **Task Options** dialog box. - - -3. Set the **Body** field to some string (it doesn't matter what), then set the **Assigned To** property to the variable you are using to store the author identifier (in our case, **ItemAuthorId**). - - -4. Change the title of the task, as shown in Figure 17. - - **Figure 17. Task Title setting** - - - - ![The screenshot shows how to change the title of the task.](../images/WorkingWithTasksSharePointWorkflowsFig17.png) - - - - - -5. Finally, set the **Outcome Options** to use the new custom content type and custom outcome column. - - The dialog box determines what is available by looking at all the content types that are derived from the **Workflow Task (SharePoint)** content type, as shown in Figure 18. - - - **Figure 18. Outcome Options settings** - - - - ![The screenshot shows that the dialog box determines what is available by looking at all the content types that are derived from the Workflow Task content type.](../images/WorkingWithTasksSharePointWorkflowsFig18.png) - - - +1. Finally, set the **Outcome Options** to use the new custom content type and custom outcome column. + The dialog box determines what is available by looking at all the content types that are derived from the **Workflow Task (SharePoint 2013)** content type, as shown in Figure 18. + **Figure 18. Outcome Options settings** + ![The screenshot shows that the dialog box determines what is available by looking at all the content types that are derived from the Workflow Task content type.](../images/WorkingWithTasksSharePointWorkflowsFig18.png) ### Update the AssignedTo field -Before we go any further, we need to update the **AssignedTo** field on the **SingleTask** activity because it is expecting a string, not an integer. To remedy this, add **ToString()** to the end of the expression. - - +Before we go any further, we need to update the **AssignedTo** field on the **SingleTask** activity because it's expecting a string, not an integer. To remedy this, add **ToString()** to the end of the expression. Also, notice that the **Outcome** property automatically created a variable named **outcome_0**. To see what is in this variable, add a **WriteToHistory** activity on the design surface and update the message to write out the result. - - - ### Update the workflow task list -The final step is to configure the workflow task list. By default, the task list that the app creates only accepts the content type **Workflow Task (SharePoint)**. This workflow uses a custom content type for the custom outcome. Open the `Elements.xml` file for the workflow task list and change the **\** element's **ContentTypeId** attribute to match the content type in the project, as shown in the code example following. - - - +The final step is to configure the workflow task list. By default, the task list that the app creates only accepts the content type **Workflow Task (SharePoint 2013)**. This workflow uses a custom content type for the custom outcome. Open the `Elements.xml` file for the workflow task list and change the **\** element's **ContentTypeId** attribute to match the content type in the project, as shown in the code example following. ```XML - ``` - ### Test the custom content task with a custom task outcome Now let's test the workflow. +1. In Visual Studio, press **F5** or select the **Start** button. If testing in an on-premises local install of SharePoint, Visual Studio will start the Workflow Manager Test Service Host utility and deploy the workflow to the developer site. After a moment, the developer site will open. +1. Navigate to the **Announcements** list and create a new item. After creating the item, start the custom workflow manually. +1. Next, return to the workflow instance's status page to find the task that was created by the workflow. +1. Select on the task and, using the **Edit** button in the ribbon, switch to edit mode. At the bottom of the form there should be four buttons. The first two buttons are the custom outcome buttons that, when pressed, will mark the task as complete. The second two buttons are the default **Save** and **Cancel** buttons that simply update the list item without completing the task, as shown in Figure 19. - - -1. In Visual Studio 2012, press **F5** or click the **Start** button. If testing in an on-premises local install of SharePoint, Visual Studio 2012 will start the Workflow Manager Test Service Host utility and deploy the workflow to the developer site. After a moment, the developer site will open. - - -2. Navigate to the **Announcements** list and create a new item. After creating the item, start the custom workflow manually. - - -3. Next, return to the workflow instance's status page to find the task that was created by the workflow. - - -4. Click on the task and, using the **Edit** button in the ribbon, switch to edit mode. At the bottom of the form there should be four buttons. The first two buttons are the custom outcome buttons that, when pressed, will mark the task as complete. The second two buttons are the default **Save** and **Cancel** buttons that simply update the list item without completing the task, as shown in Figure 19. - - **Figure 19. Custom outcome buttons** - - - - ![The screenshot shows that the second two buttons are the default Save and Cancel buttons that simply update the list item without completing the task.](../images/WorkingWithTasksSharePointWorkflowsFig.png) - - - - - + **Figure 19. Custom outcome buttons** + ![The screenshot shows that the second two buttons are the default Save and Cancel buttons that simply update the list item without completing the task.](../images/WorkingWithTasksSharePointWorkflowsFig.png) ## Conclusion -Microsoft introduced workflows into the SharePoint 2007 platform, and they remained mostly unchanged in SharePoint 2010 in architecture, implementation, or process. This was also true for tasks in SharePoint workflows. However, SharePoint has introduced many changes to workflows in architecture and implementation. - - - -This article discussed the changes related to workflow tasks that were driven from changes to the workflow story in SharePoint. It demonstrated how to create a simple workflow that leveraged tasks in SharePoint using Visual Studio 2012. These types of tasks are suitable for many developers, although at times custom tasks and custom outcomes are desired, which can be accomplished using Visual Studio 2012 as has been shown. - - +Microsoft introduced workflows into the SharePoint Server 2007 platform, and they remained mostly unchanged in SharePoint Server 2010 in architecture, implementation, or process. This was also true for tasks in SharePoint workflows. However, SharePoint Server 2013 has introduced many changes to workflows in architecture and implementation. (And these changes remain accessible in SharePoint Server 2016, SharePoint Server 2019, and SharePoint Server Subscription Edition.) +This article discussed the changes related to workflow tasks that were driven from changes to the workflow story in SharePoint. It demonstrated how to create a simple workflow that applied tasks in SharePoint using Visual Studio. These types of tasks are suitable for many developers, although at times custom tasks and custom outcomes are desired, which can be accomplished using Visual Studio as has been shown. ## See also - - - -- [Workflows in SharePoint](https://msdn.microsoft.com/library/jj163986.aspx) - - -- [Authorization and authentication for apps in SharePoint](https://msdn.microsoft.com/library/office/fp142384.aspx) - -- [How To Customize a List View in Apps for SharePoint Using Client-Side Rendering](https://msdn.microsoft.com/library/jj220045.aspx) +- [Workflows in SharePoint](/sharepoint/dev/general-development/workflows-in-sharepoint) +- [Authorization and authentication for apps in SharePoint](/sharepoint/dev/sp-add-ins/authorization-and-authentication-of-sharepoint-add-ins) +- [How To Customize a List View in Apps for SharePoint Using Client-Side Rendering](/sharepoint/dev/sp-add-ins/customize-a-list-view-in-sharepoint-add-ins-using-client-side-rendering) diff --git a/docs/images/118-release-notes/ace-search-box.png b/docs/images/118-release-notes/ace-search-box.png new file mode 100644 index 000000000..8640cf6c5 Binary files /dev/null and b/docs/images/118-release-notes/ace-search-box.png differ diff --git a/docs/images/118-release-notes/ace-text-input-body.png b/docs/images/118-release-notes/ace-text-input-body.png new file mode 100644 index 000000000..6f7a71a79 Binary files /dev/null and b/docs/images/118-release-notes/ace-text-input-body.png differ diff --git a/docs/images/118-release-notes/ace-text-input-footer.png b/docs/images/118-release-notes/ace-text-input-footer.png new file mode 100644 index 000000000..ff1a64f1f Binary files /dev/null and b/docs/images/118-release-notes/ace-text-input-footer.png differ diff --git a/docs/images/119-release-notes/chart-card-viva-connections.png b/docs/images/119-release-notes/chart-card-viva-connections.png new file mode 100644 index 000000000..f400665bd Binary files /dev/null and b/docs/images/119-release-notes/chart-card-viva-connections.png differ diff --git a/docs/images/120-release-notes/chart-cards-options.png b/docs/images/120-release-notes/chart-cards-options.png new file mode 100644 index 000000000..e35deb436 Binary files /dev/null and b/docs/images/120-release-notes/chart-cards-options.png differ diff --git a/docs/images/120-release-notes/html-quick-views.png b/docs/images/120-release-notes/html-quick-views.png new file mode 100644 index 000000000..25b355490 Binary files /dev/null and b/docs/images/120-release-notes/html-quick-views.png differ diff --git a/docs/images/121-release-notes/card-personalization.png b/docs/images/121-release-notes/card-personalization.png new file mode 100644 index 000000000..227a84abc Binary files /dev/null and b/docs/images/121-release-notes/card-personalization.png differ diff --git a/docs/images/121-release-notes/flex-layout.png b/docs/images/121-release-notes/flex-layout.png new file mode 100644 index 000000000..527d2c6c6 Binary files /dev/null and b/docs/images/121-release-notes/flex-layout.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-add-api-permissions.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-add-api-permissions.png new file mode 100644 index 000000000..5dc7ea25b Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-add-api-permissions.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-automatic-permissions.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-automatic-permissions.png new file mode 100644 index 000000000..ccd9b6a35 Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-automatic-permissions.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-grant-api-permissions.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-grant-api-permissions.png new file mode 100644 index 000000000..4d7459ea7 Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-grant-api-permissions.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-manual-certificate-upload.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-manual-certificate-upload.png new file mode 100644 index 000000000..c0aa1e15d Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-manual-certificate-upload.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-registered.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-registered.png new file mode 100644 index 000000000..ef014bdbe Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-registered.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-registrations.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-registrations.png new file mode 100644 index 000000000..2d9f9e25f Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-app-registrations.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-register-an-application.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-register-an-application.png new file mode 100644 index 000000000..d0d556967 Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-aad-register-an-application.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-appinv.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-appinv.png new file mode 100644 index 000000000..15b9778ee Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-appinv.png differ diff --git a/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-appregnew.png b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-appregnew.png new file mode 100644 index 000000000..e8533c3b0 Binary files /dev/null and b/docs/images/add-in-transform/from-acs-to-aad-apps/from-acs-to-aad-apps-acs-appregnew.png differ diff --git a/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-app-manifest.png b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-app-manifest.png new file mode 100644 index 000000000..33c6c757c Binary files /dev/null and b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-app-manifest.png differ diff --git a/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-app-part-ui.png b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-app-part-ui.png new file mode 100644 index 000000000..8fa7fdea9 Binary files /dev/null and b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-app-part-ui.png differ diff --git a/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-spfx-outline.png b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-spfx-outline.png new file mode 100644 index 000000000..78cdfbb8a Binary files /dev/null and b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-spfx-outline.png differ diff --git a/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-workbench-add.png b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-workbench-add.png new file mode 100644 index 000000000..28dd87473 Binary files /dev/null and b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-workbench-add.png differ diff --git a/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-workbench-output.png b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-workbench-output.png new file mode 100644 index 000000000..e5408b588 Binary files /dev/null and b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-workbench-output.png differ diff --git a/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-yo-console.png b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-yo-console.png new file mode 100644 index 000000000..5c3d22806 Binary files /dev/null and b/docs/images/add-in-transform/from-app-parts-to-modern-web-parts/from-app-parts-to-modern-web-parts-yo-console.png differ diff --git a/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-output.png b/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-output.png new file mode 100644 index 000000000..281d954b4 Binary files /dev/null and b/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-output.png differ diff --git a/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-spfx-outline.png b/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-spfx-outline.png new file mode 100644 index 000000000..37fa6ed69 Binary files /dev/null and b/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-spfx-outline.png differ diff --git a/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-yo-console.png b/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-yo-console.png new file mode 100644 index 000000000..a9f4a116d Binary files /dev/null and b/docs/images/add-in-transform/from-classic-dialogs-to-modern-dialogs/from-classic-dialogs-to-modern-dialogs-yo-console.png differ diff --git a/docs/images/add-in-transform/from-jsom-to-client-side/from-jsom-to-client-side-yo-console-react.png b/docs/images/add-in-transform/from-jsom-to-client-side/from-jsom-to-client-side-yo-console-react.png new file mode 100644 index 000000000..cf7654de4 Binary files /dev/null and b/docs/images/add-in-transform/from-jsom-to-client-side/from-jsom-to-client-side-yo-console-react.png differ diff --git a/docs/images/add-in-transform/from-jsom-to-client-side/from-jsom-to-client-side-yo-console.png b/docs/images/add-in-transform/from-jsom-to-client-side/from-jsom-to-client-side-yo-console.png new file mode 100644 index 000000000..f1c523816 Binary files /dev/null and b/docs/images/add-in-transform/from-jsom-to-client-side/from-jsom-to-client-side-yo-console.png differ diff --git a/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-header-output.png b/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-header-output.png new file mode 100644 index 000000000..abaa009c8 Binary files /dev/null and b/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-header-output.png differ diff --git a/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-spfx-outline.png b/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-spfx-outline.png new file mode 100644 index 000000000..aba992ffc Binary files /dev/null and b/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-spfx-outline.png differ diff --git a/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-yo-console.png b/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-yo-console.png new file mode 100644 index 000000000..7e2b12c84 Binary files /dev/null and b/docs/images/add-in-transform/from-notifications-to-application-customizers/from-notifications-to-application-customizers-yo-console.png differ diff --git a/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-aad-app-permissions.png b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-aad-app-permissions.png new file mode 100644 index 000000000..2dfb6d703 Binary files /dev/null and b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-aad-app-permissions.png differ diff --git a/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-01.png b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-01.png new file mode 100644 index 000000000..44021cbb3 Binary files /dev/null and b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-01.png differ diff --git a/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-02.png b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-02.png new file mode 100644 index 000000000..fa4d464c1 Binary files /dev/null and b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-02.png differ diff --git a/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-03.png b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-03.png new file mode 100644 index 000000000..c820926eb Binary files /dev/null and b/docs/images/add-in-transform/from-provider-hosted-to-aad-applications/from-provider-hosted-to-aad-applications-vs2022-wizard-03.png differ diff --git a/docs/images/add-in-transform/from-remote-event-receivers-to-webhooks/from-remote-event-receivers-to-webhooks-outline.png b/docs/images/add-in-transform/from-remote-event-receivers-to-webhooks/from-remote-event-receivers-to-webhooks-outline.png new file mode 100644 index 000000000..0d443ad6d Binary files /dev/null and b/docs/images/add-in-transform/from-remote-event-receivers-to-webhooks/from-remote-event-receivers-to-webhooks-outline.png differ diff --git a/docs/images/add-in-transform/from-sharepoint-hosted-to-client-side/from-sharepoint-hosted-to-client-side-generator.png b/docs/images/add-in-transform/from-sharepoint-hosted-to-client-side/from-sharepoint-hosted-to-client-side-generator.png new file mode 100644 index 000000000..a0410e9b8 Binary files /dev/null and b/docs/images/add-in-transform/from-sharepoint-hosted-to-client-side/from-sharepoint-hosted-to-client-side-generator.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-app-manifest.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-app-manifest.png new file mode 100644 index 000000000..9032ca015 Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-app-manifest.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-ecb.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-ecb.png new file mode 100644 index 000000000..d01adbb99 Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-ecb.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-old-output.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-old-output.png new file mode 100644 index 000000000..eabdf3b56 Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-old-output.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-ribbon.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-ribbon.png new file mode 100644 index 000000000..b23d78363 Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-ribbon.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-spfx-outline.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-spfx-outline.png new file mode 100644 index 000000000..482fa4934 Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-spfx-outline.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-spfx-output.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-spfx-output.png new file mode 100644 index 000000000..022342e6f Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-spfx-output.png differ diff --git a/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-yo-console.png b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-yo-console.png new file mode 100644 index 000000000..8b2d605d1 Binary files /dev/null and b/docs/images/add-in-transform/from-ui-extensions-to-listview-command-sets/from-ui-extension-to-listview-command-set-yo-console.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-maker-ui-01.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-maker-ui-01.png new file mode 100644 index 000000000..49c4320b1 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-maker-ui-01.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-maker-ui-02.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-maker-ui-02.png new file mode 100644 index 000000000..a23ff9dec Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-maker-ui-02.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-01.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-01.png new file mode 100644 index 000000000..f996c5559 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-01.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-02.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-02.png new file mode 100644 index 000000000..8af3599a0 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-02.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-03.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-03.png new file mode 100644 index 000000000..ab31482a2 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-03.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-04.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-04.png new file mode 100644 index 000000000..c8dc45748 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-04.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-05.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-05.png new file mode 100644 index 000000000..95513157f Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-05.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-06.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-06.png new file mode 100644 index 000000000..3759ccd43 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-06.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-07.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-07.png new file mode 100644 index 000000000..a3b60c0c2 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-07.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-08.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-08.png new file mode 100644 index 000000000..f5f4da85a Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-08.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-09.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-09.png new file mode 100644 index 000000000..780312e0b Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-09.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-10.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-10.png new file mode 100644 index 000000000..24a6cfab5 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-10.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-11.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-11.png new file mode 100644 index 000000000..c54814988 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-11.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-12.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-12.png new file mode 100644 index 000000000..3ab4773d1 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-12.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-13.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-13.png new file mode 100644 index 000000000..641dc7a6e Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-13.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-14.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-14.png new file mode 100644 index 000000000..5b10bbb8e Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-14.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-15.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-15.png new file mode 100644 index 000000000..2f3405033 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-spo-ui-15.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-01.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-01.png new file mode 100644 index 000000000..1111bf9dc Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-01.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-02.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-02.png new file mode 100644 index 000000000..dda1dde2a Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-02.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-03.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-03.png new file mode 100644 index 000000000..f6a485e0b Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-03.png differ diff --git a/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-04.png b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-04.png new file mode 100644 index 000000000..20ac5d2c6 Binary files /dev/null and b/docs/images/add-in-transform/from-workflow-apps-to-power-automate/from-workflow-apps-to-power-automate-vs2019-04.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-01.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-01.png new file mode 100644 index 000000000..1693eec35 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-01.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-02.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-02.png new file mode 100644 index 000000000..26d8cdad7 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-02.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-03.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-03.png new file mode 100644 index 000000000..2461433af Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-03.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-04.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-04.png new file mode 100644 index 000000000..e30a7e163 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-04.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-05.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-05.png new file mode 100644 index 000000000..422709e30 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-05.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-06.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-06.png new file mode 100644 index 000000000..f27b1e322 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-06.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-07.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-07.png new file mode 100644 index 000000000..f1ec8804e Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-column-formatting-ui-07.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-01.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-01.png new file mode 100644 index 000000000..5013e0537 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-01.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-02.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-02.png new file mode 100644 index 000000000..55d10a129 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-02.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-03.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-03.png new file mode 100644 index 000000000..5213c6bb9 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-03.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-04.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-04.png new file mode 100644 index 000000000..0e9f151bc Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-form-formatting-ui-04.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-initial-list.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-initial-list.png new file mode 100644 index 000000000..27baf4918 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-initial-list.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-01.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-01.png new file mode 100644 index 000000000..fa5069db1 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-01.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-02.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-02.png new file mode 100644 index 000000000..69fe670d7 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-02.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-03.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-03.png new file mode 100644 index 000000000..d9d20cd4d Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-03.png differ diff --git a/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-04.png b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-04.png new file mode 100644 index 000000000..aa6b64ac2 Binary files /dev/null and b/docs/images/add-in-transform/from-xslt-to-list-formatting/from-xslt-to-list-formatting-list-view-formatting-ui-04.png differ diff --git a/docs/images/add-in-transform/modern-provisioning/modern-provisioning-spfx-outline.png b/docs/images/add-in-transform/modern-provisioning/modern-provisioning-spfx-outline.png new file mode 100644 index 000000000..02046e2e8 Binary files /dev/null and b/docs/images/add-in-transform/modern-provisioning/modern-provisioning-spfx-outline.png differ diff --git a/docs/images/add-in-transform/modern-provisioning/modern-provisioning-vs-addin-outline.png b/docs/images/add-in-transform/modern-provisioning/modern-provisioning-vs-addin-outline.png new file mode 100644 index 000000000..ea51c32e1 Binary files /dev/null and b/docs/images/add-in-transform/modern-provisioning/modern-provisioning-vs-addin-outline.png differ diff --git a/docs/images/add-in-transform/modern-provisioning/modern-provisioning-yo-console.png b/docs/images/add-in-transform/modern-provisioning/modern-provisioning-yo-console.png new file mode 100644 index 000000000..7ed756382 Binary files /dev/null and b/docs/images/add-in-transform/modern-provisioning/modern-provisioning-yo-console.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-app-registration.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-app-registration.png new file mode 100644 index 000000000..12c9f5dba Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-app-registration.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-endpoints.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-endpoints.png new file mode 100644 index 000000000..a9c79cddb Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-endpoints.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-enterprise-application.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-enterprise-application.png new file mode 100644 index 000000000..64ce75e65 Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-enterprise-application.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-admin-tenant-not-admin.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-admin-tenant-not-admin.png new file mode 100644 index 000000000..0d16f1ac9 Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-admin-tenant-not-admin.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-admin-tenant.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-admin-tenant.png new file mode 100644 index 000000000..c35387cde Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-admin-tenant.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-user-admin.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-user-admin.png new file mode 100644 index 000000000..d8b8d16e0 Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-user-admin.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-user-not-admin.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-user-not-admin.png new file mode 100644 index 000000000..1b80a3556 Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions-grant-user-not-admin.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions.png new file mode 100644 index 000000000..5e721780b Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-permissions.png differ diff --git a/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-spfx-consent-flow.png b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-spfx-consent-flow.png new file mode 100644 index 000000000..55cfb6b1b Binary files /dev/null and b/docs/images/add-in-transform/multi-tenant-applications/multi-tenant-applications-aad-spfx-consent-flow.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-01.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-01.png new file mode 100644 index 000000000..8435e6f80 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-01.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-02.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-02.png new file mode 100644 index 000000000..dd96f01f3 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-02.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-03.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-03.png new file mode 100644 index 000000000..390a69e81 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-03.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-04.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-04.png new file mode 100644 index 000000000..be55238de Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-04.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-05.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-05.png new file mode 100644 index 000000000..eae601af6 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-05.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-06.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-06.png new file mode 100644 index 000000000..aad608120 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-06.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-07.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-07.png new file mode 100644 index 000000000..fef1faa3e Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-07.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-08.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-08.png new file mode 100644 index 000000000..41b69865d Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-08.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-09.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-09.png new file mode 100644 index 000000000..26dd8c70e Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-09.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-10.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-10.png new file mode 100644 index 000000000..f6f0674ef Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-10.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-11.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-11.png new file mode 100644 index 000000000..fc248c3e6 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-11.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-12.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-12.png new file mode 100644 index 000000000..4e36c9958 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-12.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-13.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-13.png new file mode 100644 index 000000000..276b0c299 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-13.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-14.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-14.png new file mode 100644 index 000000000..514ac20d7 Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-14.png differ diff --git a/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-15.png b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-15.png new file mode 100644 index 000000000..ae5c0862f Binary files /dev/null and b/docs/images/add-in-transform/publishing-modern-sharepoint-apps-on-appsource/publishing-modern-sharepoint-apps-on-appsource-partner-center-15.png differ diff --git a/docs/images/add-in-transform/understanding-aad-oauth-for-spfx/understanding-aad-oauth-for-spfx-msgraph-access-token-claims.png b/docs/images/add-in-transform/understanding-aad-oauth-for-spfx/understanding-aad-oauth-for-spfx-msgraph-access-token-claims.png new file mode 100644 index 000000000..ebfe5f417 Binary files /dev/null and b/docs/images/add-in-transform/understanding-aad-oauth-for-spfx/understanding-aad-oauth-for-spfx-msgraph-access-token-claims.png differ diff --git a/docs/images/add-in-transform/understanding-aad-oauth-for-spfx/understanding-aad-oauth-for-spfx-msgraph-access-token-webpart-ui.png b/docs/images/add-in-transform/understanding-aad-oauth-for-spfx/understanding-aad-oauth-for-spfx-msgraph-access-token-webpart-ui.png new file mode 100644 index 000000000..e0ad055da Binary files /dev/null and b/docs/images/add-in-transform/understanding-aad-oauth-for-spfx/understanding-aad-oauth-for-spfx-msgraph-access-token-webpart-ui.png differ diff --git a/docs/images/add-in-transform/understanding-rsc-for-msgraph-and-sharepoint-online/understanding-rsc-for-msgraph-and-sharepoint-online-sites.selected-graph.png b/docs/images/add-in-transform/understanding-rsc-for-msgraph-and-sharepoint-online/understanding-rsc-for-msgraph-and-sharepoint-online-sites.selected-graph.png new file mode 100644 index 000000000..4ae737bb3 Binary files /dev/null and b/docs/images/add-in-transform/understanding-rsc-for-msgraph-and-sharepoint-online/understanding-rsc-for-msgraph-and-sharepoint-online-sites.selected-graph.png differ diff --git a/docs/images/add-in-transform/understanding-rsc-for-msgraph-and-sharepoint-online/understanding-rsc-for-msgraph-and-sharepoint-online-sites.selected-spo.png b/docs/images/add-in-transform/understanding-rsc-for-msgraph-and-sharepoint-online/understanding-rsc-for-msgraph-and-sharepoint-online-sites.selected-spo.png new file mode 100644 index 000000000..c2249fb68 Binary files /dev/null and b/docs/images/add-in-transform/understanding-rsc-for-msgraph-and-sharepoint-online/understanding-rsc-for-msgraph-and-sharepoint-online-sites.selected-spo.png differ diff --git a/docs/images/appregnewaspx.png b/docs/images/appregnewaspx.png new file mode 100644 index 000000000..ae371d078 Binary files /dev/null and b/docs/images/appregnewaspx.png differ diff --git a/docs/images/brand-center-spfx-01.png b/docs/images/brand-center-spfx-01.png new file mode 100644 index 000000000..de9de224c Binary files /dev/null and b/docs/images/brand-center-spfx-01.png differ diff --git a/docs/images/brand-center-spfx-02.png b/docs/images/brand-center-spfx-02.png new file mode 100644 index 000000000..4ee2380c6 Binary files /dev/null and b/docs/images/brand-center-spfx-02.png differ diff --git a/docs/images/brand-center-spfx-03.png b/docs/images/brand-center-spfx-03.png new file mode 100644 index 000000000..c951e8e2b Binary files /dev/null and b/docs/images/brand-center-spfx-03.png differ diff --git a/docs/images/brand-center-spfx-04.png b/docs/images/brand-center-spfx-04.png new file mode 100644 index 000000000..c648b76f2 Binary files /dev/null and b/docs/images/brand-center-spfx-04.png differ diff --git a/docs/images/brand-center-spfx-05.png b/docs/images/brand-center-spfx-05.png new file mode 100644 index 000000000..6640c1e2f Binary files /dev/null and b/docs/images/brand-center-spfx-05.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/add-app-with-tss.png b/docs/images/content-securty-policy-trusted-script-sources/add-app-with-tss.png new file mode 100644 index 000000000..9c0aaafb8 Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/add-app-with-tss.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/add-script-source.png b/docs/images/content-securty-policy-trusted-script-sources/add-script-source.png new file mode 100644 index 000000000..bcfa4234b Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/add-script-source.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/browser-console.png b/docs/images/content-securty-policy-trusted-script-sources/browser-console.png new file mode 100644 index 000000000..a81043c0e Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/browser-console.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/purview-audit-record.png b/docs/images/content-securty-policy-trusted-script-sources/purview-audit-record.png new file mode 100644 index 000000000..247ab069f Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/purview-audit-record.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/purview-results.png b/docs/images/content-securty-policy-trusted-script-sources/purview-results.png new file mode 100644 index 000000000..491a23ee3 Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/purview-results.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/purview-search.png b/docs/images/content-securty-policy-trusted-script-sources/purview-search.png new file mode 100644 index 000000000..a61356271 Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/purview-search.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/spac-tss-nav.png b/docs/images/content-securty-policy-trusted-script-sources/spac-tss-nav.png new file mode 100644 index 000000000..2efbafa58 Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/spac-tss-nav.png differ diff --git a/docs/images/content-securty-policy-trusted-script-sources/spac-tss-page.png b/docs/images/content-securty-policy-trusted-script-sources/spac-tss-page.png new file mode 100644 index 000000000..9c40b5537 Binary files /dev/null and b/docs/images/content-securty-policy-trusted-script-sources/spac-tss-page.png differ diff --git a/docs/images/discoverdomainisolatedwebpartusage.png b/docs/images/discoverdomainisolatedwebpartusage.png new file mode 100644 index 000000000..c23769db3 Binary files /dev/null and b/docs/images/discoverdomainisolatedwebpartusage.png differ diff --git a/docs/images/ext-tenant-wide-solution-deployment-modern.png b/docs/images/ext-tenant-wide-solution-deployment-modern.png new file mode 100644 index 000000000..abd78938d Binary files /dev/null and b/docs/images/ext-tenant-wide-solution-deployment-modern.png differ diff --git a/docs/images/overview/spfx-across-apps.png b/docs/images/overview/spfx-across-apps.png new file mode 100644 index 000000000..a960e43cc Binary files /dev/null and b/docs/images/overview/spfx-across-apps.png differ diff --git a/docs/images/overview/viva-spfx-extensibility.png b/docs/images/overview/viva-spfx-extensibility.png new file mode 100644 index 000000000..d7b94d5dd Binary files /dev/null and b/docs/images/overview/viva-spfx-extensibility.png differ diff --git a/docs/images/react-cascading-dropdowns-item-dropdown-list-items.png b/docs/images/react-cascading-dropdowns-item-dropdown-list-items.png index 1b7c83b09..757f77180 100644 Binary files a/docs/images/react-cascading-dropdowns-item-dropdown-list-items.png and b/docs/images/react-cascading-dropdowns-item-dropdown-list-items.png differ diff --git a/docs/images/react-cascading-dropdowns-itemname-property-pane-dropdown.png b/docs/images/react-cascading-dropdowns-itemname-property-pane-dropdown.png index 189d09d25..16efa490d 100644 Binary files a/docs/images/react-cascading-dropdowns-itemname-property-pane-dropdown.png and b/docs/images/react-cascading-dropdowns-itemname-property-pane-dropdown.png differ diff --git a/docs/images/react-cascading-dropdowns-list-dropdown-available-lists.png b/docs/images/react-cascading-dropdowns-list-dropdown-available-lists.png index 5f1dfaa10..722ab3a02 100644 Binary files a/docs/images/react-cascading-dropdowns-list-dropdown-available-lists.png and b/docs/images/react-cascading-dropdowns-list-dropdown-available-lists.png differ diff --git a/docs/images/react-cascading-dropdowns-list-selected-item-disabled.png b/docs/images/react-cascading-dropdowns-list-selected-item-disabled.png index dd8f57ddc..f88e54c24 100644 Binary files a/docs/images/react-cascading-dropdowns-list-selected-item-disabled.png and b/docs/images/react-cascading-dropdowns-list-selected-item-disabled.png differ diff --git a/docs/images/react-cascading-dropdowns-listname-property-pane-dropdown.png b/docs/images/react-cascading-dropdowns-listname-property-pane-dropdown.png index b445decac..0c3c6275e 100644 Binary files a/docs/images/react-cascading-dropdowns-listname-property-pane-dropdown.png and b/docs/images/react-cascading-dropdowns-listname-property-pane-dropdown.png differ diff --git a/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-items.png b/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-items.png index bfa0614d0..22e60d00b 100644 Binary files a/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-items.png and b/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-items.png differ diff --git a/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-list-info.png b/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-list-info.png index e0e957a8e..cf666b5a9 100644 Binary files a/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-list-info.png and b/docs/images/react-cascading-dropdowns-loading-indicator-when-loading-list-info.png differ diff --git a/docs/images/react-cascading-dropdowns-web-part-first-run.png b/docs/images/react-cascading-dropdowns-web-part-first-run.png index ad207fd7f..5223d61af 100644 Binary files a/docs/images/react-cascading-dropdowns-web-part-first-run.png and b/docs/images/react-cascading-dropdowns-web-part-first-run.png differ diff --git a/docs/images/spfx-add-to-all-sites.png b/docs/images/spfx-add-to-all-sites.png new file mode 100644 index 000000000..6f8009932 Binary files /dev/null and b/docs/images/spfx-add-to-all-sites.png differ diff --git a/docs/images/spfx-add-to-teams.png b/docs/images/spfx-add-to-teams.png new file mode 100644 index 000000000..1ff5aa56a Binary files /dev/null and b/docs/images/spfx-add-to-teams.png differ diff --git a/docs/images/viva-design/img-custom-card-layouts.png b/docs/images/viva-design/img-custom-card-layouts.png new file mode 100644 index 000000000..12177a71a Binary files /dev/null and b/docs/images/viva-design/img-custom-card-layouts.png differ diff --git a/docs/images/viva-design/img-examples-01-card-withoutimage.png b/docs/images/viva-design/img-examples-01-card-withoutimage.png new file mode 100644 index 000000000..9df0d2132 Binary files /dev/null and b/docs/images/viva-design/img-examples-01-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-02-card-withoutimage.png b/docs/images/viva-design/img-examples-02-card-withoutimage.png new file mode 100644 index 000000000..cf706474c Binary files /dev/null and b/docs/images/viva-design/img-examples-02-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-03-card-withoutimage.png b/docs/images/viva-design/img-examples-03-card-withoutimage.png new file mode 100644 index 000000000..9b3867455 Binary files /dev/null and b/docs/images/viva-design/img-examples-03-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-04-card-withoutimage.png b/docs/images/viva-design/img-examples-04-card-withoutimage.png new file mode 100644 index 000000000..0306aec9b Binary files /dev/null and b/docs/images/viva-design/img-examples-04-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-05-card-withoutimage.png b/docs/images/viva-design/img-examples-05-card-withoutimage.png new file mode 100644 index 000000000..16023f1c9 Binary files /dev/null and b/docs/images/viva-design/img-examples-05-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-06-card-withoutimage.png b/docs/images/viva-design/img-examples-06-card-withoutimage.png new file mode 100644 index 000000000..7987bd368 Binary files /dev/null and b/docs/images/viva-design/img-examples-06-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-07-card-withoutimage.png b/docs/images/viva-design/img-examples-07-card-withoutimage.png new file mode 100644 index 000000000..15db9834b Binary files /dev/null and b/docs/images/viva-design/img-examples-07-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-examples-08-card-withoutimage.png b/docs/images/viva-design/img-examples-08-card-withoutimage.png new file mode 100644 index 000000000..ad7ba79b1 Binary files /dev/null and b/docs/images/viva-design/img-examples-08-card-withoutimage.png differ diff --git a/docs/images/viva-design/img-large-card-layout.png b/docs/images/viva-design/img-large-card-layout.png new file mode 100644 index 000000000..55884c054 Binary files /dev/null and b/docs/images/viva-design/img-large-card-layout.png differ diff --git a/docs/images/viva-design/img-medium-card-layout.png b/docs/images/viva-design/img-medium-card-layout.png new file mode 100644 index 000000000..d151c17bd Binary files /dev/null and b/docs/images/viva-design/img-medium-card-layout.png differ diff --git a/docs/images/viva-design/img-permutation-01-card-layout.png b/docs/images/viva-design/img-permutation-01-card-layout.png new file mode 100644 index 000000000..6db004a68 Binary files /dev/null and b/docs/images/viva-design/img-permutation-01-card-layout.png differ diff --git a/docs/images/viva-design/img-permutation-02-card-layout.png b/docs/images/viva-design/img-permutation-02-card-layout.png new file mode 100644 index 000000000..083cd56b7 Binary files /dev/null and b/docs/images/viva-design/img-permutation-02-card-layout.png differ diff --git a/docs/images/viva-design/img-permutation-03-card-layout.png b/docs/images/viva-design/img-permutation-03-card-layout.png new file mode 100644 index 000000000..93d41a1d2 Binary files /dev/null and b/docs/images/viva-design/img-permutation-03-card-layout.png differ diff --git a/docs/images/viva-design/img-permutation-04-card-layout.png b/docs/images/viva-design/img-permutation-04-card-layout.png new file mode 100644 index 000000000..2f5fc12a2 Binary files /dev/null and b/docs/images/viva-design/img-permutation-04-card-layout.png differ diff --git a/docs/images/viva-design/img-permutation-05-card-layout.png b/docs/images/viva-design/img-permutation-05-card-layout.png new file mode 100644 index 000000000..641e8cac0 Binary files /dev/null and b/docs/images/viva-design/img-permutation-05-card-layout.png differ diff --git a/docs/images/viva-design/img-search-box-card.png b/docs/images/viva-design/img-search-box-card.png new file mode 100644 index 000000000..e6e582e58 Binary files /dev/null and b/docs/images/viva-design/img-search-box-card.png differ diff --git a/docs/images/viva-design/img-search-template.png b/docs/images/viva-design/img-search-template.png new file mode 100644 index 000000000..87d523aca Binary files /dev/null and b/docs/images/viva-design/img-search-template.png differ diff --git a/docs/images/viva-design/img_quickview_new_ios_theme.png b/docs/images/viva-design/img_quickview_new_ios_theme.png new file mode 100644 index 000000000..a9ede4a6b Binary files /dev/null and b/docs/images/viva-design/img_quickview_new_ios_theme.png differ diff --git a/docs/images/viva-design/img_quickview_tutorial_dark.png b/docs/images/viva-design/img_quickview_tutorial_dark.png new file mode 100644 index 000000000..c95d30187 Binary files /dev/null and b/docs/images/viva-design/img_quickview_tutorial_dark.png differ diff --git a/docs/images/viva-design/img_quickview_tutorial_light.png b/docs/images/viva-design/img_quickview_tutorial_light.png new file mode 100644 index 000000000..0d6a68742 Binary files /dev/null and b/docs/images/viva-design/img_quickview_tutorial_light.png differ diff --git a/docs/images/viva-design/img_quickview_tutorial_light_and_dark.png b/docs/images/viva-design/img_quickview_tutorial_light_and_dark.png new file mode 100644 index 000000000..2b59f988c Binary files /dev/null and b/docs/images/viva-design/img_quickview_tutorial_light_and_dark.png differ diff --git a/docs/images/viva-extensibility/ace-basic-html-quickview-01.png b/docs/images/viva-extensibility/ace-basic-html-quickview-01.png new file mode 100644 index 000000000..cdfe65cf0 Binary files /dev/null and b/docs/images/viva-extensibility/ace-basic-html-quickview-01.png differ diff --git a/docs/images/viva-extensibility/ace-basic-html-quickview-02.png b/docs/images/viva-extensibility/ace-basic-html-quickview-02.png new file mode 100644 index 000000000..2d153c24e Binary files /dev/null and b/docs/images/viva-extensibility/ace-basic-html-quickview-02.png differ diff --git a/docs/images/viva-extensibility/data-visualization/ace-dataviz-allup.png b/docs/images/viva-extensibility/data-visualization/ace-dataviz-allup.png new file mode 100644 index 000000000..f094aced0 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/ace-dataviz-allup.png differ diff --git a/docs/images/viva-extensibility/data-visualization/ace-default.png b/docs/images/viva-extensibility/data-visualization/ace-default.png new file mode 100644 index 000000000..400fa0029 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/ace-default.png differ diff --git a/docs/images/viva-extensibility/data-visualization/bar-chart.png b/docs/images/viva-extensibility/data-visualization/bar-chart.png new file mode 100644 index 000000000..fad7ddadb Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/bar-chart.png differ diff --git a/docs/images/viva-extensibility/data-visualization/chart-on-right-side.png b/docs/images/viva-extensibility/data-visualization/chart-on-right-side.png new file mode 100644 index 000000000..ebe45b330 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/chart-on-right-side.png differ diff --git a/docs/images/viva-extensibility/data-visualization/chart-three-series.png b/docs/images/viva-extensibility/data-visualization/chart-three-series.png new file mode 100644 index 000000000..7bc3f4050 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/chart-three-series.png differ diff --git a/docs/images/viva-extensibility/data-visualization/donut-chart.png b/docs/images/viva-extensibility/data-visualization/donut-chart.png new file mode 100644 index 000000000..ad6110b75 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/donut-chart.png differ diff --git a/docs/images/viva-extensibility/data-visualization/pie-chart.png b/docs/images/viva-extensibility/data-visualization/pie-chart.png new file mode 100644 index 000000000..99ad323b8 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/pie-chart.png differ diff --git a/docs/images/viva-extensibility/data-visualization/regular-chart.png b/docs/images/viva-extensibility/data-visualization/regular-chart.png new file mode 100644 index 000000000..f20005e09 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/regular-chart.png differ diff --git a/docs/images/viva-extensibility/data-visualization/toolbox.png b/docs/images/viva-extensibility/data-visualization/toolbox.png new file mode 100644 index 000000000..745880918 Binary files /dev/null and b/docs/images/viva-extensibility/data-visualization/toolbox.png differ diff --git a/docs/images/viva-extensibility/geolocation/geoloactionCardView.png b/docs/images/viva-extensibility/geolocation/geoloactionCardView.png index 476e4c5b6..251665267 100644 Binary files a/docs/images/viva-extensibility/geolocation/geoloactionCardView.png and b/docs/images/viva-extensibility/geolocation/geoloactionCardView.png differ diff --git a/docs/images/viva-extensibility/geolocation/geoloactionQuickView.png b/docs/images/viva-extensibility/geolocation/geoloactionQuickView.png index 6d826706b..f8c5bba61 100644 Binary files a/docs/images/viva-extensibility/geolocation/geoloactionQuickView.png and b/docs/images/viva-extensibility/geolocation/geoloactionQuickView.png differ diff --git a/docs/images/viva-extensibility/geolocation/geoloactionQuickViewCoordinates.png b/docs/images/viva-extensibility/geolocation/geoloactionQuickViewCoordinates.png new file mode 100644 index 000000000..fe3dbe433 Binary files /dev/null and b/docs/images/viva-extensibility/geolocation/geoloactionQuickViewCoordinates.png differ diff --git a/docs/images/viva-extensibility/icons-limitations-card-bar-mobile.png b/docs/images/viva-extensibility/icons-limitations-card-bar-mobile.png new file mode 100644 index 000000000..25bda5d46 Binary files /dev/null and b/docs/images/viva-extensibility/icons-limitations-card-bar-mobile.png differ diff --git a/docs/images/viva-extensibility/icons-limitations-card-bar.png b/docs/images/viva-extensibility/icons-limitations-card-bar.png new file mode 100644 index 000000000..4bde9e64b Binary files /dev/null and b/docs/images/viva-extensibility/icons-limitations-card-bar.png differ diff --git a/docs/images/viva-extensibility/icons-limitations-supported-icons.png b/docs/images/viva-extensibility/icons-limitations-supported-icons.png new file mode 100644 index 000000000..20b14db02 Binary files /dev/null and b/docs/images/viva-extensibility/icons-limitations-supported-icons.png differ diff --git a/docs/images/viva-extensibility/icons-limitations-toolbox.png b/docs/images/viva-extensibility/icons-limitations-toolbox.png new file mode 100644 index 000000000..4ad88d289 Binary files /dev/null and b/docs/images/viva-extensibility/icons-limitations-toolbox.png differ diff --git a/docs/images/viva-extensibility/lab1-default.png b/docs/images/viva-extensibility/lab1-default.png index 1bdfe663e..69772fc52 100644 Binary files a/docs/images/viva-extensibility/lab1-default.png and b/docs/images/viva-extensibility/lab1-default.png differ diff --git a/docs/images/viva-extensibility/lab1-hw-ace.png b/docs/images/viva-extensibility/lab1-hw-ace.png index 52b6f5a3a..5b9515b5a 100644 Binary files a/docs/images/viva-extensibility/lab1-hw-ace.png and b/docs/images/viva-extensibility/lab1-hw-ace.png differ diff --git a/docs/images/viva-extensibility/lab1-hw-ql.png b/docs/images/viva-extensibility/lab1-hw-ql.png index 95d396712..8ab211ade 100644 Binary files a/docs/images/viva-extensibility/lab1-hw-ql.png and b/docs/images/viva-extensibility/lab1-hw-ql.png differ diff --git a/docs/images/viva-extensibility/lab1-large.png b/docs/images/viva-extensibility/lab1-large.png index 79ded0c71..b064b90c8 100644 Binary files a/docs/images/viva-extensibility/lab1-large.png and b/docs/images/viva-extensibility/lab1-large.png differ diff --git a/docs/images/viva-extensibility/lab1-medium.png b/docs/images/viva-extensibility/lab1-medium.png new file mode 100644 index 000000000..cda7f42ad Binary files /dev/null and b/docs/images/viva-extensibility/lab1-medium.png differ diff --git a/docs/images/viva-extensibility/lab1-new-ql.png b/docs/images/viva-extensibility/lab1-new-ql.png index 0f37645d7..d6748a12a 100644 Binary files a/docs/images/viva-extensibility/lab1-new-ql.png and b/docs/images/viva-extensibility/lab1-new-ql.png differ diff --git a/docs/images/viva-extensibility/lab1-textinput-ace.png b/docs/images/viva-extensibility/lab1-textinput-ace.png new file mode 100644 index 000000000..b23014192 Binary files /dev/null and b/docs/images/viva-extensibility/lab1-textinput-ace.png differ diff --git a/docs/images/viva-extensibility/lab2-ace-1.png b/docs/images/viva-extensibility/lab2-ace-1.png index e9269e496..f8e77688e 100644 Binary files a/docs/images/viva-extensibility/lab2-ace-1.png and b/docs/images/viva-extensibility/lab2-ace-1.png differ diff --git a/docs/images/viva-extensibility/lab2-ace-2.png b/docs/images/viva-extensibility/lab2-ace-2.png index b28c7ddda..4c7f8e027 100644 Binary files a/docs/images/viva-extensibility/lab2-ace-2.png and b/docs/images/viva-extensibility/lab2-ace-2.png differ diff --git a/docs/images/viva-extensibility/lab2-ace-3.png b/docs/images/viva-extensibility/lab2-ace-3.png index 1776394c6..88069bb46 100644 Binary files a/docs/images/viva-extensibility/lab2-ace-3.png and b/docs/images/viva-extensibility/lab2-ace-3.png differ diff --git a/docs/images/viva-extensibility/lab2-ace-4.png b/docs/images/viva-extensibility/lab2-ace-4.png index e5b60889c..24ab54b67 100644 Binary files a/docs/images/viva-extensibility/lab2-ace-4.png and b/docs/images/viva-extensibility/lab2-ace-4.png differ diff --git a/docs/images/viva-extensibility/lab2-ace-5.png b/docs/images/viva-extensibility/lab2-ace-5.png index 18beed01a..abed1eba2 100644 Binary files a/docs/images/viva-extensibility/lab2-ace-5.png and b/docs/images/viva-extensibility/lab2-ace-5.png differ diff --git a/docs/images/viva-extensibility/lab2-ace-6.png b/docs/images/viva-extensibility/lab2-ace-6.png index cfbf416bd..77ce499d3 100644 Binary files a/docs/images/viva-extensibility/lab2-ace-6.png and b/docs/images/viva-extensibility/lab2-ace-6.png differ diff --git a/docs/images/viva-extensibility/lab3-ace-1.png b/docs/images/viva-extensibility/lab3-ace-1.png index e567d0435..0107b16f2 100644 Binary files a/docs/images/viva-extensibility/lab3-ace-1.png and b/docs/images/viva-extensibility/lab3-ace-1.png differ diff --git a/docs/images/viva-extensibility/lab3-detailed.png b/docs/images/viva-extensibility/lab3-detailed.png index a87349cad..42cd60012 100644 Binary files a/docs/images/viva-extensibility/lab3-detailed.png and b/docs/images/viva-extensibility/lab3-detailed.png differ diff --git a/docs/images/viva-extensibility/people-search/ace-default.png b/docs/images/viva-extensibility/people-search/ace-default.png new file mode 100644 index 000000000..8640cf6c5 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/ace-default.png differ diff --git a/docs/images/viva-extensibility/people-search/qv-item-default.png b/docs/images/viva-extensibility/people-search/qv-item-default.png new file mode 100644 index 000000000..80f59b5b6 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/qv-item-default.png differ diff --git a/docs/images/viva-extensibility/people-search/qv-person.png b/docs/images/viva-extensibility/people-search/qv-person.png new file mode 100644 index 000000000..0b3dacbb8 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/qv-person.png differ diff --git a/docs/images/viva-extensibility/people-search/qv-results-default.png b/docs/images/viva-extensibility/people-search/qv-results-default.png new file mode 100644 index 000000000..cb1e8e649 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/qv-results-default.png differ diff --git a/docs/images/viva-extensibility/people-search/qv-suggested.png b/docs/images/viva-extensibility/people-search/qv-suggested.png new file mode 100644 index 000000000..ef2d149c0 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/qv-suggested.png differ diff --git a/docs/images/viva-extensibility/people-search/search-results.png b/docs/images/viva-extensibility/people-search/search-results.png new file mode 100644 index 000000000..bc9c82d57 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/search-results.png differ diff --git a/docs/images/viva-extensibility/people-search/toolbox.png b/docs/images/viva-extensibility/people-search/toolbox.png new file mode 100644 index 000000000..0a413d8b1 Binary files /dev/null and b/docs/images/viva-extensibility/people-search/toolbox.png differ diff --git a/docs/images/webpart-top-actions.png b/docs/images/webpart-top-actions.png index aa1c3f749..010338c18 100644 Binary files a/docs/images/webpart-top-actions.png and b/docs/images/webpart-top-actions.png differ diff --git a/docs/index.yml b/docs/index.yml index 7114ea6ca..b2648b18f 100644 --- a/docs/index.yml +++ b/docs/index.yml @@ -40,24 +40,20 @@ landingContent: url: /sharepoint/dev/spfx/web-parts/get-started/using-microsoft-graph-apis # Card (optional) - - title: Contact us + - title: SharePoint Embedded linkLists: - - linkListType: video - links: - - text: Microsoft 365 Community - url: https://www.youtube.com/channel/UC_mKdhw-V6CeCM7gTo_Iy7w - linkListType: overview links: - - text: Developer Blog - url: https://devblogs.microsoft.com/microsoft365dev/ - - text: Community - url: https://pnp.github.io/ - - text: Submit a new idea - url: https://aka.ms/feedback/sharepoint - - text: Issues - url: https://github.com/SharePoint/sp-dev-docs/issues - - text: Forum - url: https://aka.ms/spdev-community + - text: Overview of SharePoint Embedded + url: /sharepoint/dev/embedded/overview + - text: Enable SharePoint Embedded + url: /sharepoint/dev/embedded/getting-started/enable-sharepoint-embedded + - linkListType: tutorial + links: + - text: SharePoint Embedded - Overview & Configuration + url: /training/modules/sharepoint-embedded-setup + - text: SharePoint Embedded - Building an App + url: /training/modules/sharepoint-embedded-create-app # Card (optional) - title: Samples @@ -185,3 +181,23 @@ landingContent: url: /sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online - text: Modernize your classic SharePoint sites url: /sharepoint/dev/transform/modernize-classic-sites + + # Card (optional) + - title: Contact us + linkLists: + - linkListType: video + links: + - text: Microsoft 365 Community + url: https://www.youtube.com/channel/UC_mKdhw-V6CeCM7gTo_Iy7w + - linkListType: overview + links: + - text: Developer Blog + url: https://devblogs.microsoft.com/microsoft365dev/ + - text: Community + url: https://pnp.github.io/ + - text: Submit a new idea + url: https://aka.ms/feedback/sharepoint + - text: Issues + url: https://github.com/SharePoint/sp-dev-docs/issues + - text: Forum + url: https://aka.ms/spdev-community diff --git a/docs/schema/beginswith-element-query.md b/docs/schema/beginswith-element-query.md index 8837d1b6e..5078b623b 100644 --- a/docs/schema/beginswith-element-query.md +++ b/docs/schema/beginswith-element-query.md @@ -1,7 +1,7 @@ --- title: BeginsWith element (Query) manager: soliver -ms.date: 3/9/2015 +ms.date: 03/28/2023 ms.audience: Developer ms.topic: reference ms.localizationpriority: medium @@ -62,8 +62,12 @@ The following example uses the **BeginsWith** element within a string that is as SPWeb mySite = SPControl.GetContextWeb(Context); SPList list = mySite.Lists["List_Name "]; SPQuery query = new SPQuery(); -query.Query = "" + - "City"; +query.Query = "" + + "" + + "" + + "City" + + "" + + ""; SPListItemCollection myItems = list.GetItems(query); foreach (SPListItem item in myItems) { diff --git a/docs/schema/column-element-view.md b/docs/schema/column-element-view.md index 1f85943c9..9ba0c767e 100644 --- a/docs/schema/column-element-view.md +++ b/docs/schema/column-element-view.md @@ -1,7 +1,7 @@ --- title: Column element (View) manager: soliver -ms.date: 3/9/2015 +ms.date: 03/28/2023 ms.audience: Developer ms.topic: reference ms.localizationpriority: medium @@ -24,15 +24,15 @@ Returns the raw data value for a particular field, as opposed to the formatted v AutoHyperLink = "TRUE" | "FALSE" AutoHyperLinkNoEncoding = "TRUE" | "FALSE" AutoNewLine = "TRUE" | "FALSE" - Default = "Text" + Default = "Text" Format="DateTime" - HTMLEncode = "TRUE" | "FALSE" - Name = "Text" - ShowField = "Text" - StripWS = "TRUE" | "FALSE" + HTMLEncode = "TRUE" | "FALSE" + Name = "Text" + ShowField = "Text" + StripWS = "TRUE" | "FALSE" SubColumnNumber = Integer - URLEncode = "TRUE" | "FALSE" - URLEncodeAsURL = "TRUE" | "FALSE"> + URLEncode = "TRUE" | "FALSE" + URLEncodeAsURL = "TRUE" | "FALSE"> ``` @@ -42,20 +42,20 @@ The following sections describe attributes, child elements, and parent elements. ### Attributes -|**Attribute**|**Description**| -|:-----|:-----| -|**AutoHyperLink**
    |Optional **Boolean**. **TRUE** to surround text with `` tags if the text appears like a hyperlink (for example, `www.microsoft.com`).
    | -|**AutoHyperLinkNoEncoding**
    |Optional **Boolean**. **TRUE** to surround text with `
    ` tags if the text appears like a hyperlink (for example, `www.microsoft.com`) but without HTML encoding.
    | -|**AutoNewLine**
    |Optional **Boolean**. **TRUE** to insert `
    ` tags into the text stream and to replace multiple spaces with a nonbreaking space (` `).
    | -|**Default**
    |Optional **Text**. Renders the text assigned to this attribute if the value returned by a selection is an empty string (`""`).
    | -|**Format**
    |Optional **Text**. Controls the date formatting for date fields. Supported formats include **DateTime**, **DateOnly**, **TimeOnly**, **ISO8601**, **ISO8601Basic**, and **ISO8601Gregorian**.
    | -|**HTMLEncode**
    |Optional **Boolean**. **TRUE** to convert embedded characters so that they are displayed as text in the browser. In other words, characters that could be confused with HTML tags are converted to entities.
    | -|**Name**
    |Optional **Text**. Allows the **Column** element to be used outside the field rendering context by supplying an ID (for example, ``).
    | -|**ShowField**
    |Optional **Text**. The **ShowField** attribute can be set to the column name to display. By default, a hyperlinked text from the **Title** column of the record in the external list is displayed. But the **ShowField** attribute can be used to override that and display another field from the external list.
    The following data types are allowed as targets of a **ShowField** attribute: **Text**, **Choice**, and **Counter**.
    | -|**StripWS**
    |Optional **Boolean**. **TRUE** to remove white space from the beginning and end of the value returned by the element.
    | -|**SubColumnNumber**
    |Optional **Integer**.
    | -|**URLEncode**
    |Optional **Boolean**. **TRUE** to convert special characters, such as spaces, to quoted UTF-8 format (for example, `%c3%ab` for character `ë`).
    | -|**URLEncodeAsURL**
    |Optional **Boolean**. Like **URLEncode**, but **TRUE** to specify that the string to encode is a path component of a URL so that forward slashes (`/`) are not encoded.
    | +| **Attribute** | **Description** | +| :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **AutoHyperLink** | Optional **Boolean**. **TRUE** to surround text with `
    ` tags if the text appears like a hyperlink (for example, `www.microsoft.com`). | +| **AutoHyperLinkNoEncoding** | Optional **Boolean**. **TRUE** to surround text with `` tags if the text appears like a hyperlink (for example, `www.microsoft.com`) but without HTML encoding. | +| **AutoNewLine** | Optional **Boolean**. **TRUE** to insert `
    ` tags into the text stream and to replace multiple spaces with a nonbreaking space (` `). | +| **Default** | Optional **Text**. Renders the text assigned to this attribute if the value returned by a selection is an empty string (`""`). | +| **Format** | Optional **Text**. Controls the date formatting for date fields. Supported formats include **DateTime**, **DateOnly**, **TimeOnly**, **ISO8601**, **ISO8601Basic**, and **ISO8601Gregorian**. | +| **HTMLEncode** | Optional **Boolean**. **TRUE** to convert embedded characters so that they're displayed as text in the browser. In other words, characters that could be confused with HTML tags are converted to entities. | +| **Name** | Optional **Text**. Allows the **Column** element to be used outside the field rendering context by supplying an ID (for example, ``). | +| **ShowField** | Optional **Text**. The **ShowField** attribute can be set to the column name to display. By default, a hyperlinked text from the **Title** column of the record in the external list is displayed. But the **ShowField** attribute can be used to override that and display another field from the external list. The following data types are allowed as targets of a **ShowField** attribute: **Text**, **Choice**, and **Counter**.| +| **StripWS** | Optional **Boolean**. **TRUE** to remove white space from the beginning and end of the value returned by the element. | +| **SubColumnNumber** | Optional **Integer**. | +| **URLEncode** | Optional **Boolean**. **TRUE** to convert special characters, such as spaces, to quoted UTF-8 format (for example, `%c3%ab` for character `ë`). | +| **URLEncodeAsURL** | Optional **Boolean**. Like **URLEncode**, but **TRUE** to specify that the string to encode is a path component of a URL so that forward slashes (`/`) aren't encoded. | ### Child elements @@ -72,7 +72,7 @@ Numerous ### Remarks -Note that when an empty **Column** element (``) is used, it is sensitive to the current setting of the `DisplayMode` variable. The display mode is set implicitly according to the current command being used. +When an empty **Column** element (``) is used, it's sensitive to the current setting of the `DisplayMode` variable. The display mode is set implicitly according to the current command being used. If a view or item is being displayed, `DisplayMode` is set to **Display**. If an item is being created from a form, `DisplayMode` is set to **New**. If an existing item is being edited, `DisplayMode` is set to **Edit**. The `DisplayMode` variable can be overridden in the page by setting it directly, for example, `Edit`. diff --git a/docs/schema/column2-element-view.md b/docs/schema/column2-element-view.md index f01bcaa29..4266df0c4 100644 --- a/docs/schema/column2-element-view.md +++ b/docs/schema/column2-element-view.md @@ -1,7 +1,7 @@ --- title: Column2 element (View) manager: soliver -ms.date: 3/9/2015 +ms.date: 03/28/2023 ms.audience: Developer ms.topic: reference ms.localizationpriority: medium @@ -41,19 +41,19 @@ The following sections describe attributes, child elements, and parent elements. ### Attributes -|**Attribute**|**Description**| -|:-----|:-----| -|**AutoHyperLink**
    |Optional **Boolean**. **TRUE** to surround text with `
    ` tags if the text appears like a hyperlink (for example, `www.microsoft.com`).
    | -|**AutoHyperLinkNoEncoding**
    |Optional **Boolean**. **TRUE** to surround text with `
    ` tags if the text appears like a hyperlink (for example, `www.microsoft.com`) but without HTML encoding.
    | -|**AutoNewLine**
    |Optional **Boolean**. **TRUE** to insert `
    ` tags into the text stream and to replace multiple spaces with a nonbreaking space (` `).
    | -|**Default**
    |Optional **Text**. Renders the text assigned to this attribute if the value returned by a selection is an empty string (`""`).
    | -|**ExpandXML**
    |Optional **Boolean**. **TRUE** to re-pass the rendered content through the Collaborative Application Markup Language (CAML) interpreter, which allows CAML to render CAML.
    | -|**HTMLEncode**
    |Optional **Boolean**. **TRUE** to convert embedded characters so that they are displayed as text in the browser. In other words, characters that could be confused with HTML tags are converted to entities.
    | -|**Name**
    |Optional **Text**. Allows the **Column** element to be used outside the field rendering context by supplying an ID (for example, ``).
    | -|**ShowField**
    |Optional **Text**. The **ShowField** attribute can be set to the column name to display. By default, a hyperlinked text from the Title column of the record in the external list is displayed. But the **ShowField** attribute can be used to override that and display another field from the external list.
    The following data types are allowed as targets of a **ShowField** attribute: **Text**, **Choice**, and **Counter**.
    | -|**StripWS**
    |Optional **Boolean**. **TRUE** to remove white space from the beginning and end of the value returned by the element.
    | -|**URLEncode**
    |Optional **Boolean**. **TRUE** to convert special characters, such as spaces, to quoted UTF-8 format (for example, `%c3%ab` for character `ë`).
    | -|**URLEncodeAsURL**
    |Optional **Boolean**. Like **URLEncode**, but **TRUE** to specify that the string to encode is a path component of a URL so that forward slashes (`/`) are not encoded.
    | +| **Attribute** | **Description** | +| :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **AutoHyperLink** | Optional **Boolean**. **TRUE** to surround text with `
    ` tags if the text appears like a hyperlink (for example, `www.microsoft.com`). | +| **AutoHyperLinkNoEncoding** | Optional **Boolean**. **TRUE** to surround text with `` tags if the text appears like a hyperlink (for example, `www.microsoft.com`) but without HTML encoding. | +| **AutoNewLine** | Optional **Boolean**. **TRUE** to insert `
    ` tags into the text stream and to replace multiple spaces with a nonbreaking space (` `). | +| **Default** | Optional **Text**. Renders the text assigned to this attribute if the value returned by a selection is an empty string (`""`). | +| **ExpandXML** | Optional **Boolean**. **TRUE** to re-pass the rendered content through the Collaborative Application Markup Language (CAML) interpreter, which allows CAML to render CAML. | +| **HTMLEncode** | Optional **Boolean**. **TRUE** to convert embedded characters so that they're displayed as text in the browser. In other words, characters that could be confused with HTML tags are converted to entities. | +| **Name** | Optional **Text**. Allows the **Column** element to be used outside the field rendering context by supplying an ID (for example, ``). | +| **ShowField** | Optional **Text**. The **ShowField** attribute can be set to the column name to display. By default, a hyperlinked text from the Title column of the record in the external list is displayed. But the **ShowField** attribute can be used to override that and display another field from the external list. The following data types are allowed as targets of a **ShowField** attribute: **Text**, **Choice**, and **Counter**. | +| **StripWS** | Optional **Boolean**. **TRUE** to remove white space from the beginning and end of the value returned by the element. | +| **URLEncode** | Optional **Boolean**. **TRUE** to convert special characters, such as spaces, to quoted UTF-8 format (for example, `%c3%ab` for character `ë`). | +| **URLEncodeAsURL** | Optional **Boolean**. Like **URLEncode**, but **TRUE** to specify that the string to encode is a path component of a URL so that forward slashes (`/`) aren't encoded. | ### Child elements @@ -70,7 +70,7 @@ Numerous ## Example -The following [Switch](switch-element-view.md) statement evaluates the **Column2** value and, if it is empty, sets the HTML encoding of the [Column](column-element-view.md) element value (in other words, of the URL) to **TRUE**. Otherwise, it sets the HTML encoding of the URL's descriptive text to **TRUE**. +The following [Switch](switch-element-view.md) statement evaluates the **Column2** value and, if it's empty, sets the HTML encoding of the [Column](column-element-view.md) element value (in other words, of the URL) to **TRUE**. Otherwise, it sets the HTML encoding of the URL's descriptive text to **TRUE**. ```XML diff --git a/docs/schema/currency-element-regional-settings.md b/docs/schema/currency-element-regional-settings.md index a4ee50c45..8587e197c 100644 --- a/docs/schema/currency-element-regional-settings.md +++ b/docs/schema/currency-element-regional-settings.md @@ -112,7 +112,7 @@ The following table lists the locale identifiers (LCID) and currency formats, or |1028
    |NT$125 (Taiwan)
    | |1054
    |฿125 (Thailand)
    | |7169
    |125 .ت.د (Tunisia)
    | -|1055
    |125 TL (Turkey)
    | +|1055
    |125 TL (Türkiye)
    | |14337
    |125 .إ.د (U.A.E)
    | |2057
    |£125 (United Kingdom)
    | |1033
    |$125 (United States)
    | diff --git a/docs/schema/customaction-element.md b/docs/schema/customaction-element.md index 554d23421..5261fdf24 100644 --- a/docs/schema/customaction-element.md +++ b/docs/schema/customaction-element.md @@ -2,7 +2,7 @@ title: CustomAction Element description: Outlines the CustomAction element, which defines an extension to the user interface, such as a button on a toolbar or a link on a site settings page. manager: soliver -ms.date: 06/09/2022 +ms.date: 03/28/2023 ms.audience: Developer ms.topic: reference ms.localizationpriority: medium @@ -50,75 +50,46 @@ Defines an extension to the user interface, such as a button on a toolbar or a l The following sections describe attributes, child elements, and parent elements. ### Attributes + |Attribute |Description| |----------|-----------| -|`**RequiredAdmin**`|Optional `**Text**`. Specifies the administrative rights that are required for the custom action to apply. This value is used to trim links in Central Administration. Possible values are:
    • `**Delegated**`

    • `**Farm**`

    • `**Machine**`

    | -|`**ControlAssembly**`|Optional `**Text**`. Specifies the assembly of a control that supports the custom action.| -|`**ControlClass**`|Optional `**Text**`. Specifies a control class that supports the custom action.| -|`**ControlSrc**`|Optional `**Text**`. Specifies the relative URL of the .ascx file that serves as the source for the custom action, for example, `"~/_controltemplates/myCustomAction.ascx"`.| -|`**Description**`|Optional `**Text**`. Specifies a longer description for the action that is exposed as a tooltip or sub-description for the action.| -|`**FeatureId**`|Optional `**Text**`. Identifies the Feature that is associated with the custom action.| -|`**GroupId**`|Optional `**Text**`. Identifies an action group that contains the action, for example, `"SiteManagement"`. If it is contained within a custom action group, the value of the `**GroupId**` attribute must equal the group ID of the [CustomActionGroup](customactiongroup-element-custom-action.md) element.

    For a list of the default custom action group IDs that are used in Microsoft SharePoint Foundation, see [Default Custom Action Locations and IDs](default-custom-action-locations-and-ids.md).| -|`**Id**`|Optional `**Text**`. Specifies a unique identifier for the custom action. The ID may be a GUID, or it may be a unique term, for example, `"HtmlViewer"`.| -|`**ImageUrl**`|Optional `**Text**`. Specifies a virtual server relative link to an image that presents an icon for the item.| -|`**Location**`|Optional `**Text**`. Specifies the location of this custom action, for example, `"Microsoft.SharePoint.SiteSettings"`.

    If the `**CustomAction**` element contains a `**CommandUIExtension**` child element, the `**Location**` must start with "CommandUI.Ribbon". For a list of default locations that are used with the Server ribbon, see [Default Server Ribbon Customization Locations](https://msdn.microsoft.com/library/9ca6e4cc-9c51-4579-8f57-cf5aa59de5fd(Office.15).aspx).

    If the custom action is a menu item or toolbar button, the possible options include `**EditControlBlock**`, `**NewFormToolbar**`, `**DisplayFormToolbar**`, and `**EditFormToolbar**`.

    If it is contained within a custom action group, the value of the `**Location**` attribute must equal the location of the [CustomActionGroup](customactiongroup-element-custom-action.md) element.

    For a list of the default custom action locations that are used in SharePoint Foundation, see [Default Custom Action Locations and IDs](default-custom-action-locations-and-ids.md). -|`**RegistrationId**`|Optional `**Text**`. Specifies the identifier of the list or item content type that this action is associated with, or the file type or programmatic identifier (`**ProgID**`).| -|`**RegistrationType**`|Optional `**Text**`. Specifies the registration attachment for a per-item action. Possible values include:

    • `**None**`

    • `**List**`

    • `**ContentType**`

    • `**ProgId**`

    • `**FileType**`

    | -|`**RequireSiteAdministrator**`|Optional `**Boolean**`. `**TRUE**` to specify that the item be displayed only if the user is a site administrator; otherwise, `**FALSE**`. Using the `**RequireSiteAdministrator**` attribute for the drop-down menu of SharePoint Foundation commands that are associated with list items is not supported.| -|`**Rights**`|Optional `**Text**`. Specifies a set of rights that the user must have for the link to be visible, for example, `"ViewListItems,ManageAlerts"`. If it is not specified, the action always appears in the list of actions. To specify multiple rights, separate the values by using commas. The set of rights are grouped logically according to `**AND**` logic, which means that a user must have all the specified rights to see an action. For a list of possible values, see Microsoft.SharePoint.SPBasePermissions.| -|`**RootWebOnly**`|Optional `**Boolean**`. `**TRUE**` to deploy the custom action only on root websites. This attribute applies to custom actions in a sandboxed solution.| -|`**ScriptSrc**`|Optional `**Text**`. Specifies a file that contains script to be executed. This attribute is only applicable when the `**Location**` attribute is set to `**ScriptLink**`.| -|`**ScriptBlock**`|Optional `**Text**`. Specifies a block of script to be executed. This attribute is only applicable when the `**Location**` attribute is set to `**ScriptLink**`.| -|`**Sequence**`|Optional `**Integer**`. Specifies the ordering priority for actions.| -|`**ShowInLists**`|This attribute is deprecated and should not be used.

    Optional `**Boolean**`. `**TRUE**` if the custom action is only displayed for lists on the page for managing content types. The default value is `**FALSE**`.

    | -|`**ShowInReadOnlyContentTypes**`|Optional `**Boolean**`. `**TRUE**` if the custom action is only displayed for read-only content types on the page for managing content types. The default value is `**FALSE**`.| -|`**ShowInSealedContentTypes**`|Optional `**Boolean**`. `**TRUE**` if the custom action is only displayed for sealed content types on the page for managing content types. The default value is `**FALSE**`.| -|`**Title**`|Required `**Text**`. Specifies the end-user description for this action.| -|`**UIVersion**`|Optional `**Integer**`. Specifies the version of the user interface in which this custom action should be listed.| - +|**RequiredAdmin**|Optional **Text**. Specifies the administrative rights that are required for the custom action to apply. This value is used to trim links in Central Administration. Possible values are:
    • Delegated
    • Farm
    • Machine
    | +|**ControlAssembly**|Optional **Text**. Specifies the assembly of a control that supports the custom action.| +|**ControlClass**|Optional **Text**. Specifies a control class that supports the custom action.| +|**ControlSrc**|Optional **Text**. Specifies the relative URL of the .ascx file that serves as the source for the custom action, for example, `~/_controltemplates/myCustomAction.ascx`.| +|**Description**|Optional **Text**. Specifies a longer description for the action that is exposed as a tooltip or sub-description for the action.| +|**FeatureId**|Optional **Text**. Identifies the Feature that is associated with the custom action.| +|**GroupId**|Optional **Text**. Identifies an action group that contains the action, for example, `"SiteManagement"`. If it is contained within a custom action group, the value of the **GroupId** attribute must equal the group ID of the [CustomActionGroup](customactiongroup-element-custom-action.md) element.

    For a list of the default custom action group IDs that are used in Microsoft SharePoint Foundation, see [Default Custom Action Locations and IDs](default-custom-action-locations-and-ids.md).| +|**Id**|Optional **Text**. Specifies a unique identifier for the custom action. The ID may be a GUID, or it may be a unique term, for example, `"HtmlViewer"`.| +|**ImageUrl**|Optional **Text**. Specifies a virtual server relative link to an image that presents an icon for the item.| +|**Location**|Optional **Text**. Specifies the location of this custom action, for example, `"Microsoft.SharePoint.SiteSettings"`.

    If the **CustomAction** element contains a **CommandUIExtension** child element, the **Location** must start with "CommandUI.Ribbon". For a list of default locations that are used with the Server ribbon, see [Default Server Ribbon Customization Locations](https://msdn.microsoft.com/library/9ca6e4cc-9c51-4579-8f57-cf5aa59de5fd(Office.15).aspx).

    If the custom action is a menu item or toolbar button, the possible options include **EditControlBlock**, **NewFormToolbar**, **DisplayFormToolbar**, and **EditFormToolbar**.

    If it is contained within a custom action group, the value of the **Location** attribute must equal the location of the [CustomActionGroup](customactiongroup-element-custom-action.md) element.

    For a list of the default custom action locations that are used in SharePoint Foundation, see [Default Custom Action Locations and IDs](default-custom-action-locations-and-ids.md). +|**RegistrationId**|Optional **Text**. Specifies the identifier of the list or item content type that this action is associated with, or the file type or programmatic identifier (**ProgID**).| +|**RegistrationType**|Optional **Text**. Specifies the registration attachment for a per-item action. Possible values include:
    • None
    • List
    • ContentType
    • ProgId
    • FileType
    | +|**RequireSiteAdministrator**|Optional **Boolean**. **TRUE** to specify that the item be displayed only if the user is a site administrator; otherwise, **FALSE**. Using the **RequireSiteAdministrator** attribute for the drop-down menu of SharePoint Foundation commands that are associated with list items is not supported.| +|**Rights**|Optional **Text**. Specifies a set of rights that the user must have for the link to be visible, for example, `"ViewListItems,ManageAlerts"`. If it is not specified, the action always appears in the list of actions. To specify multiple rights, separate the values by using commas. The set of rights are grouped logically according to **AND** logic, which means that a user must have all the specified rights to see an action. For a list of possible values, see Microsoft.SharePoint.SPBasePermissions.| +|**RootWebOnly**|Optional **Boolean**. **TRUE** to deploy the custom action only on root websites. This attribute applies to custom actions in a sandboxed solution.| +|**ScriptSrc**|Optional **Text**. Specifies a file that contains script to be executed. This attribute is only applicable when the **Location** attribute is set to **ScriptLink**.| +|**ScriptBlock**|Optional **Text**. Specifies a block of script to be executed. This attribute is only applicable when the **Location** attribute is set to **ScriptLink**.| +|**Sequence**|Optional **Integer**. Specifies the ordering priority for actions.| +|**ShowInLists**|This attribute is deprecated and should not be used.

    Optional **Boolean**. **TRUE** if the custom action is only displayed for lists on the page for managing content types. The default value is **FALSE**.| +|**ShowInReadOnlyContentTypes**|Optional **Boolean**. **TRUE** if the custom action is only displayed for read-only content types on the page for managing content types. The default value is **FALSE**.| +|**ShowInSealedContentTypes**|Optional **Boolean**. **TRUE** if the custom action is only displayed for sealed content types on the page for managing content types. The default value is **FALSE**.| +|**Title**|Required **Text**. Specifies the end-user description for this action.| +|**UIVersion**|Optional **Integer**. Specifies the version of the user interface in which this custom action should be listed.| ### Child elements - --- - - - - - - - - -

    CommandUIExtension

    UrlAction

    +- [CommandUIExtension](commanduiextension-element.md) +- [UrlAction](urlaction-element.md) ### Parent elements - --- - - - - - -

    Elements

    +- [Elements](elements-element-custom-action.md) ### Occurrences - --- - - - - - -

    Minimum: 1

    -

    Maximum: Unbounded

    +- Minimum: 1 +- Maximum: Unbounded ### Remarks @@ -129,36 +100,34 @@ You can use the **CustomAction** element to add standard ASP.NET controls and us The following example is part of a Feature that replaces a button on the Server ribbon. ```XML - - - - - -