<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Liangying.Wei</title>
    <description>The latest articles on DEV Community by Liangying.Wei (@vicancy).</description>
    <link>https://dev.to/vicancy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F775866%2F40aef651-300d-4e0f-a44f-bac2d2c312ae.jpeg</url>
      <title>DEV Community: Liangying.Wei</title>
      <link>https://dev.to/vicancy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vicancy"/>
    <language>en</language>
    <item>
      <title>Add real-time capability to your application using Web PubSub and API Management</title>
      <dc:creator>Liangying.Wei</dc:creator>
      <pubDate>Thu, 06 Jan 2022 08:03:56 +0000</pubDate>
      <link>https://dev.to/azure/add-real-time-capability-to-your-application-using-web-pubsub-and-api-management-268j</link>
      <guid>https://dev.to/azure/add-real-time-capability-to-your-application-using-web-pubsub-and-api-management-268j</guid>
      <description>&lt;p&gt;Businesses everywhere are looking to extend their operations as a digital platform, creating new channels, finding new customers, and driving deeper engagement with existing ones. Now, with the &lt;a href="https://azure.microsoft.com/services/api-management" rel="noopener noreferrer"&gt;API Management (APIM)&lt;/a&gt; and &lt;a href="https://azure.microsoft.com/en-us/services/web-pubsub/#overview" rel="noopener noreferrer"&gt;Web PubSub service (AWPS)&lt;/a&gt;, you are able to expand the real-time messaging capability of your application with a consistent and modern API gateway.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build apps faster and deliver immediate value to your customers through API-first approaches.&lt;/li&gt;
&lt;li&gt;Transform your legacy services into modern REST-based APIs or WebSocket APIs.&lt;/li&gt;
&lt;li&gt;Consistent experience to manage APIs (REST and WebSocket) across clouds and on-premises.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334297i8992406D73FCD7F0%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334297i8992406D73FCD7F0%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" alt="The overall architecture using Web PubSub and API Management"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s go through the key steps together and learn how to implement this reference solution:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the Azure Web PubSub Service&lt;/li&gt;
&lt;li&gt;Create the Azure API Management service and configure the WebSocket rules&lt;/li&gt;
&lt;li&gt;Update a Web PubSub sample to use the created Azure API Management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup Web PubSub
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Follow the &lt;a href="https://docs.microsoft.com/azure/azure-web-pubsub/howto-develop-create-instance" rel="noopener noreferrer"&gt;steps&lt;/a&gt; to create your Web PubSub service which we refer to as &lt;strong&gt;AWPS1&lt;/strong&gt; in the following sections.&lt;/li&gt;
&lt;li&gt;When created, go to the &lt;strong&gt;Keys&lt;/strong&gt; tab for the resource from the Azure portal, and you can see the hostname and connection strings of your resource. There is also a &lt;strong&gt;Client URL Generator tool&lt;/strong&gt; in the portal that it can generate some temporarily valid URLs for your WebSocket clients to connect to. Let's use this tool to generate an URL for our demo with a hub called &lt;em&gt;&lt;strong&gt;demoHub&lt;/strong&gt;&lt;/em&gt;. This tool is for quick test purposes only, we also provide APIs in various languages to generate the URL for production usage, for example, &lt;a href="https://docs.microsoft.com/dotnet/api/azure.messaging.webpubsub.webpubsubserviceclient.getclientaccessuri?view=azure-dotnet" rel="noopener noreferrer"&gt;WebPubSubServiceClient.GetClientAccessUri Method for .NET&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy&lt;/strong&gt; the generated &lt;strong&gt;Client Access URL&lt;/strong&gt; for later use. Let's have a quick look into the &lt;strong&gt;Client Access URL&lt;/strong&gt;, it contains:

&lt;ul&gt;
&lt;li&gt;the hostname of the Web PubSub service &lt;em&gt;&lt;strong&gt;xxx.webpubsub.azure.com&lt;/strong&gt;&lt;/em&gt; with &lt;em&gt;&lt;strong&gt;wss&lt;/strong&gt;&lt;/em&gt; scheme,&lt;/li&gt;
&lt;li&gt;and the path containing the hub name &lt;em&gt;&lt;strong&gt;/client/hubs/demoHub&lt;/strong&gt;&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;and a query parameter &lt;em&gt;&lt;strong&gt;access_token&lt;/strong&gt;&lt;/em&gt; which is the &lt;strong&gt;JWT&lt;/strong&gt; token that the Web PubSub service uses to validate and authenticate the WebSocket clients. 
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334631i5358313326E447A0%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" alt="The Keys tab to get the Client Access URL"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setup API Management
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Follow the &lt;a href="https://docs.microsoft.com/azure/api-management/get-started-create-service-instance" rel="noopener noreferrer"&gt;steps&lt;/a&gt; to create your API Management service which we refer to as &lt;strong&gt;APIM1&lt;/strong&gt; in the following sections.&lt;/li&gt;
&lt;li&gt;When created, go to the &lt;strong&gt;APIs&lt;/strong&gt; tab for the resource from the Azure portal, click &lt;strong&gt;Add API&lt;/strong&gt; and choose &lt;strong&gt;WebSocket&lt;/strong&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334319i04767427E08A4946%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" alt="Add the WebSocket API"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create with the following parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WebSocket URL&lt;/strong&gt;: &lt;code&gt;wss://&amp;lt;your_webpubsub_name&amp;gt;.webpubsub.azure.com/client/hubs/demoHub&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;&amp;lt;your_webpubsub_name&amp;gt;&lt;/code&gt; with the name of your &lt;strong&gt;AWPS1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API URL suffix&lt;/strong&gt;: ·client/hubs/demoHub·
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334632iBCE9E24FD71813F4%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" alt="Set the WebSocket API"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now you are all set, select the API and use the &lt;strong&gt;Test&lt;/strong&gt; tab to test the connection.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remember the &lt;strong&gt;access_token&lt;/strong&gt; query parameter we get from the &lt;strong&gt;AWPS1&lt;/strong&gt; Client Access URL? Paste it here as the &lt;strong&gt;access_token&lt;/strong&gt; query parameter, and &lt;strong&gt;Connect&lt;/strong&gt;.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334635i0C371B28D440C83E%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" alt="Test the WebSocket API"&gt;
&lt;/li&gt;
&lt;li&gt;You can now see in the output &lt;strong&gt;Connected&lt;/strong&gt;
 &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F334636i48FF3DD93018DB82%2Fimage-size%2Flarge%3Fv%3Dv2%26px%3D999" alt="Result for the WebSocket API test"&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try samples
&lt;/h2&gt;

&lt;p&gt;Let's update this &lt;a href="https://docs.microsoft.com/azure/azure-web-pubsub/tutorial-pub-sub-messages?tabs=csharp" rel="noopener noreferrer"&gt;publish and subscribe message sample&lt;/a&gt; to use &lt;strong&gt;APIM1&lt;/strong&gt;, the &lt;strong&gt;only&lt;/strong&gt; thing to change is to let &lt;a href="https://docs.microsoft.com/azure/azure-web-pubsub/tutorial-pub-sub-messages?tabs=csharp#set-up-the-subscriber" rel="noopener noreferrer"&gt;the WebSocket subscriber&lt;/a&gt; connect to &lt;strong&gt;APIM1&lt;/strong&gt; instead.&lt;/p&gt;

&lt;p&gt;After the subscriber gets the full URL to connect to &lt;strong&gt;AWPS1&lt;/strong&gt;, let's update the &lt;strong&gt;URL&lt;/strong&gt; to connect to &lt;strong&gt;APIM&lt;/strong&gt;, and don't forget to append the &lt;strong&gt;subscription-key&lt;/strong&gt; query parameter if your APIM settings enabled it.&lt;/p&gt;

&lt;p&gt;For example, in C#, update the code as below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebPubSubServiceClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetClientAccessUri&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Replace the Host with APIM1's, and append APIM1's subscription-key query parameter if it is enabled&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;urlBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UriBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Replace the hostname with APIM's&lt;/span&gt;
    &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;APIM1_host_name&amp;gt;.azure-api.net"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the subscription-key if you enabled it in APIM portal&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;subscriptionKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;the_subscription_key&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;subscriptionKeyQuery&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"subscription-key=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subscriptionKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;subscriptionKeyQuery&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subscriptionKeyQuery&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;apim1Url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Start the WebSocket connection&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebsocketClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apim1Url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>azure</category>
      <category>websocket</category>
      <category>apim</category>
      <category>webpubsub</category>
    </item>
  </channel>
</rss>
