<?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: Dean Ashton</title>
    <description>The latest articles on DEV Community by Dean Ashton (@deanashton).</description>
    <link>https://dev.to/deanashton</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%2F72207%2F5f8185d9-1b72-4773-9d76-9a2eec694d0d.jpg</url>
      <title>DEV Community: Dean Ashton</title>
      <link>https://dev.to/deanashton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/deanashton"/>
    <language>en</language>
    <item>
      <title>Being a developer in 1998 was so cool and fun</title>
      <dc:creator>Dean Ashton</dc:creator>
      <pubDate>Tue, 01 Nov 2022 13:02:49 +0000</pubDate>
      <link>https://dev.to/deanashton/being-a-developer-in-1998-was-so-cool-and-fun-3cmg</link>
      <guid>https://dev.to/deanashton/being-a-developer-in-1998-was-so-cool-and-fun-3cmg</guid>
      <description>&lt;p&gt;I started writing code in 1986 as a kid. My first program was in BASIC on a Commodore 64 with a tape drive: 10 BEEP 20 GOTO 10. Made my father proud. Annoyed my mother with the constant beeping.&lt;/p&gt;

&lt;p&gt;In 1998, I was writing code in Delphi. It was great. The Delphi language was cool, better than VB6 at the time, so many built-in components. I was developing Windows applications internally for a company that did vibration monitoring on large machines.&lt;/p&gt;

&lt;p&gt;The systems back then were simpler. The UI was less sophisticated, so we didn't use any third party frameworks. We didn't use a lot of abstraction / design patterns, we just made it work and changed it later if it needed changing, because it was easy to change the code because it was so simple (but harder to roll out because we released code on floppy disks). &lt;/p&gt;

&lt;p&gt;Fixing bugs was so much quicker, because there were not as many layers - there was the UI and the code that handled the UI. That's it. &lt;/p&gt;

&lt;p&gt;Now in 2022 I am writing software doing ETL for a company that does grocery analytics. There is a UI written in Angluar, then a C# API with a controller, which sends a mediator message, which is handled by a handler, which calls a service (potentially in another API), which calls it's dependencies to get things done, and then finally calls a repository to save things. Sometimes we have different APIs for each part, sending messages via RabbitMQ and NServiceBus. So many layers, so hard to trace bugs. &lt;/p&gt;

&lt;p&gt;Now we write code with less coupling and it is more able to handle business logic changes easily without breaking the rest of the code because it is abstracted, and we have unit tests to test changes have not broken existing code. I see why these things are good, but they have a cost in terms of productivity and developer frustration.&lt;/p&gt;

&lt;p&gt;In 1998 I had to know Delphi and it's database to be good at my job. In 2022, I have to know C#, SQL Server, Azure, Docker, Html/CSS, JSON, Http, Anguar/React/Vue. I also have to know how to use many third party C# and UI framework components and how to do units tests in front end and back end. &lt;/p&gt;

&lt;p&gt;Honestly, I felt more productive, and less frustrated as a developer, back in 1998, when everything was simpler.&lt;/p&gt;

&lt;p&gt;Perhaps there is value in making things as simple as we can, and only making them more complex when they need to be, instead of doing it because it is considered industry practice to do so.&lt;/p&gt;

&lt;p&gt;Topic idea came from reading this post on Hacker News...&lt;/p&gt;

&lt;p&gt;What was being a software developer like about 30 years ago?&lt;br&gt;
&lt;a href="https://news.ycombinator.com/item?id=33403174"&gt;https://news.ycombinator.com/item?id=33403174&lt;/a&gt;&lt;/p&gt;

</description>
      <category>oldskool</category>
      <category>history</category>
    </item>
    <item>
      <title>MediatR in 5 mins</title>
      <dc:creator>Dean Ashton</dc:creator>
      <pubDate>Wed, 06 Apr 2022 20:57:30 +0000</pubDate>
      <link>https://dev.to/deanashton/mediatr-in-5-mins-331</link>
      <guid>https://dev.to/deanashton/mediatr-in-5-mins-331</guid>
      <description>&lt;p&gt;Writing this for my own benefit... Need to know this for work, so learning it and wanted to capture my learning.&lt;/p&gt;

&lt;p&gt;How to do MediatR in 5 mins. The very basic stuff and how to get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why use it?&lt;/strong&gt;&lt;br&gt;
To reduce complexity in a complex system. Rather than classes depending on lots of other classes, a mediator class (using the mediator pattern) handles query requests and commands by farming them out to the appropriate class to service the request or command. The calling class does not know which class handles it, they just know they have requested something and it gets returned/done.&lt;/p&gt;

&lt;p&gt;Also allows your code to follow the Command Query Responsibility Segregation (CQRS) architecture so you can seperate and scale up the reads or the writes if necessary. For example a read query for a list might access a reporting server that is updated every 2 minutes, whereas updates might go to the live database.&lt;/p&gt;

&lt;p&gt;MediatR also has a great pipeline behaviors feature. This allows you to seperate concerns, so things like validation and logging can be done separate to (pre or post) the request handler. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your API project, manage Nuget Packages and add MediatR.Extension.Microsoft.DependencyInjection. This will add the MediatR NuGet package too as it is a dependency.&lt;/li&gt;
&lt;li&gt;Add a new project for your infrastructure layer&lt;/li&gt;
&lt;li&gt;Manage Nuget packages and add MediatR for you infrastructure layer project&lt;/li&gt;
&lt;li&gt;Add folders for commands, queries and handlers in your infrastructure layer project&lt;/li&gt;
&lt;li&gt;Each request for data (a query) or create/update (a command) should be a record (if using C# 9.0 and above) that implements the &lt;code&gt;IRequest&amp;lt;return type&amp;gt;&lt;/code&gt; interface.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record GetBankAccountsQuery() : IRequest&amp;lt;List&amp;lt;BankAccount&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Each request should have a handler. Handlers are classes that implement the &lt;code&gt;IRequestHandler&amp;lt;request type, return type&amp;gt;&lt;/code&gt; interface.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class GetBankAccountsHandler() : IRequestHandler&amp;lt;GetBankAccountsQuery, List&amp;lt;BankAccount&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Right click on the interface and choose "Implement Interface". This will create a Handle method. Enter code within the Handle method to handle the request e.g. access data in the database or a file.&lt;/li&gt;
&lt;li&gt;In the ConfigureServices method in your API, add the MediatR to the services collection: &lt;code&gt;services.AddMediatR(typeof(any class where you have mediatr code e.g. a class that implements IRequest).Assembly)&lt;/code&gt;. The .Assembly part allows MediatR to look through the asembly and find all the classes that implement IRequest or IRequestHandler and set up the mapping between them.&lt;/li&gt;
&lt;li&gt;In the code where you need to recieve the value returned from the query e.g. list of BankAccounts, add IMediator as a dependency to the constructor and then do code like this: &lt;code&gt;var accounts = mediator.Send(GetBankAccountQuery);&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why would you not use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once your application gets to a size where multiple handlers need to process an event, you might be better going to a message handling system such as NServiceBus or MassTransit.&lt;/p&gt;

&lt;p&gt;MediatR can have multiple handlers per event via notifications, but they are executed in the same process, so if one fails and the others don't you are left in a funny state - has it worked and you report success or not worked because one of the handlers failed?&lt;/p&gt;

&lt;p&gt;Message based systems like NServiceBus allow you to process each event individually and respond to errors as you find them. For example say the event for making the payment from the BankAccount succeeded but the event for send confirmation email failed. Well, just re-queue the send confirmation email event again and try it again at another time when the email server is back up. No need to fail the whole event because one part failed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract MediatR?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We should really abstract the implementation of the mediator pattern, so that we can use other mediator packages other than MediatR if necessary, without breaking our code.&lt;/p&gt;

&lt;p&gt;However... this requires extra code and complexity. If your project is small, this may not be worth it. e.g. a small microservice that just sends confirmation emails. Balance the benefit of being able to swap this out later easily vs speed of delivery.&lt;/p&gt;

</description>
      <category>mediatr</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Get your C# WebAPI controller to keep processing a request after returning 200 OK</title>
      <dc:creator>Dean Ashton</dc:creator>
      <pubDate>Fri, 11 Sep 2020 02:38:48 +0000</pubDate>
      <link>https://dev.to/deanashton/get-your-c-webapi-controller-to-keep-processing-a-request-after-returning-200-ok-38m2</link>
      <guid>https://dev.to/deanashton/get-your-c-webapi-controller-to-keep-processing-a-request-after-returning-200-ok-38m2</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9anbym0kkcay7es6fmlo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9anbym0kkcay7es6fmlo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ever needed a "fire and forget" solution where a client calls a C# WebAPI controller that does something long running, but doesn't really care about the result? &lt;/p&gt;

&lt;p&gt;For example, say you have a job scheduling system that runs a series of tasks and one of them is a call to a C# WebAPI service to create something like an export of data from a SQL Server table to a file. &lt;/p&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;The table is large and the export will tie up the job scheduling system from running the rest of the tasks in the process, or timeout the job scheduling process. And the result of the WebAPI service doesn't mean anything to the end result of the process, with the WebAPI reporting errors in another way such as by email. &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Make the C# WebAPI report a HttpStatus code of 200 OK and say that the request is complete to the calling client, while still continuing to work on the request in the background.&lt;/p&gt;

&lt;p&gt;For this fire and forget functionality, in your WebAPI controller, do this:&lt;/p&gt;

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

public async Task&amp;lt;IActionResult&amp;gt; Post(string id)
{
    try
    {
        return Ok("Request submitted successfully");
    }
    finally
    {
        Response.OnCompleted(async () =&amp;gt;
        {
            await DoProcessing(id);
        });
    }
}


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

&lt;/div&gt;

&lt;p&gt;The key is the "Response.OnCompleted" part, which allows your code to execute even after reporting HttpStatus 200 OK to the client.&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
