<?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>Forem: Dino Lozina</title>
    <description>The latest articles on Forem by Dino Lozina (@dlozina).</description>
    <link>https://forem.com/dlozina</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%2F658305%2F5bc405ee-69b2-4afe-9f33-4b658b388bad.jpeg</url>
      <title>Forem: Dino Lozina</title>
      <link>https://forem.com/dlozina</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dlozina"/>
    <language>en</language>
    <item>
      <title>Write a URL Shortener in 26 Lines of Code with .NET Minimal APIs</title>
      <dc:creator>Dino Lozina</dc:creator>
      <pubDate>Thu, 13 Jan 2022 13:16:45 +0000</pubDate>
      <link>https://forem.com/infobipdev/write-a-url-shortener-in-26-lines-of-code-with-net-minimal-apis-2k0k</link>
      <guid>https://forem.com/infobipdev/write-a-url-shortener-in-26-lines-of-code-with-net-minimal-apis-2k0k</guid>
      <description>&lt;p&gt;I was looking forward to .NET minimal API framework for a very long time and now, it is finally out! Let’s dive into new version of .NET6 and answer the following questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is .NET minimal API?&lt;/li&gt;
&lt;li&gt;How to refactor existing URL shortener?&lt;/li&gt;
&lt;li&gt;How to add dependency to service?&lt;/li&gt;
&lt;li&gt;How to add endpoint to service?&lt;/li&gt;
&lt;li&gt;Where are using statements?&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🤔 1. Introducing .NET Minimal APIs
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;”Do you need all of this stuff just to shorten URL?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was a first reaction of a friend (who happens to be a Python programmer) when I showed him my &lt;a href="https://github.com/dlozina/url-shortener-service-v2"&gt;first shortner example&lt;/a&gt;. "Yes" would have been a pretty accurate answer, but not the one that I’d be happy with.&lt;/p&gt;

&lt;p&gt;There was a lot of boilerplate code compared to other frameworks.&lt;br&gt;
One benefit is that the structure is already set up — very convenient when we have larger projects to tackle. On the other hand, not ideal when I need to create a small service as part of a microservices architecture. &lt;br&gt;
Most SaaS providers are using microservice architecture for its scalability,smaller/faster deployments, and ease of understanding.&lt;/p&gt;

&lt;p&gt;Take a look at the Flask API template:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In just 5 lines of code, we have our first endpoint! Single file, no other setup needed. All we need to focus on is the feature of this new service.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at the .NET template. Out of the box we get &lt;em&gt;Startup.cs&lt;/em&gt;, &lt;em&gt;Program.cs&lt;/em&gt;, &lt;em&gt;Controllers&lt;/em&gt;…a lot of boilerplate code. This could be unnecessary if the goal is to write one small service as part of a SaaS product or just a prototype.  &lt;/p&gt;

&lt;p&gt;Fortunately, .NET6 addresses this issue. Let's rewrite the previous example in &lt;strong&gt;.NET6 with a new template&lt;/strong&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;4 lines of code for our first endpoint and a single file. This is new .NET minimal API!&lt;/p&gt;

&lt;p&gt;Back to my friend’s question - &lt;em&gt;“Do you need all of this stuff just to shorten URL?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No.&lt;br&gt;
I can do better.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✂️ 2. Refactored URL shortener example
&lt;/h3&gt;

&lt;p&gt;A while back, I wrote a post on &lt;a href="https://dev.to/infobipdev/how-to-write-url-shortener-in-net5-weve-made-it-seem-easy-1-5c56"&gt;how to create a URL shortener in .NET5&lt;/a&gt;), but I never imagined that I'd be able to rewrite it in 26 lines of code and a single file.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Note: we actually have two files—we will get to the bottom of that in the fifth section, bear with me.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Refactored code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can find the previous URL shortener example in this &lt;a href="https://github.com/dlozina/url-shortener-service-v2"&gt;github repository&lt;/a&gt;. There is nothing minimal about the codebase.&lt;br&gt;&lt;br&gt;
If we compare the old code to our minimal shortener, we will see the hidden complexity of the minimal API framework right away.&lt;/p&gt;

&lt;p&gt;We start from scratch in the minimal API template and only introduce the dependencies we need. We can concentrate on the important stuff—the code for the requested feature.   &lt;/p&gt;

&lt;p&gt;Let's analyse the code and see what new things come with .NET6 that you could start implementing in your services.&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚙️ 3. Adding Dependencies
&lt;/h3&gt;

&lt;p&gt;My service needs database, so I'm adding a dependency to LiteDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package LiteDB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Usually, we would go to Startup.cs and set up our dependency. Since we don’t have one, the way to go is shown below on line 2. Same code, different position.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  🔗 4. Adding an Endpoint
&lt;/h3&gt;

&lt;p&gt;All the methods we need are in the app—or should I say framework?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MapGet(pattern, handler)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MapPost(pattern, handler)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MapPut(pattern, handler)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MapDelete(pattern, handler)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check how to implement &lt;code&gt;POST&lt;/code&gt; method and &lt;code&gt;GET&lt;/code&gt; method in the example below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The first parameter is route pattern, the second parameter is handler. The handler is delegate executed when endpoint is matched.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;Url&lt;/code&gt; object is &lt;code&gt;record&lt;/code&gt;, also something new in .NET6. It could be a class as well, but I just wanted to shred couple of lines of code to get those 26 magic lines.&lt;/p&gt;

&lt;p&gt;Data that our &lt;code&gt;POST&lt;/code&gt; method (body of req) needs to contain is&lt;br&gt;
defined by the &lt;code&gt;record&lt;/code&gt;. (It is enough to send &lt;code&gt;longURL&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt; will be set automatically by our &lt;code&gt;db&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;We have our database in the list of services that our app uses. The next step is to inject it into the endpoint. The delegate needs to have our database context to add data from the client to the database.&lt;/p&gt;

&lt;p&gt;In the end, set up your service address and port.&lt;br&gt;
And you are done!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.Run("http://localhost:4000");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  🙋 5. Where are using statements?
&lt;/h3&gt;

&lt;p&gt;Global using statements is another feature I am happy with. Do you remember something like this on top of every file in your project?&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Reflection;
using System.Linq;
using System.Net.Http;
using System.Linq;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Implicit usings are hidden in auto generated file inside your &lt;em&gt;obj&lt;/em&gt; folder. That file declares global &lt;code&gt;using&lt;/code&gt; statements behind the scenes. If you go to project folder then go &lt;em&gt;obj/Debug/net6.0&lt;/em&gt;, you will find a file titled &lt;em&gt;“{ProjectName}.GlobalUsings.g.cs”&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Open this file, and see the content:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Since this is an autogenerated file, we can’t edit it here. &lt;br&gt;
In our minimal shortener we have two packages (LiteDB, Hashids.net) that we depend upon, and we will actually need to place &lt;code&gt;using&lt;/code&gt; statements in our &lt;em&gt;Program.cs&lt;/em&gt; to use code from packages.&lt;/p&gt;

&lt;p&gt;Instead, let's manually create a file that will hold our global &lt;code&gt;using&lt;/code&gt; statements. This way, we keep our &lt;em&gt;Program.cs&lt;/em&gt; free from all using statements.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;It might be overkill in this particular example, but imagine adding more dependencies. It is a good option for keeping code clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎊 So, is it possible? Of course! 🎊
&lt;/h3&gt;

&lt;p&gt;Most of the time, we don’t need all the ceremony that we got with previous .NET webapi templates. &lt;/p&gt;

&lt;p&gt;Now we have the option to start from scratch and add only stuff that we really need. Missing MVC Controllers? No problem.Add them later. Need Authentication? Same thing.&lt;/p&gt;

&lt;p&gt;The template code has fewer files and a more intuitive setup for newcomers in the .NET world—this is probably one of the best benefits of this framework. I am really looking forward to seeing what future updates bring along.  &lt;/p&gt;

&lt;p&gt;If you enjoyed following along and building your own URL shortener in .NET6, keep an eye out for this blog!&lt;br&gt;
In the next article, we will place this minimal URL Shortener in Docker and explore another essential piece of the tech stack.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to schedule tasks in .NET? We've made it seem easy #2</title>
      <dc:creator>Dino Lozina</dc:creator>
      <pubDate>Thu, 18 Nov 2021 08:25:29 +0000</pubDate>
      <link>https://forem.com/infobipdev/how-to-schedule-tasks-in-net-weve-made-it-seem-easy-2-511n</link>
      <guid>https://forem.com/infobipdev/how-to-schedule-tasks-in-net-weve-made-it-seem-easy-2-511n</guid>
      <description>&lt;p&gt;Welcome to the second part of the series about "URL shortener in .NET". In the first post of this series we created simple URL shortener web service, and tested it manually with Postman. Check &lt;a href="https://dev.to/infobipdev/how-to-write-url-shortener-in-net5-weve-made-it-seem-easy-1-5c56"&gt;part one&lt;/a&gt; here or skip it if you only want to find out how to schedule services in .NET.&lt;/p&gt;

&lt;p&gt;In part two, we want to expand functionality of our web service with some additional features, such as SMS reports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This post aims to show you:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to send SMS &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to easily add scheduler to our web service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to send SMS periodically &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use my &lt;a href="https://github.com/dlozina/url-shortener-service-v2"&gt;github&lt;/a&gt; to find a finished project and avoid the nuisance of writing the code yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  📱 &lt;strong&gt;First Step: Send SMS&lt;/strong&gt; ✔️
&lt;/h3&gt;

&lt;p&gt;For our SMS provider we will use Infobip. Please access our free trial self service account through this &lt;a href="https://www.infobip.com/docs/api"&gt;link&lt;/a&gt;. After grabbing our API key and URL you just need to implement client library in the project. &lt;/p&gt;

&lt;p&gt;Library: (&lt;a href="https://github.com/infobip/infobip-api-csharp-client"&gt;github&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Infobip.Api.Client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, place your user settings in &lt;em&gt;appsettings.json&lt;/em&gt;, so that you can easily grab them through our web app.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Based on Infobip library, we will create method SendNotificationSms:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's go through &lt;code&gt;SendNotificationSms(string smsNotificationMessage)&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we set up the configuration we will send to &lt;code&gt;SendSmsApi&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;Then create &lt;code&gt;SmsTextualMessage&lt;/code&gt; by setting up Form, Destination and Text fields.&lt;/li&gt;
&lt;li&gt;Finally, add created message to &lt;code&gt;SmsAdvancedTextualRequest&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SendSmsMessage method from Infobip library will do the trick and send the message to our user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;smsResponse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sendSmsApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendSmsMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;smsRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that the basic functionality is up and running, adding it to your scheduler shouldn't be a problem. &lt;/p&gt;
&lt;h3&gt;
  
  
  ⏰ &lt;strong&gt;Second Step: Add scheduler&lt;/strong&gt; ✔️
&lt;/h3&gt;

&lt;p&gt;For this feature we will use Quartz.NET. &lt;br&gt;
One could describe Quartz.NET as a full-featured, open-source job-scheduling system.&lt;/p&gt;

&lt;p&gt;There are two important points you need to know; Job Scheduling and Job Execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Job Scheduling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jobs are scheduled to run when a given trigger occurs, triggers support wide variety of scheduling options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Job Execution&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jobs can be any .NET class that implements the simple &lt;code&gt;IJob&lt;/code&gt; interface, leaving infinite possibilities for the work that jobs can perform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets's add package to our project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Quartz.Extensions.Hosting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, we have to configure and register our Quartz service. Use &lt;em&gt;Program.cs&lt;/em&gt; for that. You can follow documentation &lt;a href="https://www.quartz-scheduler.net/"&gt;https://www.quartz-scheduler.net/&lt;/a&gt; on how to configure and register in detail. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;In this code example, we try to keep &lt;em&gt;Program.cs&lt;/em&gt; as short as possible, hence the extension method for our settings.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  ⏲️ &lt;strong&gt;Third Step: Send SMS periodically&lt;/strong&gt; ✔️
&lt;/h3&gt;

&lt;p&gt;Scheduler is all set up and now you need to add jobs. In our report feature we decided to send SMS messages daily, weekly and monthly. &lt;/p&gt;

&lt;p&gt;Example &lt;a href="https://github.com/dlozina/url-shortener-service-v2"&gt;project&lt;/a&gt; has three jobs defined in project Jobs folder.&lt;/p&gt;

&lt;p&gt;Remember: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jobs can be any .NET class that implements the simple &lt;code&gt;IJob&lt;/code&gt; interface.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example code below sends daily SMS report of how many URLs are shortened:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You may ask yourself: Where is the scheduled time in this code? How can I change it?&lt;/p&gt;

&lt;p&gt;Well…that is the beauty of Quartz - it uses Cron expression which is easy to set up.&lt;br&gt;
For example, we have moved scheduler setup to our application settings, so there are separate settings for every job in our application.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can check out for various settings on &lt;a href="https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/crontriggers.html"&gt;cron triggers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cron expression: "0 0 8 ? * MON-SUN" -&amp;gt; Daily - MON-SUN on 08:00 CET for the previous day&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cron expression: "0 1 8 ? * MON" -&amp;gt; Weekly - MON on 08:01 CET for the past week&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cron expression: "0 2 8 * * MON#1" -&amp;gt; Monthly - first MON on the month for the past month&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you go back to &lt;em&gt;Program.cs&lt;/em&gt; you will see how we grab and use this settings with our extension method.&lt;/p&gt;

&lt;p&gt;Now our web service is ready to send scheduled reports to users.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Conclusion 🎉 🍾&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It comes as no surprise that scheduling jobs in applications can be a really daunting work. Quartz makes it so much easier. Bare in mind that we just scratched the surface with our settings. There is a lot more stuff under the hood but probably this is enough for most of use cases.&lt;/p&gt;

&lt;p&gt;The same thing can be said about our SMS notification feature. You don't need to write API request to Infobip platform. Just add library to your .NET project, set config, create your message objects and than send an SMS. It is also possible to expand this simple example and send reports with other&lt;br&gt;
information channels, such as Email and Whatsapp.&lt;br&gt;
Find other available options on &lt;a href="https://www.infobip.com/docs/api"&gt;Infobip Api&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stay well,&lt;/p&gt;

&lt;p&gt;Dino&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to write URL shortener in .NET5? We've made it seem easy #1</title>
      <dc:creator>Dino Lozina</dc:creator>
      <pubDate>Thu, 11 Nov 2021 09:10:04 +0000</pubDate>
      <link>https://forem.com/infobipdev/how-to-write-url-shortener-in-net5-weve-made-it-seem-easy-1-5c56</link>
      <guid>https://forem.com/infobipdev/how-to-write-url-shortener-in-net5-weve-made-it-seem-easy-1-5c56</guid>
      <description>&lt;p&gt;Welcome to our tutorial series, a place to be for those looking for a quick and efficient guide to writing URL shortener.&lt;br&gt;&lt;br&gt;
In this series we will try to show you how easy it is to write a service that shortens URLs with .NET5. On top of that, we will add an additional functionality - service will have to send an SMS when target URL is shortened and periodically send SMS reports.&lt;/p&gt;

&lt;p&gt;Stick with me until the end and you will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create youtube like links for short URLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use embedded NoSQL database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schedule web service, ex. send reports every day, week and/or month&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send SMS from our service&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just to give you heads up, this is by no means an extensive tutorial on how to build production grade shortening systems. For production grade systems we need to take into account scale and load. It would be nice to have some kind of analytics, but we have to start from somewhere, right?&lt;/p&gt;

&lt;p&gt;Software engineering nowadays can be compared to playing with LEGO bricks. All the nice bricks are out there, we need to implement them in a smart way. We don't want to reinvent the wheel every time we start programming, so we're going to use a couple of packages to make all this magic happen.&lt;/p&gt;

&lt;p&gt;First, we're going to need some SDK-s and tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For IDE we can use (&lt;a href="https://code.visualstudio.com/"&gt;https://code.visualstudio.com/&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need .NET core SDK (&lt;a href="https://dotnet.microsoft.com/download"&gt;https://dotnet.microsoft.com/download&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Postman (&lt;a href="https://www.postman.com/downloads/"&gt;https://www.postman.com/downloads/&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On my &lt;a href="https://github.com/dlozina/url-shortener-service-v2"&gt;github&lt;/a&gt; you will find the finished project so there's no need for you to write code yourself.&lt;/p&gt;

&lt;p&gt;Once we have .NET framework in place we will just check if everything is working for us with (type in terminal):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the test we can create our template project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new webapi -n "Shortener.Service" -lang "C#" -au none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;*&lt;em&gt;parameter -au none means there is no default authentication for our webapi&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With this command we get template webapi project. Now that we have all things up and running let’s start with step by step guide.&lt;/p&gt;
&lt;h3&gt;
  
  
  🎮 &lt;strong&gt;First Step: Create controller methods ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Remove default web api controller and create your own. For this simple example we will have one GET and one POST method.&lt;/p&gt;

&lt;p&gt;Let’s dig into POST method. User will provide us with URL (simple UrlDataDto object) that needs to be shortened. We will store that URL we will store in LiteDB.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;GET method needs a parameter shortUrl. If we have that shortUrl in our database, method will redirect us to “long” URL if request was made by browser. Request could also be made by “thin” client like Postman, so we will make sure that we return JSON with “long” URL. (In that case we don’t want to redirect) &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  💾 &lt;strong&gt;Second Step: Add database ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As mentioned, we need DB to store our shortened URLs. For this small service we really don’t want to install DB or do something beforehand. Goal is just to “press play” and our app is ready to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package LiteDB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will give us small NoSql database, perfect for our proof of concept.&lt;/p&gt;

&lt;p&gt;Now we need to link our application with DB:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚙️ &lt;strong&gt;Third Step: Add services ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As you can see, our controller is simple and whole business logic is in services. Let’s just check what we did in services.&lt;/p&gt;

&lt;p&gt;First of all, let's create service that will write data to our DB.&lt;/p&gt;

&lt;p&gt;Add to DB:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Get from DB:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We need logic that will shorten our URL. For this we can use cool package Hashids.net and get youtube like short ids. We can chose length and "salt" for our links. Check out &lt;a href="https://github.com/ullmark/hashids.net"&gt;hashids.net&lt;/a&gt; for short instructions.&lt;/p&gt;

&lt;p&gt;For example, if we sent UrlDataDto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "url": "https://www.infobip.com/docs/api"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We get in response nice youtube-like short links:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "url": "http://localhost:8000/V1oExr"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's add this feature:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Hashids.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Method in service for encode:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;As you can see, we will encode DB id and generate our short URL from that data. (We will use this service in POST method)&lt;/p&gt;

&lt;p&gt;Method in service for decode:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Vice versa, on the other endpoint (our GET method) we will decode shortUrl to get id.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧪 &lt;strong&gt;Fourth Step: Test with Postman ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After &lt;code&gt;dotnet build&lt;/code&gt; and &lt;code&gt;dotnet run&lt;/code&gt; commands you are all set for manual test! Postman collections for you will find as part of the project, so that you can easily import.&lt;/p&gt;

&lt;p&gt;POST:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkak83l78wo1yy4l7aym9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkak83l78wo1yy4l7aym9.png" alt="Post method in Postman" width="753" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GET:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tm6zlxgyvtvixyr3tn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tm6zlxgyvtvixyr3tn7.png" alt="Get method in Postman" width="751" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;That's all, folks! Or is it? 🎉 🍾&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In part one of this series, we have created a simple URL shortener. We've showed you how to save data without installing database and generate short URLs with Hashids.net.&lt;/p&gt;

&lt;p&gt;Application passed our manual test with Postman, and we have set up stage to implement notifications in our web service.&lt;/p&gt;

&lt;p&gt;In part two of this series, we will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schedule tasks in .NET applications&lt;/li&gt;
&lt;li&gt;Send SMS via Infobip platform&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Api Broadcasting with .NET</title>
      <dc:creator>Dino Lozina</dc:creator>
      <pubDate>Thu, 14 Oct 2021 07:42:41 +0000</pubDate>
      <link>https://forem.com/dlozina/api-broadcasting-with-net-7mk</link>
      <guid>https://forem.com/dlozina/api-broadcasting-with-net-7mk</guid>
      <description>&lt;p&gt;How to notify all your client apps that server content has changed?&lt;/p&gt;

&lt;p&gt;That requirement is perhaps a standard nowadays since we have various hungry devices (and minds also 😊) for new notifications. In this article I have tested .NET signalR since it looks like it is &lt;strong&gt;easy to deploy, handles connection management automatically and scales easily.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Goal is to write server-side code that can broadcast content changes to client as soon as the content changes. SignalR supports following WebSocekets, Server-Side Events and Long Pooling techniques for handling real-time communication. To communicate between clients and servers SignalR uses hubs. A hub is a high-level pipeline that allows a client and server to call methods on each other and we will write one of those methods.&lt;/p&gt;

&lt;p&gt;On my &lt;a href="https://github.com/dlozina/public-address-book"&gt;github&lt;/a&gt; you will find finished project so that you do not need to write code yourself. We have Web API that knows how to do CRUD operations and client Blazor WebAssembly application that consumes data.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;First Step: Define a hub ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We write a custom class, and the most important thing is to inherit from Hub class.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;LiveUpdatesHub.cs&lt;/em&gt;&lt;br&gt;
&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;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.SignalR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;PublicAddressBook.Api.Hubs&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LiveUpdatesHub&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="k"&gt;public&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;LiveUpdate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LiveUpdate"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&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;



&lt;p&gt;&lt;strong&gt;Note: be sure to add using statement for SignalR&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Second Step: Configure our newly created class (LiveUpdatesHub) ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;All the configuration for .NET 5 or Core applications is done in application Startup.cs. We will need to add endpoint over which we will broadcast data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Startup.cs&lt;/em&gt;&lt;br&gt;
&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSignalR&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PublicAddressBookContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                     &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseNpgsql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PublicAddressBookConnection"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

            &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IContacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;ex&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;



&lt;p&gt;And also add service in ConfigureServicesMethod:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Startup.cs&lt;/em&gt;&lt;br&gt;
&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IWebHostEnvironment&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;

            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseEndpoints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoints&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapHub&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LiveUpdatesHub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"/liveupdateshub"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&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;






&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Third Step: Notify change ✔️&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In context of this application, I want to notify or perhaps it is better to say broadcast data change. Data will change when our API receives create contact POST request. If the data is OK we will write data to DB. After that we just need to call our Hub method (“LiveUpdate”).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ContactsController.cs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HttpPost&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;CreateContact&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;FromBody&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Contact&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

 &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;

    &lt;span class="k"&gt;try&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;createdContact&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_contactsService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddContact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="c1"&gt;// Live Update for Client Apps&lt;/span&gt;
          &lt;span class="n"&gt;_hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LiveUpdate"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"contact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createdContact&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PublicAddressBookApiError: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StatusCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status500InternalServerError&lt;/span&gt;&lt;span class="p"&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;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:Be sure to add hub service to controller constructor&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Fourth Step: Consume changed data ✔️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since we stayed in .NET world it is easy to consume "data change event" or should I say listen to changes on client side. &lt;br&gt;
In our Blazor component in method OnInitializedAsync() we will make a new instance of hub HubConnectionBuilder() and register what we are listening for.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ContactOverview.razor.cs&lt;/em&gt;&lt;br&gt;
&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;namespace&lt;/span&gt; &lt;span class="nn"&gt;PublicAddressBook.Client.Pages&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactOverview&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&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;OnInitializedAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;hubConnection&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;HubConnectionBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NavigationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToAbsoluteUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUrl&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;liveUpdateEndPoint&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;hubConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;On&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LiveUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;GetLiveNotificationData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="nf"&gt;StateHasChanged&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hubConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&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;



&lt;p&gt;&lt;strong&gt;Note: On client side, be sure to add SignalR client package&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Conclusion 🎉 🍾&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As you can se from this example it is very easy to set up real-time updates with SignalR. On client side you are of course not limited to .NET client and on this &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-5.0&amp;amp;tabs=visual-studio"&gt;link&lt;/a&gt; you can find examples for JavaScript and TypeScript. Also, I must mention that your hub method can have parameters, there is a nice chat example on fore mentioned link.&lt;/p&gt;

&lt;p&gt;Stay well,&lt;/p&gt;

&lt;p&gt;Dino&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>api</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
