Tuesday, December 24, 2019

Select the right Microsoft 365 Live Events type best fitting your needs

Microsoft 365 includes 3 different options to execute Live Events: via Microsoft Stream, Microsoft Teams and Yammer. The 3 have their similarities, and also their differentiatiors. How-to select the Live Event type aka webcast solution that best fits your needs on a specific event? Microsoft itself does not really provide direction on this question, although they published how their own Core Services Engineering and Operations (CSEO) team deals with it:
A different angle you can utilize is to address it from the product side...
Use MS Teams Live Event, if:
  • Your event audience is for public anonymous access;
  • Your event audience includes external guests known in your Office 365 directory (via Azure B2B);
  • Your event audience is for internal-only access AND you want to provide an inline conversation;
  • It is allowed that the video recording is not stored in your own Office 365 tenant; (see)
  • Your audience is guaranteed known before the live event starts; (see)
  • There is no need to capture the conversation (Q&A) beyond the scope of the live event
Produce your MS Teams Live Event by:
  • 'Self-production' / embedded encoder via MS Teams, if
    • You want to quickly setup the event, and have no requirements for advanced production quality (as animations, fade-in/fade-out; agumented reality, ....);
    • You as event organizer are confident to do the event production (camera, audio, PowerPoints, ...) yourself;
  • Use 'External App production' via MS Teams, if:
    • You need advanced production quality to bring the message;
    • You're not confident to do the production yourself in MS Teams App;
Use MS Stream Live Event, if:
  • Your event audience is for internal-only access, AND
    • you want to broadcast / send a communication message
    • your online audience size is larger, and you must protect your network from saturation via an eCDN solution
  • You want a branded landings-page for the audience to join the live event;
  • It is not allowed to store on-demand recording of the live event outside your own Office 365 tenant; (see)
  • You need to be able to on-the-fly while live event already in progress, authorize + revoke authorization of persons to watch the live event;
  • You want to easily capture the conversation (Q&A) beyond the scope of the live event; e.g. for trends analysis;
A variation on decision-tree to select proper live events type
Check / Differentiator Questions
  1. What is the audience of your event: internal-only, or also outside your company? (with MS Stream not possible current>)
  2. What is the size of your online audience? (as with larger, network optimization needed)
  3. How sophisticated do you need the production quality of your event to be? (is the simplicity of MS Teams Live Event 'self-production' good-enough)
  4. Do you have dedicated production equipment, or even a production company to produce the event via external encoder?
  5. Do you need to provide a company-branded experience to join the live event?

Monday, November 25, 2019

Beware: unique library permissions breaks drag-and-drop capability (classic site)

Breaking permissions is advised against, unless... Main rationale for this generic rule of thumb is the complexity that unique permissions brings to permission management in a SharePoint site. However, in addition it can also have a limitating effect on the user experience: persons of which the authorization in a site is limited to only contribute in a specific document library, face issues on upload of documents. Quick investigation revealed that the problem occurs when the document upload is done via drag-and-drop; uploading a document via the explicit 'upload' UI flow does succeed.
On SharePoint platform level, these functional equivalent actions are executed via other flows. In the drag-and-drop scenario, SharePoint executes a CSOM call to read the site properties. But if a person is only authorized to the document library, the 'SelectAllProperties' processQuery action on SharePoint Site level returns 'Access Denied'. Solution is to grant the persons also a limited permission level on the site level, so they are allowed to read the site properties.
With this ‘Read Site Props’ permission level granted at site level, the respective persons are still correct blocked to access entities and content on site level; except for the library to which explicit granted via unique library permissions.
Noteworthy is that the issue does not occur in modern sites, even although also in that context with 'drag-and-drown' execution the site properties are retrieved via CSOM call.

Friday, October 18, 2019

Beware: immediate after upload into Stream, video is available in only 1 quality / rendition

A business user recent approached me with question why his uploaded video was only available in one, and not the highest bitrate / quality in Microsoft Stream. However, when we opened the video to inspect, he was pleasant surprised that all of a sudden the video could be played in more qualities, including with higher bitrates. This behavior is completely explainable, as on Stream side processing takes place to convert the uploaded video in multiple bitrates; and that processing simples takes its time to complete. But it is good to be aware of, and realize that you just need to be a bit patient for the different video qualities to become available.

Sunday, October 13, 2019

Beware: Open Project Online resource in 'Edit Resource' blocks the automated modification of that item

The Project Online ResourcePool can be automated managed, e.g. to update a (Custom)Field of an EnterpriseResource. Something that I became aware of is that the automated modification is blocked in case the resource is opened in 'Edit Resource' of the Project Online Web Application (PWA). Apparent PWA applies defensive locking, and already immediate locks the resource through checkout when opening it in the form, and not delayed / just-in-time at the moment of possible save. The automation is blocked both when doing the modification via ProjectServer REST service, as when via the ProjectServer.Client CSOM library.
Open a PO resource in the ‘Edit Form’
(<pwa-url>/_layouts/15/PWA/Admin/AddModifyUser.aspx )
Automation code-snippet to modify EnterpriseResource via REST service
 $body = "{ 'Name':'Test Name', 'Group':'Test Group' }";
 Patch-ReSTRequest $pwaUrl "ProjectServer/EnterpriseResources('$resourceId')" $body
Combination of 'Edit form' + automation execution results in error
{
  "error":
    {
       "code":"10101, Microsoft.ProjectServer.PJClientCallableException",
       "message":
           {
              "lang":"en-US",
              "value":"PJClientCallableException: CICOAlreadyCheckedOutToYou"
           }
    }
}

Sunday, September 29, 2019

Be aware: join as MS Teams Live Events guest requires that one is pre-authenticated against the inviting tenant

With MS Teams Live Events produced via Teams (aka QuickStart) it is already supported to invite externals (MS Teams produced via External App will support it once the underlying Microsoft Stream Live Events capability supports guest access). Guest access in MS Teams Live Events by Teams is realized by utilizing the Azure AD B2B capability, similar as is done in the external sharing of a MS Teams instance itself with external guests, and also in external sharing SharePoint Online sites. Interesting is that the external does not need to be invited to any MS Teams instance of the inviting company. This makes sense, as a MS Teams Live Events instance itself is not tied to a particular MS Teams instance; it is scheduled from the MS Teams Calendar.
Guests can join the Live Event via the browser or via the MS Teams App. In case of the latter: In your joiner instruction to invited guests, please make sure to inform them that they first must authenticate themselves against your (the inviting) tenant, before trying to join the MS Teams Live Event via the distributed 'attendee link'.
No permission to join as guest in case not authenticated before
Authenticate as Azure AD guest to the MS Teams of the inviting tenant; first authentication is 'federated' against the invited guest identity administration, and next most likely second / multi-factor authentication against the inviting tenant
Once authenticated as AAD guest to the inviting MS Teams tenant, allowed to join the invited Live Events direct via the 'attendee link'

Saturday, September 21, 2019

In the dungeons of Azure AD B2B: properties of external Azure AD account might block creation of guest account

Collaboration between organizations in an ecosystem has become more and more essential to the value organizations create. But also in these Business-2-Business (B2B) collaboration scenarios, the authorization principle of 'need-to-known' must be adhered: employees from the partner organizations should only be granted access to the information on which they actually collaborate with the inviting organization. To be able to grant selective authorizations to the externals, requires that each of them must be known with identifying identities in the information system(s) of the inviting company.
In the Azure AD B2B model, Microsoft introduced the notion of 'guest accounts' for this, based on the concept of "bring-your-own-identity". An Azure AD B2B guest account is a lightweight account, that in fact acts as placeholder in the Azure AD context of the inviting organization to external identity managed outside the responsibility of the inviting organization. As such, Azure AD B2B collaboration supports cross-company relationships by enabling partners to selectively access your corporate applications and data using their self-managed identities
Azure AD B2B supports 2 modes to invite external guests via their corporate email addresses: a federation model from the Azure AD of the inviting organization to the external Azure AD of invited partner organization. And in the case that the invited company is itself not (yet) an user of Azure AD for their identity management, via just-in-time created accounts which are then administrated in a so-called 'viral' tenancy (see: Understand the B2B user).
Guest accounts are created in the inviting Azure AD with their own (external company) email address applied as their guest account / identity name. Azure AD requirement here is that the guest identity name is not yet in-usage as proxy-address within another account in the Azure AD tenant. The typical situation in which this could occur is when an external employee already has also a Member account in the Azure AD of the inviting organization, and has the own corporate email assigned to that Member account. When next you try to create a guest account for that external email, Azure AD refuses with error message: "The user you're inviting already exists in the directory. They can simply sign in into shared apps and resources."
The most pragmatic approach to fix this guest account provision error, is to 'free' the external corporate email address of the 'to-be AAD guest': disconnect it from assignment in the Member account in the Azure AD of inviting organization.
Another apparent feasible approach is to simple select another external corporate email as guest account name: e.g. instead of '<External>.<User>@>ExternalOrg<.com', provision a guest account via '<External>.<User>1@>ExternalOrg<.com'. This is certainly a creative alternative. But you need to be aware of some pitfalls with it. 1) Redemption in Azure AD B2B is an email-verified process. Meaning that the alternative corporate email address must actually exist and resolve to an email inbox in the domain of the invited organization. 2) In case of federated Azure AD tenants, the requirement that the proxyAddresses must be unique, is verified in the combination of the Azure AD tenants of both the inviting as the invited organizations. Resulting that in case to the alternative account in the Azure AD of the invited organization, the original corporate email of person is administrated in the proxyAddresses, then the provisioning of guest account in Azure AD of the inviting organization still blocks. See How can we improve Azure Active Directory? - Show the B2B-blocking proxy address in my tenant's logs where this is shortly described.
Code snippet to have run in the Azure AD tenant of the invited organization, to identify whether and which proxyAddress value is the cause of the blocking:
Connect-AzureAD

Get-AzureADUser -Filter "mail eq '<firstName>.<lastName>1@externalcompany.com'"
   -all $true |
Select-Object displayName, @{L = "ProxyAddresses"; E = { $_.ProxyAddresses -join ";"}} |
Export-Csv -Path C:\temp\ReportOutOnAADAccount.csv -NoTypeInformation

Sunday, September 15, 2019

Caveat with MS Teams Live Events: once started, your audience is fixed

Do you recognize this? You started "the party", and while in full flux you're friendly reminded that you forgot to invite your best friend... This metaphore also holds for webcasts with selected audience: as people move accross diverse departments in an organization, it is an easy miss to not authorize/invite someone new joined. And dependent on the content and information sensitivity of the information shared, even more important can be to retract the authorization of someone that moved to another department. With Stream Live Events, the owner aka organizer of the Live Events is enabled to on-the-fly make modifications to the authorized / invited audience of the event, also when the event is already live. With Teams Live Events this is not possible: once the planned event is started, the audience is locked: you can neither add new attendees (nor presenters), or remove persons that should not be allowed. It is even not possible to modify in MS Teams the audience after the event is ended.
As the positioning of MS Teams Live Events compared with MS Stream Live Events is that the first is aimed for webcast distribution with a typical known team (of people), the lack of dynamic authorization may in reality not be a concrete issue. But good to be aware of, also to make a judged selection between webcast via MS Teams Live Events or via MS Stream Live Events.

Friday, September 13, 2019

Just be aware: recorded data of MS Team Live Events "QuickStart" is stored outside own tenant

Microsoft Teams Live Events supports 2 flavours: Teams (formerly code-named "QuickStart"), and External App using Microsoft Stream. The charm of the Teams option is illustrated by its code-naming: it's very easy to start up and use. In the most basic and raw form, the only thing needed is a laptop with onboard camera, and Microsoft Teams desktop application installed. And then anyone granted the Teams Live Events scheduling authorisation (TeamsMeetingBroadcastPolicy -AllowBroadcastScheduling parameter = True; Who can create and schedule live events?), can self-schedule and self-produce a Live Event. However, a caveat to at least be aware of is on the location where collected data is stored: the video recording, and the data of the Moderated Q&A. When using Microsoft Stream for event webcasting, the recording is stored in your own tenant and under your direct control. The MS Teams situation is to date different:
  1. The video recordings are stored as Azure Blob in the Microsoft system instance of Azure Media Service, a generic tenant shared accross multiple customers. The AMS instance is within the same data center as your tenant (not much information on this shared, but see: Manage a live event recording and reports in Teams: "Recordings from live events produced in Teams are currently not saved in Microsoft Stream", and Teams Live Events storage location);
  2. Captured Questions & Answers are stored in a combination of Azure Tables and CosmosDb, also in a generic tenant. The QnA data is automatic deleted 180 days after end of the Live Event, unless earlier explicit deleted by yourself.
It can very well be that this outside-tenant administration of your's company data is totally irrelevant for your organization. If so, you don't need to concern yourself nor your information security. However, in case you are in a business for which legal compliance and/or data privacy holds, I do advise that you consult your information security and compliance office on whether the outside-tenant administration does not impose a continuity risk. Better be safe than afterwards sorry...

Thursday, August 15, 2019

Beware with Unique Permissions on PublishingPages, AddAndCustomizePages and Embed Code in a page

Interesting puzzle solved: page authors complained that some of them face an issue when they try to insert a Microsoft Stream video via embed code in the page body:
The message clearly points to missing of 'AddAndCustomizePages' permission for the logged-on page author. However, on checking the permissions, all the authors / editors do have that permission via an assigned 'Content Management' permission level. After some trial-and-error, I discovered the SharePoint internal cause. The below error message on trying to insert a ScriptEditor webpart in the page content, led me to the Eureka insight:
This site says... Aha: In the site the permission inheritance is broken, to achieve that page authors can only create and modify page (= news) items, but are restricted from modifying anything else in the site. The 'Content Management' permission level is for that purpose not assigned to them on site level, but on the Pages library. On required permission for their author task this assignment is sufficient. But a flaw in SharePoint is that it checks in the 'Insert Embed-code' handling whether the 'AddAndCustomizePages' permission is granted to the logged-on author on site level.
With this insight / understanding on SharePoint level, the fix clear: make sure that all the page authors are also granted a permission level on site level that includes the 'AddAndCustomizePages' permission. And with that fix, all page authors are enabled / authorized to user-friendly apply 'Embed Code' in page edit mode:

Saturday, August 10, 2019

Misleading Conditional Access response on trying access with expired Azure AD B2B guest invitation

In the situation that an invited Azure AD B2B guest is homed in an external instance of Azure AD, there is no need to await redemption by the invited guest before the guest account can be utilized in the inviting Office 365 tenant to grant access in a SharePoint site. Instead, on first visit of the invited + authorized external / guest account, the redemption will take place implicit. This improved B2B invitation experience is available since May 2018 (Exciting improvements to the B2B collaboration experience).
However, this scenario breaks in the situation that the invited guest lets the invite expire:
That the implicit redemption in such situation fails is on itself logical and the correct behavior. However, the error notification that the guest receives is misleading. It does not point to the cause that the guest invitation is not accepted yet (and thus guest account still in 'Invited User' state), but falls through to the conditional access for regular Member accounts:
The correct fix in this situation is to either resend the invitation in Azure Portal, or re-invite via New-AzureADMSInvitation cmdlet. The invited person is then re-enabled to accept the invite. Either redeem explicit via the URL in the invitation email, or redeem implicit on first access to a site in the inviting SharePoint Online tenant that is shared with the guest account.

Monday, August 5, 2019

Confusing SharePoint UI to add guest to Modern Group-connected Site

Once in Azure AD a guest account is created for an external, site owners can use that guest account in same way as for regular accounts to grant access in a SharePoint Site: 'Share' the site, and lookup the guest account. However, within Modern / Office 365 Group-connected site, this similarity is broken. The cause is that in the SharePoint UI of a Group-connected site, the Membership in the top-level UI is actually referring to the Office 365 Group; not that of the connected SharePoint Site. Yet external / guest accounts cannot be added via SharePoint to an Office 365 Group, this needs to be done via Outlook on Web as membership management interface (Manage guest access in Office 365 Groups).
Not possible to add guests to Office 365 Groups via SharePoint top-level UI
The proper way to add guest accounts to the B2B shared site, remains to authorize them on level of SharePoint site. Preferable utilizing SharePoint Groups, instead of direct individual assigned authorization. The path in the UI to this is via 'Settings' menu, 'Site permissions', 'Invite people'. And in this step, select 'Share site only':
How-to authorize guests to access Modern Site via SharePoint UI
The above experience is a smoothened version for the old-fashioned SharePoint membership management: making one aware on the existance and concrete membership management of the SharePoint Groups in the site. This 'old-way' is also still available, via 'Advanced permissions settings'. Or for those knowledgable SharePoint insiders...; direct via the known URL (<site-URL>/_layouts/15/user.aspx).
(old-way) How-to authorize guests to access Modern Site via SharePoint UI

Thursday, August 1, 2019

Beware: with B2B sharing enabled on SharePoint tenant level, all new provisioned Modern sites are by default open for non-constrained sharing

The governance of B2B sharing of SharePoint Online is setup on 2 levels: at first, on tenant level the SharingCapability must be configured in an enabled state (SharingCapabilities enumeration), otherwise all sharing in the full collection of sites in the tenant will be disallowed / blocked. Also on tenant level, SharePoint admin can configure allowed (whitelisted) and disallowed (blacklisted) domains of invited organizations. On the 2nd level, the SharingCapability of individual site collection must also be configured to same enabled state, to enable sharing of that particular site. Plus also on this level, SharePoint admin can specify both allowed and disallowed domains.
With this 2-step configuration, the inviting organization is enabled with explicit (IT) control on which of the site collections, their business owner(s) can invite (authorize for access) guests of targeted invited partner organizations.
Something to be aware of in this SharePoint Online B2B governance is that on site collection level of Modern / Group-enabled sites, the default setting of the SharingCapability property follows the tenant-configured value. This means that in the situation where sharing is enabled on tenant level, all new provisioned Modern sites by default are also direct configured to allow sharing.
In the 2-step B2B governance process this is not compliant; individual site collections may only be configured for sharing on explicit business request and approval, and potential for identified domain(s) only.
To get back into compliant state, each new provisioned site collection must be configured via an after-step to reset the SharingCapability into ‘Disabled’. This after-step can be executed via Site Designs, or in case a site provisioning solution is used (e.g. PnP provisioning) as post-processing provision step. Another approach is via a scheduled automation job (e.g. Azure Automation, or remote PowerShell).
Note: remarkable is the difference with classic sites: these are by default always provisioned with disabled 'SharingCapability', independent of the setting on tenant level.

Inconsistency within MS Teams External Sharing activation

A special case is with the SharePoint sites that are created underneath MS Teams instances (for the ‘Files’ capability). Also on the tenant level of MS Teams, the external / guest capability is configured. However, there is an inconsistency in the context of the MS Teams B2B configuration when external sharing is enabled on SharePoint tenant level, but not on MS Teams tenant level: the underlying SharePoint sites follow the SharePoint tenant setting, not that of their ‘owning’ MS Teams. The effect is that external guests may be authorized for access to the SharePoint site underneath a MS Teams instance, despite that on MS Teams tenant level external sharing is explicit disabled.
To correct this inconsistency, any of the above sketched set of ‘compliance’ approaches can be applied on the SharePoint sites that are created 'underneath' MS Teams instances.

Thursday, June 20, 2019

Redeploy your SPFx Extension to SharePoint

One of the charms of SPFx Extensions is that they apply tenant-wide: they can be configured for immediate utilization in all modern site collections in your tenant. On SharePoint foundational level this works via the concept of good-old CustomAction that is injected into the context of each modern site collection. In the SPFx Extension package the CustomAction is configured as Feature deployment. Via the parameter 'skipFeatureDeployment' in the package-solution.json (see 'Tenant-scoped solution deployment for SharePoint Framework solutions') you can configure the SPFx Extension to be immediate available across all the sites in the tenant when the solution package is installed to the tenant app catalog, without need to explicit activate the CustomAction feature in each individual site.
This works out fine on the initial deployment of your SPFx extension: the deployed SPFx header automatically is included and active on each site.
On initial deploy, SPFx Extension included once in each modern site
However, in case of need for redeployment, you must be aware of a current glitch: the SPFx Extension gets multiplied per each re-deployment. The cause of this is in how the (semi)immediate and tenant-wide application of the CustomAction is applied. The CustomAction is not injected in the scope of each individual site (Web.UserCustomActions does not include the CustomAction of the SPFx Extension); but is injected as Tenant Wide Extensions. In case of "skipFeatureDeployment": true in the package-solution.json file, on upload / install of the .sppkg file in the tenant App Catalog the administrator is asked to set the 'Make this solution available to all sites in the organization' checkbox. If set, a row is added in the list 'Tenant Wide Extensions' in the App Catalog site. And on re-upload / redeploy, the checked setting is applied again, resulting in duplicate entries for the same SPFx Extension in the Tenant Wide Extensions list. This results that the CustomAction is applied multiple times per each site, and therefore that the SPFx Extension is included multiple times in each site...
As side-effect of re-deploy, SPFx Extension is multiplied in 'Tenant Wide Extensions' list
Result is that the SPFx Extension is included multiple times per each site
Correcting this faulty situation is simple once you know how-to (thanks to Vesa Vujonen for fast response on support question raised): just remove the duplicate entries from the Tenant Wide Extensions list. Mind you, it can take some elapse time before the effect of this is structural applied accross all the WFE's involved in serving the sites of one's tenant.
Fix by removing the duplicate rows in Tenant Wide Extensions
Then the SPFx Extension again included once, and referring to latest package version

Saturday, June 15, 2019

How-to remain in control of Live Events scheduling

See previous post, in the production of a Stream Live Events are 3 different roles involved:
  • Organizer
  • Producer
  • Presenter
The organizer is the person that can schedule / create new Live Events, and becomes the owner of them. Although there is no limitation stated on the amount of Live Events running in parallel, it makes perfect sense to govern this. You don't want to risk that the webcast experience of the CEO Townhall is hampered because too many other Live Events are running within same or overlapping timeslot. In order to avoid wildspread of Live Events, Stream supports via admin settings that the authorization to create Live Events is restricted to specific identified persons only / not for everyone in your organization.
The person creating / scheduling a Live Event, automatically also becomes the owner. However, in the differentiation of the webcast roles; the organizer should not need to be involved in any of the production aspects on the actual moment of the event. To achieve that, the person that will act as the producer of a specific event, must also be made the owner of the scheduled Live Event. As owner, the producer can pick up the scheduled Live Event, set it in edit mode, and then start and stop the event from the Stream webapplication.
Organizer creates / schedules (on request of Producer) a new Live Event
Organizer assigns / shares ownership of the scheduled Live Event to the Producer
On scheduled datetime of webcast, the Producer looks up the scheduled Live Event in Stream web application
On scheduled date of webcast, the Producer starts Setup of the Live Event
On scheduled date of webcast, the Producer is in-control to start the actual broadcasting once the production encoder sends the stream input signal

Friday, June 14, 2019

Plug-In outside producer in Stream Live Events

In a broadcast execution via Stream Live Events, the following roles are involved:
  • Organizer
  • Producer
  • Presenter
(source: Get started with Microsoft Teams Live Events). The person within the Organizer role schedules the live event, and requires the proper authorization in your tenant for that. But next the system design of Stream Live Events allows that for the production part you can delegate to outside your company infra. The plug-in interface for this is the unique RTMP(S) ingress endpoint address of the scheduled Live Event. This endpoint is accessible on the public internet. The producer can configure the encoder on the production / event location to stream as input of the Live Event for broadcasting within your Office 365 tenant. The ultimate production control remains with the authorized owner(s) of the Stream Live Event: to start the actual broadcasting once the received stream input is ok for sending to the audience, and stop the Live Event once the event / presenter is finished (and also when in unlikely case that the producer produces a live recording that is inappropriate or non-compliant with your business policy).

Wednesday, May 8, 2019

Opt-In Modern List Experience on Communication Site obstructs upgrade SPFx app via UI

An approach to upgrade a deployed 'App for SharePoint' is to open the site that contains the AppCatalog (either tenant, or site collection with own app catalog) in a browser, go to 'Site Contents', and double click the App. In the 'About' dialog it will then present the option to upgrade. When the site is in Modern List experience, this approach is hampered: also the 'Site Contents' view is then within Modern View; and the available options there for any App are limited to 'Monitor' and 'Remove'. Microsoft is aware of the issue, and for now advises to apply a workaround: in the Modern 'Site Contents' view, click in the lower-left corner on 'Return to classic SharePoint'. This results that on the fly the 'Site Contents' view is rendered in classic mode, and the approach to upgrade App are available for usage. However, it turns out this workaround is only available for Modern Team sites, but not for Modern Communication Sites. Direct cause is that Communication Sites by Microsoft Design do not have the 'Left Navigation' (see Modern SharePoint Sites navigation options). And by Microsoft Design flaw this lack of left navigation is propagated into application and listview pages, including 'Site Contents' (Communication Site - Left Navigation Missing in Lists / Libraries). This leaves as only workaround for Communication Site to support upgrade of (SPFx) Apps interactive through the SharePoint UI, is “Opt out of the Modern list and library experience” for that site; at least for the moment when you need to upgrade any of the (SPFx) Apps in the (site) app catalog.
Note that the non-UI approach of upgrade via PowerShell (Update-SPAppInstance)is not hampered by the Modern List Experience.

Tuesday, May 7, 2019

Beware: Co-Authoring in SharePoint stored Excel sheet conflicts with column-filtering

For the scenario that multiple persons must be enabled to simultaneous maintain their records in a shared data container, at first consideration the usage of Excel file stored in SharePoint Online appears a valid option. Thanks the Co-Authoring capability available in Excel Online and Excel Client. This setup may fit the usage scenario, unless the users want to make use of filtering in the Excel sheet to easily find the records one needs to maintain. The motivation that this breaks the scenario is that column-filtering is not limited to the operational view state within the clients, but is itself part of the saved state of the Excel file. This results that the filter applied by user A in his/her client context with the Excel file, via AutoSave almost immediately is propagated into the shared saved state of the Excel file, and next influences the application view state of user B that also has the sheet opened. This non-isolated behavior of applying a column filter kills the usability of the Excel viewing and editing in co-authoring mode. In case the data to manage is flat of structure, and without need for Excel macros, a better option is administer the data records in a SharePoint list, and educate the business to maintain their own records in that list in quick edit mode combined with column-filtering. Contrary to Excel editing, the full client context of working with a SharePoint list is isolated to only the list view; and not persistent in the data.
Note: this behavior is already requested for change on uservoice: Filtering Needs to Work in Co-Authoring. But apparent a difficult capability to deliver: the idea submission originates of 2017, the response by Microsoft development team is nearly 2 years later. However, that acknowledgement and moreover its recent date does give trust that Microsoft will now fix it in foreseeable time.

Friday, April 26, 2019

Weighing of customizing options for Questions & Feedback capability with Stream Live Events

In "Options considered for extending Stream Live Events with live chat/questions capability" I enumerated multiple options for enriching the Stream Live Events experience with Questions & Feedback capability. In below overview, I enlist pros and cons weighing of the diverse options.
OptionProsCons
Via Yammer
  • Existing / available IT building block within Office 365 suite;
  • Low-code solution: only a bit of JavaScript needed for correct visual embedding in the landings page;
  • Access can be limited to selected audience;
  • Live feed visible of questions, also the ones raised by others;
  • Possible to respond on questions / feedback of others;
  • Chat-like experience
  • Separated information container from the webcast;
  • Authorization to be done 2x (Stream and Yammer), with risk of inconsistency / out-sync
  • Not every webcast visitor is an active Yammer user;
  • On authorizing account to the Yammer channel, one receives a notification email; while the context is totally unclear, and the Yammer channel should not even be open for submitting questions & feedback;
  • Questions and Feedback of others are visible to all;
  • Yammer channel remains afterwards, Need to remove all access to avoid unwanted visits after the webcast;
  • Not simple to capture / archive the questions & feedback
Via MS Forms + MS Flow + SharePoint Online List;
Forms embedded on page via MS Forms webpart
  • Existing / available IT building blocks within Office 365 suite;
  • Fully No-Code solution;
  • Access limited to the webcast authorized audience;
  • Included in same data container as webcast, sufficient to authorize once;
  • Access after live event can be removed via SharePoint permission handling;
  • No need for additional Yammer accounts / affinity;
  • Possible to add classification in the questions, eg from dropdown select a topic area. In the capture list, possible to group on the topics;
  • Easy to get a dump of the feedback, eg in Excel; and then decide whether to delete the list or simple make it inaccessible;
  • Modern look, responsive behavior
  • No live feed for webcast visitors on total of submitted questions / feedback;
  • Limited styling capability;
  • Placeholder per question is always “Enter your answer” / not possible to change that;
  • The usage experience after submit input is aimed at “survey scenario” (“your response was submitted”);
Variant of above:
Forms embedded on page via iframe construct
  • Same list as above;
  • and in addition it is possible to preserve the style heading and hide the message at bottom
  • Same list as above, with exception of message at bottom;
  • After submit input, out-of-context the submitter is confronted with ‘promotional’ message that one can create your own form / survey. The user cannot relate this message.
SharePoint List + default / classic NewForm
  • Existing / available IT building block;
  • Fully No-Code solution;
  • Embedded NewForm can be embedded without LeftNavigation + Header in ‘dialog-mode’ (put “&IsDlg=1” on URL);
  • Access limited to the webcast authorized audience;
  • Included in same data container as webcast, sufficient to authorize once;
  • Access after live event can be removed via SharePoint permission handling;
  • No need for additional Yammer accounts / affinity;
  • Possible to add classification in the questions, eg from dropdown select a topic area. In the capture list, possible to group on the topics;
  • Easy to get a dump of the feedback, eg in Excel; and then decide whether to delete the list or simple make it inaccessible;
  • UI-look not optimized for user-experience of ‘Questions & Feedback’ capability;
    • Toolbar in top, including actions not relevant in this context
    • Cancel button in bottom; also irrelevant in this context
  • Width of NewForm is that large that it requires 2-column page layout ( 2:1 layout results in horizontal scrollbar); which results that the available screen estate for webcast is reduced, and that in the layout the webcast UI is not allowed more significance above the Questions & Feedback UI;
  • Customization of the default NewForm needed to only show the multiline ‘Question’ input field;
  • After submit of a new item, the iframe loads the list view iso returning to (empty) NewForm;
SharePoint List + customized NewForm via PowerApps
  • Existing / available IT building blocks within Office 365 suite;
  • Low-code solution: only a bit of JavaScript needed for correct visual embedding in the landings page;
  • Access limited to the webcast authorized audience;
  • Included in same data container as webcast, sufficient to authorize once;
  • Access after live event can be removed via SharePoint permission handling;
  • No need for additional Yammer accounts / affinity;
  • Possible to add classification in the questions, eg from dropdown select a topic area. In the capture list, possible to group on the topics;
  • Easy to get a dump of the feedback, eg in Excel; and then decide whether to delete the list or simple make it inaccessible;
  • Modern look, responsive behavior;
  • The canvas of PowerApps is positioned at the layout of Phone App, and cannot be reduced in height, even when the App itself does not need that height. Scrollbars can be avoided however by reserving the needed height in screen layout, “wasting” screen estate. In this context acceptable, as no other controls are included on the page and positioned below the Question & Feedback. However, the increased page height does result in unnecessary browser scrollbar on the right;
  • Embedded part shows toolbar in top, and not a submit button below the question/feedback input;
  • Embedded NewForm default shows the label ‘New item’;
  • After submit of a new item, the iframe loads the list view iso returning to (empty) NewForm
All of above drawbacks can be prevented, via a bit of custom code
Custom UI / control + SharePoint List
  • Access limited to the webcast authorized audience;
  • Included in same data container as webcast, sufficient to authorize once;
  • Access after live event can be removed via SharePoint permission handling;
  • No need for additional Yammer accounts / affinity;
  • Possible to add classification in the questions, eg from dropdown select a topic area. In the capture list, possible to group on the topics;
  • Easy to get a dump of the feedback, eg in Excel; and then decide whether to delete the list or simple make it inaccessible;
  • Modern look, responsive behavior;
  • Custom coded solution: Requires custom development, testing and deployment;
  • Deployment as control requires some additional preparation on SharePoint site (Site Collection App Catalog)
Standalone PowerApps + SharePoint List
  • Existing / available IT building blocks within Office 365 suite;
  • Low-code solution: PowerApps itself + embedding in SharePoint page;
  • No need for additional Yammer accounts / affinity;
  • Possible to add classification in the questions, eg from dropdown select a topic area. In the capture list, possible to group on the topics;
  • Easy to get a dump of the feedback, eg in Excel; and then decide whether to delete the list or simple make it inaccessible;
  • Modern look, responsive behavior;
  • PowerApp also available for Mobile
  • Separated information container from the webcast;
  • Authorization to be done 2x (Stream and PowerApps);
  • Webcast Questions & Feedback App is available on tenant level, not limited within the boundary / scope of the associated webcast event;
  • Webcast Questions & Feedback App on Mobile is separate from Stream Mobile App, user would have to switch between Apps to submit question/feedback;
Azure Bot
  • Proactive + automated responses on recurring questions and reported issues;
  • Self-learning knowledge base
  • Considerable design + development effort
  • Bots experience no natural fit for submitting questions and feedback

Sunday, April 7, 2019

Options considered for extending Stream Live Events with live chat/questions capability

With the recent GA of Stream Live Events, Microsoft delivers a low-entry option to easily setup company-internal webcasts. All you need in addition are on the webcast producing side: 1) recording equipment - camera + audio, and 2) an encoder solution to transmit the recording inputs into the Live Events endpoint. The camera + audio options vary from the onboard webcam + microphone of a laptop, USB-based externals, upto high-end studio-quality equipment. For Stream Live Events handling the sophistication on the producing input side does not make a difference, the inputted RTMP(S) signal is from input endpoint processed the same. Whether an organization also needs some additionals on the consumption side depends on the audience side plus the internal network capacity. Watching a Live Event instantiates an individual / unicast stream per event viewer. Under assumption that the company network is sufficient scaled for nowaday cloud solutions usage, it is feasile to simultanuous watch a 'LIVE' Stream event per network location upto a maximum of few hundreds. In case of bigger audience, Microsoft states that it is needed to reduce the network load via a video distribution approach through a SDN/eSDN solution.
In its first released version, Stream Live Events capabilities are focussed on the core streaming + playing aspects. Business demands on a webcast typical go beyond that. The biggest additional demand is for interaction between the webcast audience and the presenter. Thus a chat window in which individual attendees can submit their questions, and that the presenter can follow + respond on. It is on the roadmap of Stream Live Events to deliver this (note: Stream recent delivered 'quizzes/ polls' capability, but this is targetted at inserting in already recorded videos for a.o. training purposes; not for dynamic interaction with live streaming), but not out-of-the-box delivered nowadays. However, with Office 365 as underlying platform you have as event developer a feature-rich toolbox at hand in which you can deliver yourself a webcast experience in which viewers have the live stream and chatbox combined, via no-code or low-code approaches. The hosting platform of such landingspage is naturally SharePoint Online....; as every created Stream Group is effectively an Office 365 Group, it has an own SharePoint Modern Team Site provisioned. The persons authorized to this site is the same audience that are permitted to join the scheduled Live Event. Create in this site a new page to function as the webcast entrance, and select the '2:1 columns' layout. In the left column embed the Stream Live Event instance - one gets this from Stream via 'Share' and then pick the 'Embed' option. With this setup, all left is to extend with chatbox / questions input control. There you have multiple options. One is to utilize the rich capabilities of Yammer, and embed a Yammer channel on the page. This gives you immediate a 'chat-like' experience, in which one can enter questions, semi-live follow the inputs / chats of others, respond on inputs of others. This immediate visibility of all the responses of ones peers may be unwanted, e.g. due potential sensitivity. In that case an alternative setup is to capture the inputs in a SharePoint list in the site, and only grant the webcast facilitators the authorization to view all received inputs. The webcast attendees submit their questions and feedback via an input form embedded on the SharePoint page. For this on sublevel again multiple alternatives are available. You can embed the out-of-the-box NewForm of the list; customize the NewForm via PowerApps; a MS Forms instance that via MS Flow sends the input to SharePoint List; or build a custom control via SPFx or even as a chatbot via Azure Bot Service. Of these options all except for the latter 2 are no/low-code 'mash-up' compositions, that deliver on the needed job. The decision-weighing between them is mostly on the user-experience and branding, see screen impressions of the various options.

Saturday, March 23, 2019

Beware: the omnipresent of Office 365 Groups complicates Information Architecture

Pre Office 365, setting up your information architecture was so much simpler (to understand)...

So your organization has implemented Office 365 as office productivity suite, which provides to you the richness in its various services / tools to employ. Say as a business department I need:
  • A place to store documents ➔ create in SharePoint Online a Modern Site
  • A place to work and chat together ➔ create a MS Teams instance
  • A place to plan work ➔ create a plan in MS Planner
  • A place to store and expose department videos ➔ create in MS Stream a Stream Group
  • A shared mailbox ➔ create via Outlook an Office 365 Group
However, one of the result of these 5 create actions in different Office 365 Services is that you do not have one (1) SharePoint site to your exposure, but actually five (5)!
And all of these 5 Modern Sites are created alike: same structure in the site, layout; all a standard provisioned Modern Site
And also in Azure AD the same multiplication effect is visible, noticable as an Azure AD Group (actually: Office 365 Groups):
Lesson: you need to think upfront on your Information Architecture, and then setup your utilization of the Office 365 services that it matches. Beware that this governance is hard to achieve, as all the creation in Office 365 is via self-service made so easy...

Thursday, March 14, 2019

Beware: User Information List (UIL) acts as memory for PeoplePicker when need to renew Azure AD B2B guest account for changed email

In Azure AD B2B, guest accounts are provisioned and redeemed with as their unique external account identifier, the own external email address of the invited guests. In rare situation that the external email changes, the guest account situation needs to be synchronized with this external identity change. However, as the email address is the primary identifier, it is not possible to change this as attribute in the existing Azure AD guest account. One needs to create in the Azure AD of the inviting company a new guest account based on the new / modified external email address, and potentially can also delete the no longer valid old guest account. On the SharePoint Online side, in each site collection in which the guest needs access, the access must also be repeated for the new guest account. Something to be aware of in such situation is the relationship between SharePoint PeoplePicker and the hidden User Information List (UIL) in site collection. The PeoplePicker uses UIL as one of its entrances to try to resolve user information for looked-up user name. As of SharePoint 2013, whenever an account on individual basis is granted access to a SharePoint site collection, immediate an entry for that account is administrated in the UIL (in SharePoint 2010 and before, the addition in UIL was delayed until first access by the authorized account). The effect in the use case where guest account is renewed by deleting from and creating new, is that the PeoplePicker default will still resolve to the user entry in UIL that was created there when earlier the guest was authorized on the previous guest account. Resulting in an inconsistent situation: the guest is assigned a new Azure AD guest account, the former might even be deleted in Azure AD, but in SharePoint Online via UIL as memory the previous account is selected by PeoplePicker upon granting access. Effect is that the guest can successful logon with the renewed guest account against the Azure AD of inviting company, but in the next step this authenticated guest account is not granted access in the SharePoint Online site: "You need permission to access this site". The way to resolve this is to go as Site Collection Administrator (SCA) into the UIL through <site-url>/_layouts/15/people.aspx?MembershipGroupId=0 , select the entry that refers to the previous guest account, and in the 'Actions' menu select "Delete users from Site Collection". After this corrective management action, the PeoplePicker on looking up the guest (by name or email) will no longer find the stale entry in the UIL, and create a new one that corresponds correct with the renewed guest account. And the invited Azure AD guest is enabled to successful access the site via modified email address as his/her 'bring-your-own-identity'.

Wednesday, March 13, 2019

Peculiarity with Azure AD B2B and Modern / Active Authentication for guest accounts

In the authentication model of Azure AD B2B, external guests are granted access on concept of 'bring-your-own-identity'. The general applied pattern in AAD B2B usage is to invite guests on their email address as the own identity. For invited guests from an organization that itself utilizes Azure AD for their cloud identity management, in AAD B2B the authentication flow delegates to the external Azure AD (see). This can result in a peculiarity, in which the invited guests after successful first authentication that is federated against the own external Azure AD, in the 2nd step cannot successful pass the MFA challenge via the Microsoft Authenticator App against the Azure AD of the inviting company. The situation arises where in the external Azure AD (of the invited organization) the UserPrincipalName (UPN) differs from the primary Office 365 email address, and the external access is via a client application that utilizes modern / active authentication. In such situation, the inviting company should invite the guest on basis of their Azure AD UPN, and not via their different Office 365 email / SMTP address. For client applications that apply passive authentication (aka: webapplications) it works fine to explicit logon with the own email as their Office 365 identity. But clients that utilize active authentication get into a conflict situation: the automated logon in active authentication flow against the external Azure AD is done on basis of the UPN, afterwards the authenticated account in the client application runtime context is equal to the UPN value of the logged-on guest. However, as the MFA enrollment is earlier done on basis of the email as guest identity, the result is an endless loop in the Authenticator App failing due mismatch in authenticated UPN logon and MFA-enrolled email.

Saturday, March 2, 2019

Execute 'Site information' (logo, privacy settings) on "Modern" team site requires to be Office 365 Group owner

Site information option in Modern team sites is the way to change the site logo and/or the privacy settings. This menu option + application popup dialog is available for accounts that are Site Collection Administrator (SCA). However, this is not enough. As "only" SCA I get the error "Problem uploading your picture. Please try again later." (see also uservoice on this: "Bug? Uploading team logo does not always work"). It appears that one needs to be an owner of the Office 365 Group that is connected to the Modern team site, then one can successfully change e.g. the site logo. Cause of this behavior is that "SharePoint Online team sites that are connected to an Office 365 group use the same logo as the Office 365 group to which they are connected. When you change the logo for your SharePoint group-connected team site, the logo for the corresponding Office 365 group will change also." (Manage your SharePoint site settings)

Sunday, February 10, 2019

'Check Permissions' displays 'Deny' for Azure AD B2B guest of domains that are not whitelisted

Individual authorized guests of non-whitelisted domains rightful denied access

SharePoint external sharing via Azure AD B2B adds an additional access-control layer. On top of the authorizations granted in the SharePoint site collection, you can explicitly control for guests whether their domain is allowed. Although I personally consider it a design flaw that business users can share their site with guests of non-whitelisted domains without warning that they are not actually allowed access, what eventually matters is that these invited guests will be blocked from accessing the site as long as it is not allowed on the higher authorisation-governance level of site collection sharing. The invited guests of non-whitelisted domains will get an Access Denied on trying to access the site for which they received a SharePoint invitation. Also when you as site owner check the permissions of such a guest, you will see both an allowed part for the authorizations granted via the site permissions, as well as a long list of 'Deny' due the lack of their guest domain within the list of whitelisted domains.
Domain of guest account not whitelisted in site collection sharing settings
Guest account can be invited to the site although its external domain not whitelisted
"Check Permissions" displays 'Deny'-permissions for guest accounts of non-whitelisted domain
"Check Permissions" displays for guest accounts of whitelisted domain only granted site-permissions
Noteworthy also is that the observed behavior is different depending on whether the guest invitation is redeemed or not. The above is for an invited Azure AD B2B guest account which has been activated already, and invited guest tries to access the SharePoint site. For non-redeemed guest account it is still possible to authorize to SharePoint site despite the domain not white-listed. But for non-redeemed, 'Check Permissions' displays "None", independent on whether the external domain is whitelisted.
Guest account can be invited to the site although its external domain not whitelisted

Saturday, February 2, 2019

Alternative to detach initial page loadtime from retrieving structural navigation

In the post 'Optimize for bad-performing navigation in SharePoint Online' I outlined an approach to release the initial pageload from the server-side execution time to retrieve the global site navigation. This approach serves its purpose to optimize the pageload time. However, it also comes with some aspects that complicate the usage. In particular in the perception of the site owner (maintainer): one thinks to configure the global navigation via "Site Settings \ Navigation", but next experience that it does not have immediate effect due the caching, nor is it complete in case one explicitly adds entries in the navigation that are not tied to the site structure itself. To address these drawbacks I designed + developed an alternative approach:
  1. Use webservice call /_api/navigation/menustate?mapprovidername='GlobalNavigationSwitchableProvider' to client-side request the navigation structure, exact as how it is configured by the site owner via "Site Settings \ Navigation'
  2. Cache the retrieved structure in the property bag available for all users
  3. Each time the Site Settings page is succesful loaded in browser, which implies it must be by someone with site maintenance authorization, redetermine via the webservice the global navigation structure, compare it with the one cached in property bag, and if changed replace the value in the property bag
Main advantage of this alternative compared to the 'search-driven' is that this restores for site owners the capability to manage the displayed global navigation via the out-of-the-box "Site Settings \ Navigation" configuration. And this includes the option to add specific entries also direct in that same configuration experience, no need to maintain a separate 'additional links' administration. Another advantage is that changes in the Navigation are now immediate applied, and for all users. No need to wait on client cache expiration. Which likely occurs on different moments for different visitors, and colleague X then can see a different menu from his/her colleague Y sitting on next desk. Also on code- and execution-level some improvements: the code is severly reduced + simplified, and there is no longer a dependency on Linq.js to runtime derive tree-model data structure from the flat web-nodes data structure determined via search.
Disadvantage is that the retrieved + cached global navigation is based on the authorizations of the person visiting the site settings page. In case some elements in the global navigation structure are restricted for other site visitors, they will now see those items in the global navigation. SharePoint authorization model prevents them from actually accessing the non-authorized content, however at the expense of a dissatisfying user experience: click on a menu item, and then get a 404 Access Denied. Therefore in case you have restrictive areas in the global navigation, then this approach might not be the one to use. A 2nd alternative is then to combine the 2: in essence, let each individual visitor request via the webservice the global navigation structure that (s)he is authorized to access, and cache this clientside for reuse on next visits. The drawback of this approach is that it suffers from risk of outdated navigation: if site owner makes changes to the navigation via "Site Settings \ Navigate", there is no trigger to enforce flush of all the individual site-visitors cached representations. But that can still be softened by putting a maximum on the cache duration, e.g. after 3 hours re-invoke the webservice to potential renew the navigation structure for you.

Sunday, January 20, 2019

Tip: how-to resolve in SharePoint 2016, XsltListViewWebPart displaying Calculated Fields as HTML-encoded

As of June 2017, Microsoft made a change to explicit block in XlstListViewWebPart the rendering of custom HTML markup in Calculated Fields: Handling HTML markup in SharePoint calculated fields: "Some users have added HTML markup or script elements to calculated fields. This is an undocumented use of the feature, and we will block the execution of custom markup in calculated fields in SharePoint Online from June 13, 2017 onwards. The June 2017 Public Update (PU) and later PUs will make blocking a configurable option for on-premises use in SharePoint Server 2016 and SharePoint Server 2013." In the article, Microsoft states that for SharePoint on-premises (2013 version and later) one can restore to the previous behavior through a new property on webapplication level: CustomMarkupInCalculatedFieldDisabled. For SharePoint Online there is no such configuration option provided.
A bit by coincidence (and also by mere perseverance 😉), I detected an alternative - undocumented - approach that does not require an overall webapplication setting. And as bonus, likely also works in SPO context. Default the XslLink property in XsltListViewWebPart XmlDefinition is configured via the View property: SPView.XslLink. The essence of the workaround / approach is to make use of the Xsl-behavior in the superclass of XsltListViewWebPart: DataFormWebPart. If you specify Xslt transformation at that level (either via XslLink, or via Xsl property), then you can configure for single XsltListViewWebPart instance that custom HTML markup of Calculated Field is still executed.
Although undocumented, it is an own Microsoft source that helped me discovering this => the SharePoint Escalation Service Team Blog - Guidance for XslLink property with the XsltListViewWebPart: "There exist other alternatives to let the XsltListViewWebPart use your XSL Transform. "
Note also that when you used 'Design' mode in SharePoint Designer 2010 to customize the Xslt-rendering of a list column, the customized Xslt-template is also injected in the Xsl property on webpart level.
My findings clarified through pictures:

At first the issue: custom HTML markup of Calculated Field is rendered as html-encoded

Move in the XMLDefinition the location of XslLink from 'View' to 'WebPart' level

And the rendering of custom HTML markup is restored, as we know it from before

Thing to be aware of: with using the 'XslLink' property it is a prerequisite that the applied Xslt stylesheet file is located in the layouts folder (see: Guidance for XslLink property with the XsltListViewWebPart: "however you would need to place your XSL file in the default “_layouts/xsl” folder"). In the above scenario that is guaranteed as I simply refer to the standard 'main.xsl' stylesheet that is by Microsoft itself provisioned in the layouts folder, both on-premises as online. If however you need a deviation from the standard XsltListViewWebPart rendering, then you need to provision your own custom Xsl stylesheet thus also in the layouts folder. Which in SharePoint Online context is of course not possible. If the deviation is only minimal, e.g. to override the standard rendering for only one column, then I advise to make use of the 'Xsl' property instead, and only include in it the overloading 'xsl:template'.
Example applied to scenario of above
<xsl>
   <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" 
      xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" 
      version="1.0" 
      exclude-result-prefixes="xsl msxsl ddwrt" 
      xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" 
      xmlns:asp="http://schemas.microsoft.com/ASPNET/20" 
      xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
      xmlns:SharePoint="Microsoft.SharePoint.WebControls" 
      xmlns:ddwrt2="urn:frontpage:internal" 
      xmlns:o="urn:schemas-microsoft-com:office:office">
         <xsl:include href="/_layouts/15/xsl/main.xsl"/>
         <xsl:include href="/_layouts/15/xsl/internal.xsl"/>
         <xsl:param name="AllRows" select="/dsQueryResponse/Rows/Row[$EntityName = '' or (position() >= $FirstRow and position() <= $LastRow)]"/>
         <xsl:param name="dvt_apos">'</xsl:param>                                                      
         <xsl:template match="FieldRef[@Name='Folder']" mode="Number_body">
            <xsl:param name="thisNode" select="."/>
            <b><i>
            <xsl:value-of disable-output-escaping="yes" select="$thisNode/@*[name()=current()/@Name]" />
            </i></b>
         </xsl:template>
   </xsl:stylesheet>
</xsl>

Saturday, January 19, 2019

Tip: how-to easily expose the underlying XML datastructure retrieved in XsltListViewWebPart

If for what ever reason you want to inspect the XML structure or content of underlying data source retrieved from a SharePoint List/Library before it is rendered via Xslt-transformation, you can do that as follows:
  • Open SharePoint Designer 2013 (or 2010 version in case you need it in older SharePoint 2010 context)
  • Open the page on which the XsltListViewWebPart is included (list View, SitePage)
  • Select to edit the page in raw HTML mode, and locate the 'XsltListViewWebPart' node in the HTML
  • Inject the below Xslt-snippet as value for 'Xsl' property of the XsltListViewWebPart definition:
    <xsl>
       <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" 
          xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" 
          version="1.0" 
          exclude-result-prefixes="xsl msxsl ddwrt" 
          xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" 
          xmlns:asp="http://schemas.microsoft.com/ASPNET/20" 
          xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" 
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
          xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
          xmlns:SharePoint="Microsoft.SharePoint.WebControls" 
          xmlns:ddwrt2="urn:frontpage:internal" 
          xmlns:o="urn:schemas-microsoft-com:office:office">
             <xsl:output method="xml" indent="yes" />
             <xsl:template match="/">
                <xmp>
                  <xsl:copy-of select="*"/>
                </xmp>
             </xsl:template>
       </xsl:stylesheet>
    </xsl>
    
  • Save the page in SharePoint Designer
  • Open or refresh the page in browser; if the underlying XML not immediate displayed (XsltListViewWebPart applies caching in it's Xslt pipeline), reload once more
  • And you are able to inspect in browser the underlying XML data island structure retrieved by the query applied in the XsltListViewWebPart instance: