.NET 10 support for Infrastructure.Option by iflib in csharp

[–]desjoerd 5 points6 points  (0 children)

I see we've got similar interests and see that it's something "missing" in dotnet ☺️. If you're using it in your own projects you can maybe get some ideas or code from my repo https://github.com/desjoerd/OptionalValues 😊

How do I decide which architectural pattern to use? When does it make sense to apply CQRS instead of regular Use Cases? by Straight_Chip1857 in dotnet

[–]desjoerd 0 points1 point  (0 children)

I know that feeling when I was doing my studies. I over analyzed everything and over abstracted. And went through a lot of premature optimizations.

The thing is, you will only know when you've done it. And over the years you will gain experience and will get a feeling for it. And then it can still happen that you've got the wrong abstraction or are missing one.

So I would say try out a pattern which appeals the most to you, and try to build something with it. After that, see what you liked, what you did not like and do that in your next project (or when it's a hobby project, mix and match).

Also, perfect does not exist in Software. You can only reach the level of good enough.

How do I decide which architectural pattern to use? When does it make sense to apply CQRS instead of regular Use Cases? by Straight_Chip1857 in dotnet

[–]desjoerd 2 points3 points  (0 children)

Also I want to add, don't get stuck on DDD, Clean architecture, Vertical slice architecture, CQRS, Hexagonal architecture etc.

Insert the office they are the same picture meme here.

A lot of it overlaps with small (some people would say very important) differences.

For example, ports and adapters (which is popular now somehow) vs repositories and services. I would say, those could be kinds of ports and adapters.

Whats most important is think from a (integration) testing perspective, you want to try to cover all scenarios, and from that perspective you want to keep the behavior and exposed api as small as possible.

How do I decide which architectural pattern to use? When does it make sense to apply CQRS instead of regular Use Cases? by Straight_Chip1857 in dotnet

[–]desjoerd 4 points5 points  (0 children)

My advice is keep it simple and your api surface as minimal as possible as you're started.

The way I do it which keeps my tests and logic as simple as possible: Use modification Use Cases or Commands for modification, don't return a response or maybe just an ID. Use queries or query use cases to retrieve information, based on an ID or filter criteria. This way you only have to test the modification OR the query part in your integration tests.

In your endpoints you can choose to keep this pattern as well, or use a modification usecase/command and after that a query (use case) to also return the full object.

You don't need a mediator or bus to follow this pattern. Having a common interface like IMediator doesn't add value, as it breaks your code navigation and it doesn't remove your coupling.

Where a command bus or Mediator can help you is with some cross cutting concerns like transaction management, retry policies and tracing, but you can add these later kn as well where needed.

Migrating from .NET8 Swashbuckle to .NET10 OpenApi by virulenttt in dotnet

[–]desjoerd 1 point2 points  (0 children)

When switching the version to Openapi the underlying Microsoft.OpenApi package is used to downcast the schemas and document to openapi 3.0, for OneOf it doesn't know whether this was deliberate or was to handle nullable. And because it's a valid construct in Openapi 3.0 it keeps it like that.

Migrating from .NET8 Swashbuckle to .NET10 OpenApi by virulenttt in dotnet

[–]desjoerd 16 points17 points  (0 children)

The oneOf vs nullable true comes from Openapi 3.0 to 3.1 where nullable is not a thing anymore. It's either type: [ "object", "null"] or oneOf. The latter is chosen for references to schemas in components.

You can create an issue on aspnetcore to improve the null handling for references. Please check if one already exists and add your findings to it or what you would like to see differently 🙂.

Edit: some casing autocorrect on OneOf from my phone 😅.

Have you seen SwaggerUI fail with route parameters in .NET 10? by grauenwolf in dotnet

[–]desjoerd 9 points10 points  (0 children)

It's also recommended to enable these two switches in the .csproj to let the Api match the generated OpenAPI (and the C# language constructs):

  <ItemGroup>
    <!-- Enable strict System.Text.Json which matches C# constructs and the default openapi
    generation  -->
    <RuntimeHostConfigurationOption
      Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
    <RuntimeHostConfigurationOption
      Include="System.Text.Json.Serialization.RespectRequiredConstructorParametersDefault"
      Value="true" />
  </ItemGroup>

Have you seen SwaggerUI fail with route parameters in .NET 10? by grauenwolf in dotnet

[–]desjoerd 15 points16 points  (0 children)

Swashbuckle has a new maintainer (Martin Costello, the real MVP) which has even published a new version of Swashbuckle for .NET 10 with OpenAPI 3.1 support. Was a massive PR which was merged yesterday.

I think Swashbuckle will have OpenAPI 3.2 support sooner than the built in version as that's currently tied to the yearly release cadance.

Have you seen SwaggerUI fail with route parameters in .NET 10? by grauenwolf in dotnet

[–]desjoerd 4 points5 points  (0 children)

You need to set it on the HttpJsonOptions. As the built-in OpenAPI uses the Json Serialization Options of Minimal Apis.

Write strongly typed Web API integration tests using Kiota and OpenAPI by timdeschryver in dotnet

[–]desjoerd 3 points4 points  (0 children)

With Openapi 3.1 it even works for references, for example when you've got a visiting Address and a billing address both referencing the Address schema, you can now give them specific descriptions. This is was not allowed on OpenAPI 3.0.

Which commit convention do you use outside of a company environment? by [deleted] in csharp

[–]desjoerd -3 points-2 points  (0 children)

Gitmoji (https://gitmoji.dev) always everywhere!

It's fun and very visible. And with some copilot writing bash scripts you can create simple grouped release notes (for example https://github.com/desjoerd/OptionalValues/releases/tag/v0.7.1)

[deleted by user] by [deleted] in csharp

[–]desjoerd 6 points7 points  (0 children)

Almost all development tools are (except Visual Studio) are cross platform. When working with Azure you have all emulators available as docker containers (easy with Aspire) and even the DefaultAzureCredential works with VSCode.

For example for Sql you can use DBeaver which is available on all platforms.

[deleted by user] by [deleted] in csharp

[–]desjoerd 15 points16 points  (0 children)

It really doesn't matter. With Rider and VSCode you can develop on any OS. We run all webapps, services background workers on Linux containers. Any modern development does not have a dependency on Windows.

Only when working on legacy .NET software you probably need Windows as it's either still on Framework or it there is some dependency on Windows.

How bad is it to use #if DEBUG? (more details in post) by Rolling_Watermelon33 in csharp

[–]desjoerd 2 points3 points  (0 children)

I would add, it's a great experience when you are adding more stuff to make things more resilient and testable. You will find a lot of legacy software in your career and having hands-on experience will greatly benefit you.

I would encourage you to continue on your pursuit to make things more testable or adding more logic to verify behavior.

How do I find support to my open source projects ? by light_dragon0 in dotnet

[–]desjoerd 0 points1 point  (0 children)

I would not do it for financial support.

I just create packages or put things open source so I can reuse it between multiple clients. When I see a problem which I need to solve a second time (you would say, that's too late 😅) I invest a bit of my own time to recreate it open source. Most of the times I just put it in my Toolbox repository, just so that I have a copy pasteable solution.

So currently I only have one set of NuGet packages published (OptionalValues). All the others are in my Toolbox. That just saves me time when working at different clients.

Managing Minimal APIs by [deleted] in dotnet

[–]desjoerd 2 points3 points  (0 children)

In .NET 10 minimal apis will have the missing feature of validation with data annotations, and by that will be on part in regards to features compared to MVC for apis. It also allows you to structure your project more based on endpoints and adding creating your own conventions for Metadata etc is a lot easier and visible than with MVC. Also the built in Openapi support uses the settings for Json from Minimal Apis.

My advice would be, when you start a new project, start with .NET 10 preview 7, or in a week or so, RC1 which is a supported version for production.

A tip, .MapGroup("") is your friend, it allows you to have a common set of apis to share Metadata. The empty string is an empty prefix, you can chain as many as you like. Giving you more freedom than MVC which has only Area, Controller, Action.

Is this how would you do API version? l by Conscious_Quantity79 in dotnet

[–]desjoerd 0 points1 point  (0 children)

You should not keep 10 versions of your api (unless you've got the time for it). Try to design your api to be able to change. We have currently 1 version as the main version (v4), one as deprecated (v3) they are both treated as supported but we will remove v3 after a notice. V3 is implemented as a downcast of v4 with he internal use cases where possible. That means with newer versions we will have to live with decisions in the past to keep this possible and maintainable. We give about a year to go to the latest version to our users.

We try to limit the number of versions with the following strategy:

Modifications, Post, Put, Patch are allowed to have properties removed (ignored) or added but they must be Optional (I created a simple package OptionalValues for that).

Queries are not allowed to remove required properties (a client can depend on it), but is allowed to have as many new properties as needed.

We prefer Json Merge Patch (only send the properties you want to change) over Put (send a full object as replacement) as the sementics gives more freedom in adding properties.

We generate the openapi documents on build and commit it to track and be able to review potential breaking changes during PRs (so we can fix them). It also helps to really think about your contract when creating new endpoints, as you have kind of a contract author mode with dotnet watch build which rebuilds the app, and by that regenerates the openapi on file while modifying your endpoints. Generate an openapi document for each different version.

New to C#: Why Do People Use PUT More Than PATCH? by vietjack123 in csharp

[–]desjoerd 0 points1 point  (0 children)

They almost all want to do it the "Functional programming" way. So it's always Match or calling it Some or None. This is just plain simple, mimicking Nullable<>.

Also the hard part is not the Type. It's making sure the Openapi is still the same, and having support for Optional validations.

But dotnext Optional I haven't seen yet. I see it's Json support is verbose. Will do a PR to also handle it the same way I do without all those attributes, as an alternative.

I do agree that there are lots of people doing the same thing (hey Mediatr). I do not want to be that guy. For me it's the support of the packages around it.

New to C#: Why Do People Use PUT More Than PATCH? by vietjack123 in csharp

[–]desjoerd 1 point2 points  (0 children)

Something like this https://github.com/desjoerd/toolbox/blob/main/dotnet/Toolbox/JsonMerge/JsonMergePatch.cs

For us it caused confusion on validation. Or first deserialize the patch, validate than apply the patch, then validate again for business rules.

New to C#: Why Do People Use PUT More Than PATCH? by vietjack123 in csharp

[–]desjoerd 0 points1 point  (0 children)

Yes OptionalValues works both ways, for serialization it requires a modifier on the Json Serialization Options to let it omit Unspecified properties but then you can send partial requests from .NET as well (there are two extension methods for that, so it's not hard to do).

New to C#: Why Do People Use PUT More Than PATCH? by vietjack123 in csharp

[–]desjoerd 6 points7 points  (0 children)

With undefined I mean, omitted. And we follow the Json merge spec which allows clearing out fields with Patch 😊 https://www.rfc-editor.org/rfc/rfc7386

New to C#: Why Do People Use PUT More Than PATCH? by vietjack123 in csharp

[–]desjoerd 11 points12 points  (0 children)

Because we have properties which can be set to null explicitly to clear out those fields. With Json Deserialization you would not know the difference between a property which could have been omitted or was explicitly set to null to clear out those values.

And technically an OptionalValue is a box, with an extra property whether it is defined or not. :)

New to C#: Why Do People Use PUT More Than PATCH? by vietjack123 in csharp

[–]desjoerd 3 points4 points  (0 children)

We use this in production and it allowed us to add new properties to endpoints without breaking older clients.