<?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: chsami</title>
    <description>The latest articles on DEV Community by chsami (@chsami).</description>
    <link>https://dev.to/chsami</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%2F1298664%2Fce3e3f59-0fe0-4b97-8a37-dcad0bd2c24a.jpeg</url>
      <title>DEV Community: chsami</title>
      <link>https://dev.to/chsami</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chsami"/>
    <language>en</language>
    <item>
      <title>Better Reverse Engineering with Frida and Ghidra</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Thu, 10 Apr 2025 04:54:31 +0000</pubDate>
      <link>https://dev.to/chsami/better-reverse-engineering-with-frida-and-ghidra-l0b</link>
      <guid>https://dev.to/chsami/better-reverse-engineering-with-frida-and-ghidra-l0b</guid>
      <description>&lt;h1&gt;
  
  
  Frida and Ghidra: A Powerful Reverse Engineering Team
&lt;/h1&gt;

&lt;p&gt;Reverse engineering can feel like trying to understand a machine without its instruction manual. Tools like Ghidra are great for taking the machine apart and looking at all the pieces. But sometimes, you need to see the machine running to really get how it works. That's where Frida comes in handy.&lt;/p&gt;

&lt;p&gt;Ghidra is a free and open-source tool that lets you see the code and structure of computer programs. It helps you understand the blueprint of the software. Frida, on the other hand, is like a special toolkit that lets you poke around inside a program while it's actually running on a computer, phone, or other device. You can inject little bits of code (using a language called JavaScript) to watch what's happening and even change things as they go.&lt;/p&gt;

&lt;p&gt;So, why is using Frida together with Ghidra so helpful for reverse engineering?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They work together to give you a full picture:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ghidra shows you what the program &lt;em&gt;could&lt;/em&gt; do.&lt;/strong&gt; Frida shows you what it &lt;em&gt;actually&lt;/em&gt; does when it's running. You can see the real data being used, which helps confirm what you see in Ghidra.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some programs try to hide their inner workings.&lt;/strong&gt; Ghidra can have trouble with these. But Frida can often bypass these tricks by looking at the program after it has already revealed its true form in the computer's memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ghidra can draw maps of how the program flows.&lt;/strong&gt; Frida can show you the exact path the program takes when you perform a specific action. This makes it easier to understand complicated logic and how different parts of the program connect.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Frida lets you really focus your investigation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You can "hook" functions.&lt;/strong&gt; This means you can jump in whenever a specific part of the program (a function) is used. You can see what information goes into the function and what comes out. You can even change the information or make the function do something different. This is super useful for seeing how different parts of a program communicate and for finding potential weaknesses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can look at and change the program's memory.&lt;/strong&gt; Frida lets you peek at the raw data the program is using and even modify it. This can help you understand how information is stored, find hidden secrets, or test if the program is vulnerable to attacks (in a safe, controlled way, of course!).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can trace what the program is doing.&lt;/strong&gt; Frida can keep a detailed log of the program's actions – what functions it calls, what system commands it uses, and other important events. This gives you a timeline of the program's activity, making it easier to figure out exactly what's happening.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Using Frida makes Ghidra even more powerful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The real-world information you get from Frida makes your analysis in Ghidra more accurate.&lt;/strong&gt; You can add notes to the code in Ghidra based on what you observe with Frida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you have an idea about how something works in Ghidra, you can use Frida to test that idea in the running program.&lt;/strong&gt; This back-and-forth process speeds up your reverse engineering work and makes it more reliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sometimes, parts of a program only run in very specific situations that are hard to figure out just by looking at the code in Ghidra.&lt;/strong&gt; Frida can help you trigger these situations and see what happens, revealing hidden or less obvious features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Imagine this example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You're using Ghidra to look at a mobile app and you find a strange piece of code that seems to handle private user information. With Frida, you could:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; See exactly when and how this piece of code is used.&lt;/li&gt;
&lt;li&gt; Record the actual private information it's working with.&lt;/li&gt;
&lt;li&gt; Look at the information in the app's memory while this code is running.&lt;/li&gt;
&lt;li&gt; Try giving it different kinds of information to see if there are any security issues.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This live view, combined with Ghidra's ability to show you the code itself, gives you a much clearer picture of what's going on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to get started:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both Frida and Ghidra have good documentation and helpful communities online. To start using them together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Install Ghidra:&lt;/strong&gt; You can download the latest version from the official Ghidra website: &lt;a href="https://ghidra-sre.org/" rel="noopener noreferrer"&gt;https://ghidra-sre.org/&lt;/a&gt;. Follow the installation instructions provided on the site.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Install Frida:&lt;/strong&gt; Frida is typically installed using pip, the package installer for Python. Open your terminal or command prompt and run: &lt;code&gt;pip install frida-tools&lt;/code&gt;. You can find more information about Frida installation on their documentation page: &lt;a href="https://frida.re/docs/installation/" rel="noopener noreferrer"&gt;https://frida.re/docs/installation/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Learn a little bit of JavaScript:&lt;/strong&gt; Frida uses JavaScript for its scripting capabilities. There are many online resources for learning JavaScript, such as the Mozilla Developer Network (MDN) JavaScript guide: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Read Frida's documentation:&lt;/strong&gt; The official Frida documentation provides a comprehensive guide to its features and API: &lt;a href="https://frida.re/docs/home/" rel="noopener noreferrer"&gt;https://frida.re/docs/home/&lt;/a&gt;. Pay particular attention to the sections on "Core Concepts" and the "API Reference."&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Start by practicing on simple programs:&lt;/strong&gt; Try using Frida to look at basic applications on your computer to get a feel for how to hook functions and observe their behavior. There are often tutorials and examples available online that can guide you through your first Frida scripts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;In conclusion:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ghidra is a fantastic tool for taking software apart and seeing its structure. Frida adds the crucial ability to see that software in action. When you combine these two tools, you get a really powerful way to understand how any program works, find hidden features, and uncover potential security problems. They make the often-difficult job of reverse engineering much more effective and insightful. So, give Frida and Ghidra a try and see what you can discover!&lt;/p&gt;

</description>
      <category>reverse</category>
      <category>javascript</category>
      <category>programming</category>
      <category>re</category>
    </item>
    <item>
      <title>.NET 10 field backed property</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Fri, 28 Feb 2025 04:32:45 +0000</pubDate>
      <link>https://dev.to/chsami/net-10-field-backed-property-37jl</link>
      <guid>https://dev.to/chsami/net-10-field-backed-property-37jl</guid>
      <description>&lt;p&gt;With the update to C# 13 Microsoft introduced a new field keyword&lt;/p&gt;

&lt;h3&gt;
  
  
  Before – The Old Way
&lt;/h3&gt;

&lt;p&gt;You had two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Implemented Property (No Validation):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&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;class&lt;/span&gt; &lt;span class="nc"&gt;TimePeriod&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Hours&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;This creates a compiler-generated backing field, but you can't inject any logic into the get or set accessors.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Manually Implemented Property (With Validation):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&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;class&lt;/span&gt; &lt;span class="nc"&gt;TimePeriod&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;_hours&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Hours&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_hours&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="k"&gt;set&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                   &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"The value must not be negative"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
               &lt;span class="n"&gt;_hours&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&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;Here, you have full control and can add range checking, but you lose the brevity and clarity of auto-properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  After – With the New &lt;code&gt;field&lt;/code&gt; Keyword (C# 13 Preview)
&lt;/h3&gt;

&lt;p&gt;The new contextual keyword &lt;code&gt;field&lt;/code&gt; lets you mix the best of both worlds. You can use auto-property syntax and still include custom logic in one accessor without declaring your own backing field:&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;class&lt;/span&gt; &lt;span class="nc"&gt;TimePeriod&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Hours&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;
            &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"The value must not be negative"&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;What’s happening here?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Implemented Backing Field:&lt;/strong&gt; The compiler still creates the backing field for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Set Logic:&lt;/strong&gt; You add a validation in the &lt;code&gt;set&lt;/code&gt; accessor by directly accessing the synthesized backing field via &lt;code&gt;field&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Redundant Code:&lt;/strong&gt; There's no need to manually declare the backing field or implement both accessors with full method bodies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
    <item>
      <title>How do spellcheckers work?</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Fri, 28 Feb 2025 03:16:11 +0000</pubDate>
      <link>https://dev.to/chsami/how-do-spellcheckers-work-2lpp</link>
      <guid>https://dev.to/chsami/how-do-spellcheckers-work-2lpp</guid>
      <description>&lt;p&gt;We all know those wiggly red lines that show up under misspelled words—a small but helpful feature we don’t often think about. It uses a smart system to keep our writing clear. When our team received an intriguing request from the business to implement a spellchecker, it truly captured my attention in a way I never anticipated. Yup... I could've just used an api that does the spellchecking for me, but I was more interested in how things work behind the scene, so this led me to investigating how spellcheckers work.&lt;/p&gt;

&lt;p&gt;let's take a look at the timeline&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16jlhnn01b9gdz0vpf4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16jlhnn01b9gdz0vpf4s.png" alt="Image description" width="800" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  late 1950s and early 1960s
&lt;/h2&gt;

&lt;p&gt;The idea for spellcheckers started in the late 1950s and early 1960s with Herbert Glance in 1957 and Charles Blair in 1960. They came up with a way to check every word someone typed against a list of right spellings, pointing out any that didn’t fit. These early systems couldn’t suggest fixes, but they were important first steps for spellchecking tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  1965: Levenshtein distance algorithm
&lt;/h2&gt;

&lt;p&gt;In 1965: Vladimir Levenshtein published the Levenshtein distance algorithm.&lt;/p&gt;

&lt;p&gt;Let's say you wanted to turn the word "kitten" into "sitting". The goal is to do this in as few steps as possible.&lt;/p&gt;

&lt;p&gt;This is where the Levenshtein Algorithm helps you figure out the minimum number of changes needed to transform one word into another. These changes can be:&lt;/p&gt;

&lt;p&gt;Inserting a letter (e.g., adding an "s" to "kitten" to make "kittens").&lt;/p&gt;

&lt;p&gt;Deleting a letter (e.g., removing the "k" from "kitten" to make "itten").&lt;/p&gt;

&lt;p&gt;Replacing a letter (e.g., swapping the "k" in "kitten" with an "s" to make "sitten").&lt;/p&gt;

&lt;p&gt;This first implementation matches the naive recursive way. This is later on improved by using dynamic programming.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b0p5r0buq03qdipt12x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b0p5r0buq03qdipt12x.png" alt="Image description" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Early 1970s: Ralph Gorin created "Spell," a program
&lt;/h2&gt;

&lt;p&gt;Early 1970s: Ralph Gorin created "Spell," a program that identified misspelled words and suggested plausible correct spellings with an edit distance of one, meaning corrections involving a single letter insertion, deletion, or substitution. In 1971, Ralph published his program making it publicly available and quickly spreading its use worldwide. A limitation of this program was its inability to calculate plausible words beyond an edit distance of one.&lt;/p&gt;

&lt;h2&gt;
  
  
  1974: Robert Wagner and Michael Fischer introduced dynamic programming
&lt;/h2&gt;

&lt;p&gt;1974: Robert Wagner and Michael Fischer introduced dynamic programming to improve the efficiency of calculating edit distance. The Wagner-Fischer algorithm broke down complex problems into simpler subproblems, solving each subproblem once and storing the solutions to avoid repetitive work.&lt;/p&gt;

&lt;p&gt;Here is a visualization in claude: &lt;a href="https://claude.site/artifacts/1bb87561-f087-4ad8-9a95-df5d2a30262e" rel="noopener noreferrer"&gt;https://claude.site/artifacts/1bb87561-f087-4ad8-9a95-df5d2a30262e&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1980s and 1990s: Microsoft Word
&lt;/h2&gt;

&lt;p&gt;1980s and 1990s: Programs like Word Check and Microsoft Word used more evolved and optimized versions of these algorithms&lt;/p&gt;

&lt;h2&gt;
  
  
  2000 and beyond Spell Checkers: More Than Just Simple Fixes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Understanding the Sentence
&lt;/h3&gt;

&lt;p&gt;Today’s spell checkers don’t just look at words by themselves. They use smart tricks (called Natural Language Processing, or NLP) to figure out what a whole sentence means. For example, a word might be spelled right on its own, but if it doesn’t make sense in the sentence, the spell checker can catch it. This makes them better at avoiding mistakes and helps them work smoother for us.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guessing What You Meant
&lt;/h3&gt;

&lt;p&gt;A lot of spell checkers use an idea called the "noisy channel model." It’s like treating a misspelled word as a scrambled version of the right one. Then, it uses math and guesses to pick the word you probably wanted. A guy named Peter Norvig made a simple version of this popular by mixing how often words show up with how close they are to what you typed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning From Tons of Words
&lt;/h3&gt;

&lt;p&gt;Now, spell checkers are getting even smarter with things like machine learning and deep learning. These are like teaching a computer brain (neural networks) to study huge piles of text. This helps them fix tricky stuff—like words that sound the same (like "their" and "there"), mistakes based on the sentence, and even grammar—not just basic typos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fitting You Perfectly
&lt;/h3&gt;

&lt;p&gt;Spell checkers today can also change to fit you. You can add your own special words (like job terms or names) to a custom list, and they’ll learn from the fixes you make over time. This way, they keep up with new words or weird spellings you use a lot.&lt;/p&gt;

&lt;p&gt;I hope this brief introduction sparked your interest in spell checkers. Give it a try yourself!&lt;/p&gt;

&lt;p&gt;Happy coding! :)&lt;/p&gt;

</description>
      <category>spellchecker</category>
      <category>algorithms</category>
      <category>ai</category>
    </item>
    <item>
      <title>Why does clustering with redis suck?</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Thu, 02 Jan 2025 21:42:22 +0000</pubDate>
      <link>https://dev.to/chsami/why-does-clustering-with-redis-sucks-2o98</link>
      <guid>https://dev.to/chsami/why-does-clustering-with-redis-sucks-2o98</guid>
      <description></description>
      <category>redis</category>
    </item>
    <item>
      <title>Semantic search with Azure MS SQL and EF Core</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Wed, 01 Jan 2025 12:41:47 +0000</pubDate>
      <link>https://dev.to/chsami/semantic-search-with-azure-ms-sql-and-ef-core-34og</link>
      <guid>https://dev.to/chsami/semantic-search-with-azure-ms-sql-and-ef-core-34og</guid>
      <description>&lt;p&gt;In &lt;strong&gt;May&lt;/strong&gt; 2024, the &lt;strong&gt;first version&lt;/strong&gt; of the EFCore.SqlServer.VectorSearch extension was released. This was a significant step towards simplifying vector operations for EF Core users working with Azure SQL.&lt;br&gt;
 This plugin is currently in &lt;strong&gt;prerelease status&lt;/strong&gt;, so the APIs and features may evolve before the final release. Here's a quick overview of what it offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does the Plugin Do?
&lt;/h2&gt;

&lt;p&gt;This plugin bridges EF Core and Azure SQL Database's native vector support, enabling developers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perform &lt;strong&gt;vector similarity searches&lt;/strong&gt; using LINQ.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;insert and retrieve vector data&lt;/strong&gt; in Azure SQL.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&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;ProductContext&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;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;connection string&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseVectorSearch&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelBuilder&lt;/span&gt; &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"vector(3)"&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;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;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;Embedding&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;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;someVector&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3f&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;products&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Products&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OrderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;VectorDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cosine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArrayAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, working with embeddings and vectorized data becomes possible, directly within your EF Core projects.&lt;/p&gt;

&lt;p&gt;A full sample using EF Core and vector is available here: &lt;a href="https://github.com/Azure-Samples/azure-sql-db-vector-search/tree/main/EF-Core" rel="noopener noreferrer"&gt;https://github.com/Azure-Samples/azure-sql-db-vector-search/tree/main/EF-Core&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Azure SQL's Native Vector Support
&lt;/h2&gt;

&lt;p&gt;Since &lt;strong&gt;November&lt;/strong&gt; 2024, Azure SQL Database has been supporting embeddings through its &lt;strong&gt;Public Preview&lt;/strong&gt; of native vector functionality. This development has made it possible to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store and manage vector data.&lt;/li&gt;
&lt;li&gt;Perform advanced operations like similarity searches directly in SQL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more details, check out the official announcement: &lt;a href="https://devblogs.microsoft.com/azure-sql/exciting-announcement-public-preview-of-native-vector-support-in-azure-sql-database/" rel="noopener noreferrer"&gt;Public Preview of Native Vector Support in Azure SQL Database&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Learn more about the vector features in Azure SQL in this guide: &lt;a href="https://aka.ms/azure-sql-vector-public-preview" rel="noopener noreferrer"&gt;Azure SQL Vector Public Preview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more details, visit the GitHub repository: &lt;a href="https://github.com/efcore/EFCore.SqlServer.VectorSearch" rel="noopener noreferrer"&gt;EFCore.SqlServer.VectorSearch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More of this on: &lt;a href="https://chsami.com" rel="noopener noreferrer"&gt;https://chsami.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>vectordatabase</category>
      <category>sql</category>
      <category>efcore</category>
    </item>
    <item>
      <title>Stop using try catch in your code</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Wed, 01 Jan 2025 12:34:47 +0000</pubDate>
      <link>https://dev.to/chsami/stop-using-try-catch-in-your-code-15mp</link>
      <guid>https://dev.to/chsami/stop-using-try-catch-in-your-code-15mp</guid>
      <description>&lt;p&gt;Have you ever found yourself looking through your code and noticing a lot of &lt;code&gt;try-catch&lt;/code&gt; blocks scattered everywhere? It can get messy, hard to maintain, and often feels like a chore to manage. Luckily, there’s a better way to handle this: &lt;strong&gt;middleware&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My little guideline for when to throw exceptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use exceptions only for critical issues that require attention.&lt;/li&gt;
&lt;li&gt;Keep exceptions aligned with the purpose of the method or class.&lt;/li&gt;
&lt;li&gt;Reserve exceptions for rare, unexpected situations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Use Middleware?
&lt;/h2&gt;

&lt;p&gt;Middleware brings several benefits to your project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Middleware keeps error-handling logic separate from your core application logic, making your code cleaner and easier to understand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Performance&lt;/strong&gt;: By centralizing error handling, you reduce repetitive operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Maintainability&lt;/strong&gt;: Having one place to manage errors makes it easier to update and debug your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized Responses&lt;/strong&gt;: Middleware ensures your app consistently returns well-structured error messages to users or other services.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Implement an Exception Middleware
&lt;/h2&gt;

&lt;p&gt;Here’s a step-by-step guide to implementing an exception middleware in your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Set Up the Middleware
&lt;/h3&gt;

&lt;p&gt;In your middleware, you’ll catch exceptions that occur anywhere in your application. This helps centralize error management and keeps the rest of your code free from repetitive &lt;code&gt;try-catch&lt;/code&gt; blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Use the ProblemDetails Convention
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;ProblemDetails&lt;/strong&gt; convention is a standard way to format error responses. It provides a consistent structure for APIs to communicate issues, making it easier for consumers (like front-end apps) to understand what went wrong.&lt;/p&gt;

&lt;p&gt;ProblemDetails responses typically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Status Code&lt;/strong&gt;: Indicates the type of error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Title&lt;/strong&gt;: A brief explanation of the error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detail&lt;/strong&gt;: A more detailed description of what happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance&lt;/strong&gt;: A URI that uniquely identifies the error occurrence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using ProblemDetails in your exception middleware, you ensure that all errors are communicated in a clear and standardized format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Implementation
&lt;/h3&gt;

&lt;p&gt;Here’s a basic template for setting up an exception middleware:&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;class&lt;/span&gt; &lt;span class="nc"&gt;ExceptionMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;RequestDelegate&lt;/span&gt; &lt;span class="n"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ExceptionMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RequestDelegate&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&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;InvokeAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;HandleExceptionAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;HandleExceptionAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&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;exception&lt;/span&gt;&lt;span class="p"&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;problemDetails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ProblemDetails&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Status&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="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"An unexpected error occurred."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Detail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&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="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContentType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsJsonAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;problemDetails&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;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-9.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-9.0&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-9.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-9.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More of this on &lt;a href="https://chsami.com" rel="noopener noreferrer"&gt;https://chsami.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>exceptions</category>
    </item>
    <item>
      <title>Configuring a custom domain for your Azure Static Web App</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Sat, 28 Dec 2024 13:04:32 +0000</pubDate>
      <link>https://dev.to/chsami/configuring-a-custom-domain-for-your-azure-static-web-app-1igc</link>
      <guid>https://dev.to/chsami/configuring-a-custom-domain-for-your-azure-static-web-app-1igc</guid>
      <description>&lt;p&gt;Configuring a custom domain for your Azure Static Web App is straightforward. Follow these simple steps to get your website running on your own domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Open the Custom Domains Page
&lt;/h2&gt;

&lt;p&gt;Go to your Azure Static Web App in the Azure Portal. From the left-hand menu, click on &lt;strong&gt;Custom domains&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o1xlsekbqdgekmo4i4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o1xlsekbqdgekmo4i4x.png" alt="Custom domains page" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Add a Custom Domain
&lt;/h2&gt;

&lt;p&gt;Click the &lt;strong&gt;Add&lt;/strong&gt; button and choose the option for &lt;strong&gt;Custom domain on other DNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03r5aiydzzdh4g192l2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03r5aiydzzdh4g192l2j.png" alt="Add Custom domain" width="679" height="1279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Verify Your Domain
&lt;/h2&gt;

&lt;p&gt;To verify your domain, you need to add a TXT record to your DNS provider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyx10tf8ay0qd57ry88iu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyx10tf8ay0qd57ry88iu.png" alt="TXT Record" width="643" height="1264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the generated TXT record value and paste it into your DNS provider’s settings. This unique value provides a valid connection between Azure and your DNS provider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs249776ku2h38m0ykxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs249776ku2h38m0ykxx.png" alt="DNS provider TXT Record" width="648" height="1265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, if you use Hostinger, it might look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxpdbsxpabijng3j9i44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxpdbsxpabijng3j9i44.png" alt="Image description" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Add a WWW Subdomain
&lt;/h2&gt;

&lt;p&gt;Repeat the process, but this time use &lt;strong&gt;&lt;a href="http://www.yourdomain.com" rel="noopener noreferrer"&gt;www.yourdomain.com&lt;/a&gt;&lt;/strong&gt; instead of &lt;strong&gt;yourdomain.com&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgce12bgozfmpqer2jdfb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgce12bgozfmpqer2jdfb.png" alt="Hostinger Example" width="638" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Configure CNAME Records
&lt;/h2&gt;

&lt;p&gt;In the Azure portal, select &lt;strong&gt;CNAME&lt;/strong&gt; and click the &lt;strong&gt;Add&lt;/strong&gt; button at the bottom of the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fug585ed0ui9g6tb9w9hh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fug585ed0ui9g6tb9w9hh.png" alt="Add WWW Domain" width="631" height="1256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your DNS provider’s settings, add or edit the following CNAME records:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For &lt;strong&gt;&lt;a href="http://www.yourdomain.com" rel="noopener noreferrer"&gt;www.yourdomain.com&lt;/a&gt;&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bgd77zgamy6wgvpvu6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bgd77zgamy6wgvpvu6s.png" alt="CNAME Record for www" width="565" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For the root domain (yourdomain.com), add an alias (CNAME):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9pof4pipupomdkr4mwwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9pof4pipupomdkr4mwwo.png" alt="Alias" width="580" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These configurations make sure your website works with both &lt;strong&gt;www&lt;/strong&gt; and without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Done!
&lt;/h2&gt;

&lt;p&gt;That’s it! Your custom domain is now linked to your Azure Static Web App. Enjoy!&lt;/p&gt;




</description>
      <category>staticwebapps</category>
      <category>dns</category>
      <category>azure</category>
    </item>
    <item>
      <title>TestContainers in .NET with PostgreSQL and PgVector</title>
      <dc:creator>chsami</dc:creator>
      <pubDate>Sat, 28 Dec 2024 06:28:19 +0000</pubDate>
      <link>https://dev.to/chsami/testcontainers-in-net-with-postgresql-and-pgvector-4m93</link>
      <guid>https://dev.to/chsami/testcontainers-in-net-with-postgresql-and-pgvector-4m93</guid>
      <description>&lt;h2&gt;
  
  
  What are we solving?
&lt;/h2&gt;

&lt;p&gt;How to include postgresql extension in a docker image through C# for integration tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;I’m using C# with the Testcontainers.PostgreSql NuGet package, which makes it easy to spin up PostgreSQL containers for integration testing. The core idea behind this setup is to ensure that each test class gets a clean, isolated database instance. This database is used to execute integration tests and is deleted afterward.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Testcontainers for .NET is a library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions. The library is built on top of the .NET Docker remote API and provides a lightweight implementation to support your test environment in all circumstances.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Container Configuration
&lt;/h2&gt;

&lt;p&gt;Here’s how I configured the PostgreSQL container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private const ushort Port = 5432;
private const string Username = "postgres";
private const string Password = "postgres";
private const string Database = "postgres";
private const string Host = "localhost";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private readonly PostgreSqlContainer _dbContainer = new PostgreSqlBuilder()
    .WithImage("pgvector/pgvector:pg16")
    .WithUsername(Username)
    .WithPassword(Password)
    .WithPortBinding(Port, true)
 .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(Port))
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that I used the pgvector:pg16 Docker image, as it already comes configured with the pgvector extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding PostgreSQL Extensions
&lt;/h2&gt;

&lt;p&gt;The project requires three PostgreSQL extensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasPostgresExtension("vector");  
    modelBuilder.HasPostgresExtension("btree_gin");
    modelBuilder.HasPostgresExtension("pg_trgm");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using HasPostgresExtension ensures that EF Core manages these extensions as part of the migrations or schema setup process. The following SQL commands are automatically generated and executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE EXTENSION IF NOT EXISTS "vector";
CREATE EXTENSION IF NOT EXISTS "btree_gin";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HasPostgresExtension vs UseVector
&lt;/h3&gt;

&lt;p&gt;There is a distinction between HasPostgresExtension("vector") and using the extension directly through UseVector:&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Differences:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;HasPostgresExtension("vector")&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures that EF Core includes the extension during migrations or schema updates.&lt;/li&gt;
&lt;li&gt;Manages the database schema and ensures the extension is installed. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UseVector&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Configures Npgsql to utilize the vector extension’s functionality, such as advanced type mappings and query capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enables application-level usage, like executing vector similarity queries:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM my_table ORDER BY embedding &amp;lt;-&amp;gt; query_embedding LIMIT 10;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing the Database with Scripts
&lt;/h2&gt;

&lt;p&gt;In addition to setting up extensions through EF Core, I discovered an alternative method to initialize the database in the test container using a SQL script. This is achieved with WithResourceMapping:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WithResourceMapping("./Scripts/extensions.sql", "/docker-entrypoint-initdb.d")&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does docker-entrypoint-initdb.d Do?
&lt;/h2&gt;

&lt;p&gt;The docker-entrypoint-initdb.d directory allows you to provide SQL or script files that PostgreSQL executes automatically during container initialization. This approach is ideal for preloading extensions or setting up other database configurations without embedding logic directly in the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using EF Core with Testcontainers, I’ve set up a way to make sure each test gets a fresh and clean database. Extensions like vector, btree_gin, and pg_trgm provide useful features, and the automated setup makes it easy to get everything ready without extra work. This keeps tests reliable and maintenance straightforward.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>testcontainers</category>
      <category>docker</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
