In the previous post
we have seen how we are able to activate a Progressive Web App on Windows 10 from a toast notification. However, the sample used in the post had a limitation compared to a real world scenario: the notification was generated by the app itself, as a consequence of the user pressing a button. In a real application, this is hardly the case. Notifications can be received at anytime, even when the application isn’t running. This is the reason why the mobile world has embraced since a long time the push notification concept, which is a way to engage with the user and at the same time respect the battery and the performances of the device. Before push notifications, most of the notifications scenarios were implemented with a polling approach. The client (in our case, the application) keeps checking with the server if there’s nothing new and, if that’s the case, displays a notification to the user.
Push notifications, instead, work the other way around. The server establishes a channel with the client and, whenever there’s something to notify, it sends a signal to the client, which processes it. This channel is always alive, even when the application is not running. Push notifications are the best technology when the event that triggers the notification doesn’t happen locally, but in a remote environment. Let’s take, as example, the news PWA we’ve built in the previous post. Let’s image that it’s a companion app for a news website, which has a backend that offers a text editing interface to add a news. In this scenario it’s me, the news writer, who is aware that I’m about to add an important news in the backend, not the application. As such, I would imagine to see a checkbox labelled “This is a breaking news” in the editing page. When I flag it and I post the news, automatically every registered device will receive a push notification.
Let’s see how we can extended the previous sample to add this specific behavior. At startup, the PWA will register itself to receive push notifications. Then we’re going to build a simple backend (in this case, it will be made by a Windows Forms app) which is capable to send push notifications to our app. Let’s start!
Web notifications vs Windows notifications
W3C has defined a standard Web API to handle push notifications, which is supported by all the major browsers. The Edge team has published a great tutorial on this on their samples website:
https://webpushdemo.azurewebsites.net/
This implementation is cross-platform from a client point of view, meaning that the same code will work regardless of the browser. However, it’s not the same for the server side implementation. The URL where to send the notification, in fact, will change based on the browser which is rendering the PWA.
However, since we’re running on Windows, we have also the opportunity to leverage the native Windows APIs to support push notifications. The client side code won’t be cross-platform anymore, but we will gain much more power and flexibility, since we can support
the rich adaptive toast notification model
introduced with Windows 10. This means the opportunity to send notifications with hero images, interactive elements like buttons or text boxes, etc. In this post we’re going to see how to implement this kind of notifications in our web application.
Push notifications overview
From a high level overview, push notifications work in the same way regardless of the platform and it involves three actors:
A cloud service provided by the owner of the platform, which acts as a middle man between the client and the server
A client, which connects to the cloud service and establish a communication channel
A server, which sends notifications to the clients passing through the cloud service
The difference, based on the platform, is the way you communicate with the cloud service. In case of Windows, the service is called WNS (Windows Notification Service). Whenever a client registers with the WNS, it gets assigned a unique channel which is represented by a URI. Whenever the backend wants to send a notification to that device, it must compose a XML payload (which is different based on the notification type you want to send) and push it using a HTTP POST command against the assigned URI.
As you can see, the advantage of this approach is that it doesn’t rely on any proprietary SDK or API, but on standard protocols and languages like XML and HTTP. As such, you will be able to integrate push notifications no matter which is the technology you have used to build the backend of your project.
The server side
As first step, we need to implement the backend which is going to send the push notification to our web application. As I’ve described before, in a real world scenario you’ll probably have a web application, an Azure function or any other kind of trigger that sends it. In our case, since we’re building just a sample, we’re going to create a Windows Forms application. The application will allow to specify some information about the notification (like title and text) and the URL of the device. After pressing a button, the application will send the notification payload to the WNS using the assigned URL, which will take care of routing the notification to the correct device.
As an overview, interacting with the WNS requires two steps:
First you need to authenticate against WNS, using a set of credentials that the Store assigns to your application when you register it on the Dev Center.
After you have successfully authenticated, you will receive a token that you will need to append to every request to the WNS. Without this token, the request will be rejected.
The process isn’t very complex, but it requires lot of work:
You need to manually build the HTTP request to authenticate and store the returned token.
You need to manually build the HTTP request to send the notification. It’s enough to specify the wrong content type or the wrong header to see the request failing, so you have to be very careful in following the documentation.
You need to build a retry mechanism, in case the authentication token is expired and you need a new one.
To make things simpler please welcome
PushSharp
, an open source library built by a member of the Xamarin team which makes the server side implementation of push notifications much easier. Instead of manually building all the required HTTP requests, you’re going to use a set of high level #C APIs which will make all the hard work for you under the hood. In this post we’re going to see the specific Windows implementation, but PushSharp is a cross-platform library. This means that you can send push notifications from any C# based backend to iOS, Android and Windows devices.
Before writing some code, however, we need to register our PWA on the Dev Center, in order to get the credentials to authenticate against WNS. This step is required, otherwise a malicious developer would be able to send push notifications to our customers just by spoofing the channel URI. I’m assuming that you already have a Dev Center account, so you can just go to
https://dev.windows.com
, login and reserve a new name for the application you want to publish (in case you don’t have it already). Once you have done it, you will have access to the full dashboard for your app.
Click on the WNS/MPSN option and then click on the
Live Services Site
link that you will find in the page under the WNS section:
After clicking on it, you will be redirected to a page that will contain all the registration information of your application against the Microsoft services. The information we need to retrieve for our purposes are:
The secret, under
Application Secrets
The
Package SID
, under
Windows Store
The Package Family Name, which can be extracted from the
Name
attribute of the
Identity
tag in the
Application Identity
section
Note them down because we’re going to need them later.
Now let’s build the server app. I’m taking, as code base, the same solution I’ve built
for the previous post
and that you can find on GitHub at
https://github.com/Microsoft/Windows-AppConsult-samples-PWA/tree/master/ToastActivation.
As already shared, I’m going to build a Windows Forms project but it could be a WPF app or an ASP.NET Core website. The PushSharp library, in fact, works across any C# based framework, including .NET Core. This is the simple user interface I’ve built:
The first field will be used to specify the title of the notification
The second field will be used to specify the text of the notification
The third field will be used to specify the ID of the news (so that we can redirect the user to correct detail page)
The fourth field will be used to specify the channel URI of the device where we want to send the notification
Now let’s move to the code and, as first thing, let’s right click on the project, choose
Manage NuGet packages
and install the
PushSharp.Core
package:
Now let’s open the code behind of the main form of our application and let’s add the following namespace to the header of the class:
using PushSharp.Windows;
Do you remember the information we have previously noted about our application from the Dev Center? Now it’s time to use them! Let’s create a variable inside our class, one for each information:
string secret = ""; // need to replace this with your own secret
string sid = ""; // need to replace this with your own sid
string package = "29949MatteoPagani.ExpenseIt-Test" // need to replace this with your package family name;
Of course, fill the empty values with the correct information you have retrieved from the Dev Center.
Now we can start implementing the method that actually sends the push notification to our web app. Let’s see the whole code and then let’s comment it piece by piece:
public void SendNotification(string uri, string title, string text, string newsId)
{
var config = new WnsConfiguration(package, sid, secret);
var wnsBroker = new WnsServiceBroker(config);
// See what kind of exception it was to further diagnose
if (ex is WnsNotificationException)
{
var notificationException = (WnsNotificationException)ex;
Debug.WriteLine($"WNS Notification Failed: {notificationException.Message}");
}
else
{
Debug.WriteLine("WNS Notification Failed for some (Unknown Reason)");
}
The method accepts 4 parameters in input, which are the ones retrieved from the various text boxes in the user interface. The first step is to build a
WnsConfiguration
object, which require the authentication information we have previously stored. Then we can create a
WnsBroker
object, passing the configuration as parameter. It’s the object that we’re going to use to communicate with the WNS.
The next lines of code aren’t strictly required, but they can be really helpful for debugging or logging purposes. We subscribe to the:
OnNotificationFailed
event, which is triggered when one or more of the notifications we have sent can’t be delivered. From the
Message
property of the notification we can understand which is the issue, so we print it in the output window of Visual Studio.
OnNotificationSucceded
event, which is triggered instead one one or more of the notifications we have sent has been successfully queued by the WNS.
Then we can write the real code to send the notification. First we start the broker by calling the
Start()
method. Then we prepare the content of the notification, in this case by using a
WnsToastNotification
object since we want to send a toast notification. We build the object by specifying the
ChannelUri
property (the URI of the channel where to send the notification) and the
Payload
property (the XML that represents the notification). In this case, the payload is the same we have seen in the previous post and it’s the standard one for a generic toast notification. The difference is that we populate the
launch
attribute and the two
text
nodes using the information specified by the user in the UI.
Then we queue the notification by passing the object we have just created to the
QueueNotification
() method and we stop the broker by calling the
Stop()
method.
In a real world scenario the code would be pretty much the same, except that the
QueueNotification()
method might be called multiple times, based on the scenario we need to implement. For example, if it’s a messaging app, probably we will call it just once because we need to notify only the sender that there’s a new message. In case of a news app, instead, we will likely call it for each device that we have registered in our system, which represents every user that has subscribed to receive breaking news.
That’s all! As you can see, the
PushSharp library makes the overall operation much easier. You can notice how, for example, we didn’t need to take care of making two separate HTTP calls, one for the authentication and one for sending the actual notification. The library performs automatically the authentication request under the hood and takes care, if the token is expired, to refresh it.
Now we can move to the client code: our Progressive Web App!
The Progressive Web App
We won’t start from scratch, but we’re going to add push notifications support to the PWA we’ve built
in the previous post
, which is included
in the sample on GitHub
and which is made by two components:
The
ToastWebsite
project, which is the real web application. It’s an ASP.NET Core 2.0 website which I’ve deployed to an Azure Web App.
The
App
project, which is a Hosted Web App project that, in the manifest, just points to the URL where I’ve deployed the web application. Thanks to this project, I’m able to run my website like if it’s a native application.
Since the second project is just a wrapper for the website, we’re going to write all the actual code in the first project. Let’s move to
Pages –> Index.cshtml
, which is the main page of the website. It’s the page where, in the last post, we have added some code to:
Display a toast notification when the user presses a button
Register for the
activated
event, so that when the user clicks on the notification we can intercept it and redirect him to the appropriate landing page
We’re going to add some new code, specifically a couple of new functions and a property:
<script type="text/javascript">
var channel;
if (typeof Windows !== 'undefined' &&
typeof Windows.UI !== 'undefined' &&
typeof Windows.UI.Notifications !== 'undefined') {
function registerPush() {
var channelOperation = Windows.Networking.PushNotifications.PushNotificationChannelManager.createPushNotificationChannelForApplicationAsync();
var rval = channelOperation.then(function (newChannel) {
channel = newChannel;
channel.addEventListener("pushnotificationreceived", onPushNotification, false);
console.log('Channel: ' + channel.uri);
document.getElementById('channelUri').innerHTML = channel.uri;
},
function (error) {
console.log('Error: ' + error);
}
);
First, let’s remember that we need to wrap the new functions inside a
if (typeof Windows)
statement. We need to leverage this code only if the application is running as a PWA on Windows 10, because we’re going to use some specific WinRT APIs exposed by the Universal Windows Platform. As such, the previous code would generate an exception if the web app is executed inside a browser or on another platform.
Inside the
registerPush()
function we use the APIs included in the
Windows.Networking.PushNotifications
namespace to create a new channel URI. Specifically, we use the
createPushNotificationChannelForApplicationAsync()
method exposed by the
PushNotificationChannelManager
class. If the operation is successful, it means that the WNS has created a new channel for us. If that’s the case, we can use the promises approach to define a function that is invoked when the creation of the channel is completed. All the information about it are stored inside a parameter of the function. The most interesting one, for us, is inside the
uri
property. It’s the full URI that our backend will need to use to send us a push notification. In a real world scenario, at this point we would need to send the URI to the backend, for example by invoking a REST API exposed by our server. The REST API will take care of storing the URI inside a database, so that we can retrieve it at a later stage when needed.
In our sample, to make things easier, we just display it in the HTML page, inside a
div
control I’ve placed. It will be up to us to copy the URL and paste it inside the user interface of the Windows Forms application we have built.
Please notice another important piece of our code: we register to an event exposed by the channel we have just created called
pushnotificationreceived
, which is invoked every time we receive a push notification and the app is currently running. Inside this event we have access to an object which exposes a
cancel
property, which is a boolean. By setting it to
true
, we are telling to Windows that we want to take care of the notification and that it should ignore it. The final result is that the user won’t see the toast notification appearing in the bottom right corner of the screen and then being stored in the Action Center. Subscribing to this event isn’t a requirement, but it can be useful in some scenarios to provide a better user experience. For example, if you’re building a messaging app and the user receives a message on the chat he’s already looking at, you can decide to not display any notification and just add the message to the history. In our case, we’re using this event to block the toast notification and display a message to the user directly in the page.
As last step, let’s just add in our page a button connected to this new function we have just created, plus a couple of div elements to display the output to the user:
Now we can test if the code we have written works. However, before doing that, there’s an important step to make. At the beginning of the post we have registered a new application on the Dev Center in order to get the credentials needed to authenticate with WNS. However, we have never linked this application to our PWA. We can do it by right clicking on our UWP project (the
App
one which, in the previous post, we have created using
PWA Builder
) and choosing
Store –> Associate App with the Store
. You will be able to login with your developer account and choose, from the list, the same name you have reserved in the beginning. This way the manifest will be automatically filled with the correct identity.
Now we can move on with the testing. First, we need to publish the changes we have made to our website on our web server. In my case, I’m using again an Azure Web App, but this time I’ve published it on another URI, which is
https://toastwebsitewithpush.azurewebsites.net/
If you want to do the same, remember to follow
the guidance of the previous post
and make sure to set, in the
Application
and
Content URIs
sections of the manifest, the new URI.
Deploy the
App
project on your machine and launch the PWA. Remember that you can’t test this code directly from the browser, since you don’t have access to the WinRT APIs we’re using to create a push notification channel. Click on the
Register for push notifications
button and, if everything goes well, you should see a long URI appearing below:
Now, from Visual Studio, launch the Windows Forms app we’ve built and fill the Title, Text and News Id fields with some values. Make sure, in the URL field, to paste the URI that you are seeing in the main page of your PWA.
Now press the
Send Push
button. If everything goes well, after a while you should see the message
Notification received
in the main page of your PWA.
If you remember the code we have written, this is happening because we have subscribed to the
pushnotificationreceived
event and we are telling to Windows that we want to handle it. As a consequence, the user is seeing just the message on the page, but he’s not seeing any toast notification popping up.
Now close the PWA and, in the Windows Forms app, press again the
Send Push button.
This time the notification is popping up in Windows. The application, in fact, is not running, so the
pushnotificationreceived
event can’t be raised.
Enhancing your PWA with tile notifications
The advantage of using a WNS infrastructure for sending push notifications is that you can leverage it to further enhance your PWA, by adding for example live tiles support. The same exact technique we’ve seen so far, in fact, can be used also to update the tile of your application and make it more engaging. From the backend, you just need to send a different payload,
based on the adaptive tile schema
. Additionally, toast and tile notifications can be sent together at the same time, so that the user will receive both updates at the same time. Here is, for example, how I changed the last part of the code of the Windows Forms app to achieve this goal:
As you can see, the code is the same. The only differences are the payload and the usage of another class, called
WnsTileNotification
, to setup the tile notification. At the end, I use the broker to queue it together with the toast notification I’ve previously created.
As outcome, other then seeing the toast notification or the message in the app (depending if it’s running or not), you’ll see the tile on the Start menu being updated. Of course, to see it, you will need first to right click on the icon in your Start menu and choose
Pin to start
.
Wrapping up
In this post we’ve seen how to further expand the previous sample, by adding support for real push notifications in our PWA. You have the option to implement web notifications, which are more limited but they work cross-platform and also inside the browser, or native Windows notifications, which offers more power and flexibility. We’ve also seen how to implement a simple backend environment and how we can use it not just to send standard push notifications, but also to light up other Windows features like live tiles.
"}},"componentScriptGroups({\"componentId\":\"custom.widget.MicrosoftFooter\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/ranks/UserRankLabel\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"components/tags/TagView/TagViewChip\"]})":[{"__ref":"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserRegistrationDate\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserRegistrationDate-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeAvatar-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeDescription\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeDescription-1745505307000"}],"cachedText({\"lastModified\":\"1745505307000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1745505307000"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Deleted","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"MMM dd yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US","es-ES"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1747046962822":{"__typename":"CachedAsset","id":"pages-1747046962822","value":[{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"UserBlogPermissions.Page","type":"COMMUNITY","urlPath":"/c/user-blog-permissions/page","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"AllEvents","type":"CUSTOM","urlPath":"/Events","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"CommunityHub.Page","type":"CUSTOM","urlPath":"/Directory","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"AllBlogs.Page","type":"CUSTOM","urlPath":"/blogs","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1747046962822,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/cmstNC05WEo0blc\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/cmstNC05WEo0blc","height":512,"width":512,"mimeType":"image/png"},"Rank:rank:4":{"__typename":"Rank","id":"rank:4","position":6,"name":"Microsoft","color":"333333","icon":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/cmstNC05WEo0blc\"}"},"rankStyle":"OUTLINE"},"User:user:44595":{"__typename":"User","id":"user:44595","uid":44595,"login":"Matteo Pagani","deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS00NDU5NS02MzA4OGkwNTU0MkU2NzQwODM2NTE0"},"rank":{"__ref":"Rank:rank:4"},"email":"","messagesCount":117,"biography":null,"topicsCount":39,"kudosReceivedCount":132,"kudosGivenCount":1,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":null,"registrationTime":"2017-03-19T04:38:14.936-07:00","confirmEmailStatus":null},"followersCount":null,"solutionsCount":1},"Category:category:microsoft365":{"__typename":"Category","id":"category:microsoft365","entityType":"CATEGORY","displayId":"microsoft365","nodeType":"category","depth":3,"title":"Microsoft 365","shortTitle":"Microsoft 365","parent":{"__ref":"Category:category:products-services"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","entityType":"CATEGORY","displayId":"top","nodeType":"category","depth":0,"title":"Top","shortTitle":"Top"},"Category:category:communities":{"__typename":"Category","id":"category:communities","entityType":"CATEGORY","displayId":"communities","nodeType":"category","depth":1,"parent":{"__ref":"Category:category:top"},"title":"Communities","shortTitle":"Communities"},"Category:category:products-services":{"__typename":"Category","id":"category:products-services","entityType":"CATEGORY","displayId":"products-services","nodeType":"category","depth":2,"parent":{"__ref":"Category:category:communities"},"title":"Products","shortTitle":"Products"},"Blog:board:ModernWorkAppConsult":{"__typename":"Blog","id":"board:ModernWorkAppConsult","entityType":"BLOG","displayId":"ModernWorkAppConsult","nodeType":"board","depth":4,"conversationStyle":"BLOG","repliesProperties":{"__typename":"RepliesProperties","sortOrder":"REVERSE_PUBLISH_TIME","repliesFormat":"threaded"},"tagProperties":{"__typename":"TagNodeProperties","tagsEnabled":{"__typename":"PolicyResult","failureReason":null}},"requireTags":true,"tagType":"PRESET_ONLY","description":"","title":"Modern Work App Consult Blog","shortTitle":"Modern Work App Consult Blog","parent":{"__ref":"Category:category:microsoft365"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:gxcuf89792"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:communities"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:products-services"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:microsoft365"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"theme":{"__ref":"Theme:customTheme1"},"boardPolicies":{"__typename":"BoardPolicies","canViewSpamDashBoard":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.access_spam_quarantine.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.access_spam_quarantine.allowed.accessDenied","args":[]}},"canArchiveMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.content_archivals.enable_content_archival_settings.accessDenied","key":"error.lithium.policies.content_archivals.enable_content_archival_settings.accessDenied","args":[]}},"canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}}}},"BlogTopicMessage:message:317283":{"__typename":"BlogTopicMessage","uid":317283,"subject":"Push notifications in a PWA running on Windows 10","id":"message:317283","revisionNum":4,"repliesCount":0,"author":{"__ref":"User:user:44595"},"depth":0,"hasGivenKudo":false,"board":{"__ref":"Blog:board:ModernWorkAppConsult"},"conversation":{"__ref":"Conversation:conversation:317283"},"messagePolicies":{"__typename":"MessagePolicies","canPublishArticleOnEdit":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","args":[]}},"canModerateSpamMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","args":[]}}},"contentWorkflow":{"__typename":"ContentWorkflow","state":"PUBLISH","scheduledPublishTime":null,"scheduledTimezone":null,"userContext":{"__typename":"MessageWorkflowContext","canSubmitForReview":null,"canEdit":false,"canRecall":null,"canSubmitForPublication":null,"canReturnToAuthor":null,"canPublish":null,"canReturnToReview":null,"canSchedule":false},"shortScheduledTimezone":null},"readOnly":false,"editFrozen":false,"moderationData":{"__ref":"ModerationData:moderation_data:317283"},"teaser":"First published on MSDN on Jun 07, 2018 In the previous post we have seen how we are able to activate a Progressive Web App on Windows 10 from a toast notification.","body":"\n \n \n First published on MSDN on Jun 07, 2018\n \n \n
\n \n In the previous post\n \n we have seen how we are able to activate a Progressive Web App on Windows 10 from a toast notification. However, the sample used in the post had a limitation compared to a real world scenario: the notification was generated by the app itself, as a consequence of the user pressing a button. In a real application, this is hardly the case. Notifications can be received at anytime, even when the application isn’t running. This is the reason why the mobile world has embraced since a long time the push notification concept, which is a way to engage with the user and at the same time respect the battery and the performances of the device. Before push notifications, most of the notifications scenarios were implemented with a polling approach. The client (in our case, the application) keeps checking with the server if there’s nothing new and, if that’s the case, displays a notification to the user.\n
\n
\n Push notifications, instead, work the other way around. The server establishes a channel with the client and, whenever there’s something to notify, it sends a signal to the client, which processes it. This channel is always alive, even when the application is not running. Push notifications are the best technology when the event that triggers the notification doesn’t happen locally, but in a remote environment. Let’s take, as example, the news PWA we’ve built in the previous post. Let’s image that it’s a companion app for a news website, which has a backend that offers a text editing interface to add a news. In this scenario it’s me, the news writer, who is aware that I’m about to add an important news in the backend, not the application. As such, I would imagine to see a checkbox labelled “This is a breaking news” in the editing page. When I flag it and I post the news, automatically every registered device will receive a push notification.\n
\n
\n Let’s see how we can extended the previous sample to add this specific behavior. At startup, the PWA will register itself to receive push notifications. Then we’re going to build a simple backend (in this case, it will be made by a Windows Forms app) which is capable to send push notifications to our app. Let’s start!\n
\n
\n Web notifications vs Windows notifications\n
\n
\n W3C has defined a standard Web API to handle push notifications, which is supported by all the major browsers. The Edge team has published a great tutorial on this on their samples website:\n \n https://webpushdemo.azurewebsites.net/\n \n This implementation is cross-platform from a client point of view, meaning that the same code will work regardless of the browser. However, it’s not the same for the server side implementation. The URL where to send the notification, in fact, will change based on the browser which is rendering the PWA.\n
\n
\n However, since we’re running on Windows, we have also the opportunity to leverage the native Windows APIs to support push notifications. The client side code won’t be cross-platform anymore, but we will gain much more power and flexibility, since we can support\n \n the rich adaptive toast notification model\n \n introduced with Windows 10. This means the opportunity to send notifications with hero images, interactive elements like buttons or text boxes, etc. In this post we’re going to see how to implement this kind of notifications in our web application.\n
\n
\n Push notifications overview\n
\n
\n From a high level overview, push notifications work in the same way regardless of the platform and it involves three actors:\n
\n \n
\n A cloud service provided by the owner of the platform, which acts as a middle man between the client and the server\n
\n
\n A client, which connects to the cloud service and establish a communication channel\n
\n
\n A server, which sends notifications to the clients passing through the cloud service\n
\n \n
\n \n
\n
\n The difference, based on the platform, is the way you communicate with the cloud service. In case of Windows, the service is called WNS (Windows Notification Service). Whenever a client registers with the WNS, it gets assigned a unique channel which is represented by a URI. Whenever the backend wants to send a notification to that device, it must compose a XML payload (which is different based on the notification type you want to send) and push it using a HTTP POST command against the assigned URI.\n
\n
\n As you can see, the advantage of this approach is that it doesn’t rely on any proprietary SDK or API, but on standard protocols and languages like XML and HTTP. As such, you will be able to integrate push notifications no matter which is the technology you have used to build the backend of your project.\n
\n
\n The server side\n
\n
\n As first step, we need to implement the backend which is going to send the push notification to our web application. As I’ve described before, in a real world scenario you’ll probably have a web application, an Azure function or any other kind of trigger that sends it. In our case, since we’re building just a sample, we’re going to create a Windows Forms application. The application will allow to specify some information about the notification (like title and text) and the URL of the device. After pressing a button, the application will send the notification payload to the WNS using the assigned URL, which will take care of routing the notification to the correct device.\n
\n
\n As an overview, interacting with the WNS requires two steps:\n
\n \n
\n First you need to authenticate against WNS, using a set of credentials that the Store assigns to your application when you register it on the Dev Center.\n
\n
\n After you have successfully authenticated, you will receive a token that you will need to append to every request to the WNS. Without this token, the request will be rejected.\n
\n \n
\n The process isn’t very complex, but it requires lot of work:\n
\n \n
\n You need to manually build the HTTP request to authenticate and store the returned token.\n
\n
\n You need to manually build the HTTP request to send the notification. It’s enough to specify the wrong content type or the wrong header to see the request failing, so you have to be very careful in following the documentation.\n
\n
\n You need to build a retry mechanism, in case the authentication token is expired and you need a new one.\n
\n \n
\n To make things simpler please welcome\n \n PushSharp\n \n , an open source library built by a member of the Xamarin team which makes the server side implementation of push notifications much easier. Instead of manually building all the required HTTP requests, you’re going to use a set of high level #C APIs which will make all the hard work for you under the hood. In this post we’re going to see the specific Windows implementation, but PushSharp is a cross-platform library. This means that you can send push notifications from any C# based backend to iOS, Android and Windows devices.\n
\n
\n Before writing some code, however, we need to register our PWA on the Dev Center, in order to get the credentials to authenticate against WNS. This step is required, otherwise a malicious developer would be able to send push notifications to our customers just by spoofing the channel URI. I’m assuming that you already have a Dev Center account, so you can just go to\n \n https://dev.windows.com\n \n , login and reserve a new name for the application you want to publish (in case you don’t have it already). Once you have done it, you will have access to the full dashboard for your app.\n
\n
\n \n
\n
\n Click on the WNS/MPSN option and then click on the\n \n Live Services Site\n \n link that you will find in the page under the WNS section:\n
\n
\n \n
\n
\n After clicking on it, you will be redirected to a page that will contain all the registration information of your application against the Microsoft services. The information we need to retrieve for our purposes are:\n
\n The Package Family Name, which can be extracted from the\n \n Name\n \n attribute of the\n \n Identity\n \n tag in the\n \n Application Identity\n \n section\n \n \n \n
\n \n
\n Note them down because we’re going to need them later.\n
\n
\n Now let’s build the server app. I’m taking, as code base, the same solution I’ve built\n \n for the previous post\n \n and that you can find on GitHub at\n \n https://github.com/Microsoft/Windows-AppConsult-samples-PWA/tree/master/ToastActivation.\n \n As already shared, I’m going to build a Windows Forms project but it could be a WPF app or an ASP.NET Core website. The PushSharp library, in fact, works across any C# based framework, including .NET Core. This is the simple user interface I’ve built:\n
\n
\n \n
\n
\n
\n The first field will be used to specify the title of the notification\n
\n
\n The second field will be used to specify the text of the notification\n
\n
\n The third field will be used to specify the ID of the news (so that we can redirect the user to correct detail page)\n
\n
\n The fourth field will be used to specify the channel URI of the device where we want to send the notification\n
\n
\n
\n Now let’s move to the code and, as first thing, let’s right click on the project, choose\n \n Manage NuGet packages\n \n and install the\n \n PushSharp.Core\n \n package:\n
\n
\n \n
\n
\n Now let’s open the code behind of the main form of our application and let’s add the following namespace to the header of the class:\n
\n using PushSharp.Windows;\n \n
\n Do you remember the information we have previously noted about our application from the Dev Center? Now it’s time to use them! Let’s create a variable inside our class, one for each information:\n
\n string secret = \"\"; // need to replace this with your own secret\n \n string sid = \"\"; // need to replace this with your own sid\n \n string package = \"29949MatteoPagani.ExpenseIt-Test\" // need to replace this with your package family name;\n \n
\n Of course, fill the empty values with the correct information you have retrieved from the Dev Center.\n
\n
\n Now we can start implementing the method that actually sends the push notification to our web app. Let’s see the whole code and then let’s comment it piece by piece:\n
\n public void SendNotification(string uri, string title, string text, string newsId)\n \n {\n \n var config = new WnsConfiguration(package, sid, secret);\n \n var wnsBroker = new WnsServiceBroker(config);\n \n \n wnsBroker.OnNotificationFailed += (notification, aggregateEx) => {\n \n \n aggregateEx.Handle(ex => {\n \n \n // See what kind of exception it was to further diagnose\n \n if (ex is WnsNotificationException)\n \n {\n \n var notificationException = (WnsNotificationException)ex;\n \n Debug.WriteLine($\"WNS Notification Failed: {notificationException.Message}\");\n \n }\n \n else\n \n {\n \n Debug.WriteLine(\"WNS Notification Failed for some (Unknown Reason)\");\n \n }\n \n \n // Mark it as handled\n \n return true;\n \n });\n \n };\n \n \n wnsBroker.OnNotificationSucceeded += (notification) => {\n \n Debug.WriteLine(\"WNS Notification Sent!\");\n \n };\n \n \n // Start the broker\n \n wnsBroker.Start();\n \n string payload = $\"<toast launch=\\\"{newsId}\\\"><visual><binding template=\\\"ToastGeneric\\\"><text>{title}</text><text>{text}</text></binding></visual></toast>\";\n \n \n WnsToastNotification toastNotification = new WnsToastNotification\n \n {\n \n ChannelUri = uri,\n \n Payload = XElement.Parse(payload)\n \n };\n \n \n wnsBroker.QueueNotification(toastNotification);\n \n wnsBroker.Stop();\n \n }\n \n
\n The method accepts 4 parameters in input, which are the ones retrieved from the various text boxes in the user interface. The first step is to build a\n \n WnsConfiguration\n \n object, which require the authentication information we have previously stored. Then we can create a\n \n WnsBroker\n \n object, passing the configuration as parameter. It’s the object that we’re going to use to communicate with the WNS.\n
\n
\n The next lines of code aren’t strictly required, but they can be really helpful for debugging or logging purposes. We subscribe to the:\n
\n
\n
\n \n OnNotificationFailed\n \n event, which is triggered when one or more of the notifications we have sent can’t be delivered. From the\n \n Message\n \n property of the notification we can understand which is the issue, so we print it in the output window of Visual Studio.\n
\n
\n \n OnNotificationSucceded\n \n event, which is triggered instead one one or more of the notifications we have sent has been successfully queued by the WNS.\n
\n
\n
\n Then we can write the real code to send the notification. First we start the broker by calling the\n \n Start()\n \n method. Then we prepare the content of the notification, in this case by using a\n \n WnsToastNotification\n \n object since we want to send a toast notification. We build the object by specifying the\n \n ChannelUri\n \n property (the URI of the channel where to send the notification) and the\n \n Payload\n \n property (the XML that represents the notification). In this case, the payload is the same we have seen in the previous post and it’s the standard one for a generic toast notification. The difference is that we populate the\n \n launch\n \n attribute and the two\n \n text\n \n nodes using the information specified by the user in the UI.\n
\n
\n Then we queue the notification by passing the object we have just created to the\n \n QueueNotification\n \n () method and we stop the broker by calling the\n \n Stop()\n \n method.\n
\n
\n In a real world scenario the code would be pretty much the same, except that the\n \n QueueNotification()\n \n method might be called multiple times, based on the scenario we need to implement. For example, if it’s a messaging app, probably we will call it just once because we need to notify only the sender that there’s a new message. In case of a news app, instead, we will likely call it for each device that we have registered in our system, which represents every user that has subscribed to receive breaking news.\n
\n
\n That’s all! As you can see, the\n \n \n PushSharp library makes the overall operation much easier. You can notice how, for example, we didn’t need to take care of making two separate HTTP calls, one for the authentication and one for sending the actual notification. The library performs automatically the authentication request under the hood and takes care, if the token is expired, to refresh it.\n
\n
\n Now we can move to the client code: our Progressive Web App!\n
\n
\n The Progressive Web App\n
\n
\n We won’t start from scratch, but we’re going to add push notifications support to the PWA we’ve built\n \n in the previous post\n \n , which is included\n \n in the sample on GitHub\n \n and which is made by two components:\n
\n \n
\n The\n \n ToastWebsite\n \n project, which is the real web application. It’s an ASP.NET Core 2.0 website which I’ve deployed to an Azure Web App.\n
\n
\n The\n \n App\n \n project, which is a Hosted Web App project that, in the manifest, just points to the URL where I’ve deployed the web application. Thanks to this project, I’m able to run my website like if it’s a native application.\n
\n \n
\n Since the second project is just a wrapper for the website, we’re going to write all the actual code in the first project. Let’s move to\n \n Pages –> Index.cshtml\n \n , which is the main page of the website. It’s the page where, in the last post, we have added some code to:\n
\n \n
\n Display a toast notification when the user presses a button\n
\n
\n Register for the\n \n activated\n \n event, so that when the user clicks on the notification we can intercept it and redirect him to the appropriate landing page\n
\n \n
\n We’re going to add some new code, specifically a couple of new functions and a property:\n
\n First, let’s remember that we need to wrap the new functions inside a\n \n if (typeof Windows)\n \n statement. We need to leverage this code only if the application is running as a PWA on Windows 10, because we’re going to use some specific WinRT APIs exposed by the Universal Windows Platform. As such, the previous code would generate an exception if the web app is executed inside a browser or on another platform.\n
\n
\n Inside the\n \n registerPush()\n \n function we use the APIs included in the\n \n Windows.Networking.PushNotifications\n \n namespace to create a new channel URI. Specifically, we use the\n \n createPushNotificationChannelForApplicationAsync()\n \n method exposed by the\n \n PushNotificationChannelManager\n \n class. If the operation is successful, it means that the WNS has created a new channel for us. If that’s the case, we can use the promises approach to define a function that is invoked when the creation of the channel is completed. All the information about it are stored inside a parameter of the function. The most interesting one, for us, is inside the\n \n uri\n \n property. It’s the full URI that our backend will need to use to send us a push notification. In a real world scenario, at this point we would need to send the URI to the backend, for example by invoking a REST API exposed by our server. The REST API will take care of storing the URI inside a database, so that we can retrieve it at a later stage when needed.\n
\n
\n In our sample, to make things easier, we just display it in the HTML page, inside a\n \n div\n \n control I’ve placed. It will be up to us to copy the URL and paste it inside the user interface of the Windows Forms application we have built.\n
\n
\n Please notice another important piece of our code: we register to an event exposed by the channel we have just created called\n \n pushnotificationreceived\n \n , which is invoked every time we receive a push notification and the app is currently running. Inside this event we have access to an object which exposes a\n \n cancel\n \n property, which is a boolean. By setting it to\n \n true\n \n , we are telling to Windows that we want to take care of the notification and that it should ignore it. The final result is that the user won’t see the toast notification appearing in the bottom right corner of the screen and then being stored in the Action Center. Subscribing to this event isn’t a requirement, but it can be useful in some scenarios to provide a better user experience. For example, if you’re building a messaging app and the user receives a message on the chat he’s already looking at, you can decide to not display any notification and just add the message to the history. In our case, we’re using this event to block the toast notification and display a message to the user directly in the page.\n
\n
\n As last step, let’s just add in our page a button connected to this new function we have just created, plus a couple of div elements to display the output to the user:\n
\n Now we can test if the code we have written works. However, before doing that, there’s an important step to make. At the beginning of the post we have registered a new application on the Dev Center in order to get the credentials needed to authenticate with WNS. However, we have never linked this application to our PWA. We can do it by right clicking on our UWP project (the\n \n App\n \n one which, in the previous post, we have created using\n \n PWA Builder\n \n ) and choosing\n \n Store –> Associate App with the Store\n \n . You will be able to login with your developer account and choose, from the list, the same name you have reserved in the beginning. This way the manifest will be automatically filled with the correct identity.\n
\n
\n Now we can move on with the testing. First, we need to publish the changes we have made to our website on our web server. In my case, I’m using again an Azure Web App, but this time I’ve published it on another URI, which is\n \n https://toastwebsitewithpush.azurewebsites.net/\n \n If you want to do the same, remember to follow\n \n the guidance of the previous post\n \n and make sure to set, in the\n \n Application\n \n and\n \n Content URIs\n \n sections of the manifest, the new URI.\n
\n
\n Deploy the\n \n App\n \n project on your machine and launch the PWA. Remember that you can’t test this code directly from the browser, since you don’t have access to the WinRT APIs we’re using to create a push notification channel. Click on the\n \n Register for push notifications\n \n button and, if everything goes well, you should see a long URI appearing below:\n
\n
\n \n
\n
\n Now, from Visual Studio, launch the Windows Forms app we’ve built and fill the Title, Text and News Id fields with some values. Make sure, in the URL field, to paste the URI that you are seeing in the main page of your PWA.\n
\n
\n \n
\n
\n Now press the\n \n Send Push\n \n button. If everything goes well, after a while you should see the message\n \n Notification received\n \n in the main page of your PWA.\n
\n
\n \n
\n
\n If you remember the code we have written, this is happening because we have subscribed to the\n \n pushnotificationreceived\n \n event and we are telling to Windows that we want to handle it. As a consequence, the user is seeing just the message on the page, but he’s not seeing any toast notification popping up.\n
\n
\n Now close the PWA and, in the Windows Forms app, press again the\n \n Send Push button.\n \n
\n
\n \n
\n
\n This time the notification is popping up in Windows. The application, in fact, is not running, so the\n \n pushnotificationreceived\n \n event can’t be raised.\n
\n
\n Enhancing your PWA with tile notifications\n
\n
\n The advantage of using a WNS infrastructure for sending push notifications is that you can leverage it to further enhance your PWA, by adding for example live tiles support. The same exact technique we’ve seen so far, in fact, can be used also to update the tile of your application and make it more engaging. From the backend, you just need to send a different payload,\n \n based on the adaptive tile schema\n \n . Additionally, toast and tile notifications can be sent together at the same time, so that the user will receive both updates at the same time. Here is, for example, how I changed the last part of the code of the Windows Forms app to achieve this goal:\n
\n As you can see, the code is the same. The only differences are the payload and the usage of another class, called\n \n WnsTileNotification\n \n , to setup the tile notification. At the end, I use the broker to queue it together with the toast notification I’ve previously created.\n
\n
\n As outcome, other then seeing the toast notification or the message in the app (depending if it’s running or not), you’ll see the tile on the Start menu being updated. Of course, to see it, you will need first to right click on the icon in your Start menu and choose\n \n Pin to start\n \n .\n
\n
\n \n
\n
\n Wrapping up\n
\n
\n In this post we’ve seen how to further expand the previous sample, by adding support for real push notifications in our PWA. You have the option to implement web notifications, which are more limited but they work cross-platform and also inside the browser, or native Windows notifications, which offers more power and flexibility. We’ve also seen how to implement a simple backend environment and how we can use it not just to send standard push notifications, but also to light up other Windows features like live tiles.\n
\n \n","body@stringLength":"37013","rawBody":"\n \n \n First published on MSDN on Jun 07, 2018\n \n \n
\n \n In the previous post\n \n we have seen how we are able to activate a Progressive Web App on Windows 10 from a toast notification. However, the sample used in the post had a limitation compared to a real world scenario: the notification was generated by the app itself, as a consequence of the user pressing a button. In a real application, this is hardly the case. Notifications can be received at anytime, even when the application isn’t running. This is the reason why the mobile world has embraced since a long time the push notification concept, which is a way to engage with the user and at the same time respect the battery and the performances of the device. Before push notifications, most of the notifications scenarios were implemented with a polling approach. The client (in our case, the application) keeps checking with the server if there’s nothing new and, if that’s the case, displays a notification to the user.\n
\n
\n Push notifications, instead, work the other way around. The server establishes a channel with the client and, whenever there’s something to notify, it sends a signal to the client, which processes it. This channel is always alive, even when the application is not running. Push notifications are the best technology when the event that triggers the notification doesn’t happen locally, but in a remote environment. Let’s take, as example, the news PWA we’ve built in the previous post. Let’s image that it’s a companion app for a news website, which has a backend that offers a text editing interface to add a news. In this scenario it’s me, the news writer, who is aware that I’m about to add an important news in the backend, not the application. As such, I would imagine to see a checkbox labelled “This is a breaking news” in the editing page. When I flag it and I post the news, automatically every registered device will receive a push notification.\n
\n
\n Let’s see how we can extended the previous sample to add this specific behavior. At startup, the PWA will register itself to receive push notifications. Then we’re going to build a simple backend (in this case, it will be made by a Windows Forms app) which is capable to send push notifications to our app. Let’s start!\n
\n
\n Web notifications vs Windows notifications\n
\n
\n W3C has defined a standard Web API to handle push notifications, which is supported by all the major browsers. The Edge team has published a great tutorial on this on their samples website:\n \n https://webpushdemo.azurewebsites.net/\n \n This implementation is cross-platform from a client point of view, meaning that the same code will work regardless of the browser. However, it’s not the same for the server side implementation. The URL where to send the notification, in fact, will change based on the browser which is rendering the PWA.\n
\n
\n However, since we’re running on Windows, we have also the opportunity to leverage the native Windows APIs to support push notifications. The client side code won’t be cross-platform anymore, but we will gain much more power and flexibility, since we can support\n \n the rich adaptive toast notification model\n \n introduced with Windows 10. This means the opportunity to send notifications with hero images, interactive elements like buttons or text boxes, etc. In this post we’re going to see how to implement this kind of notifications in our web application.\n
\n
\n Push notifications overview\n
\n
\n From a high level overview, push notifications work in the same way regardless of the platform and it involves three actors:\n
\n \n
\n A cloud service provided by the owner of the platform, which acts as a middle man between the client and the server\n
\n
\n A client, which connects to the cloud service and establish a communication channel\n
\n
\n A server, which sends notifications to the clients passing through the cloud service\n
\n \n
\n \n
\n
\n The difference, based on the platform, is the way you communicate with the cloud service. In case of Windows, the service is called WNS (Windows Notification Service). Whenever a client registers with the WNS, it gets assigned a unique channel which is represented by a URI. Whenever the backend wants to send a notification to that device, it must compose a XML payload (which is different based on the notification type you want to send) and push it using a HTTP POST command against the assigned URI.\n
\n
\n As you can see, the advantage of this approach is that it doesn’t rely on any proprietary SDK or API, but on standard protocols and languages like XML and HTTP. As such, you will be able to integrate push notifications no matter which is the technology you have used to build the backend of your project.\n
\n
\n The server side\n
\n
\n As first step, we need to implement the backend which is going to send the push notification to our web application. As I’ve described before, in a real world scenario you’ll probably have a web application, an Azure function or any other kind of trigger that sends it. In our case, since we’re building just a sample, we’re going to create a Windows Forms application. The application will allow to specify some information about the notification (like title and text) and the URL of the device. After pressing a button, the application will send the notification payload to the WNS using the assigned URL, which will take care of routing the notification to the correct device.\n
\n
\n As an overview, interacting with the WNS requires two steps:\n
\n \n
\n First you need to authenticate against WNS, using a set of credentials that the Store assigns to your application when you register it on the Dev Center.\n
\n
\n After you have successfully authenticated, you will receive a token that you will need to append to every request to the WNS. Without this token, the request will be rejected.\n
\n \n
\n The process isn’t very complex, but it requires lot of work:\n
\n \n
\n You need to manually build the HTTP request to authenticate and store the returned token.\n
\n
\n You need to manually build the HTTP request to send the notification. It’s enough to specify the wrong content type or the wrong header to see the request failing, so you have to be very careful in following the documentation.\n
\n
\n You need to build a retry mechanism, in case the authentication token is expired and you need a new one.\n
\n \n
\n To make things simpler please welcome\n \n PushSharp\n \n , an open source library built by a member of the Xamarin team which makes the server side implementation of push notifications much easier. Instead of manually building all the required HTTP requests, you’re going to use a set of high level #C APIs which will make all the hard work for you under the hood. In this post we’re going to see the specific Windows implementation, but PushSharp is a cross-platform library. This means that you can send push notifications from any C# based backend to iOS, Android and Windows devices.\n
\n
\n Before writing some code, however, we need to register our PWA on the Dev Center, in order to get the credentials to authenticate against WNS. This step is required, otherwise a malicious developer would be able to send push notifications to our customers just by spoofing the channel URI. I’m assuming that you already have a Dev Center account, so you can just go to\n \n https://dev.windows.com\n \n , login and reserve a new name for the application you want to publish (in case you don’t have it already). Once you have done it, you will have access to the full dashboard for your app.\n
\n
\n \n
\n
\n Click on the WNS/MPSN option and then click on the\n \n Live Services Site\n \n link that you will find in the page under the WNS section:\n
\n
\n \n
\n
\n After clicking on it, you will be redirected to a page that will contain all the registration information of your application against the Microsoft services. The information we need to retrieve for our purposes are:\n
\n The Package Family Name, which can be extracted from the\n \n Name\n \n attribute of the\n \n Identity\n \n tag in the\n \n Application Identity\n \n section\n \n \n \n
\n \n
\n Note them down because we’re going to need them later.\n
\n
\n Now let’s build the server app. I’m taking, as code base, the same solution I’ve built\n \n for the previous post\n \n and that you can find on GitHub at\n \n https://github.com/Microsoft/Windows-AppConsult-samples-PWA/tree/master/ToastActivation.\n \n As already shared, I’m going to build a Windows Forms project but it could be a WPF app or an ASP.NET Core website. The PushSharp library, in fact, works across any C# based framework, including .NET Core. This is the simple user interface I’ve built:\n
\n
\n \n
\n
\n
\n The first field will be used to specify the title of the notification\n
\n
\n The second field will be used to specify the text of the notification\n
\n
\n The third field will be used to specify the ID of the news (so that we can redirect the user to correct detail page)\n
\n
\n The fourth field will be used to specify the channel URI of the device where we want to send the notification\n
\n
\n
\n Now let’s move to the code and, as first thing, let’s right click on the project, choose\n \n Manage NuGet packages\n \n and install the\n \n PushSharp.Core\n \n package:\n
\n
\n \n
\n
\n Now let’s open the code behind of the main form of our application and let’s add the following namespace to the header of the class:\n
\n using PushSharp.Windows;\n \n
\n Do you remember the information we have previously noted about our application from the Dev Center? Now it’s time to use them! Let’s create a variable inside our class, one for each information:\n
\n string secret = \"\"; // need to replace this with your own secret\n \n string sid = \"\"; // need to replace this with your own sid\n \n string package = \"29949MatteoPagani.ExpenseIt-Test\" // need to replace this with your package family name;\n \n
\n Of course, fill the empty values with the correct information you have retrieved from the Dev Center.\n
\n
\n Now we can start implementing the method that actually sends the push notification to our web app. Let’s see the whole code and then let’s comment it piece by piece:\n
\n public void SendNotification(string uri, string title, string text, string newsId)\n \n {\n \n var config = new WnsConfiguration(package, sid, secret);\n \n var wnsBroker = new WnsServiceBroker(config);\n \n \n wnsBroker.OnNotificationFailed += (notification, aggregateEx) => {\n \n \n aggregateEx.Handle(ex => {\n \n \n // See what kind of exception it was to further diagnose\n \n if (ex is WnsNotificationException)\n \n {\n \n var notificationException = (WnsNotificationException)ex;\n \n Debug.WriteLine($\"WNS Notification Failed: {notificationException.Message}\");\n \n }\n \n else\n \n {\n \n Debug.WriteLine(\"WNS Notification Failed for some (Unknown Reason)\");\n \n }\n \n \n // Mark it as handled\n \n return true;\n \n });\n \n };\n \n \n wnsBroker.OnNotificationSucceeded += (notification) => {\n \n Debug.WriteLine(\"WNS Notification Sent!\");\n \n };\n \n \n // Start the broker\n \n wnsBroker.Start();\n \n string payload = $\"<toast launch=\\\"{newsId}\\\"><visual><binding template=\\\"ToastGeneric\\\"><text>{title}</text><text>{text}</text></binding></visual></toast>\";\n \n \n WnsToastNotification toastNotification = new WnsToastNotification\n \n {\n \n ChannelUri = uri,\n \n Payload = XElement.Parse(payload)\n \n };\n \n \n wnsBroker.QueueNotification(toastNotification);\n \n wnsBroker.Stop();\n \n }\n \n
\n The method accepts 4 parameters in input, which are the ones retrieved from the various text boxes in the user interface. The first step is to build a\n \n WnsConfiguration\n \n object, which require the authentication information we have previously stored. Then we can create a\n \n WnsBroker\n \n object, passing the configuration as parameter. It’s the object that we’re going to use to communicate with the WNS.\n
\n
\n The next lines of code aren’t strictly required, but they can be really helpful for debugging or logging purposes. We subscribe to the:\n
\n
\n
\n \n OnNotificationFailed\n \n event, which is triggered when one or more of the notifications we have sent can’t be delivered. From the\n \n Message\n \n property of the notification we can understand which is the issue, so we print it in the output window of Visual Studio.\n
\n
\n \n OnNotificationSucceded\n \n event, which is triggered instead one one or more of the notifications we have sent has been successfully queued by the WNS.\n
\n
\n
\n Then we can write the real code to send the notification. First we start the broker by calling the\n \n Start()\n \n method. Then we prepare the content of the notification, in this case by using a\n \n WnsToastNotification\n \n object since we want to send a toast notification. We build the object by specifying the\n \n ChannelUri\n \n property (the URI of the channel where to send the notification) and the\n \n Payload\n \n property (the XML that represents the notification). In this case, the payload is the same we have seen in the previous post and it’s the standard one for a generic toast notification. The difference is that we populate the\n \n launch\n \n attribute and the two\n \n text\n \n nodes using the information specified by the user in the UI.\n
\n
\n Then we queue the notification by passing the object we have just created to the\n \n QueueNotification\n \n () method and we stop the broker by calling the\n \n Stop()\n \n method.\n
\n
\n In a real world scenario the code would be pretty much the same, except that the\n \n QueueNotification()\n \n method might be called multiple times, based on the scenario we need to implement. For example, if it’s a messaging app, probably we will call it just once because we need to notify only the sender that there’s a new message. In case of a news app, instead, we will likely call it for each device that we have registered in our system, which represents every user that has subscribed to receive breaking news.\n
\n
\n That’s all! As you can see, the\n \n \n PushSharp library makes the overall operation much easier. You can notice how, for example, we didn’t need to take care of making two separate HTTP calls, one for the authentication and one for sending the actual notification. The library performs automatically the authentication request under the hood and takes care, if the token is expired, to refresh it.\n
\n
\n Now we can move to the client code: our Progressive Web App!\n
\n
\n The Progressive Web App\n
\n
\n We won’t start from scratch, but we’re going to add push notifications support to the PWA we’ve built\n \n in the previous post\n \n , which is included\n \n in the sample on GitHub\n \n and which is made by two components:\n
\n \n
\n The\n \n ToastWebsite\n \n project, which is the real web application. It’s an ASP.NET Core 2.0 website which I’ve deployed to an Azure Web App.\n
\n
\n The\n \n App\n \n project, which is a Hosted Web App project that, in the manifest, just points to the URL where I’ve deployed the web application. Thanks to this project, I’m able to run my website like if it’s a native application.\n
\n \n
\n Since the second project is just a wrapper for the website, we’re going to write all the actual code in the first project. Let’s move to\n \n Pages –> Index.cshtml\n \n , which is the main page of the website. It’s the page where, in the last post, we have added some code to:\n
\n \n
\n Display a toast notification when the user presses a button\n
\n
\n Register for the\n \n activated\n \n event, so that when the user clicks on the notification we can intercept it and redirect him to the appropriate landing page\n
\n \n
\n We’re going to add some new code, specifically a couple of new functions and a property:\n
\n First, let’s remember that we need to wrap the new functions inside a\n \n if (typeof Windows)\n \n statement. We need to leverage this code only if the application is running as a PWA on Windows 10, because we’re going to use some specific WinRT APIs exposed by the Universal Windows Platform. As such, the previous code would generate an exception if the web app is executed inside a browser or on another platform.\n
\n
\n Inside the\n \n registerPush()\n \n function we use the APIs included in the\n \n Windows.Networking.PushNotifications\n \n namespace to create a new channel URI. Specifically, we use the\n \n createPushNotificationChannelForApplicationAsync()\n \n method exposed by the\n \n PushNotificationChannelManager\n \n class. If the operation is successful, it means that the WNS has created a new channel for us. If that’s the case, we can use the promises approach to define a function that is invoked when the creation of the channel is completed. All the information about it are stored inside a parameter of the function. The most interesting one, for us, is inside the\n \n uri\n \n property. It’s the full URI that our backend will need to use to send us a push notification. In a real world scenario, at this point we would need to send the URI to the backend, for example by invoking a REST API exposed by our server. The REST API will take care of storing the URI inside a database, so that we can retrieve it at a later stage when needed.\n
\n
\n In our sample, to make things easier, we just display it in the HTML page, inside a\n \n div\n \n control I’ve placed. It will be up to us to copy the URL and paste it inside the user interface of the Windows Forms application we have built.\n
\n
\n Please notice another important piece of our code: we register to an event exposed by the channel we have just created called\n \n pushnotificationreceived\n \n , which is invoked every time we receive a push notification and the app is currently running. Inside this event we have access to an object which exposes a\n \n cancel\n \n property, which is a boolean. By setting it to\n \n true\n \n , we are telling to Windows that we want to take care of the notification and that it should ignore it. The final result is that the user won’t see the toast notification appearing in the bottom right corner of the screen and then being stored in the Action Center. Subscribing to this event isn’t a requirement, but it can be useful in some scenarios to provide a better user experience. For example, if you’re building a messaging app and the user receives a message on the chat he’s already looking at, you can decide to not display any notification and just add the message to the history. In our case, we’re using this event to block the toast notification and display a message to the user directly in the page.\n
\n
\n As last step, let’s just add in our page a button connected to this new function we have just created, plus a couple of div elements to display the output to the user:\n
\n Now we can test if the code we have written works. However, before doing that, there’s an important step to make. At the beginning of the post we have registered a new application on the Dev Center in order to get the credentials needed to authenticate with WNS. However, we have never linked this application to our PWA. We can do it by right clicking on our UWP project (the\n \n App\n \n one which, in the previous post, we have created using\n \n PWA Builder\n \n ) and choosing\n \n Store –> Associate App with the Store\n \n . You will be able to login with your developer account and choose, from the list, the same name you have reserved in the beginning. This way the manifest will be automatically filled with the correct identity.\n
\n
\n Now we can move on with the testing. First, we need to publish the changes we have made to our website on our web server. In my case, I’m using again an Azure Web App, but this time I’ve published it on another URI, which is\n \n https://toastwebsitewithpush.azurewebsites.net/\n \n If you want to do the same, remember to follow\n \n the guidance of the previous post\n \n and make sure to set, in the\n \n Application\n \n and\n \n Content URIs\n \n sections of the manifest, the new URI.\n
\n
\n Deploy the\n \n App\n \n project on your machine and launch the PWA. Remember that you can’t test this code directly from the browser, since you don’t have access to the WinRT APIs we’re using to create a push notification channel. Click on the\n \n Register for push notifications\n \n button and, if everything goes well, you should see a long URI appearing below:\n
\n
\n \n
\n
\n Now, from Visual Studio, launch the Windows Forms app we’ve built and fill the Title, Text and News Id fields with some values. Make sure, in the URL field, to paste the URI that you are seeing in the main page of your PWA.\n
\n
\n \n
\n
\n Now press the\n \n Send Push\n \n button. If everything goes well, after a while you should see the message\n \n Notification received\n \n in the main page of your PWA.\n
\n
\n \n
\n
\n If you remember the code we have written, this is happening because we have subscribed to the\n \n pushnotificationreceived\n \n event and we are telling to Windows that we want to handle it. As a consequence, the user is seeing just the message on the page, but he’s not seeing any toast notification popping up.\n
\n
\n Now close the PWA and, in the Windows Forms app, press again the\n \n Send Push button.\n \n
\n
\n \n
\n
\n This time the notification is popping up in Windows. The application, in fact, is not running, so the\n \n pushnotificationreceived\n \n event can’t be raised.\n
\n
\n Enhancing your PWA with tile notifications\n
\n
\n The advantage of using a WNS infrastructure for sending push notifications is that you can leverage it to further enhance your PWA, by adding for example live tiles support. The same exact technique we’ve seen so far, in fact, can be used also to update the tile of your application and make it more engaging. From the backend, you just need to send a different payload,\n \n based on the adaptive tile schema\n \n . Additionally, toast and tile notifications can be sent together at the same time, so that the user will receive both updates at the same time. Here is, for example, how I changed the last part of the code of the Windows Forms app to achieve this goal:\n
\n As you can see, the code is the same. The only differences are the payload and the usage of another class, called\n \n WnsTileNotification\n \n , to setup the tile notification. At the end, I use the broker to queue it together with the toast notification I’ve previously created.\n
\n
\n As outcome, other then seeing the toast notification or the message in the app (depending if it’s running or not), you’ll see the tile on the Start menu being updated. Of course, to see it, you will need first to right click on the icon in your Start menu and choose\n \n Pin to start\n \n .\n
\n
\n \n
\n
\n Wrapping up\n
\n
\n In this post we’ve seen how to further expand the previous sample, by adding support for real push notifications in our PWA. You have the option to implement web notifications, which are more limited but they work cross-platform and also inside the browser, or native Windows notifications, which offers more power and flexibility. We’ve also seen how to implement a simple backend environment and how we can use it not just to send standard push notifications, but also to light up other Windows features like live tiles.\n
\n \n","kudosSumWeight":0,"postTime":"2019-01-15T14:42:27.618-08:00","images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzRpODVEOTFCQ0Q2NjIzNkRGRA?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzZpOTVCOTlDQzYzQ0Q0Mzk0OA?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzhpMUQyQjNBNTg3MjU4NTY0Ng?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzlpNkU5RDhGMDkzMEI5MkE1Mg?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODFpMUYxM0Q5N0E5MUY1M0NBMA?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODJpMDg3QjFFNDQxNUE2OUU2Qg?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDc","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODNpRDYyMjNDRDJBNkZENjgyRA?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDg","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODVpRjNDQzZGRURDMDk1RDYxMg?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDk","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODdpODhBQkI0MTEwREQ0MjNDMg?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEw","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODhpRTdCNDQyOTVEMjUzNjg4OQ?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEx","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTBpRUZGNkE1MkZBQzlFQUE5OQ?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEy","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTJpNzZDRUQ5QkZBQzU2RUQzNQ?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEz","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTRpNUU5NkRCODlEQjQwQ0QwMw?revision=4\"}"}}],"totalCount":13,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"attachments":{"__typename":"AttachmentConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[]},"tags":{"__typename":"TagConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDE","node":{"__typename":"Tag","id":"tag:Progressive Web Apps","text":"Progressive Web Apps","time":"2019-01-15T14:30:22.852-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDI","node":{"__typename":"Tag","id":"tag:Universal Windows Platform","text":"Universal Windows Platform","time":"2017-08-22T12:18:41.301-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}}]},"timeToRead":17,"rawTeaser":"First published on MSDN on Jun 07, 2018 In the previous post we have seen how we are able to activate a Progressive Web App on Windows 10 from a toast notification.","introduction":"","coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""},"currentRevision":{"__ref":"Revision:revision:317283_4"},"latestVersion":{"__typename":"FriendlyVersion","major":"4","minor":"0"},"metrics":{"__typename":"MessageMetrics","views":4905},"visibilityScope":"PUBLIC","canonicalUrl":null,"seoTitle":null,"seoDescription":null,"placeholder":false,"originalMessageForPlaceholder":null,"contributors":{"__typename":"UserConnection","edges":[]},"nonCoAuthorContributors":{"__typename":"UserConnection","edges":[]},"coAuthors":{"__typename":"UserConnection","edges":[]},"blogMessagePolicies":{"__typename":"BlogMessagePolicies","canDoAuthoringActionsOnBlog":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.blog.action_can_do_authoring_action.accessDenied","key":"error.lithium.policies.blog.action_can_do_authoring_action.accessDenied","args":[]}}},"archivalData":null,"replies":{"__typename":"MessageConnection","edges":[],"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"customFields":[],"revisions({\"constraints\":{\"isPublished\":{\"eq\":true}},\"first\":1})":{"__typename":"RevisionConnection","totalCount":4}},"Conversation:conversation:317283":{"__typename":"Conversation","id":"conversation:317283","solved":false,"topic":{"__ref":"BlogTopicMessage:message:317283"},"lastPostingActivityTime":"2022-11-22T12:24:04.735-08:00","lastPostTime":"2019-01-15T14:42:27.618-08:00","unreadReplyCount":0,"isSubscribed":false},"ModerationData:moderation_data:317283":{"__typename":"ModerationData","id":"moderation_data:317283","status":"APPROVED","rejectReason":null,"isReportedAbuse":false,"rejectUser":null,"rejectTime":null,"rejectActorType":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzRpODVEOTFCQ0Q2NjIzNkRGRA?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzRpODVEOTFCQ0Q2NjIzNkRGRA?revision=4","title":"","associationType":"BODY","width":576,"height":275,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzZpOTVCOTlDQzYzQ0Q0Mzk0OA?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzZpOTVCOTlDQzYzQ0Q0Mzk0OA?revision=4","title":"","associationType":"BODY","width":306,"height":480,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzhpMUQyQjNBNTg3MjU4NTY0Ng?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzhpMUQyQjNBNTg3MjU4NTY0Ng?revision=4","title":"","associationType":"BODY","width":640,"height":262,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzlpNkU5RDhGMDkzMEI5MkE1Mg?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyNzlpNkU5RDhGMDkzMEI5MkE1Mg?revision=4","title":"","associationType":"BODY","width":640,"height":113,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODFpMUYxM0Q5N0E5MUY1M0NBMA?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODFpMUYxM0Q5N0E5MUY1M0NBMA?revision=4","title":"","associationType":"BODY","width":640,"height":266,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODJpMDg3QjFFNDQxNUE2OUU2Qg?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODJpMDg3QjFFNDQxNUE2OUU2Qg?revision=4","title":"","associationType":"BODY","width":640,"height":226,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODNpRDYyMjNDRDJBNkZENjgyRA?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODNpRDYyMjNDRDJBNkZENjgyRA?revision=4","title":"","associationType":"BODY","width":640,"height":79,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODVpRjNDQzZGRURDMDk1RDYxMg?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODVpRjNDQzZGRURDMDk1RDYxMg?revision=4","title":"","associationType":"BODY","width":640,"height":407,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODdpODhBQkI0MTEwREQ0MjNDMg?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODdpODhBQkI0MTEwREQ0MjNDMg?revision=4","title":"","associationType":"BODY","width":640,"height":208,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODhpRTdCNDQyOTVEMjUzNjg4OQ?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyODhpRTdCNDQyOTVEMjUzNjg4OQ?revision=4","title":"","associationType":"BODY","width":640,"height":407,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTBpRUZGNkE1MkZBQzlFQUE5OQ?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTBpRUZGNkE1MkZBQzlFQUE5OQ?revision=4","title":"","associationType":"BODY","width":640,"height":178,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTJpNzZDRUQ5QkZBQzU2RUQzNQ?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTJpNzZDRUQ5QkZBQzU2RUQzNQ?revision=4","title":"","associationType":"BODY","width":454,"height":480,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTRpNUU5NkRCODlEQjQwQ0QwMw?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMTcyODMtNjcyOTRpNUU5NkRCODlEQjQwQ0QwMw?revision=4","title":"","associationType":"BODY","width":19,"height":19,"altText":null},"Revision:revision:317283_4":{"__typename":"Revision","id":"revision:317283_4","lastEditTime":"2022-11-22T12:24:04.735-08:00"},"CachedAsset:theme:customTheme1-1747046960229":{"__typename":"CachedAsset","id":"theme:customTheme1-1747046960229","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["default"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"favicon-1730836283320.png","imageLastModified":"1730836286415","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"favicon-1730836271365.png","imageLastModified":"1730836274203","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1300px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_BROWSER","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"3px","borderRadius":"3px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"16px","paddingXHero":"60px","fontStyle":"NORMAL","fontWeight":"700","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-200)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-200)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"LIGHT","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.16)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.12)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-link-color)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","forumColor":"#4099E2","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#148563","blogColor":"#1CBAA0","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#4C6B90","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#FF8000","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#D13A1F","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#333333","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#717171","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0069D4","secondary":"#333333","bodyText":"#1E1E1E","bodyBg":"#FFFFFF","info":"#409AE2","success":"#41C5AE","warning":"#FCC844","danger":"#BC341B","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#D3F5A4","#243A5E"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Segoe UI","fontStyle":"NORMAL","fontWeight":"400","h1FontSize":"34px","h2FontSize":"32px","h3FontSize":"28px","h4FontSize":"24px","h5FontSize":"20px","h6FontSize":"16px","lineHeight":"1.3","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":"","imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"40px","defaultMessageHeaderMarginBottom":"20px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"40px","specialMessageHeaderMarginBottom":"20px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Segoe UI","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.5","fontSizeBase":"16px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"14px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[{"source":"SERVER","name":"Segoe UI","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"},{"style":"NORMAL","weight":"300","__typename":"FontStyleData"},{"style":"NORMAL","weight":"600","__typename":"FontStyleData"},{"style":"NORMAL","weight":"700","__typename":"FontStyleData"},{"style":"ITALIC","weight":"400","__typename":"FontStyleData"}],"assetNames":["SegoeUI-normal-400.woff2","SegoeUI-normal-300.woff2","SegoeUI-normal-600.woff2","SegoeUI-normal-700.woff2","SegoeUI-italic-400.woff2"],"__typename":"CustomFont"},{"source":"SERVER","name":"MWF Fluent Icons","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"}],"assetNames":["MWFFluentIcons-normal-400.woff2"],"__typename":"CustomFont"}],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1745505307000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:quilt:o365.prod:pages/blogs/BlogMessagePage:board:ModernWorkAppConsult-1747046956382":{"__typename":"CachedAsset","id":"quilt:o365.prod:pages/blogs/BlogMessagePage:board:ModernWorkAppConsult-1747046956382","value":{"id":"BlogMessagePage","container":{"id":"Common","headerProps":{"backgroundImageProps":null,"backgroundColor":null,"addComponents":null,"removeComponents":["community.widget.bannerWidget"],"componentOrder":null,"__typename":"QuiltContainerSectionProps"},"headerComponentProps":{"community.widget.breadcrumbWidget":{"disableLastCrumbForDesktop":false}},"footerProps":null,"footerComponentProps":null,"items":[{"id":"blog-article","layout":"ONE_COLUMN","bgColor":null,"showTitle":null,"showDescription":null,"textPosition":null,"textColor":null,"sectionEditLevel":"LOCKED","bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"OneColumnQuiltSection","columnMap":{"main":[{"id":"blogs.widget.blogArticleWidget","className":"lia-blog-container","props":null,"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"}},{"id":"section-1729184836777","layout":"MAIN_SIDE","bgColor":"transparent","showTitle":false,"showDescription":false,"textPosition":"CENTER","textColor":"var(--lia-bs-body-color)","sectionEditLevel":null,"bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"MainSideQuiltSection","columnMap":{"main":[],"side":[],"__typename":"MainSideSectionColumns"}}],"__typename":"QuiltContainer"},"__typename":"Quilt","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1745505307000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/blogs/BlogMessagePage-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-pages/blogs/BlogMessagePage-1745505307000","value":{"title":"{contextMessageSubject} | {communityTitle}","errorMissing":"This blog post cannot be found","name":"Blog Message Page","section.blog-article.title":"Blog Post","archivedMessageTitle":"This Content Has Been Archived","section.section-1729184836777.title":"","section.section-1729184836777.description":"","section.CncIde.title":"Blog Post","section.tifEmD.description":"","section.tifEmD.title":""},"localOverride":false},"CachedAsset:quiltWrapper:o365.prod:Common:1747046899119":{"__typename":"CachedAsset","id":"quiltWrapper:o365.prod:Common:1747046899119","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"community.widget.navbarWidget","props":{"showUserName":true,"showRegisterLink":true,"useIconLanguagePicker":true,"useLabelLanguagePicker":true,"className":"QuiltComponent_lia-component-edit-mode__0nCcm","links":{"sideLinks":[],"mainLinks":[{"children":[],"linkType":"INTERNAL","id":"gxcuf89792","params":{},"routeName":"CommunityPage"},{"children":[],"linkType":"EXTERNAL","id":"external-link","url":"/Directory","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft365","params":{"categoryId":"microsoft365"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows","params":{"categoryId":"Windows"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"Common-microsoft365-copilot-link","params":{"categoryId":"Microsoft365Copilot"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-teams","params":{"categoryId":"MicrosoftTeams"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-securityand-compliance","params":{"categoryId":"microsoft-security"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"azure","params":{"categoryId":"Azure"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"Common-content_management-link","params":{"categoryId":"Content_Management"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"exchange","params":{"categoryId":"Exchange"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows-server","params":{"categoryId":"Windows-Server"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"outlook","params":{"categoryId":"Outlook"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-endpoint-manager","params":{"categoryId":"microsoftintune"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-2","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities","url":"/","target":"BLANK"},{"children":[{"linkType":"INTERNAL","id":"a-i","params":{"categoryId":"AI"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"education-sector","params":{"categoryId":"EducationSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"partner-community","params":{"categoryId":"PartnerCommunity"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"i-t-ops-talk","params":{"categoryId":"ITOpsTalk"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"healthcare-and-life-sciences","params":{"categoryId":"HealthcareAndLifeSciences"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-mechanics","params":{"categoryId":"MicrosoftMechanics"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"public-sector","params":{"categoryId":"PublicSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"s-m-b","params":{"categoryId":"MicrosoftforNonprofits"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"io-t","params":{"categoryId":"IoT"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"startupsat-microsoft","params":{"categoryId":"StartupsatMicrosoft"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"driving-adoption","params":{"categoryId":"DrivingAdoption"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-1","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities-1","url":"/","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external","url":"/Blogs","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external-1","url":"/Events","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft-learn-1","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-learn-blog","params":{"boardId":"MicrosoftLearnBlog","categoryId":"MicrosoftLearn"},"routeName":"BlogBoardPage"},{"linkType":"EXTERNAL","id":"external-10","url":"https://learningroomdirectory.microsoft.com/","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-3","url":"https://docs.microsoft.com/learn/dynamics365/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-4","url":"https://docs.microsoft.com/learn/m365/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-5","url":"https://docs.microsoft.com/learn/topics/sci/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-6","url":"https://docs.microsoft.com/learn/powerplatform/?wt.mc_id=techcom_header-webpage-powerplatform","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-7","url":"https://docs.microsoft.com/learn/github/?wt.mc_id=techcom_header-webpage-github","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-8","url":"https://docs.microsoft.com/learn/teams/?wt.mc_id=techcom_header-webpage-teams","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-9","url":"https://docs.microsoft.com/learn/dotnet/?wt.mc_id=techcom_header-webpage-dotnet","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-2","url":"https://docs.microsoft.com/learn/azure/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"}],"linkType":"INTERNAL","id":"microsoft-learn","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"community-info-center","params":{"categoryId":"Community-Info-Center"},"routeName":"CategoryPage"}]},"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","controllerHighlightColor":"hsla(30, 100%, 50%)","linkFontWeight":"400","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkBoxShadowHover":"none","linkFontSize":"14px","backgroundOpacity":0.8,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","hamburgerColor":"var(--lia-nav-controller-icon-color)","linkTextBorderBottom":"none","brandLogoHeight":"30px","linkBgHoverColor":"transparent","linkLetterSpacing":"normal","collapseMenuDividerOpacity":0.16,"dropdownPaddingBottom":"15px","paddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"1px solid var(--lia-bs-border-color)","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","collapseMenuDividerBg":"var(--lia-nav-link-color)","linkColor":"var(--lia-bs-body-color)","linkJustifyContent":"flex-start","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","controllerTextColor":"var(--lia-nav-controller-icon-color)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-body-color)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid var(--lia-bs-body-color)","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","linkPaddingX":"10px","linkPaddingY":"5px","paddingTop":"15px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkBgColor":"transparent","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkDropdownPaddingY":"9px","controllerIconColor":"var(--lia-bs-body-color)","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"var(--lia-bs-body-color)"},"showSearchIcon":false,"languagePickerStyle":"iconAndLabel"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"transparent","linkHighlightColor":"var(--lia-bs-primary)","visualEffects":{"showBottomBorder":true},"linkTextColor":"var(--lia-bs-gray-700)"},"__typename":"QuiltComponent"},{"id":"custom.widget.HeroBanner","props":{"widgetVisibility":"signedInOrAnonymous","usePageWidth":false,"useTitle":true,"cMax_items":3,"useBackground":false,"title":"","lazyLoad":false,"widgetChooser":"custom.widget.HeroBanner"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.MicrosoftFooter","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1745505307000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"QueryVariables:TopicReplyList:message:317283:4":{"__typename":"QueryVariables","id":"TopicReplyList:message:317283:4","value":{"id":"message:317283","first":10,"sorts":{"postTime":{"direction":"DESC"}},"repliesFirst":3,"repliesFirstDepthThree":1,"repliesSorts":{"postTime":{"direction":"DESC"}},"useAvatar":true,"useAuthorLogin":true,"useAuthorRank":true,"useBody":true,"useKudosCount":true,"useTimeToRead":false,"useMedia":false,"useReadOnlyIcon":false,"useRepliesCount":true,"useSearchSnippet":false,"useAcceptedSolutionButton":false,"useSolvedBadge":false,"useAttachments":false,"attachmentsFirst":5,"useTags":true,"useNodeAncestors":false,"useUserHoverCard":false,"useNodeHoverCard":false,"useModerationStatus":true,"usePreviewSubjectModal":false,"useMessageStatus":true}},"ROOT_MUTATION":{"__typename":"Mutation"},"CachedAsset:component:custom.widget.HeroBanner-en-us-1747047001950":{"__typename":"CachedAsset","id":"component:custom.widget.HeroBanner-en-us-1747047001950","value":{"component":{"id":"custom.widget.HeroBanner","template":{"id":"HeroBanner","markupLanguage":"REACT","style":null,"texts":{"searchPlaceholderText":"Search this community","followActionText":"Follow","unfollowActionText":"Following","searchOnHoverText":"Please enter your search term(s) and then press return key to complete a search.","blogs.sidebar.pagetitle":"Latest Blogs | Microsoft Tech Community","followThisNode":"Follow this node","unfollowThisNode":"Unfollow this node"},"defaults":{"config":{"applicablePages":[],"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.HeroBanner","form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"__typename":"Component","localOverride":false},"globalCss":null,"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"}},"localOverride":false},"CachedAsset:component:custom.widget.MicrosoftFooter-en-us-1747047001950":{"__typename":"CachedAsset","id":"component:custom.widget.MicrosoftFooter-en-us-1747047001950","value":{"component":{"id":"custom.widget.MicrosoftFooter","template":{"id":"MicrosoftFooter","markupLanguage":"HANDLEBARS","style":".context-uhf {\n min-width: 280px;\n font-size: 15px;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.c-uhff-link {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.c-uhff {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.c-uhff-nav {\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n .c-heading-4 {\n color: #616161;\n word-break: break-word;\n font-size: 15px;\n line-height: 20px;\n padding: 36px 0 4px;\n font-weight: 600;\n }\n .c-uhff-nav-row {\n .c-uhff-nav-group {\n display: block;\n float: left;\n min-height: 1px;\n vertical-align: text-top;\n padding: 0 12px;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.c-list.f-bare {\n font-size: 11px;\n line-height: 16px;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 8px 0;\n margin: 0;\n }\n }\n }\n }\n}\n.c-uhff-base {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 30px 5% 16px;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.c-uhff-ccpa {\n font-size: 11px;\n line-height: 16px;\n float: left;\n margin: 3px 0;\n }\n a.c-uhff-ccpa:hover {\n text-decoration: underline;\n }\n ul.c-list {\n font-size: 11px;\n line-height: 16px;\n float: right;\n margin: 3px 0;\n color: #616161;\n li {\n padding: 0 24px 4px 0;\n display: inline-block;\n }\n }\n .c-list.f-bare {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 30px 24px 16px;\n }\n}\n\n.social-share {\n position: fixed;\n top: 60%;\n transform: translateY(-50%);\n left: 0;\n z-index: 1000;\n}\n\n.sharing-options {\n list-style: none;\n padding: 0;\n margin: 0;\n display: block;\n flex-direction: column;\n background-color: white;\n width: 43px;\n border-radius: 0px 7px 7px 0px;\n}\n.linkedin-icon {\n border-top-right-radius: 7px;\n}\n.linkedin-icon:hover {\n border-radius: 0;\n}\n.social-share-rss-image {\n border-bottom-right-radius: 7px;\n}\n.social-share-rss-image:hover {\n border-radius: 0;\n}\n\n.social-link-footer {\n position: relative;\n display: block;\n margin: -2px 0;\n transition: all 0.2s ease;\n}\n.social-link-footer:hover .linkedin-icon {\n border-radius: 0;\n}\n.social-link-footer:hover .social-share-rss-image {\n border-radius: 0;\n}\n\n.social-link-footer img {\n width: 40px;\n height: auto;\n transition: filter 0.3s ease;\n}\n\n.social-share-list {\n width: 40px;\n}\n.social-share-rss-image {\n width: 40px;\n}\n\n.share-icon {\n border: 2px solid transparent;\n display: inline-block;\n position: relative;\n}\n\n.share-icon:hover {\n opacity: 1;\n border: 2px solid white;\n box-sizing: border-box;\n}\n\n.share-icon:hover .label {\n opacity: 1;\n visibility: visible;\n border: 2px solid white;\n box-sizing: border-box;\n border-left: none;\n}\n\n.label {\n position: absolute;\n left: 100%;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n color: white;\n border-radius: 0 10 0 10px;\n top: 50%;\n transform: translateY(-50%);\n height: 40px;\n border-radius: 0 6px 6px 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px 5px 20px 8px;\n margin-left: -1px;\n}\n.linkedin {\n background-color: #0474b4;\n}\n.facebook {\n background-color: #3c5c9c;\n}\n.twitter {\n background-color: white;\n color: black;\n}\n.reddit {\n background-color: #fc4404;\n}\n.mail {\n background-color: #848484;\n}\n.bluesky {\n background-color: white;\n color: black;\n}\n.rss {\n background-color: #ec7b1c;\n}\n#RSS {\n width: 40px;\n height: 40px;\n}\n\n@media (max-width: 991px) {\n .social-share {\n display: none;\n }\n}\n","texts":{"New tab":"What's New","New 1":"Surface Laptop Studio 2","New 2":"Surface Laptop Go 3","New 3":"Surface Pro 9","New 4":"Surface Laptop 5","New 5":"Surface Studio 2+","New 6":"Copilot in Windows","New 7":"Microsoft 365","New 8":"Windows 11 apps","Store tab":"Microsoft Store","Store 1":"Account Profile","Store 2":"Download Center","Store 3":"Microsoft Store Support","Store 4":"Returns","Store 5":"Order tracking","Store 6":"Certified Refurbished","Store 7":"Microsoft Store Promise","Store 8":"Flexible Payments","Education tab":"Education","Edu 1":"Microsoft in education","Edu 2":"Devices for education","Edu 3":"Microsoft Teams for Education","Edu 4":"Microsoft 365 Education","Edu 5":"How to buy for your school","Edu 6":"Educator Training and development","Edu 7":"Deals for students and parents","Edu 8":"Azure for students","Business tab":"Business","Bus 1":"Microsoft Cloud","Bus 2":"Microsoft Security","Bus 3":"Dynamics 365","Bus 4":"Microsoft 365","Bus 5":"Microsoft Power Platform","Bus 6":"Microsoft Teams","Bus 7":"Microsoft Industry","Bus 8":"Small Business","Developer tab":"Developer & IT","Dev 1":"Azure","Dev 2":"Developer Center","Dev 3":"Documentation","Dev 4":"Microsoft Learn","Dev 5":"Microsoft Tech Community","Dev 6":"Azure Marketplace","Dev 7":"AppSource","Dev 8":"Visual Studio","Company tab":"Company","Com 1":"Careers","Com 2":"About Microsoft","Com 3":"Company News","Com 4":"Privacy at Microsoft","Com 5":"Investors","Com 6":"Diversity and inclusion","Com 7":"Accessiblity","Com 8":"Sustainibility"},"defaults":{"config":{"applicablePages":[],"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.MicrosoftFooter","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":{"css":".custom_widget_MicrosoftFooter_context-uhf_105bp_1 {\n min-width: 17.5rem;\n font-size: 0.9375rem;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-link_105bp_12 {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff_105bp_12 {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.custom_widget_MicrosoftFooter_c-uhff-nav_105bp_35 {\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n .custom_widget_MicrosoftFooter_c-heading-4_105bp_49 {\n color: #616161;\n word-break: break-word;\n font-size: 0.9375rem;\n line-height: 1.25rem;\n padding: 2.25rem 0 0.25rem;\n font-weight: 600;\n }\n .custom_widget_MicrosoftFooter_c-uhff-nav-row_105bp_57 {\n .custom_widget_MicrosoftFooter_c-uhff-nav-group_105bp_58 {\n display: block;\n float: left;\n min-height: 0.0625rem;\n vertical-align: text-top;\n padding: 0 0.75rem;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.custom_widget_MicrosoftFooter_c-list_105bp_78.custom_widget_MicrosoftFooter_f-bare_105bp_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 0.5rem 0;\n margin: 0;\n }\n }\n }\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff-base_105bp_94 {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 1.875rem 5% 1rem;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_105bp_107 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: left;\n margin: 0.1875rem 0;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_105bp_107:hover {\n text-decoration: underline;\n }\n ul.custom_widget_MicrosoftFooter_c-list_105bp_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: right;\n margin: 0.1875rem 0;\n color: #616161;\n li {\n padding: 0 1.5rem 0.25rem 0;\n display: inline-block;\n }\n }\n .custom_widget_MicrosoftFooter_c-list_105bp_78.custom_widget_MicrosoftFooter_f-bare_105bp_78 {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 1.875rem 1.5rem 1rem;\n }\n}\n.custom_widget_MicrosoftFooter_social-share_105bp_138 {\n position: fixed;\n top: 60%;\n transform: translateY(-50%);\n left: 0;\n z-index: 1000;\n}\n.custom_widget_MicrosoftFooter_sharing-options_105bp_146 {\n list-style: none;\n padding: 0;\n margin: 0;\n display: block;\n flex-direction: column;\n background-color: white;\n width: 2.6875rem;\n border-radius: 0 0.4375rem 0.4375rem 0;\n}\n.custom_widget_MicrosoftFooter_linkedin-icon_105bp_156 {\n border-top-right-radius: 7px;\n}\n.custom_widget_MicrosoftFooter_linkedin-icon_105bp_156:hover {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162 {\n border-bottom-right-radius: 7px;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162:hover {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169 {\n position: relative;\n display: block;\n margin: -0.125rem 0;\n transition: all 0.2s ease;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169:hover .custom_widget_MicrosoftFooter_linkedin-icon_105bp_156 {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169:hover .custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162 {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_105bp_169 img {\n width: 2.5rem;\n height: auto;\n transition: filter 0.3s ease;\n}\n.custom_widget_MicrosoftFooter_social-share-list_105bp_188 {\n width: 2.5rem;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162 {\n width: 2.5rem;\n}\n.custom_widget_MicrosoftFooter_share-icon_105bp_195 {\n border: 2px solid transparent;\n display: inline-block;\n position: relative;\n}\n.custom_widget_MicrosoftFooter_share-icon_105bp_195:hover {\n opacity: 1;\n border: 2px solid white;\n box-sizing: border-box;\n}\n.custom_widget_MicrosoftFooter_share-icon_105bp_195:hover .custom_widget_MicrosoftFooter_label_105bp_207 {\n opacity: 1;\n visibility: visible;\n border: 2px solid white;\n box-sizing: border-box;\n border-left: none;\n}\n.custom_widget_MicrosoftFooter_label_105bp_207 {\n position: absolute;\n left: 100%;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n color: white;\n border-radius: 0 10 0 0.625rem;\n top: 50%;\n transform: translateY(-50%);\n height: 2.5rem;\n border-radius: 0 0.375rem 0.375rem 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.25rem 0.3125rem 1.25rem 0.5rem;\n margin-left: -0.0625rem;\n}\n.custom_widget_MicrosoftFooter_linkedin_105bp_156 {\n background-color: #0474b4;\n}\n.custom_widget_MicrosoftFooter_facebook_105bp_237 {\n background-color: #3c5c9c;\n}\n.custom_widget_MicrosoftFooter_twitter_105bp_240 {\n background-color: white;\n color: black;\n}\n.custom_widget_MicrosoftFooter_reddit_105bp_244 {\n background-color: #fc4404;\n}\n.custom_widget_MicrosoftFooter_mail_105bp_247 {\n background-color: #848484;\n}\n.custom_widget_MicrosoftFooter_bluesky_105bp_250 {\n background-color: white;\n color: black;\n}\n.custom_widget_MicrosoftFooter_rss_105bp_254 {\n background-color: #ec7b1c;\n}\n#custom_widget_MicrosoftFooter_RSS_105bp_1 {\n width: 2.5rem;\n height: 2.5rem;\n}\n@media (max-width: 991px) {\n .custom_widget_MicrosoftFooter_social-share_105bp_138 {\n display: none;\n }\n}\n","tokens":{"context-uhf":"custom_widget_MicrosoftFooter_context-uhf_105bp_1","c-uhff-link":"custom_widget_MicrosoftFooter_c-uhff-link_105bp_12","c-uhff":"custom_widget_MicrosoftFooter_c-uhff_105bp_12","c-uhff-nav":"custom_widget_MicrosoftFooter_c-uhff-nav_105bp_35","c-heading-4":"custom_widget_MicrosoftFooter_c-heading-4_105bp_49","c-uhff-nav-row":"custom_widget_MicrosoftFooter_c-uhff-nav-row_105bp_57","c-uhff-nav-group":"custom_widget_MicrosoftFooter_c-uhff-nav-group_105bp_58","c-list":"custom_widget_MicrosoftFooter_c-list_105bp_78","f-bare":"custom_widget_MicrosoftFooter_f-bare_105bp_78","c-uhff-base":"custom_widget_MicrosoftFooter_c-uhff-base_105bp_94","c-uhff-ccpa":"custom_widget_MicrosoftFooter_c-uhff-ccpa_105bp_107","social-share":"custom_widget_MicrosoftFooter_social-share_105bp_138","sharing-options":"custom_widget_MicrosoftFooter_sharing-options_105bp_146","linkedin-icon":"custom_widget_MicrosoftFooter_linkedin-icon_105bp_156","social-share-rss-image":"custom_widget_MicrosoftFooter_social-share-rss-image_105bp_162","social-link-footer":"custom_widget_MicrosoftFooter_social-link-footer_105bp_169","social-share-list":"custom_widget_MicrosoftFooter_social-share-list_105bp_188","share-icon":"custom_widget_MicrosoftFooter_share-icon_105bp_195","label":"custom_widget_MicrosoftFooter_label_105bp_207","linkedin":"custom_widget_MicrosoftFooter_linkedin_105bp_156","facebook":"custom_widget_MicrosoftFooter_facebook_105bp_237","twitter":"custom_widget_MicrosoftFooter_twitter_105bp_240","reddit":"custom_widget_MicrosoftFooter_reddit_105bp_244","mail":"custom_widget_MicrosoftFooter_mail_105bp_247","bluesky":"custom_widget_MicrosoftFooter_bluesky_105bp_250","rss":"custom_widget_MicrosoftFooter_rss_105bp_254","RSS":"custom_widget_MicrosoftFooter_RSS_105bp_1"}},"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1745505307000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBanner-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBanner-1745505307000","value":{"messageMarkedAsSpam":"This post has been marked as spam","messageMarkedAsSpam@board:TKB":"This article has been marked as spam","messageMarkedAsSpam@board:BLOG":"This post has been marked as spam","messageMarkedAsSpam@board:FORUM":"This discussion has been marked as spam","messageMarkedAsSpam@board:OCCASION":"This event has been marked as spam","messageMarkedAsSpam@board:IDEA":"This idea has been marked as spam","manageSpam":"Manage Spam","messageMarkedAsAbuse":"This post has been marked as abuse","messageMarkedAsAbuse@board:TKB":"This article has been marked as abuse","messageMarkedAsAbuse@board:BLOG":"This post has been marked as abuse","messageMarkedAsAbuse@board:FORUM":"This discussion has been marked as abuse","messageMarkedAsAbuse@board:OCCASION":"This event has been marked as abuse","messageMarkedAsAbuse@board:IDEA":"This idea has been marked as abuse","preModCommentAuthorText":"This comment will be published as soon as it is approved","preModCommentModeratorText":"This comment is awaiting moderation","messageMarkedAsOther":"This post has been rejected due to other reasons","messageMarkedAsOther@board:TKB":"This article has been rejected due to other reasons","messageMarkedAsOther@board:BLOG":"This post has been rejected due to other reasons","messageMarkedAsOther@board:FORUM":"This discussion has been rejected due to other reasons","messageMarkedAsOther@board:OCCASION":"This event has been rejected due to other reasons","messageMarkedAsOther@board:IDEA":"This idea has been rejected due to other reasons","messageArchived":"This post was archived on {date}","relatedUrl":"View Related Content","relatedContentText":"Showing related content","archivedContentLink":"View Archived Content"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewStandard-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewStandard-1745505307000","value":{"anonymous":"Anonymous","author":"{messageAuthorLogin}","authorBy":"{messageAuthorLogin}","board":"{messageBoardTitle}","replyToUser":" to {parentAuthor}","showMoreReplies":"Show More","replyText":"Reply","repliesText":"Replies","markedAsSolved":"Marked as Solution","movedMessagePlaceholder.BLOG":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.TKB":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.FORUM":"{count, plural, =0 {This reply has been} other {These replies have been} }","movedMessagePlaceholder.IDEA":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.OCCASION":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholderUrlText":"moved.","messageStatus":"Status: ","statusChanged":"Status changed: {previousStatus} to {currentStatus}","statusAdded":"Status added: {status}","statusRemoved":"Status removed: {status}","labelExpand":"expand replies","labelCollapse":"collapse replies","unhelpfulReason.reason1":"Content is outdated","unhelpfulReason.reason2":"Article is missing information","unhelpfulReason.reason3":"Content is for a different Product","unhelpfulReason.reason4":"Doesn't match what I was searching for"},"localOverride":false},"CachedAsset:text:en_US-components/messages/ThreadedReplyList-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/ThreadedReplyList-1745505307000","value":{"title":"{count, plural, one{# Reply} other{# Replies}}","title@board:BLOG":"{count, plural, one{# Comment} other{# Comments}}","title@board:TKB":"{count, plural, one{# Comment} other{# Comments}}","title@board:IDEA":"{count, plural, one{# Comment} other{# Comments}}","title@board:OCCASION":"{count, plural, one{# Comment} other{# Comments}}","noRepliesTitle":"No Replies","noRepliesTitle@board:BLOG":"No Comments","noRepliesTitle@board:TKB":"No Comments","noRepliesTitle@board:IDEA":"No Comments","noRepliesTitle@board:OCCASION":"No Comments","noRepliesDescription":"Be the first to reply","noRepliesDescription@board:BLOG":"Be the first to comment","noRepliesDescription@board:TKB":"Be the first to comment","noRepliesDescription@board:IDEA":"Be the first to comment","noRepliesDescription@board:OCCASION":"Be the first to comment","messageReadOnlyAlert:BLOG":"Comments have been turned off for this post","messageReadOnlyAlert:TKB":"Comments have been turned off for this article","messageReadOnlyAlert:IDEA":"Comments have been turned off for this idea","messageReadOnlyAlert:FORUM":"Replies have been turned off for this discussion","messageReadOnlyAlert:OCCASION":"Comments have been turned off for this event"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyCallToAction-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyCallToAction-1745505307000","value":{"leaveReply":"Leave a reply...","leaveReply@board:BLOG@message:root":"Leave a comment...","leaveReply@board:TKB@message:root":"Leave a comment...","leaveReply@board:IDEA@message:root":"Leave a comment...","leaveReply@board:OCCASION@message:root":"Leave a comment...","repliesTurnedOff.FORUM":"Replies are turned off for this topic","repliesTurnedOff.BLOG":"Comments are turned off for this topic","repliesTurnedOff.TKB":"Comments are turned off for this topic","repliesTurnedOff.IDEA":"Comments are turned off for this topic","repliesTurnedOff.OCCASION":"Comments are turned off for this topic","infoText":"Stop poking me!"},"localOverride":false},"Category:category:Exchange":{"__typename":"Category","id":"category:Exchange","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Outlook":{"__typename":"Category","id":"category:Outlook","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Community-Info-Center":{"__typename":"Category","id":"category:Community-Info-Center","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:EducationSector":{"__typename":"Category","id":"category:EducationSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:DrivingAdoption":{"__typename":"Category","id":"category:DrivingAdoption","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Azure":{"__typename":"Category","id":"category:Azure","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows-Server":{"__typename":"Category","id":"category:Windows-Server","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftTeams":{"__typename":"Category","id":"category:MicrosoftTeams","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PublicSector":{"__typename":"Category","id":"category:PublicSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:IoT":{"__typename":"Category","id":"category:IoT","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:HealthcareAndLifeSciences":{"__typename":"Category","id":"category:HealthcareAndLifeSciences","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:ITOpsTalk":{"__typename":"Category","id":"category:ITOpsTalk","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftLearn":{"__typename":"Category","id":"category:MicrosoftLearn","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Blog:board:MicrosoftLearnBlog":{"__typename":"Blog","id":"board:MicrosoftLearnBlog","blogPolicies":{"__typename":"BlogPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:AI":{"__typename":"Category","id":"category:AI","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftMechanics":{"__typename":"Category","id":"category:MicrosoftMechanics","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftforNonprofits":{"__typename":"Category","id":"category:MicrosoftforNonprofits","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:StartupsatMicrosoft":{"__typename":"Category","id":"category:StartupsatMicrosoft","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PartnerCommunity":{"__typename":"Category","id":"category:PartnerCommunity","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Microsoft365Copilot":{"__typename":"Category","id":"category:Microsoft365Copilot","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows":{"__typename":"Category","id":"category:Windows","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Content_Management":{"__typename":"Category","id":"category:Content_Management","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft-security":{"__typename":"Category","id":"category:microsoft-security","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoftintune":{"__typename":"Category","id":"category:microsoftintune","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"CachedAsset:text:en_US-components/community/Navbar-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1745505307000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","gxcuf89792":"Tech Community","external-1":"Events","s-m-b":"Nonprofit Community","windows-server":"Windows Server","education-sector":"Education Sector","driving-adoption":"Driving Adoption","Common-content_management-link":"Content Management","microsoft-learn":"Microsoft Learn","s-q-l-server":"Content Management","partner-community":"Microsoft Partner Community","microsoft365":"Microsoft 365","external-9":".NET","external-8":"Teams","external-7":"Github","products-services":"Products","external-6":"Power Platform","communities-1":"Topics","external-5":"Microsoft Security","planner":"Outlook","external-4":"Microsoft 365","external-3":"Dynamics 365","azure":"Azure","healthcare-and-life-sciences":"Healthcare and Life Sciences","external-2":"Azure","microsoft-mechanics":"Microsoft Mechanics","microsoft-learn-1":"Community","external-10":"Learning Room Directory","microsoft-learn-blog":"Blog","windows":"Windows","i-t-ops-talk":"ITOps Talk","external-link-1":"View All","microsoft-securityand-compliance":"Microsoft Security","public-sector":"Public Sector","community-info-center":"Lounge","external-link-2":"View All","microsoft-teams":"Microsoft Teams","external":"Blogs","microsoft-endpoint-manager":"Microsoft Intune","startupsat-microsoft":"Startups at Microsoft","exchange":"Exchange","a-i":"AI and Machine Learning","io-t":"Internet of Things (IoT)","Common-microsoft365-copilot-link":"Microsoft 365 Copilot","outlook":"Microsoft 365 Copilot","external-link":"Community Hubs","communities":"Products"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1745505307000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1745505307000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1745505307000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1745505307000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1745505307000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCoverImage-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCoverImage-1745505307000","value":{"coverImageTitle":"Cover Image"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeTitle-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeTitle-1745505307000","value":{"nodeTitle":"{nodeTitle, select, community {Community} other {{nodeTitle}}} "},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTimeToRead-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTimeToRead-1745505307000","value":{"minReadText":"{min} MIN READ"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1745505307000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1745505307000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserRank-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserRank-1745505307000","value":{"rankName":"{rankName}","userRank":"Author rank {rankName}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1745505307000","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1745505307000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCustomFields-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCustomFields-1745505307000","value":{"CustomField.default.label":"Value of {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRevision-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRevision-1745505307000","value":{"lastUpdatedDatePublished":"{publishCount, plural, one{Published} other{Updated}} {date}","lastUpdatedDateDraft":"Created {date}","version":"Version {major}.{minor}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1745505307000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyButton-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyButton-1745505307000","value":{"repliesCount":"{count}","title":"Reply","title@board:BLOG@message:root":"Comment","title@board:TKB@message:root":"Comment","title@board:IDEA@message:root":"Comment","title@board:OCCASION@message:root":"Comment"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageAuthorBio-1745505307000","value":{"sendMessage":"Send Message","actionMessage":"Follow this blog board to get notified when there's new activity","coAuthor":"CO-PUBLISHER","contributor":"CONTRIBUTOR","userProfile":"View Profile","iconlink":"Go to {name} {type}"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1745505307000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1745505307000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/ranks/UserRankLabel-1745505307000","value":{"altTitle":"Icon for {rankName} rank"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagView/TagViewChip-1745505307000","value":{"tagLabelName":"Tag name {tagName}"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserRegistrationDate-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserRegistrationDate-1745505307000","value":{"noPrefix":"{date}","withPrefix":"Joined {date}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeAvatar-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeAvatar-1745505307000","value":{"altTitle":"Node avatar for {nodeTitle}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeDescription-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeDescription-1745505307000","value":{"description":"{description}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1745505307000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1745505307000","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false}}}},"page":"/blogs/BlogMessagePage/BlogMessagePage","query":{"boardId":"modernworkappconsult","messageSubject":"push-notifications-in-a-pwa-running-on-windows-10","messageId":"317283"},"buildId":"-gVUpXaWnPcjlrLJZ92B7","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"o365","openTelemetryServiceVersion":"25.3.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/customComponent/CustomComponent/CustomComponent.tsx","./components/blogs/BlogArticleWidget/BlogArticleWidget.tsx","./components/messages/MessageView/MessageViewStandard/MessageViewStandard.tsx","./components/messages/ThreadedReplyList/ThreadedReplyList.tsx","./components/external/components/ExternalComponent.tsx","../shared/client/components/common/List/UnwrappedList/UnwrappedList.tsx","./components/tags/TagView/TagView.tsx","./components/tags/TagView/TagViewChip/TagViewChip.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx"],"appGip":true,"scriptLoader":[{"id":"analytics","src":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/pagescripts/1730819800000/analytics.js?page.id=BlogMessagePage&entity.id=board%3Amodernworkappconsult&entity.id=message%3A317283","strategy":"afterInteractive"}]}