<![CDATA[Ardalis RSS Feed]]>https://ardalis.comGatsbyJSWed, 26 Jan 2022 18:12:18 GMTStevenSmithhttps://feedburner.google.com<![CDATA[Web API DTO Considerations]]>https://ardalis.com/web-api-dto-considerations/https://ardalis.com/web-api-dto-considerations/Tue, 25 Jan 2022 00:00:00 GMTWhen designing web APIs, it's important to think about how the data being passed to and from the endpoint will be structured. How important is reuse in these considerations, and how much reuse can you get away with before it starts causing other problems?

Recently someone in my devBetter coaching group asked:

Why do you create Request and Response classes in your ApiEndPoints? Is just a DTO not enough?

The question is referring to my API Endpoints package and samples, which provide generic types for API request and result types (though they could both refer to the same DTO, if desired). Let's back up for a moment, review what DTOs are and some guidance on what NOT to use for your wire protocol and your APIs, and then wrap up by answering the question.

What's a DTO and why use them for Web APIs

A DTO, or Data Transfer Object, is a type that has no behavior, only state. DTOs aren't expected to follow typical object-oriented design rules like encapsulation, but rather should simply consist of a set of public properties. Record types in C# provide an easy, succinct way to define DTOs in the latest versions of the language. DTOs are frequently used to transfer data over some medium, being serialized and then deserialized in the process. The actual class definition can exist on both ends of this transfer, as long as it includes the expected set of properties. Behavior (methods, logic) doesn't transfer, and in fact can be completely different on either end of the exchange.

The DTO provides a contract for the shape of the data. Since behavior doesn't transfer between client and server, and since client and server may not even use the same platform, framework, or language, it's best to use a simple DTO (that can serialize to JSON or another format) for web API requests and results.

By definition, DTOs only contain data, not behavior.

A DTO that contains behavior is not a DTO.

Finally, don't confuse DTOs with POCOs.

Reusing entities as web api contracts

Most data-driven apps use entities at the domain model or data model layer (or both). Domain entities should include business logic, and so are ill-suited to being used as API models. If your domain entities are DTOs, then it's likely you have an anemic domain model, which (among other things) may indicate you don't actually need to be applying Domain-Driven Design. Also, it's quite common for there to be security issues caused by exposing your app's interior structure (domain model, data model) through its API model.

In short, avoid (re)using your entities directly as your web api's model.

Web API DTO Design

So we're saying that web APIs should use DTOs for their contracts. DTOs should have no behavior, only state. And these DTOs should not be (or reference) entities in our domain and/or data models.

Back to the original question, why would we need more than one DTO for a given resource, like a Customer? Why should API endpoints have custom types for requests and results?

Let's look at a very simple Customer DTO:

public class CustomerDTO
  public int Id { get; set;}
  public string Name { get; set; }
  public DateTime DateCreated { get; set; }

Get By Id

Now let's think about how we might design certain API endpoints around this DTO. First, a simple GET endpoint that returns a customer given a valid ID:

GET /customers/123

The request for this endpoint should be an int or long or some type that includes a numeric Id property, so it can be used to look up the appropriate customer. The result could be a CustomerDTO or it could be a 404 Not Found or other result, so typically the endpoint would return at least ActionResult<CustomerDTO>, and not simply CustomerDTO, to allow for this flexibility. Something like this:

Task<ActionResult<CustomerDTO>> GetById(int id);

Let's say that's good enough and move on to a list of customers.


GET /customers

The simplest approach to returning a list of customers is to do the same thing as for a single customer, but as a list:

Task<ActionResult<List<CustomerDTO>>> List();

This might be fine if there aren't many customers, but if there are thousands or more it might make sense to incorporate more parameters into the request. Things like paging, implemented with skip and take, are pretty common to add, resulting in something more than this parameterless method. On the result side, it's not unusual to construct a result that includes paging data in it, as well as other metadata like the total record count. Sure, the result will also include some collection of CustomerDTO instances, but neither the DTO nor a simple collection of the DTO will be the result. The method might end up looking something like this:

Task<ActionResult<CustomerPagedListResult>> List();

// this could be a record if preferable
public class PagedCustomerListResult
  public int TotalRecords { get; set; }
  public int PageSize { get; set; }
  public int PageIndex {get; set; }
  public List<CustomerDTO> Customers { get; set; }


What about mutating methods? Can we just use the DTO for those? Let's start with creating a new record.

POST /customers

This one's easy, right? Just pass the DTO and we're done:

Task<ActionResult<CustomerDTO>> Create(CustomerDTO newCustomer);

Actually, it is this easy, if you're using client-generated keys. Replace the int Id with a Guid Id and this signature is perfect. You could probably even simplify it to not return the DTO with the response, since in any successful case it should be the same.

Or should it?

There are actually two things about our DTO as we defined it above that are best set on the server: Id and DateCreated. If we're using persistence-generated keys (e.g. IDENTITY column), then that will be set server-side. And the creation date is frequently something we don't want set on the client, either. For one thing, the client's time zone could result in dates being entered into our system that are all over the place (we might fix this by using DateTimeOffset instead of DateTime). More importantly, if we're using that creation date for important auditing or even business rules, we never want the client to be able to set its value. Imagine if someone could become eligible for a big discount as a loyal customer who'd been with the company for 20 years just by setting that value using Postman...

It turns out, the only thing we need to create a Customer in this case is a Name. In a real app there would probably be a bunch more things, but Id and DateCreated shouldn't be among them. So we might need something closer to this:

Task<ActionResult<CustomerDTO>> Create(CreateCustomerRequest newCustomer);

// see how compact records are?
public record CreateCustomerRequest(string name);


Now let's look at performing an update. Let's consider a typical HTTP endpoint for this operation:

PUT /customers/123

Given this route, you'll see endpoint definitions like this one:

Task<ActionResult<CustomerDTO>> Update(int id, CustomerDTO newCustomer);

Do you see the problem with this "typical" approach?

An API is a very specific contract. It shouldn't contain any ambiguity. The above signature accepts an id from the route. However, the CustomerDTO also contains an Id property. Which one should be used? What if more than one is used? Why design an API that has ambiguity baked into it and creates confusion and additional error handling? Design it so there is only one right way of doing things:

PUT /customers


Task<ActionResult<CustomerDTO>> Update(CustomerDTO newCustomer);

Great. Now there's still the DateCreated problem, though (just like for Create, above) so we'll need another Request object:

Task<ActionResult<CustomerDTO>> Update(UpdateCustomerRequest newCustomer);

public record UpdateCustomerRequest(int customerId, string name);

What about deletion?


The typical delete route:

DELETE /customers/123

and endpoint signature:

Task<ActionResult> Delete(int customerId);

This works great without changes! Yes, some developers will try to pass the DTO, but you don't need all that. And some might try to return the DTO, but the client already has it so that's not necessary, either. And sometimes folks will just return void or Task but then you don't have any way to return other results like Bad Request or Server Error or even Not Found if you're checking for that before performing the delete.

In general, it's a good idea to always return some kind of IActionResult or ActionResult so that you have flexibility in what you return, especially in non-success cases.

How did our DTO work out

Ok so our final interface for these 5 CRUD operations looks like this:

Task<ActionResult<CustomerPagedListResult>> List();
Task<ActionResult> Delete(int customerId);

Each method has request inputs and an output type, for a total of ten possible type. If we were going for maximum reuse of the CustomerDTO we would expect to see it twice on every line for a total of 10/10 possible uses. Counting up the total in the method signatures above, we get 3/10. So, there is some reuse value in the standard DTOs we choose for our API, but we shouldn't aim to just blindly copy them across every endpoint.


At first glance, it might seem that API endpoints could all make use of a single DTO representing any given resource. However, in practice there are often a lot of tradeoffs and disadvantages to this naive approach. It's simpler, yes. It's more consistent, yes. But it's also more restrictive in what it allows endpoints to return to the client and not restrictive enough in what it allows clients to send.

Think about your non-API methods. Do you try to reuse a single parameter object for dozens of methods and their return types? With rare exceptions (like return types on the Builder pattern), this isn't a good practice. Why not? Because you don't want to be passing around instances that have more properties than you need for a particular operation. So simply apply that same logic as you design the contracts on your web API endpoints.

If you found this useful, please sign up for my tips newsletter and follow me on twitter, where I'm @ardalis. Thanks!

<![CDATA[Generate SSH RSA Key Pairs on Windows with WSL]]>https://ardalis.com/generate-ssh-rsa-keys-windows-wsl/https://ardalis.com/generate-ssh-rsa-keys-windows-wsl/Thu, 20 Jan 2022 00:00:00 GMTSecure Shell Protocol (SSH) keys provide an alternate way to authenticate with many services like GitHub. Creating them on Windows is simple using Windows Subsystem for Linux (WSL).

Windows Subsystem for Linux

First you'll need to have WSL running on your computer. Set up WSL for Windows.

Generate SSH RSA Key Pair

Open a WSL terminal (Start -> WSL -> Enter) and enter the following command:


It will ask you where to save the key - just hit enter and use the default (/home/username/.ssh/id_rsa).

Enter your passphrase (or just hit enter) and confirm it.

Your key files will be generated.

WSL Terminal showing commands

Find the Keys in Windows

The easiest way to find the keys on your Windows file system is to run explorer.exe . from the appropriate directory. As you can see in the image above, change directory to your home folder (/home/ssmith in my case). Then run explorer to launch File Explorer.

File Explorer Showing Files in Folder

Protect Your Private Key

The id_rsa file contains your private key. Keep it secure and don't share it with anyone.

The id_rsa.pub file is your public key. As such, you can share it with any app with which you wish to authenticate.

If you wish to use SSH with GitHub, start here.


It's easy to set up SSH keys on Windows using WSL and the ssh-keygen command. Refer to this article next time you need to do so. Thanks!

<![CDATA[Guard Clauses and Exceptions or Validation?]]>https://ardalis.com/guard-clauses-and-exceptions-or-validation/https://ardalis.com/guard-clauses-and-exceptions-or-validation/Tue, 18 Jan 2022 00:00:00 GMTGuard Clauses provide an elegant way to ensure code inputs are valid, typically by throwing exceptions. Validation provides a solution to a similar problem, typically without the use of exceptions. When does it make sense to use each of these techniques?

This article is a response to a question I received from one of my tips newsletter subscribers, Chad Boettcher. He asked:

I just have a quick question – well, I have many questions, but I’ll start with this one: I’m implementing several value objects and I’m torn between using Guard clauses for validation vs returning an Ardalis.Result. One thing that I haven’t seen any example of is checking for the max string length in the various fields so I find myself wanting to using the result with all of the validation errors returned in the result rather than throwing an exception for each field so that the user gets all of the validation errors at once rather than one at a time...

I answered Chad via email, but he gave me permission to share his question and name so I could credit him when I wrote up a more detailed answer in this article.

What is a Guard Clause?

A guard clause is just a technique for failing fast in a method, especially in a constructor. If a method (or object instance) requires certain values in order to function properly, and there's no way the system should ever try call the code with invalid inputs, then an exception-throwing guard clause makes sense.

Code without a guard clause:

public int DoSomething(string requiredInformation)
  string server = requiredInformation.Substring(2,10);
  // other code
  return result;

Obviously this code will fail with a null or empty string, as well as strings that aren't at least 13 characters long. You can address this problem with a try/catch:

public int DoSomething(string requiredInformation)
    string server = requiredInformation.Substring(2,10);
    // other code
    return result;
    return 0; // some default or error-indicating value

While this can work, it doesn't help you to identify where the errant code is that is allowing the call with the invalid input.

Another non-guard clause approach would look like this:

public int DoSomething(string requiredInformation)
  if(requiredInformation != null)
    if(requiredInformation.Length > 12)
      string server = requiredInformation.Substring(2,10);
      // other code
      return result;
      throw new ArgumentException("Must be at least 13 characters long.");
    throw new ArgumentNullException(nameof(requiredInformation));

The big problem with this one is how verbose it is. And it only gets worse with more than one parameter to check. To convert it to use guard clauses, simply invert the if statements and eliminate the else clauses.

public int DoSomething(string requiredInformation)
  if(requiredInformation == null) throw new ArgumentNullException(nameof(requiredInformation));
  if(requiredInformation.Length <=> 12) throw new ArgumentException("Must be at least 13 characters long.");
  string server = requiredInformation.Substring(2,10);
  // other code
  return result;

If you want a standard way to work with guard clauses in your app, check out my nuget package, Ardalis.GuardClauses, which have over 3M downloads as I'm writing this.


We just saw how guard clauses work. They allow execution in methods to fail fast by immediately exiting (with an exception) when a problem is detected. This is appropriate for conditions that should never happen under normal circumstances in your code. In the example above, other code should already have ensured that the input string existed and was valid prior to the method in question being executed. By the time the application got to the point where it was ready to call the DoSomething method, the expectation is that it has everything it needs to do so. If it doesn't, something has gone terribly wrong and the application should not try to continue. It should abort the current operation, log the exception, and present the user with some friendly error message (and hopefully notify the dev team that there's a problem that must be addressed).

Guard clauses that throw exceptions are appropriate for exceptional circumstances. They're not appropriate for things like user input validation in which invalid inputs are expected, not exceptional.


Validation is used to help prevent the inadvertent or malicious input of invalid data into the system. In many cases, to improve the user experience, it makes sense to validate a large number of data value, one by one and perhaps collectively, and then present the user with all cases of invalid data in a single operation. This is the opposite of the "fail fast" approach of guard clauses, and exceptions are not well-suited to this use case.

Can you use exceptions (and potentially guard clauses) to perform validation? Yes, of course, and I'm sure many system do so. But it shouldn't be your first choice for the reasons set forth here:

  • Such validation failures are not exceptional. They're expected.
  • Exceptions are expensive, in terms of performance
  • Catching single exceptions and returning validation problems to the user one by one creates a poor user experience.
  • Exceptions break program execution, and trying to code around this to collect multiple validation failures requires coding against the idiomatic usage of exceptions and exception handlers.

I'm a big fan of the FluentValidation library, and it's my preferred way of dealing with validation that goes beyond the basic ASP.NET MVC model validation support (as well as validation that belongs in your DDD domain model).

What about partially created types from caught exceptions

Chad also pointed out a potential problem when writing code like this in a constructor:

public Customer(string firstName, string lastName)
  FirstName = Guard.Against.NullOrEmpty(firstName);
  LastName = Guard.Against.NullOrEmpty(lastName);

Ardalis.GuardClauses supports direct assignment from guard clauses, as shown in the listing above. Alternately, you can check each input, and then assign it, but that's more code:

public Customer(string firstName, string lastName)

  FirstName = firstName;
  LastName = lastName;

In the first scenario, it might be possible to produce an instance of Customer with no LastName but otherwise correctly created:

Customer customer;
  customer = new Customer("Ardalis", null);
catch {}

var output = customer.GetFullName(); // likely to fail since LastName is null

It's worth pointing out that one could apply the same try/catch statement to a type that does all of the checks first, and then the assignments, with the only difference being that no fields will have been assigned. I'm not sure that's that much better. But in any case, don't do this. There's no (good) reason to ignore the explicit guard clauses in the constructor of a type in your production code. I could imagine maybe someone would need this in a test scenario, but I would suggest any number of alternatives before this one. Use a mock. Use a fake. Create an alternate constructor. Use reflection to set the state of a valid instance of the object. But don't ignore constructor exceptions and expect to have a valid object instance as a result.


Both guard clauses and validation frameworks perform input validation. The difference boils down to whether the invalid input is expected and part of the user experience, or unexpected. Only use exceptions for unexpected cases, and use a decent validation framework (like FluentValidation or ASPNET's model validation) for expected problems with incoming data.

<![CDATA[Why Use DateTimeOffset]]>https://ardalis.com/why-use-datetimeoffset/https://ardalis.com/why-use-datetimeoffset/Mon, 17 Jan 2022 00:00:00 GMTRaise your hand if you've stored entity values in a database as DateTime.

Ok, everybody has their hand up. You can put your hand down - you look silly doing that while reading an article on some website.

Using DateTime for entity properties and database fields is ubiquitous, but if you really care about the time portion of the value, it's often ambiguous. What time zone is the date in? Is it stored as UTC? From everywhere that touches it? How can you be sure? DateTimeOffset provides a solution to this problem.

Storing DateTime Values

The simple DateTime type (which makes a great example of a Value Object), always assumes the local machine's relative time. When you ask it for .Today or .Now it uses the local system clock. This can easily cause problems between machines with different times and/or timezones. It can be helpful to look at the output of a particular DateTime value as a string.

var rightNow = new DateTime(2022,1,17,18,11,30);
// 1/17/2022 6:11:30 PM

// 1/17/2022 1:11:30 PM

// 1/17/2022 11:11:30 PM

// 2022-01-17T18:11:30

The initial time is 6:11pm on 17 Jan 2022 on my computer here in Ohio, which is Eastern Standard Time (UTC-5). The rightNow variable doesn't include any time zone data in it. The DateTime functions ToLocalTime and ToUniversalTime assume that the data they're operating is in UTC or local time, respectively. As a result, of the four different times shown, the one produced by ToLocalTime is incorrect, since it's subtracting 5 hours from the actual time of 6:11pm.

Note that when you store datetimes in your application, they'll be stored based on whatever machine timezone they're running on, unless you're extremely disciplined about using UTC times wherever you modify the dates. And even if you are, there's no way to look at your data and see that you were, after the fact. The data simply won't know.

What happens when the same code is run on different developers' machines in different timezones? What happens when tests are run in this case?

What happens when you move your cloud-hosted app from one region to another? What happens if the app spans region in production for high-availability (HA) reasons?

For all of these reasons, it can be worthwhile to store dates in your application using the DateTimeOffset type.


DateTimeOffset is both a .NET type and a SQL Server type (other databases have equivalents, too). The main difference between it and the simpler DateTime type we all know and love is that it includes a time zone offset from UTC. Thus, it's always clear when looking at a DateTimeOffset what time is meant, whether UTC or local.

It is always clear what actual time is depicted by DateTimeOffset, whether it's UTC or local.

Adding to the example above, it can be helpful to see what DateTimeOffset values look like when represented as strings:

DateTimeOffset rightNowHere = new DateTimeOffset(rightNow);

// 1/17/2022 6:11:30 PM -05:00


// 1/17/2022 11:11:30 PM +00:00

// 2022-01-17T18:11:30

Two things to note in the listing above: the ToLocalTime value is correct and the standard ToString values all include the timezone offset (-05:00 when local, +00:00 when UTC). The last value's format string doesn't include the offset, which is represented in the format string as taking a nap: zzz.

Console.WriteLine(rightNowHere.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss zzz"));
// 2022-01-17T18:11:30 -05:00

DateTimeOffset in SQL Server

SQL Server supports both DateTime and DateTimeOffset values. DateTimeOffset uses variable precision and so can take up more space than DateTime, but doesn't always do so. Compare DateTimeOffset and DateTime on SQL Server and choose which one makes sense for your needs. If you just want to quickly see the difference, run these queries:

select GetDate()

Results (note precision difference in second and third result):

2022-01-17 18:30:18.227
2022-01-17 18:30:18.2292271
2022-01-17 18:30:18.2292271 -05:00

If you're using EF Core and Migrations, they support DateTimeOffset just fine, so no need to avoid using it because of issues there.


This idea to write this article comes from a bug in the current DevBetter.com website source code caused by using a DateTime property rather than a DateTimeOffset. The group developer mentoring program includes an archive of all past coaching session videos, and new videos list their date of publication using the familiar "x minutes/hours/days ago" format, rather than the explicit time itself. Because of differences in the server time, the upload time, and the user's local time, some videos were being shown as "-11089 seconds ago" which would mean they were uploaded some time in the future...

We'll fix the issue, probably by using DateTimeOffset, and chalk it up as another learning experience for the group based on the open source web site's code.


DateTime values lack any knowledge of time zone, or lack thereof. If you need to know when things actually occurred, with more precision than just the approximate date, and you can't be 100% sure that your dates are ALWAYS stored in UTC, then you should consider using DateTimeOffset to represent your datetime values. These are unambiguous about their time zone, or lack of (when in UTC time), and thus can eliminate a host of errors that plague many real world systems.

<![CDATA[DateTime as a Value Object]]>https://ardalis.com/datetime-as-a-value-object/https://ardalis.com/datetime-as-a-value-object/Wed, 12 Jan 2022 00:00:00 GMTValue Objects are a key part of Domain-Driven Design and domain models created by this process. However, they're not used nearly as often by teams as they should be, and they're frequently misunderstood even by experienced dev teams.

When teaching teams how to better understand Value Objects and incorporate them more in their domain models, I've found the DateTime .NET type to be a useful example.

First, a quick reminder of what a Value Object is:

A Value Object is an immutable type that is distinguishable only by the state of its properties. Any two Value Objects with the same properties can be considered equal.

Can a Value Object or DateTime Stand Alone in a Model

When modeling a system, many developers struggle with when to use a value object, when to use an entity, and how to combine the two. It's not unusual to come up with a value object and expect it to act like an entity. I get questions like "can I just have a list of value objects in my model" to which the answer is almost always "no". Again this is where DateTime can help.

Would it make sense to have a list of DateTimes in your domain model? What would that even mean?

A DateTime by itself, without context, has no meaning in your domain model. It's only when it's used to describe something in your model, typically an Entity, that it becomes useful. Here's an example:


You find these in a domain model. What do they mean? What do they represent? You have no way of knowing.

How about now?

var article = new Article
  CreationDate = new DateTime(2022,1,10),
  PublicationDate = new DateTime(2022,1,11),
  LastModifiedDate = new DateTime(2022,1,12)

The same three DateTime values now have context as they are used to describe an Article entity.

(A common one I see a lot is Address, but again this has no meaning by itself. It's only when you make it a CustomerAddress or a ShipToAddress that it has meaning.)

Why is immutability important

Recall the definition of Value Object states that they are immutable. That means, once they're created, you should not be able to change them. Their properties should all be readonly. What's the point of this? I've talked about why immutability is desirable before on my podcast, but let's review here in the context of DateTime.

If you're been writing software in C#/.NET for a while, you've probably used the DateTime type many times. Now I want you to think for a moment:

How many times have you ever had to check to see if a DateTime's properties were valid months, days, etc?

Did you ever check if the Day was more than 31, or otherwise out of range for a given month? Did you ever check if the Month was 13 or more? No? Why not?

You don't need to validate instances of DateTime because it's impossible to create one in an invalid state, and they are immutable.

If you try to create a DateTime with invalid values, like this with a Month of 13, you will get an exception:

var someDate = new DateTime(2022,13,1);
// System.ArgumentOutOfRangeException: Year, Month, and Day parameters describe an un-representable DateTime.

If you try to modify it to put it into such an invalid state, you will get a compilation error:

var someDate = new DateTime(2022,12,1);
someDate.Month = 13;
// error CS0200: Property or indexer 'DateTime.Month' cannot be assigned to -- it is read only

There are other reasons why immutability is important, but from a domain modeling perspective this is the most important one. You gain confidence that these values are valid, and you eliminate a ton of duplicate code that would otherwise be necessary to confirm validity in many places. Your code is safer, simpler, and DRYer.

So how do you change them?

Value Objects can expose methods that "appear" to change them, but which actually produce new instances of the type. This is true of DateTime as well as String in the .NET Framework. Whether it's AddDays() or ToLower(), you'll find that any method you call on an instance of a value object should return a new instance, rather than modifying the state of the existing instance.

Remember this when designing your own value objects. Any methods you expose that would manipulate the state of the object should instead simply return a new instance with the updated values used to create that instance.

One obvious benefit of this approach is that your validation logic in the value object's constructor is guaranteed to be run for every modification method you expose without any need to duplicate any of it.

More on Value Objects

I've written a few articles about Value Objects. Check them out if you're looking to improve your overall understanding:


While Value Objects are most often discussed in the context of DDD, there are examples of them in frameworks you probably work with every day. In .NET, the DateTime (and string!) types are both examples of Value Objects, and keeping this in mind can help inform your design of these types in your own applications.

<![CDATA[2021 Year in Review]]>https://ardalis.com/2021-year-in-review/https://ardalis.com/2021-year-in-review/Tue, 11 Jan 2022 00:00:00 GMTTime for a recap of stats and important (and not so important) milestones from 2021, the SECOND year of the COVID-19 pandemic (yeah we thought 2020 would be THE year of the pandemic. Turns out... not so much.).

Here are some other year-in-review recaps for reference and a checklist for writing your own:


Last year I added 37 articles to my blog (about 4 fewer than in each of the previous two years). That's a little more than 3 per month and about 11 short from hitting 1/week.

I'd really like to publish 50 articles in 2022.

In terms of traffic, Google Analytics reported that I had 842,609 pages views in 2021, slightly more than in 2020 (784,114 page views). That about 7.5% more, which is a lot better than the 1.8% growth I got the year before.

2021 Ardalis.com Page Views

New Articles

Notice those larger spikes. Those were new articles I wrote that got some traction. They each saw the most immediate traffic when published, and were:

You can browse through all of my (recent or not) articles here.

Most Popular Articles

Which brings me to articles. Google Analytics is great for identifying one’s most popular content. Often it’s not what you might think, expect, or hope for, though. For example, I mostly focus on code quality topics, domain-driven design, object-oriented principles, testing, etc. My top posts… don’t always reflect that though:

  1. The More You Know The More You Realize You Don’t Know (41k impressions)
  2. Force Nuget to Reinstall Packages Without Updating (35k impressions)
  3. Solved - An attempt was made to access a socket in a way forbidden (35k impressions)
  4. Add Images Easily to GitHub (30k impressions)
  5. Clean Architecture in ASP.NET Core (24k impressions (in 1 month!))
  6. SQL Server Error User Group or Role Already Exists (14k impressions)
  7. Why Delete Old Git Branches (14k impressions)
  8. C# Generics Best Practices (13k impressions)
  9. What is the difference between a DTO and a POCO or POJO (13k impressions)
  10. How to Hide the Connection Bar in RDP (12k impressions)
  11. Avoid Wrapping DbContext in Using (11k impressions)

Currently I have about 1617 blog posts on this site. That's just a count of all the files in my blog folder now that I've moved to using markdown and Gatsby.

I'm going to keep shooting for 1 million page views in a year (specifically, in 2022).

I've had this goal for a couple of years now and have obviously thus far fallen short, but I am at least making progress in the right direction.

Weekly Dev Tips Podcast Stats

I have a podcast, Weekly Dev Tips (which is the same name as my emailed newsletter that goes out every Wednesday). You can find it on the usual podcasting apps, its website, and also on YouTube.

I've been pretty burnt out on the podcast during the pandemic. Last year I only published one new episode, on Blogging with Andrew Lock.

There's not much point in reporting stats on the podcast in 2021. I may return to it in 2022 but I'm more excited about doing actual YouTube content so we'll see.

That doesn't mean you shouldn't listen to the existing shows. Most of them are meant to be evergreen content that you would listen to in order, with a lot of great stuff packed into the first couple dozen episodes.

Here are the top shows (all time downloads):

  1. Domain Events – Before Persistence (7,635)
  2. Do I Need a Repository? (7,429)
  3. What Good is a Repository? (6,805)
  4. On Learning TDD and LISP with Uncle Bob Martin (6,768)
  5. .NET Foundation with guest Claire Novotny (6,687)
  6. Guard Clauses (6,438)
  7. Maintain Legacy Code with New Code (6,316)
  8. Layering Patterns on Repositories (6,077)
  9. On Design Patterns (6,037)
  10. Breaking Bad Coding Habits with Joe Zack (5,850)

Weekly Dev Tips Mailing List

Unlike the podcast, I rarely miss sending out an email tip on Wednesdays. I did break my streak this year while I was on vacation... But usually you'll get a new tip every Wednesday.

Currently I have 3,605 subscribers, up about 12% from a year ago (with 3,225 subscribers). You can sign up here, if you’re interested.

Goal for 2022: 4,000+ subscribers. Current growth rate should make that very attainable.

Social Media Stats

It can be difficult to get this information after the fact, so here are my stats for various social media things as of January 2021.

Actually joined TikTok (inspired by Hanselman) but someone got my username (the horror!) so I'm @ardalis0 there. No content, though...


In 2021, I published the following books and courses:

Updated my architecture eBook for .NET 6: Architecting Modern Web Applications with ASP.NET Core and Microsoft Azure

Updated my book on porting from .NET to .NET Core/.NET 5.

My Pluralsight Courses (2021) (View All)

I published 3 new courses last year (22 total). The second half of the year, Pluralsight had a hold on new dev courses. That's done now, so I expect to publish a lot more this year.

A couple of these are updates of older but often more comprehensive courses. You may find value in watching the originals as well, which are linked from my author profile.


Last year I spoke at ZERO in person conferences due to COVID. The last in-person event I spoke at was NDC London in January of 2020. After that, it was virtual only. I did a ton of virtual talks in 2020, but slowed down quite a bit in 2021 (though I had a lot more private engagements with clients). Here are some of the virtual sessions I delivered:

  • Columbus App Dev (virtual) (April 2021)
  • Stir Trek (May 2021)
  • DevIntersection (virtual) (June 2021)
  • Baton Rouge .NET Group (virtual) (June 2021)
  • VS Toolbox (virtual) (October 2021)
  • dotnetconf (virtual) (November 2021)

My talks and workshops often focused on domain driven design, clean architecture, cloud design patterns, and ASP.NET Core. Contact me if you're interested in private presentations for your team or company.


Most of the rest of this is less interesting if you just follow me for technical content. You've been warned. Also, there wasn't a ton of travel happening due to COVID. I haven't been on a plane since 2020. Trips in 2021 consisted of a couple of close-family vacations, one to Hocking Hills, Ohio and another to Emerald Isle, North Carolina. Otherwise we pretty much stayed home and tried (successfully) to avoid getting COVID.


For some reason Fitbit hasn't sent me a 2020 summary like they usually do, but here's some manual analysis (which you can do from the website at fitbit.com/activities):

2021 (with one week in April where it didn't collect any data):

  • 2.9M total steps counted
  • 5963 floors
  • 1345 miles

Not too different from 2020, really (though it counted a lot more floors - I think my tracker in early 2020 didn't track floors). Hoping to get out and do more hiking and eventually get back to playing soccer this year. Also I injured my foot a couple of months ago and that's slowing me down a bit, but hopefully that'll be better soon, too. It's rough getting old.

Work Environment and Gear

I try to keep my current list of gear and tools used up to date. In 2021 I didn't do a whole lot in terms of upgrading my gear. I got a second 49-inch Curved Samsung Monitor (affilate link) for another recording office setup. I'm quite happy with this monitor.

Looking through my order histories on various sites for 2021 I really didn't buy much in the way of work gear. My desktops and laptops are all still working fine for my needs.

About the only "fun" and kind of high tech purchase we got was a new electric zero turn mower (Ego Z6), which does a good job and has good battery life/range once you max it out with 6 batteries.

Work Stuff


Our daughter went off to school, so we lost one employee mid-year. We hired a new full time person who started in January, though. Business demand has been high, and NimblePros is helping as many clients as it can, though we still have more work than we can handle. We will probably add another couple of people in 2022.


devBetter has continued to thrive. As of now we have 8 Alumni members and 27 active subscribing members, which is pretty good! If you're not familiar, devBetter is a group coaching program that promises to accelerate developer careers. Last year several members found new jobs, one with a very significant pay increase, and the growth in membership and the community has meant more interesting conversations and sharing of resources for the whole group. I'm looking forward to what 2022 brings.

That’s It

Thanks for reading this far. This post is mostly for my own reference, but maybe you found it interesting or useful.

If you want to write your own year in review blog post, I wrote a checklist here. It's probably longer than most people will want but you can just pick and choose what works for you.

Good luck in 2022 and beyond!

<![CDATA[What are Abstractions in Software Development]]>https://ardalis.com/what-are-abstractions-in-software-development/https://ardalis.com/what-are-abstractions-in-software-development/Wed, 05 Jan 2022 00:00:00 GMTSoftware developers deal with abstractions every day. But just what is an abstraction? There are differing definitions that can sometimes cause confusion. Let's consider a few of them.


Oxford (via Google as the default/top definition) defines abstraction:

ab·strac·tion /abˈstrakSH(ə)n/


  1. the quality of dealing with ideas rather than events. "topics will vary in degrees of abstraction"
  2. freedom from representational qualities in art. "geometric abstraction has been a mainstay in her work"

These are only applicable to software development with a bit of extra thought. Software abstractions are more about ideas and generalities than specific things. And while not necessarily art in the traditional sense, abstractions in software tend to be less representational of specific real world constructs. There's something here, but these are not the most useful definitions.

Wikipedia defines abstraction:

  • The process of removing physical, spatial, or temporal details or attributes in the study of objects or systems to focus attention on details of greater importance; it is similar in nature to the process of generalization;
  • the creation of abstract concept-objects by mirroring common features or attributes of various non-abstract objects or systems of study – the result of the process of abstraction.

Abstraction, in general, is a fundamental concept in computer science and software development. The process of abstraction can also be referred to as modeling and is closely related to the concepts of theory and design. Models can also be considered types of abstractions per their generalization of aspects of reality.

Specific to software, then, abstraction is all about generalization and the process of modeling concepts in more or less specific or generalized ways. Abstraction is a process which is used to produce generalized concepts or models, but in software we often refer to individual parts of a model as abstractions as well.

When we talk about abstraction, we typically mean the process of modeling by generalizing and focusing on important (in a given context) details while paring away less important details. When we talk about an abstraction or abstractions we are referring to artifacts produced by the modeling or abstraction process.

The rest of this article will look specifically at these artifacts, where again further sub-categories and definitions exist (but are frequently used interchangeably).

Abstractions in C# and .NET

Many programming languages like C# define abstraction as part of their type system. The .NET Framework design guidelines have some useful guidance for properly using abstractions (abstract types and interfaces) which includes a very simple definition:

An abstraction is a type that describes a contract but does not provide a full implementation of the contract. Abstractions are usually implemented as abstract classes or interfaces...

The alternative to an abstraction in C# is a concrete type. It's possible to examine any type in C# and determine, based on whether it can be directly instantiated, whether that type is abstract or concrete. It's not unusual for .NET developers to refer to abstract types as abstractions (and occasionally to concrete types as "concretions").

Below are a few simple examples in C#:

// abstract type
public interface ILogger
  void Log(string message);

// another abstract type
public abstract class BaseLogger : ILogger
  public abstract void Log(string message);

// concrete type
public class ConsoleLogger : BaseLogger
  public override void Log(string message)

Using the definitions we've considered thus far, it's clear that ILogger and BaseLogger are both abstractions, while ConsoleLogger is a concrete implementation (or "concretion").

Qualities of Abstractions

Some abstractions are more useful than others. Remember from our earlier definition, the process of abstraction is the process of modeling. With that in mind, it's worth remembering this quote from statistician George Box:

All models are wrong, but some are useful.

We can look at a type in C# and determine whether or not it is abstract but it still may not be a terribly useful (or "good") abstraction. Good abstractions have certain properties, many of which are described by the SOLID Principles.

Good Abstractions do not Depend on Details

The Dependency Inversion Principle (DIP) says "Abstractions should not depend on details. Details should depend on abstractions."

We can usually look at an abstraction in isolation and determine whether it follows this principle or not. Consider the two abstractions:

public interface IOrderDataAccessA
  SqlDataReader ListOrders();
public interface IOrderDataAccessB
  FileStream ListOrders(string filename);

By definition, these are both abstractions. You can't instantiate either type; the .NET Framework considers these to be abstract. Both types provide a model for working with data, presumably in order to retrieve order information. But they clearly do not follow DIP because they both depend on low-level details. IOrderDataAccessA depends on the SqlDataReader return type, which implies that this method will only be used to query SQL databases. And IOrderDataAccessB returns a FileStream and expects a filename argument, implying that it will only be used to read data from files.

Think about how difficult it would be to implement the first interface using files or the second interface using SQL Server. A good interface should not constrain the details of its implementation(s).

Interfaces define what needs to happen; implementations define how to do it.

We can replace both of these poor abstractions with a better one by following DIP and eliminating the dependency on low level details in the interface definition:

public interface IOrderDataAccess
  IEnumerable<Order> ListOrders();

Note that you could easily implement this interface using any kind of implementation (database, files, web apis, in memory, anything). This is a direct result of the fact that it follows the Dependency Inversion Principle.

Good Abstractions are Focused

Two more SOLID principles help guide us to writing better abstractions:

SRP is typically applied to classes, but remember that when a class implements an interface, it must implement all of it (if they don't, then they're breaking another SOLID principle, Liskov Substitution). Thus, abstractions that don't follow SRP will produce classes that don't follow SRP.

One way to help keep interfaces focused is to look at how they are consumed. ISP says that classes "should not depend on methods they do not use." If you have large interfaces with many methods, it's likely that some clients will only need a subset of these, and thus will break ISP.

Good Abstractions are Stable

There are several principles that guide us to the conclusion that good abstractions should be stable. Stable in this context means that they are hard to change, and as a result, rarely changed.

First let's hit on the last of the SOLID principles, the Open-Closed Principle (OCP), which states that software constructs should be open for extension, but closed for modification. Abstractions are meant to be extended through their concrete implementation(s), which have no impact on the abstraction itself. However, sometimes abstractions within a system need frequent updates to support new requirements. Every change to an abstraction impacts all of its implementations, which can have huge ripple effects in an application. Good abstractions should change rarely, if ever.

If you find your design requires updates to certain abstractions on a regular basis, look for a better design.

The Stable Dependencies Principle (SDP) states that dependencies between packages should be in the direction of the stability of the packages. That is, a package should only depend on packages that are more stable than it is.

Likewise, the Stable Abstractions Principle suggests that the most stable packages should be the most abstract. That in fact the abstractness of a package should vary in proportion to its stability.

Taken together, these principles suggest that your application's abstractions should ideally be packaged together in a package that is more stable than the consumers of it. Following these (and other) principles will lead you to build systems using something approaching Clean Architecture or some variation thereof (ports and adapters, hexagonal, onion, etc.).

It's also worth noting that these principles are not purely subjective. Things like stability and abstractness can be calculated for a given package. Instability is often defined based on dependencies or coupling, with inbound (or "afferent") coupling and outbound ("efferent") coupling compared using this equation:

I = (Ce / (Ca + Ce))

A component that has no outbound coupling (it depends on nothing) is completely stable; instability = 0. A component that depends on many other components (and perhaps has no components depending on it, such as for many app entry points) would have an instability of 1 or close to it.

Likewise the abstractness of a package can be calculated using a similar ratio of abstract to concrete classes:

A = Sum(Abstract Classes) / Sum(Abstract and Concrete Classes)

In C# you would include interfaces as well as abstract classes to get this ratio.

Tools like NDepend can quickly calculate stability and abstractness for any given .NET app, plotting the two values on a chart to see how closely abstractness and instability align. You can use these to help ensure your package design doesn't lead you to the "Zone of Uselessness" or the "Zone of Pain."

Models as Abstractions

Remember that an abstraction is a model, and modeling isn't just about types you cannot instantiate (i.e. abstract types in C# and similar languages). Your whole domain model, not just the interfaces and abstract classes, is an abstraction. Design patterns, whether they use interfaces or not, are abstractions. User interfaces are abstractions. Any API, whether concrete or not, is an abstraction. Just about everything we deal with in the course of building working software involves abstracting from real world concepts, ideas, and things into software models that represent them.

In many instances, when someone is talking about abstractions in the context of software development, they're referring to this definition of the term. The whole application, or some part of it, is an abstraction regardless of the individual types involved, because it's modeling some process.

When evaluating rules or best practices about abstractions, keep this definition in mind as well.

Confusing (or Outright False) Rules of Abstractions

There are some articles and "rules" of abstractions that, while their intentions are generally good, can lead to confusion if taken out of context (or applied as generally as their sound bite would imply). I'd like to point out a couple here and explain why I think they would be better if they were a bit more nuanced.

Interfaces are not Abstractions

Mark Seeman wrote, some time ago, that Interfaces are not Abstractions. I have a great deal of respect for Mark and I recommend his book on Dependency Injection as required reading for any .NET developer. But I take issue with this article that makes that argument that abstractions and interfaces are totally separate things that might overlap somewhat like this:

abstractions and interfaces venn diagram

Mark goes on to discuss many ways in which an interface might not be a good abstraction, due to SOLID violations or because tools due a poor job of automatically generating interfaces from classes, etc. I agree with all of these points.

However, none of it changes the simple fact that, by every definition we've covered so far, interfaces are in fact abstractions. But some of them aren't terribly good abstractions.

This leads to the following, more nuanced Venn diagram:

good abstractions and interfaces venn diagram

And the conclusion that the article would be improved by the addition of a couple of words:

"Interfaces are not always good abstractions"

I know, it's not as catchy...

Interfaces with a single implementation are not abstractions

Vladimir Khorikov, a fellow Pluralsight author with a lot of great content, contends the following:

"Interfaces with a single implementation are not abstractions."

Which he elaborates on in his book on unit testing:

You can see just in the expanded version of his position from his book that his actual position is more nuanced than the simple statement would lead you to believe. But in conversation with him, he really does want to stick to the simple version of the "rule," rather than allow for a more accurate version. He also introduces the term "genuine abstractions" which here I'll argue is a synonym for "good abstractions".

So, what's wrong with this statement, that all interfaces with exactly one implementation are not abstractions, and also, what's right about it?

First, just like the previous article about interfaces and abstractions, it goes against every definition of abstraction we've discussed. Interfaces, all interfaces, are abstractions. Period. But are they "good" or "genuine"? Maybe, maybe not. Let's amend the rule so we can keep going:

"Interfaces with a single implementation are not good abstractions."

You should typically be able to look at an interface and determine whether or not it's a good abstraction (or at least if it exhibits known problems as described above) without seeing any other code. One problem with this "rule" is that it requires knowledge of the implementations of the interface in order to make a value judgment about it. I admit this is often helpful - your interfaces should fit within the context of your system and its model - but I can't see how this pass/fail rule makes sense. Especially if you're defining your interface in one package and potentially consuming it in other packages - how can you even be sure how many implementations of it there are, total, everywhere?

Let's look at the example I showed above, that follows DIP:

public interface IOrderDataAccess
  IEnumerable<Order> ListOrders();

Applying this (single implementation) rule, is it a (good) abstraction?

There's no way to know, since we don't know how many classes implement it. Let's say there are 0 implementations, currently. Is it an abstraction? We know it is, because it's purely abstract. This rule only says that interfaces with exactly one implementation are not (good) abstractions; it's silent about those with 0 or 2+ implementations. So it's not helpful here.

Now I add this implementation:

public class InMemoryOrderDataAccess : IOrderDataAccess
  public IEnumerable<Order> ListOrders() { return new List<Order>(); }

Boom! Now we know this interface is not a (good) abstraction, because it has exactly one implementation. Success! But wait, what changed about the interface? If it was a (good) abstraction before, why did it suddenly become a bad one now? Or if the rule is silent on 0 and 2+ implementation interfaces, is there any way to improve it so it might be more helpful? What happens when I do this?

public class InMemoryOrderDataAccess2 : IOrderDataAccess

Well, shoot. Now the rule is silent again. It's too bad it only has anything to say in exactly one case, and that somehow the changes in the interface's quantity of implementations is materially changing whether or not it's a (good) abstraction in some manner.

Hold on, what about fakes/mocks/stubs that might implement the interface? That would be a sure way to ensure it would always have at least 2 implementations: one for production use and one for tests. Nah, VK says those don't count, because, reasons.

Looking back at the context of the statement from his book:

"Genuine abstractions are discovered, not invented. The discovery, by definition, takes place post factum, when the abstraction already exists but is not clearly defined in the code."

Now I think we're back to the original definition of abstraction, which is a discovery and modeling process used to identify the important parts of an idea or process in order to build a useful model. VK is saying that frequently developers will jump to creating abstractions too quickly, rather than waiting to see how their model develops and then identifying the useful abstractions within it. It's a kind of premature optimization. I agree with this 100%.

But none of that says anything about whether interfaces are abstractions, or even good abstractions, based on their quantity of implementations.

At best we can say:

Interfaces with a single implementation in production code are a code smell, because they may be poor abstractions due to being too tightly coupled to their sole implementation.

This is a true statement. It's somewhat nuanced, but the truth often is. Code smells aren't necessarily wrong or bad, they're just worth looking a bit more deeply into because they might be a symptom of a problem in the software's design.

Perhaps an interface was created prematurely, either by hand or using a tool, that is tightly coupled to the implementation details of the sole class that does this work currently in the system. Knowing that there is a 1:1 relationship between the interface and its only implementation might help you to look into this design and see if it has any problems (like the ones described above related to SOLID, stability, etc.). In that sense, it could be a useful heuristic when evaluating code, but you'd ideally want to have a way to exclude all of the interfaces that had only one implementation but which were, in fact, good abstractions.

Overall, the rule is false on its face, and leaves out a lot of nuance. The updated, truthful rule is, sadly, not nearly as catchy. It's also much harder to fit into a tweet. But it's one I could probably stand behind. I'd still rather stick with the rules for good interfaces that I laid out above, though.


Ok, this got longer than I'd anticipated. The key takeaways are that there are multiple definitions for abstraction and even abstractions. Some ideas can be evaluated as true/false, such as whether or not a type in C# is abstract or concrete. Others may require some subjective assessment to determine whether a given abstraction is good, genuine, useful, etc. or not. And some rules which claim to assess whether something is an abstraction or not are really just talking about whether the thing is a good abstraction (or not).

If you'd like to discuss, please leave a comment below or post on twitter and be sure to mention @ardalis and this article.

<![CDATA[Make the Implicit Explicit]]>https://ardalis.com/make-implicit-explicit/https://ardalis.com/make-implicit-explicit/Tue, 07 Dec 2021 00:00:00 GMTWhen practicing software architecture and design, one important consideration is how the rules of the system are modeled. Are the rules ad hoc and a matter of tribal knowledge of the developers who came before, or are they explicit in the way the system and its classes are designed and used? Whenever possible, favor making the implicit explicit in your design, so that as developers come and go, the design remains consistent and discoverable.

Implicit design rules

Most systems include some implicit design rules. These come in many forms, but you may not know what I mean when I say "implicit rules" or "implicit design", so let's look at a few examples. Many of these are examples of code smells, which I describe and show how to address in my refactoring courses on Pluralsight (the most comprehensive one is the retired "Refactoring Fundamentals" course which you can find from my author page).

Let's say you have a system that deals with subscriptions. It includes a class MemberSubscription to represent an individual member's subscription details. It might look like this:

public class MemberSubscription
  public int Id { get; set; }
  public int MemberId { get; set; }
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }

Now, stop reading for a moment and think to yourself, are there any things a consumer of this class could do, but probably shouldn't do as a well-behaved part of the app in which this class lives? Let's ignore using reflection for the moment and only consider strongly-typed compile-time code.

Thought of any?

Here are a few that come immediately to mind for me - let me know in the comments what I missed:

  • Should I be able to set the Id at all?
  • Since the Id is an int, it's probably not set by the app, but by a database, so it probably can be readonly from the app's perspective.
  • Assuming I can set the Id, should I be able to set it to 0 or a null value?
  • What about MemberId? I probably need to set it at some point, perhaps at object creation.
  • Should I be able to set MemberId after object creation?
  • Should I be able to set it to anything, or should it be constrained to potentially valid Ids? Or actual, existing Member Ids?
  • Should I be able to change the Start Date? In this case, probably yes.
  • Should I be able to change it to any date, past or future? Possibly. Independently of End Date? Maybe.
  • What if the End Date is tomorrow - should I be able to make the Start Date some time next month? Probably not.
  • This is the whole class - there is no non-default constructor. So, should I be able to just create one of these with defaults for all values? How many of these values need to be set for this to be "valid"?

I'm sure you can probably keep going but I'll stop here. There are a lot of questions, a lot of assumptions, about what one should or shouldn't be doing with a class like this one. It doesn't leverage encapsulation or other object-oriented design techniques to enforce constraints that limit how it should be used.

Someone, reading this:

"But I don't like constraints. I like to be able to do whatever I want without restriction so nothing prevents me from building the app however I want."

Oh, my sweet summer child.

"Oh my sweet summer child from Game of Thrones"

Why constraints?

Constraints are our friends. Constraints are the reason we're able to drive millions of vehicles on roads without constant death and destruction (even with constraints, vehicles kill tons of people every year...). Let's work with this metaphor for a moment, shall we? What kinds of constraints exist that help make driving safer?

First, there are laws and regulations. Requirements to get a license to drive. Requirements for vehicle safety and inspections. Traffic rules regarding speed and which side of the road to drive on and whether you can pass or not.

These are generally pretty explicit. There are explicit rules with explicit penalties for not following them. But as an individual driver you can choose to ignore many of these rules (at your own risk) and perhaps avoid consequences. People speed. People drive without a license. People drink and drive. Often without (immediate) consequences and clearly not having been prevented by laws to the contrary.

Going beyond explicit-but-not-enforced rules you have additional constraints that you typically cannot choose to ignore. Some vehicles have their top speed limited by a governor. While you can choose to drive on the wrong side of your neighborhood road, the divided highway in the major interchange has concrete walls constraining where you can drive. Similarly, when construction crews are working, they might rely on some cones or barrels to help oncoming traffic "decide" to merge to the left, but often where the actual work is occurring the workers have the good sense to put concrete barriers between themselves and moving traffic. Some constraints are more effective than others.

Returning to software, constraints abound especially in strongly-typed languages like C# or Java. That's what strong-typed is after all, a constraint that enforces certain contracts. Want to pass an int value into a method that expects a string? The compiler isn't going to like that. Want to do the same in JavaScript? No problem! (until perhaps at runtime).

Don't like constraints, but you use public|protected|private|internal keywords? Guess what? Those are all constraints. They're limiting how other code can work with class members.

You know what doesn't have a lot of constraints? Shared, writeable global state. Have you ever been working in a method or class and felt like the variable lifetime and scoping rules were getting in your way? Just throw out that constraint and add a single public static Dictionary<object,object> AllTheThings; bag of state to your app, and look at how easily you'll be able to work with any value, any time, anywhere.

But seriously, constraints are valuable and important parts of your system design. Constraints communicate the expected use of the system. They provide guard rails (driving metaphor callback!) to keep folks working with your design on the right track.

If you get the constraints right, you make the right way easy and the wrong way hard, which helps the team fall into the pit of success.

Now, some genius will respond with "who are you to say what the 'right' way is?" to which I must make clear, I'm not. The team designing and building the app is deciding. It's the right way for that app because that's how the team designed the app.

Being Explicit

Explicit designs bake the right behavior in. They enforce the expected way to do things so that assumptions are no longer a required part of the process. Tribal knowledge and even documentation needs are reduced in systems that have fewer, clear and consistent ways to do things.

Ideally, there should only be one way to accomplish a particular task in the system. Having multiple ways to achieve the same (or apparently the same) result is poor design. It forces developers to make decisions about which is the "right" way. If you're building a general purpose framework, providing some flexibility to developers who will work with it can be a good thing. But if you're building a single application with a team of developers, it's going to work out better if the whole team is aligned and building things in a consistent fashion. Design your system so this is built in, rather than a set of conventions that are documented somewhere that hopefully all team members read and remember (every time).

Let's return to the MemberSubscription design above, and consider now the Member as well. Members may have one or more subscriptions, so the class modeling this relationship might look like this:

public class Member
  public int Id { get; private set; }
  // other properties

  public List<MemberSubscription> Subscriptions { get; private set; }

  public void AddSubscription(Subscription subscription)

Once more, stop reading ahead, look at this class, and answer this question. How many different ways are there to add a subscription to a member? And how many different kinds of subscriptions does it accept?

The obvious answer is "too many" for both questions.

Consumers of this design can do any of the following:

public void SomeMethod(Member member)
  // 1. Empty sub
  member.AddSubscription(new Subscription());
  // 2. Another empty sub
  member.Subscriptions.Add(new Subscription());
  // 3-4. Non-matching member's subscription (using AddSubscription or Subscriptions.Add)
  // member.Id == 1
  member.AddSubscription(new Subscription { MemberId = 2});
  // 5+
  // Missing start date
  // Missing end date
  // End Date precedes Start Date
  // Probably others
  // Hey at least we have strong types!

So, how would you constrain this design so that there were fewer ways to perform the operation of "add a subscription to a member" or "subscribe a member"?

First, don't expose a collection property directly. I've written a lot about this, but it's still incredibly common. Encapsulate collection properties in your domain model so you don't expose the full collection functionality (clear, delete, etc.) to the app. Once you've hidden your actual underlying collection, expose only those methods (like AddSubscription) that you want to allow.

Second, somewhere we need to make sure that we don't have garbage in the MemberSubscription instance that we add to the Member. There are a couple of approaches here. You can add a constructor to MemberSubscription, make it the only (non-private - EF might need a private one) constructor, and ensure appropriate values are set. But there are limits on this approach. For instance, how is the constructor supposed to know what members exist, and thus was memberId values are valid? Still, it's better than nothing and for rules that don't require additional context, it's a good place to enforce them. For example, if Start Date must precede End Date, the constructor is a good place to put this requirement. Another option would be to use a DateTimeRange value object type which might have this behavior baked in, and then your MemberSubscription doesn't need to worry about this rule anymore. Julie Lerman and I show an example of this in our Pluralsight DDD Fundamentals course.

Additionally, we can change how we think about the AddSubscription method, and turn it into a sort of factory method. Rather than passing in a MemberSubscription of dubious origin, we can instead create the subscription in the very method that adds it, using something like this:

public class Member
// other members omitted

// this uses the DateTimeRange value object which includes a Start and End
public void AddSubscription(DateTimeRange dateRange)
    // constructor accepts memberId and a date range
    var memberSub = new MemberSubscription(this.Id, dateRange);

    // any other checks like looking for duplicate subscriptions go here

    // any follow-on behavior or raising of events goes here

Between this method and encapsulating the Subscriptions property, there are far fewer ways to improperly add a subscription to a member. And because most of these constraints exist in the code design and are enforced by the compiler, you don't need to write unit tests for them! There's no test to see what happens when someone tries to add a subscription to a member with a member id that doesn't match because you can't do that! There's no test to see what happens if a member subscription has dates that are out of order because you can't do that! The constraints force the code to follow "the rules" without the need for extensive tribal knowledge about how things work, documentation on the "right" and "wrong" ways, and excessive tests to cover many bad paths. In short, the design has made explicit the previously implicit assumptions about how this simple relationship should work.


Making the implicit explicit is a key design principle in software design.

It goes hand-in-hand with leveraging constraints to limit possible errors and mistakes and encapsulation (itself a set of constraints). Avoid thinking about constraints as having strictly negative connotations (if you do), and instead learn to value them for their ability to guide people (developers in this case) to do the "right" thing (for your project).

Found this useful? Share your thoughts and a link on Twitter and mention @ardalis. I'll most likely retweet it. Disagree and think this is all a load of bunk? Feel free to tweet that as well and I'll be happy to (respectfully) discuss, debate, and learn with/from you.

<![CDATA[Clean Architecture with ASP.NET Core]]>https://ardalis.com/clean-architecture-asp-net-core/https://ardalis.com/clean-architecture-asp-net-core/Tue, 30 Nov 2021 00:00:00 GMTIn late 2021, I presented a 30-minute session at dotNetConf on the topic of Clean Architecture with ASP.NET Core 6. At the time of writing this 2 weeks later, the video has 82k views, making it the most-watched YouTube video of the conference (not necessarily during the live event). You can check it out here if you're interested:

In this article, I want to go into a bit more depth on the topic of Clean Architecture with ASP.NET Core.

What is Clean Architecture

Briefly, Clean Architecture is the most recent (2012) name for a style of application organization that has been around for nearly two decades. Its earlier names included Ports and Adapters, which is fairly descriptive, and Hexagonal, which IMO is a silly name based entirely on some shapes used in a diagram long ago as far as I can tell. These are credited to Alistair Cockburn. Jeffrey Palermo later coined the term Onion Architecture in 2008, but the concepts are essentially the same. All of these are examples of a domain-centric, rather than data-centric, approach to application architecture.

NOTE: If you prefer video, I talk about the differences between data-centric and domain-centric architectures in my Pluralsight courses on Creating N-Tier Applications in C#. They're retired but still relevant and you can get to them from my author page if you're interested.

The guiding principle of these very similar approaches is the Dependency Inversion Principle, part of the SOLID principles of object-oriented design. This principles states that high level modules should not depend on low level modules, but instead both should depend on abstractions. High level modules are things like business rules and domain models. Low level modules are closer to out-of-process communication, such as through the user interface or communicating with services or the file system.

The principle goes on to state that abstractions shouldn't depend on details, but that details should depend on abstractions. What this means is that your abstractions shouldn't "leak" any information about their implementations. For instance, you wouldn't want to have a method definition called ListCustomers that returned a SqlDataReader because it would make it difficult to implement that method using an implementation that didn't rely on a SQL Server database.

Given the dependency inversion principle and its rules, the goal of Clean Architecture is to ensure that high level modules and their associated abstractions live in an assembly or project that doesn't depend on low level modules or details. This project is frequently called Core or perhaps Domain, and the main rule of the architecture is that this project doesn't depend on any other project in the solution, but instead the other projects depend on it.

Low level implementation detail classes that implement the abstractions defined in Core are defined in a separate project which is typically called Infrastructure. This project should depend on Core in order to access the interfaces and domain model types defined there. Because Infrastructure depends on Core, it's impossible for the reverse to be true. This is one reason why the architecture utilizes several projects, to ensure this rule is followed and enforced by the compiler, not just by developer diligence or discipline. Some might argue that this is over-engineered but the end result is typically just 3 projects and I've never found that to be too many for any application of non-trivial complexity.

The third project is the UI project. Assuming you're building an ASP.NET Core app, this will be an ASP.NET Core project called Web or something similar. It doesn't really matter if it's using Razor Pages or MVC or API Endpoints; the important thing is that the project references Core and avoids using any types from Infrastructure directly outside of its composition root.

An app's composition root is where all of the services in the app's dependencies are defined and "wired up". In ASP.NET Core this typically happens in Startup.cs or Program.cs in a ConfigureServices method or section. Other than that one location, the Web project shouldn't use any types from Infrastructure.

Although it's rarely done (because using a reference is easier), you should be able to completely eliminate any project reference between Web and Infrastructure, and just copy the Infrastructure DLL into the Web project's bin folder after it's compiled. Then, your composition root can use reflection to read the types from the Infrastructure DLL and wire them up as usual, but without any compile-time dependency on the project. I've demonstrated how to avoid directly referencing infrastructure in Visual Studio solutions in legacy .NET 4.x apps. You can do something similar in .NET Core if you wish.

ASP.NET Core and Clean Architecture

Ok, so there are basically three projects: Core, Infrastructure, and Web. The last one should use ASP.NET Core, which will be the app's composition root and starting point. But how do you know what to put in each project? Let's start from the app itself and work our way down into its dependencies.

What belongs in the Web project?

In the Web app, you're going to have any and all of your ASP.NET Core and ASP.NET Core MVC types. These will include Controllers, Views, Pages, Filters, TagHelpers, Middleware, etc. If it has a dependency on ASP.NET Core packages, it probably belongs in this project. In addition, any DTO types you're using specifically to communicate over the wire such as ViewModels, API Models, and the like, should go here by default. There are reasons why you might want to define these in another project, such as if you're using Blazor WebAssembly and you want to share the DTOs between the client and the server. But by default they belong in the Web project until you find a good reason to move them.

What shouldn't be in the Web project? Data access concerns including how you're communicating with the data source and how you're building queries. There should be minimal LINQ expressions for data queries. There should be zero use of DbContext types or other Entity Framework or Dapper or (insert your data access library here) references. The only place these should be used (if at all) is in your app's composition root.

What about use cases or application services?

I typically will put use cases, application services, and other services that live between my UI and my domain model in the UI (Web) project, along with any interfaces that implement. You can see an example of this in the eShopOnWeb reference application, which uses a service to build up a complex viewmodel and then also leverages the Decorator pattern to add caching to that same service.

I tend to only leverage these services on an as-needed basis. Most of the time I prefer to work with my domain model directly.

What belongs in the Infrastructure project?

Anything that communicates out of your app's process belongs in Infrastructure. The biggest and most obvious one being data access, but also anything that sends emails, sends SMS messages, talks to files, communicates with web APIs, etc. would belong here. One of the major benefits of Clean Architecture is extreme testability for the most important parts of the app, the domain model and business logic. Infrastructure dependencies are notoriously difficult to unit test, so by placing all such dependencies in their own project and ensuring the Core project doesn't have any direct dependencies on these libraries or the types that use them is the main way Clean Architecture ensures the domain model remains free of nasty dependencies.

What belongs in the Core project?

If you're following Domain-Driven Design, then this is where all of your domain model types belong. This will include entities as well as potentially value objects, aggregates, domain events, specifications, factories, and more. I'm a fan of using well-defined custom exceptions and guard clauses as well as custom validators, all of which would be defined in the domain model as well.

What about sharing between apps?

If you have common abstractions or base classes that you intend to use across many apps, it can be useful to maintain a separate Shared Kernel library for this purpose. The Shared Kernel library should only be updated with consensus from all of the application teams that depend on it. Ideally it should be distributed as a NuGet package so that teams and opt into breaking changes rather than being immediately broken by them. Because the Shared Kernel package will be consumed by multiple Core projects in various app solutions, it is especially important that no infrastructure dependencies exist in Shared Kernel.

NOTE: I talk about all of these concepts and more in my free ebook, Architecting Modern Web Applications with ASP.NET Core and Microsoft Azure.

Getting Started with Clean Architecture and ASP.NET Core

The quickest way to get started using Clean Architecture for your next ASP.NET Core app is to install a template and then create a new solution from the template. You can view all of my published templates using this NuGet query. For this purpose, you want the Ardalis.CleanArchitecture.Template package. On that page, you'll find a simple dotnet CLI command you can run to install the template. If you omit the version you'll get the latest version:

dotnet new --install Ardalis.CleanArchitecture.Template

You should see output similar to this, depending on if you've previously installed a version of the template:

The following template packages will be installed:

Ardalis.CleanArchitecture.Template is already installed, version: 5.0.0, it will be replaced with version 6.0.9.
Ardalis.CleanArchitecture.Template::5.0.0 was successfully uninstalled.
Success: Ardalis.CleanArchitecture.Template::6.0.9 installed the following templates:
Template Name                        Short Name  Language  Tags
ASP.NET Clean Architecture Solution  clean-arch  [C#]      Web/ASP.NET/Clean Architecture

Note that a new template with short name clean-arch was installed. To create a new project using the template, you can just run this command:

dotnet new clean-arch -o Your.ProjectName

Whatever you specify for "Your.ProjectName" will be used for the solution name as well as your default namespace hierarchy.


Clean Architecture is a great way to organize application of moderate to high complexity. It ensure dependencies are kept isolated from business logic and the application's domain model. ASP.NET Core works very well with the Clean Architecture approach, provided that the initial solution is set up properly. Using a solution template can help ensure you get your application started on the right track.

<![CDATA[Avoid Using Exceptions to Determine API Status Codes and Responses]]>https://ardalis.com/avoid-using-exceptions-determine-api-status/https://ardalis.com/avoid-using-exceptions-determine-api-status/Tue, 16 Nov 2021 00:00:00 GMTIt's typical for API endpoints to call application or domain services. In the case of success, the API can simply return Ok and the result of the service call. But for non-success cases, should you use exceptions to communicate from the service to the endpoint, so that it can return an appropriate status code and response?

Assuming you read the title of this article, you probably already know the answer I'm going to give. But first let's look at a (bad) example. Consider the following method found in a service that will be called by an API endpoint (controller action):

public IEnumerable<WeatherForecast> GetForecast(ForecastRequestDto model)
  // hard-coded not found case
  if (model.PostalCode == "NotFound") throw new ForecastNotFoundException();

  // validate model
  if (model.PostalCode.Length > 10)
    throw new ForecastRequestInvalidException(new Dictionary<string, string>()
      { nameof(model.PostalCode), "PostalCode cannot exceed 10 characters." }

  var result = // get the result here
  return result;

This method might then be called in an action method / endpoint using try-catch logic to determine what response should be returned, like so:

public async Task<ActionResult<IEnumerable<WeatherForecast>>> CreateForecast([FromBody] ForecastRequestDto model)
  _logger.LogInformation($"Starting {nameof(CreateForecast)}");
    var result = await _weatherService.GetForecastAsync(model);
    return Ok(result);
  catch (ForecastNotFoundException ex) // avoid using exceptions for control flow
    return NotFound();
  catch (ForecastRequestInvalidException ex) // avoid using exceptions for control flow
    var dict = new ModelStateDictionary();
    foreach(var key in ex.ValidationErrors.Keys)
        dict.AddModelError(key, ex.ValidationErrors[key]);
    return BadRequest(dict);

So, what's the problem with this approach?

Why Not Use Exceptions for Flow Control

First, it violates a well-accepted principle in C# (and similar languages like Java), which suggests that you should avoid using exceptions for flow control. There are many good reasons for not using exceptions for flow control, many of which are covered in this Stack Overflow exchange, Why not use exceptions as regular flow of control. Some excerpts:

If you use exceptions for normal situations, how will you locate things that are really exception?

Debugging with "break on all exceptions" stops working if the program uses exceptions all over the place for "normal" flow.

Exceptions violate the principle of least astonishment and make programs hard to read.

Throwing exceptions is one of the most expensive operations in .NET

If the error is a common one (e.g. user tried to log in with wrong password), use return values

Use return values for input validation

You can use a hammer's claw to turn a screw, just like you can use exceptions for control flow. That doesn't mean it is the intended usage of the feature. The if statement expresses conditions, whose intended usage is controlling flow.

Ok, so in general you should avoid using exceptions for control flow. But why is it bad in the case of the service shown above?

The consumer of the service is forced to be much more complex because of the way in which the control flow was implemented. Non-exceptional cases like simple input validation problems or cases where a resource wasn't found are being treated like things that should never occur in a healthy-running system. There are performance impacts in addition to tons of repetition across actions/endpoints if every one is structured using this same approach.

So, what other options are there? How could we make this work?

Practice Thinking about Various Ways to Achieve a Design Goal

Too often I see developers myopically choosing some a poor or suboptimal approach to a design because it's the most convenient, or it's their golden hammer, or it's "the it's always been done here". Sometimes if you stop for a moment and try to consider all the ways you might alternately be able to achieve the same outcome, you may be surprised by what you find.

First, what is our desired outcome? Defining that explicitly can go a long way toward helping us identify potential solutions. What do we need?

A method that either returns a (created) instance, or informs the caller why it couldn't do so.

This is the basic requirement for the functionality we require. And none of this behavior is exceptional - it's the expected behavior of the method under normal conditions.

In our case, there are 3 possible results of calling the method:

  1. Success. It returns an instance of the expected type.
  2. Validation failure. It returns a list of validation problems and some indication that validation failed.
  3. Required resource not found. The instance could not be created because it or some dependency it has could not be found.

How can we achieve this in C# code?


See above. Throw exceptions for the non-success paths, otherwise return the instance. We've covered why this probably isn't the best option.

If you already have a lot of code using the try-catch approach in every action/endpoint, one incremental improvement you can make is to refactor the exceptions to use common base types for each expected case (NotFound, Invalid, etc.). Then create an Exception Filter that has the try-catch logic in it, using the base types, and returning the appropriate NotFound or BadRequest result. You can add this globally when you set up MVC in your app's services and it should clean up your actions substantially. I'd still seek to avoid using exceptions for expected behavior and consequent control flow, but it may be good enough for some.


You could use a convention based on the return type. For instance, you could assume that if it returns null, the associated resource wasn't found. This would work for some cases of resource lookups, but wouldn't help with handling validation errors.

out Params

You could structure the method so that it had one or more out params representing non-success (or success) cases. For instance, you could return a bool representing success and use out params for the actual value as well as not found and validation errors. Calling the method might look like this:

// note C# 7 lets you declare inline
var success = await _weatherService.GetForecastAsync(model, out IEnumerable<WeatherForecast> result, out bool notFound, out Dictionary<string,string> validationErrors);

if(success) return result;
if(notFound) return NotFound();
  var dict = new ModelStateDictionary();
  foreach(var key in ex.ValidationErrors.Keys)
    dict.AddModelError(key, ex.ValidationErrors[key]);
  return BadRequest(dict);

Return an MVC type

You could just have your service return the actual ActionResult types that your controller action will ultimately return. At that point your service is tightly coupled to MVC types, though, and your controller action probably isn't doing anything at that point aside from returning the service. I prefer to follow separation of concerns, and the specific HTTP responses an API might return are a UI concern and a responsibility of the API endpoint, not the service.

Use callbacks

You could take a page from JavaScript and have the method use OnSuccess and OnError callbacks. You'll find an example of using delegates and callbacks in a C# method in this Stack Overflow answer. Generally it's not recommended in C# apps, but it would provide another possible approach.

Return a Result type

In C# when your type doesn't communicate everything you need, your go-to solution should typically be to use another type. For instance, we could return a ForecastListResult that might look like this:

public class ForecastListResult
  public IEnumerable<WeatherForecast> Forecasts { get; } = null;
  public ResultStatus Status { get; private set; };
  public Dictionary<string,string> ValidationErrors { get; } = new();
  public ForecastListResult(IEnumerable<WeatherForecast> successResult)
    Forecasts = successResult;
    Status = ResultStatus.Success;

  public ForecastListResult(Dictionary<string,string> validationErrors)
    ValidationErrors = validationErrors;
    Status = ResultStatus.InvalidRequest;

  private ForecastListResult()
    Status = ResultStatus.NotFound;

  public static ForecastListResult NotFound() => new FoecastListResult();  

It should be easy to see how the original service method could be adjusted to return either a success result, a set of validation errors, or a not found result. In this example the three possible statuses are represented by an enum (not shown).

The biggest problem with this approach is that you end up having to write a lot of code to get there. Once you have the above Result type, it works well and does a good job of communicating intent. The calling code also gets a lot simpler because it can just use standard if conditionals to handle the NotFound() and BadRequest() cases.

Looking more at this solution, you might notice that there's not really anything in the ForecastListResult class that's specific to a ForecastList. If you were to create additional FooResult types for other resources, you would probably find that they were very similar with the exception of the Forecasts property. This is a perfect case for using generics in C#. You can replace any specific FooResult type with a generic Result<T> where T is the type of a successful response.

I have an open source package available on NuGet, Ardalis.Result, which does just this. You can see an example of how it works here. Of course, once you have a common abstraction for these kinds of results, you can also get rid of all of the conditional logic in your actions/endpoints, replacing them with extension methods or filters. These are included in a separate NuGet package since they're optional and coupled with ASP.NET Core.

An example of using an extension method would look like this:

public override ActionResult<IEnumerable<WeatherForecast>> Handle(ForecastRequestDto request)
  return this.ToActionResult(_weatherService.GetForecast(request));

  // alternately
  // return _weatherService.GetForecast(request).ToActionResult(this);

Doing the same thing with a filter would look like this:

/// <summary>
/// This uses a filter to convert an Ardalis.Result return type to an ActionResult.
/// This filter could be used per controller or globally!
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public Result<IEnumerable<WeatherForecast>> CreateForecast([FromBody] ForecastRequestDto model)
    return _weatherService.GetForecast(model);

Note that in the case of the filter ([TranslateResultToActionResult]) the actual return type of the action is Result<T> not an ActionResult<T>. The filter handles the translation.

You'll find the source for the filter and the associated extensions methods on GitHub.


There are probably more options than the ones I listed above. The one I've had the best success with is the generic Result pattern. Using this pattern works in the vast majority of cases, produces clear code, and keeps logic to a minimum in controllers while allowing standard API policies to be employed globally.

What's your preferred strategy for dealing with non-exceptional results of services and translating these into appropriate HTTP responses in your ASP.NET Core apps? Leave a comment below or post on twitter and be sure to mention @ardalis and this article.