<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Erikvdv</title>
    <description>The latest articles on DEV Community by Erikvdv (@erikvdv).</description>
    <link>https://dev.to/erikvdv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F896685%2F3db3b638-cd43-42ec-9cbe-f5b205c981cd.png</url>
      <title>DEV Community: Erikvdv</title>
      <link>https://dev.to/erikvdv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erikvdv"/>
    <language>en</language>
    <item>
      <title>Revolutionizing UI Development in DotNet with Ui Mock</title>
      <dc:creator>Erikvdv</dc:creator>
      <pubDate>Mon, 08 Jan 2024 20:24:41 +0000</pubDate>
      <link>https://dev.to/erikvdv/revolutionizing-ui-development-in-dotnet-with-ui-mock-4703</link>
      <guid>https://dev.to/erikvdv/revolutionizing-ui-development-in-dotnet-with-ui-mock-4703</guid>
      <description>&lt;p&gt;The need for speed, efficiency, and adaptability in UI development in .Net has never been greater, and I am thrilled to introduce you to my new (and very first) library, Dotnet UI Mock.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1IAF4xWnDMQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The above video provides a quick demonstration of the library's capabilities, particularly its proficiency in swiftly iterating between multiple mocked scenarios to validate the behavior of your .Net application's UI.&lt;/p&gt;

&lt;p&gt;While working with single-page applications, I've frequently utilized libraries like WireMock and ngApiMock to mock my backend REST API endpoints. However, while developing your frontend in .Net, you might encounter multiple dependencies you'd want to mock, such as databases, REST APIs from different services, GRPC services, SOAP services, etc. Achieving a similar developer experience as with Single Page Applications often felt challenging.&lt;/p&gt;

&lt;p&gt;Dotnet UI mock (&lt;a href="https://github.com/Erikvdv/dotnetUiMock"&gt;github&lt;/a&gt;) is a solution to this challenge, extending this streamlined experience to .Net UI development.&lt;/p&gt;

&lt;p&gt;You can find an example that demonstrates the use of this library in the GitHub repository. The results are displayed in the demo video above.&lt;/p&gt;

&lt;p&gt;In the demo, I initiate the sample using the dotnet watch command:&lt;br&gt;
&lt;code&gt;dotnet watch --project=sample&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The world of UI development in .Net is rapidly evolving, with an increasing demand for speed, efficiency, and adaptability. Recognizing these needs, I am excited to present my first-ever library, Dotnet UI Mock.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1IAF4xWnDMQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The above video provides a quick demonstration of the library's capabilities, particularly its proficiency in swiftly iterating between multiple mocked scenarios to validate the behavior of your .Net application's UI.&lt;/p&gt;

&lt;p&gt;During my journey working with single-page applications, I've frequently utilized libraries like WireMock and ngApiMock to mock my backend REST API endpoints. However, while developing your frontend in .Net, you might encounter multiple dependencies you'd want to mock, such as databases, REST APIs from different services, GRPC services, SOAP services, etc. Achieving a similar developer experience as with Single Page Applications often felt challenging.&lt;/p&gt;

&lt;p&gt;Dotnet UI Mock (github) is a solution to this challenge, extending this streamlined experience to .Net UI development.&lt;/p&gt;

&lt;p&gt;You can find an example that demonstrates the use of this library in the GitHub repository. The results are displayed in the demo video above.&lt;/p&gt;

&lt;p&gt;In the demo, I initiate the sample using the dotnet watch command:&lt;br&gt;
dotnet watch --project=sample&lt;/p&gt;

&lt;p&gt;This command automatically detects changes in the mock setting and refreshes the UI, which in this case, is built with Blazor. &lt;/p&gt;

&lt;p&gt;Creating a list of mocks is quite simple with Dotnet UI Mock. In its initial implementation, I've chosen Nsubstitute as the preferred mocking library (currently, it's the only supported mocking library). This powerful tool is set to revolutionize the way you approach UI development in .Net.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherServiceMock&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BaseMockService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IWeatherService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;WeatherServiceMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MethodMocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GetForecastAsync"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockScenario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"oneitem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetForecastOneItem&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockScenario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"threeitems"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetForecastThreeItems&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockScenario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetForecastAsyncException&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GetForecastAsync(string location)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockScenario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"withlocation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetForecastWithLocation&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockScenario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetForecastWithLocationException&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GetForecastOneItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;IWeatherService&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;GetForecastAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WeatherForecast&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;TemperatureC&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Freezing"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// removed other scenarios&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To wrap up this post, let's highlight some key features of the Dotnet UI Mock library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Swift iteration between multiple mocked scenarios: This allows you to validate various scenarios without spending significant time on setup.&lt;/li&gt;
&lt;li&gt;Switching to the original implementation: If you need to compare the mock with the original or just revert to the actual functionality, Dotnet UI Mock makes this a breeze.&lt;/li&gt;
&lt;li&gt;Automatic UI refresh with dotnet watch: With this feature, you can see the impact of your changes immediately, enhancing productivity and reducing debugging time.&lt;/li&gt;
&lt;li&gt;Mocking application authentication: This feature, detailed in the sample, adds another layer of flexibility to your testing approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am genuinely excited to hear your thoughts and feedback on this new library! Your insights can help make Dotnet UI Mock an even more potent tool for the .Net community. Feel free to share your experiences, suggestions, or questions. Let's collaborate and make .Net UI development more efficient and enjoyable!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating a realworld app with C# dotnet</title>
      <dc:creator>Erikvdv</dc:creator>
      <pubDate>Sat, 23 Jul 2022 14:28:44 +0000</pubDate>
      <link>https://dev.to/erikvdv/creating-a-realworld-app-with-c-dotnet-m30</link>
      <guid>https://dev.to/erikvdv/creating-a-realworld-app-with-c-dotnet-m30</guid>
      <description>&lt;p&gt;Once in a while I create a &lt;a href="https://realworld.io"&gt;realworld app&lt;/a&gt; (&lt;a href="https://demo.realworld.io/"&gt;demo&lt;/a&gt;) to learn a new framework or explore certain different ways of application architecture.&lt;/p&gt;

&lt;p&gt;After experimenting with several frameworks to implement the frontend, this time I decided to create the backend. I used C# .Net for this.&lt;/p&gt;

&lt;p&gt;My code can be found &lt;a href="https://github.com/Erikvdv/realworlddotnet"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recent years I have been using this stack extensively and this time, next to experimenting a bit, I aimed to create a clean reference that I would be able to refer to when creating future solutions.&lt;/p&gt;

&lt;p&gt;The key things I like about implementing a real world app are reading about best practices and implement them in an elegant way and experimenting with some concepts/libraries that might help with that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;For the solution I opted for a fairly traditional clean architecture setup using .Net 6. &lt;br&gt;
The solution consists of the following layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;api (wires up the solution and defines the api endpoints)&lt;/li&gt;
&lt;li&gt;core (contains the core business logic)&lt;/li&gt;
&lt;li&gt;data (contains the interaction with the DB)&lt;/li&gt;
&lt;li&gt;infrastructure (generic code that potentially could be used in different solutions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And I used the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the new WebApplication.CreateBuilder(args)&lt;/li&gt;
&lt;li&gt;file scoped namespaces&lt;/li&gt;
&lt;li&gt;global usings&lt;/li&gt;
&lt;li&gt;Entity Framework Core with SQLite db&lt;/li&gt;
&lt;li&gt;serilog for logging, integrated with application insights, including realtime monitoring&lt;/li&gt;
&lt;li&gt;Hellang.Middleware.ProblemDetails for consistent error output&lt;/li&gt;
&lt;li&gt;sonarlint for code scanning&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Justification of choices and Retrospective
&lt;/h2&gt;

&lt;p&gt;Within the remainder of this post I will reflect on the choices I made. &lt;/p&gt;

&lt;h3&gt;
  
  
  Application layering
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;using distinct projects for this specific implementation is not required within this application. However, it makes it more clear where specific responsibilities should be. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Api Layer: I have considered using the .Net 6 minimal api's. However, I do think at this moment it is a bit too early as they are still lacking features (e.g. api grouping, model validation). I could have used something like Carter, but it relies on FluentValidation, which I always find hard to debug. I prefer something like &lt;a href="https://github.com/Erikvdv/realworlddotnet/blob/9cf6781714e8d06e5e0a10769e4af2ed9612a91f/src/Core/Dto/ArticleDto.cs#L7"&gt;this&lt;/a&gt; that is easy to debug and understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have doubted if I should combine the Core and Data layer into a single layer. As I am using Entity Framework in the data layer, the core layer (or at least the developer) actually needs to be aware of the EF concepts. The benefit of the current split is that it is easier to validate the database interaction (as can be seen &lt;a href="https://github.com/Erikvdv/realworlddotnet/blob/main/tst/E2e.Tests/DataTests.cs"&gt;here&lt;/a&gt;) and that the services in the core layer are easier to unit test as the repository can easily be mocked)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I do like the the WebApplication.CreateBuilder(args) that is new in .Net 6. It is easier to just have a program.cs file where both the host, the services and request pipeline is configured, instead of having a separate Startup file as well. For bigger projects I do expect one would like to structure the program.cs file a bit more as it could become hard to navigate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;file scoped namespaces: even being small, in my view this is a huge improvement that came with .Net 6 in terms of readability. Personally I would even like to have the option to go "namespaceless" by just taking the folder structure and a rootnamespace defined in the csproj file as the namespace. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;global usings: Don't see a lot of benefits here, while developing I manually needed to move stuff that is normally just handled by my IDE.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;serilog: I do like serilog for logging, however the integration with Application Insights is limited to log events as events or as traces, which prevents requests to be logged as requests in AI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hellang.Middleware.ProblemDetails really works well for me. It makes it very easy to add a global exception handler that allows for consistent responses for all types of problems, whether they are technical or functional and works well with the .Net default ApiController problem details response for model validation. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sonarlint for code scanning: I do think this is beneficial mainly to keep a consistent code style in your project (together with the other config in .editorconfig)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I can recommend anyone to build a realworld app. It really encourages you to dive deeper in a language/framework than what you would to in your typical todo app tutorial.&lt;br&gt;
If you are more familiar with a language/framework it allows you to experiment with architectures you are less familiar with.&lt;br&gt;
Besides that, when you like solving puzzles like me, your time is definitely more valuable spend than on solving Sudoku's ;).&lt;/p&gt;

&lt;p&gt;Looking specifically at this C# .Net implementation it might help you to think about how to practically structure your application&lt;/p&gt;

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