<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="https://floatincode.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://floatincode.net/" rel="alternate" type="text/html" /><updated>2023-08-18T08:03:17+00:00</updated><id>https://floatincode.net/feed.xml</id><title type="html">Float In Code</title><subtitle></subtitle><entry><title type="html">Debugging: Only building docker image extra npm packages are downloaded</title><link href="https://floatincode.net/2021/10/04/debugging-only-building-docker-image-extra-npm-packages-are-downloaded/" rel="alternate" type="text/html" title="Debugging: Only building docker image extra npm packages are downloaded" /><published>2021-10-04T13:05:36+00:00</published><updated>2021-10-04T13:05:36+00:00</updated><id>https://floatincode.net/2021/10/04/debugging-only-building-docker-image-extra-npm-packages-are-downloaded</id><content type="html" xml:base="https://floatincode.net/2021/10/04/debugging-only-building-docker-image-extra-npm-packages-are-downloaded/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;I'm working on the hybrid angular web application. We did update the angular version and released it to our QA environment, everything went fine until we tried to release it to our other QA environment which is using docker. Angular build failed with the following error, indicating that two type definition packages are exporting the same types.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;In this blog post, I will walk through the thought process that helped me debug this problem.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Locally on our windows laptop build works fine, azure windows pipelines work fine, but docker builds fail everywhere.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;When two type definitions export same types, following error will be thrown on build.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;#12 87.41
#12 87.41 ERROR in node_modules/@types/googlemaps/reference/map.d.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: BicyclingLayer, Map, HYBRID, ROADMAP, SATELLITE, TERRAIN, MapTypeRegistry, TrafficLayer, TransitLayer
#12 87.41
#12 87.41 1 declare namespace google.maps {
#12 87.41   ~~~~~~~
#12 87.41
#12 87.41   node_modules/@types/google.maps/index.d.ts:18:1
#12 87.41     18 declare namespace google.maps {&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;From the error above we can see that there are two packages &lt;code&gt; @types/googlemaps &lt;/code&gt; and &lt;code&gt; @types/google.maps &lt;/code&gt; which provide the same type of definitions.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Thought process&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;We upgraded the angular major version, this resulted in a large portion of our other packages being upgraded as well. The first thought was that some have a new dependency, but this doesn't explain why our windows build agents can build successfully. When building on windows &lt;code&gt; @types/google.maps&lt;/code&gt; package is not present in &lt;code&gt;node_modules&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;After some searching in the project, installed packages and online, still nothing. The next step that came to my mind is to check the docker file system for this mysterious package. With a few commands, I had docker up and running with the project inside it.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;First command will create docker image and second will run that image with interactive console.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt; docker build . -t ng-debug-build
 
 docker run -it ng-debug-build /bin/ash&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;This showed that docker indeed had  &lt;code&gt; @types/google.maps&lt;/code&gt; installed. Can npm packages have dependencies based on the operating system? New google quest was born and search continued. The answer is - no.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Well if we don't have it on windows build, we don't have it in our package.json, it must be installed by someone. Using &lt;code&gt;bisection search&lt;/code&gt; on &lt;code&gt;dependencies&lt;/code&gt; and &lt;code&gt;devDependencies&lt;/code&gt; I was able to find that &lt;code&gt;@typesmarkerclusterer&lt;/code&gt; package was installing additional dependencies when building project in docker.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:379,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;,&quot;className&quot;:&quot;is-style-default&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large is-style-default&quot;&gt;&lt;img src=&quot;/assets/2021/10/image-5-1024x543.png&quot; alt=&quot;&quot; class=&quot;wp-image-379&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;I'm still not sure why we don't have issues on our windows azure build agent, it might be that we have some sort of cache that I'm not aware of.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;The issue was that &lt;code&gt;@types/google-map&lt;/code&gt; package changed its dependency. Our angular application has &lt;code&gt;@types/googlemaps&lt;/code&gt; but when this package changed its dependence conflicts arose. &lt;code&gt;@types/markerclustererplus&lt;/code&gt; has wildcard major version dependency on &lt;code&gt;@types/google-maps&lt;/code&gt;, and this situation is a perfect example of why you shouldn't do that!&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Since we are using yarn we override internal package versions. We simply rolled back to &lt;code&gt;@types/google-maps&lt;/code&gt; version that uses same &lt;code&gt;@types/googlemaps&lt;/code&gt; dependency.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Yarn provides a way to override internal package versions&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;javascript&quot; class=&quot;language-javascript&quot;&gt;    &quot;resolutions&quot;: {
        &quot;@types/markerclustererplus/**/@types/google-maps&quot;: &quot;3.2.1&quot;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;This is a perfect example demonstrating how careful you should be about versions that you specify in dependencies. Overall I'm pretty happy with this bug that we had, it led to great examples of bad code, helped me learn new things, such as resolutions, and showed that problem solving has room for improvement, since some steps took a bit longer than anticipated.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term="debugging" /><category term="thought-process" /><category term="witch-hunt" /><summary type="html">I'm working on the hybrid angular web application. We did update the angular version and released it to our QA environment, everything went fine until we tried to release it to our other QA environment which is using docker. Angular build failed with the following error, indicating that two type definition packages are exporting the same types. In this blog post, I will walk through the thought process that helped me debug this problem. Locally on our windows laptop build works fine, azure windows pipelines work fine, but docker builds fail everywhere. #12 87.41 #12 87.41 ERROR in node_modules/@types/googlemaps/reference/map.d.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: BicyclingLayer, Map, HYBRID, ROADMAP, SATELLITE, TERRAIN, MapTypeRegistry, TrafficLayer, TransitLayer #12 87.41 #12 87.41 1 declare namespace google.maps { #12 87.41 ~~~~~~~ #12 87.41 #12 87.41 node_modules/@types/google.maps/index.d.ts:18:1 #12 87.41 18 declare namespace google.maps { From the error above we can see that there are two packages @types/googlemaps and @types/google.maps which provide the same type of definitions. Thought process We upgraded the angular major version, this resulted in a large portion of our other packages being upgraded as well. The first thought was that some have a new dependency, but this doesn't explain why our windows build agents can build successfully. When building on windows @types/google.maps package is not present in node_modules directory. After some searching in the project, installed packages and online, still nothing. The next step that came to my mind is to check the docker file system for this mysterious package. With a few commands, I had docker up and running with the project inside it. docker build . -t ng-debug-build docker run -it ng-debug-build /bin/ash This showed that docker indeed had @types/google.maps installed. Can npm packages have dependencies based on the operating system? New google quest was born and search continued. The answer is - no. Well if we don't have it on windows build, we don't have it in our package.json, it must be installed by someone. Using bisection search on dependencies and devDependencies I was able to find that @typesmarkerclusterer package was installing additional dependencies when building project in docker. I'm still not sure why we don't have issues on our windows azure build agent, it might be that we have some sort of cache that I'm not aware of. The issue was that @types/google-map package changed its dependency. Our angular application has @types/googlemaps but when this package changed its dependence conflicts arose. @types/markerclustererplus has wildcard major version dependency on @types/google-maps, and this situation is a perfect example of why you shouldn't do that! Solution Since we are using yarn we override internal package versions. We simply rolled back to @types/google-maps version that uses same @types/googlemaps dependency. &quot;resolutions&quot;: { &quot;@types/markerclustererplus/**/@types/google-maps&quot;: &quot;3.2.1&quot; } This is a perfect example demonstrating how careful you should be about versions that you specify in dependencies. Overall I'm pretty happy with this bug that we had, it led to great examples of bad code, helped me learn new things, such as resolutions, and showed that problem solving has room for improvement, since some steps took a bit longer than anticipated.</summary></entry><entry><title type="html">Snap to the road: Google vs Mapbox vs Bing</title><link href="https://floatincode.net/2021/09/20/snap-to-the-road-google-vs-mapbox-vs-bing/" rel="alternate" type="text/html" title="Snap to the road: Google vs Mapbox vs Bing" /><published>2021-09-20T08:34:00+00:00</published><updated>2021-09-20T08:34:00+00:00</updated><id>https://floatincode.net/2021/09/20/snap-to-the-road-google-vs-mapbox-vs-bing</id><content type="html" xml:base="https://floatincode.net/2021/09/20/snap-to-the-road-google-vs-mapbox-vs-bing/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Recently did some research about snap-to-road functionality. In this blog post, I will try to share results and compare some edge cases where coordinates are missing or GPS noise is present.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Tech stack: Angular, leaflet with map box map provider.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Red - actual coordinates&lt;/li&gt;
&lt;li&gt;Blue - Mapbox&lt;/li&gt;
&lt;li&gt;Green - Google&lt;/li&gt;
&lt;li&gt;Purple - Bing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:361,&quot;width&quot;:645,&quot;height&quot;:736,&quot;sizeSlug&quot;:&quot;full&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img src=&quot;/assets/2021/09/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-361&quot; width=&quot;645&quot; height=&quot;736&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Bing road interpolation works over longer road periods, but at the same time, it ignores visite to gas stations. Mapbox and Google acknowledge fact that there were few coordinates at the gas station&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:362,&quot;width&quot;:645,&quot;height&quot;:558,&quot;sizeSlug&quot;:&quot;full&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img src=&quot;/assets/2021/09/image-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-362&quot; width=&quot;645&quot; height=&quot;558&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Mapbox, Google, and actual coordinates go as a straight line, however, bing interpolates large distance coordinate jump.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:363,&quot;sizeSlug&quot;:&quot;full&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img src=&quot;/assets/2021/09/image-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-363&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;A strange example of how Google decided to stop interpolation and just draw straight lines for some reason. Bing is the winner for this scenario, perfectly snapped to the road.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:364,&quot;width&quot;:645,&quot;height&quot;:777,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img src=&quot;/assets/2021/09/image-3-849x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-364&quot; width=&quot;645&quot; height=&quot;777&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Great example showing different interpolation algorithms between Mapbox and Google. Google makes a corner, while Bing just continues straight.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:366,&quot;sizeSlug&quot;:&quot;full&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img src=&quot;/assets/2021/09/image-4.png&quot; alt=&quot;&quot; class=&quot;wp-image-366&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Goole tries to make a corner but gives up in the middle.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Mapbox only provides snap to closest road and this is clearly visible when we compare with Google and Bing snap to the road with interpolation.  &lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Latitude,Longitude or Longitude,Latitude&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;This was a long-lasting question and now I know that there is no correct answer.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt; Latitude,Longitude  - Google, Bing&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt; Longitude,Latitude  - Mapbox&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:table --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-table&quot;&gt;
&lt;table /&gt;
&lt;tbody /&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;MapBox&lt;/td&gt;
&lt;td&gt;Bing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;10 USD per 1000 requests&lt;/td&gt;
&lt;td&gt;2 USD per 1000 requests&lt;/td&gt;
&lt;td&gt;Unable to find, need to contact with exact quote.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snap-to-road&lt;/td&gt;
&lt;td&gt;Great&lt;/td&gt;
&lt;td&gt;Doesn't have&lt;/td&gt;
&lt;td&gt;Best&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Road selection&lt;/td&gt;
&lt;td&gt;Tries to make much more turns and include all original points in the route.&lt;/td&gt;
&lt;td&gt;The closest road can be configured with max distance from the point (5-50meters).&lt;/td&gt;
&lt;td&gt;Will try to interpolate a straight road and will ignore some coordinates to do so.&lt;/td&gt;
&lt;/tr&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:table --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;It won't be fair to compare accuracy, I'm drawing all roads on MapBox tiles.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Bing will try to keep going straight when interpolating, while Google will wiggle around and try to include all points in the interpolated route. This brings to the main difference, Bing is more likely to remove original points to make a route while Google is more likely to add points in between.  &lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;There is no winner, this research showed fundamental differences between these providers. Based on the situation all of them are valid options.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term="bing" /><category term="google" /><category term="map" /><category term="mapbox" /><category term="research" /><category term="snap-to-road" /><summary type="html">Recently did some research about snap-to-road functionality. In this blog post, I will try to share results and compare some edge cases where coordinates are missing or GPS noise is present. Tech stack: Angular, leaflet with map box map provider. Red - actual coordinates Blue - Mapbox Green - Google Purple - Bing Bing road interpolation works over longer road periods, but at the same time, it ignores visite to gas stations. Mapbox and Google acknowledge fact that there were few coordinates at the gas station Mapbox, Google, and actual coordinates go as a straight line, however, bing interpolates large distance coordinate jump. A strange example of how Google decided to stop interpolation and just draw straight lines for some reason. Bing is the winner for this scenario, perfectly snapped to the road. Great example showing different interpolation algorithms between Mapbox and Google. Google makes a corner, while Bing just continues straight. Goole tries to make a corner but gives up in the middle. Mapbox only provides snap to closest road and this is clearly visible when we compare with Google and Bing snap to the road with interpolation. Latitude,Longitude or Longitude,Latitude This was a long-lasting question and now I know that there is no correct answer. Latitude,Longitude - Google, Bing Longitude,Latitude - Mapbox Final thoughts Google MapBox Bing Price 10 USD per 1000 requests 2 USD per 1000 requests Unable to find, need to contact with exact quote. Snap-to-road Great Doesn't have Best Road selection Tries to make much more turns and include all original points in the route. The closest road can be configured with max distance from the point (5-50meters). Will try to interpolate a straight road and will ignore some coordinates to do so. It won't be fair to compare accuracy, I'm drawing all roads on MapBox tiles. Bing will try to keep going straight when interpolating, while Google will wiggle around and try to include all points in the interpolated route. This brings to the main difference, Bing is more likely to remove original points to make a route while Google is more likely to add points in between. There is no winner, this research showed fundamental differences between these providers. Based on the situation all of them are valid options.</summary></entry><entry><title type="html">.NET Transaction scope</title><link href="https://floatincode.net/2021/09/06/transaction-scope/" rel="alternate" type="text/html" title=".NET Transaction scope" /><published>2021-09-06T03:30:00+00:00</published><updated>2021-09-06T03:30:00+00:00</updated><id>https://floatincode.net/2021/09/06/transaction-scope</id><content type="html" xml:base="https://floatincode.net/2021/09/06/transaction-scope/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;This blog post was moved from the old blog.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:separator --&gt;&lt;/p&gt;
&lt;hr class=&quot;wp-block-separator&quot; /&gt;
&lt;!-- /wp:separator --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;One way to learn something new is to write unit tests exploring a new library, that is what I'll be doing in this blog post. For tests, we will use xUnit and for database Npgsql.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Let's explore different use cases of transaction scope. We will see how transactions behave when they are nested and how exceptions are handled on different nesting levels.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Since we are using async/await workflow we need to enable&amp;nbsp;&lt;code&gt;TransactionScopeAsyncFlowOption.Enabled&lt;/code&gt;&amp;nbsp;on our transactions.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Enable transaction scope&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list {&quot;ordered&quot;:true} --&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Include&amp;nbsp;&lt;code&gt;Enlist=true&lt;/code&gt;&amp;nbsp;in your connection string.&lt;/li&gt;
&lt;li&gt;Call&amp;nbsp;&lt;code&gt;connection.EnlistTransaction(Transaction.Current);&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Newer versions of Npgsql have enlisting enabled by default.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Setup functions and constants used throughout testing&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Test setup and configuration&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;private readonly string ConnectionString = &quot;DATABASE=transaction_test;PORT=5432;USER ID=postgres;PASSWORD=postgres;HOST=localhost;&quot;;

private readonly string InsertTableAEntryQuery = @&quot;INSERT INTO public.TestTableA(value) VALUES (@value);&quot;;
private readonly string InsertTableBEntryQuery = @&quot;INSERT INTO public.TestTableB(value) VALUES (@value);&quot;;

private readonly string TableARowCountQuery = @&quot;SELECT count(*) FROM public.TestTableA;&quot;;
private readonly string TableBRowCountQuery = @&quot;SELECT count(*) FROM public.TestTableB;&quot;;

private async Task ClearDatabase()
{
    await using var connection = new NpgsqlConnection(this.ConnectionString);

    await connection.ExecuteAsync(&quot;DELETE FROM public.TestTableA&quot;);
    await connection.ExecuteAsync(&quot;DELETE FROM public.TestTableB&quot;);
}

private async Task&amp;lt;int&amp;gt; TableARowCount()
{
    await using var connection = new NpgsqlConnection(ConnectionString);
    return await connection.QuerySingleAsync&amp;lt;int&amp;gt;(TableARowCountQuery);
}

private async Task&amp;lt;int&amp;gt; TableBRowCount()
{
    await using var connection = new NpgsqlConnection(ConnectionString);
    return await connection.QuerySingleAsync&amp;lt;int&amp;gt;(TableBRowCountQuery);
}

private async Task ThrowException()
{
    await using var connection = new NpgsqlConnection(this.ConnectionString);
    using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
    throw new Exception();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;White smoke test to make sure we have everything setup correctly&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Simple test to make sure everything is connected and working.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;[Fact]
public async Task ConnectionIsWorking()
{
    await ClearDatabase();
    await using var connection = new NpgsqlConnection(ConnectionString);

    // Note: no need to open connection
    // Dapper will open it for us

    await connection.ExecuteAsync(InsertTableAEntryQuery, new { value = 123 });
    await connection.ExecuteAsync(InsertTableBEntryQuery, new { value = 321 });

    Assert.Equal(1, await TableARowCount());
    Assert.Equal(1, await TableBRowCount());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Throwing exception before transaction complete should roll back transaction&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Simple test to see if changes are rolled back if exception is thrown.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;[Fact]
public async Task SimpleTransactionRollbackOnException()
{
    await ClearDatabase();

    using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
        try
        {
            await using var connection = new NpgsqlConnection(ConnectionString);

            await connection.ExecuteAsync(InsertTableAEntryQuery, new { value = 123 });

            await ThrowException();

            scope.Complete();
        }
        catch { }
    }

    Assert.Equal(0, await TableARowCount());
    Assert.Equal(0, await TableBRowCount());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Even if we catch exception, we still can't complete transaction since connection state is set to aborted&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Exceptions inside transaction will prevent its completion.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;[Fact]
public async Task SimpleTransactionRollbackOnException2()
{
    await ClearDatabase();
    try
    {
        using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
        await using var connection2 = new NpgsqlConnection(ConnectionString);

        try
        {
            await using var connection = new NpgsqlConnection(ConnectionString);
            await connection.ExecuteAsync(InsertTableAEntryQuery, new { value = 123 });

            await ThrowException();

        }
        catch { }

        scope.Complete();
    }
    catch (TransactionAbortedException)
    {
        Assert.True(true);
    }
    catch
    {
        Assert.True(false);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Forgetting to call Complete will fail to save changes silently&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Transactions must be completed explicitly in order to persist changes&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;[Fact]
public async Task SimpleTransactionRollbackWithoutComplete()
{
    await ClearDatabase();

    using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
        await using var connection = new NpgsqlConnection(ConnectionString);

        await connection.ExecuteAsync(InsertTableAEntryQuery, new { value = 123 });
        await connection.ExecuteAsync(InsertTableBEntryQuery, new { value = 321 });

        //Forgot to call complete
        //scope.Complete();
    }

    Assert.Equal(0, await TableARowCount());
    Assert.Equal(0, await TableBRowCount());
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Nesting transaction scopes and having multiple complete functions will work fine&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Transactions can be nested.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;[Fact]
public async Task NestedTransactionsBothHavingComplete()
{
    await ClearDatabase();

    using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
        await using var connection = new NpgsqlConnection(ConnectionString);

        await connection.ExecuteAsync(InsertTableAEntryQuery, new { value = 123 });

        await NestedTransactionWithCompleteInside();

        scope.Complete();
    }

    Assert.Equal(1, await TableARowCount());
    Assert.Equal(1, await TableBRowCount());
}

private async Task NestedTransactionWithCompleteInside()
{
    using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
    await using var connection = new NpgsqlConnection(ConnectionString);

    await connection.ExecuteAsync(InsertTableBEntryQuery, new { value = 321 });

    scope.Complete();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Root transaction will fail when nested transaction isn't completed&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;All transactions must be completed explicitly&quot; class=&quot;wp-block-code&quot;&gt;&lt;code class=&quot;&quot;&gt;[Fact]
public async Task NestedTransactionsOnlyRootWithComplete()
{
    await ClearDatabase();

    try
    {
        using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
        await using var connection = new NpgsqlConnection(ConnectionString);

        await connection.ExecuteAsync(InsertTableAEntryQuery, new { value = 123 });

        await NestedTransactionWithoutCompleteInside();

        scope.Complete();
    }
    catch (TransactionAbortedException)
    {
        Assert.True(true);
    }
    catch
    {
        Assert.True(false);
    }
}

private async Task NestedTransactionWithoutCompleteInside()
{
    using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
    await using var connection = new NpgsqlConnection(ConnectionString);

    await connection.ExecuteAsync(InsertTableBEntryQuery, new { value = 321 });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If we nest transactions, all of them succeed or all of them will fail.&lt;/li&gt;
&lt;li&gt;Don't forget to call transaction scope complete method.&lt;/li&gt;
&lt;li&gt;Transaction complete method will fail if connection is in invalid state due to exception.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term=".NET" /><category term="C#" /><category term="database" /><category term="testing" /><category term="transaction" /><summary type="html">This blog post was moved from the old blog. One way to learn something new is to write unit tests exploring a new library, that is what I'll be doing in this blog post. For tests, we will use xUnit and for database Npgsql. Let's explore different use cases of transaction scope. We will see how transactions behave when they are nested and how exceptions are handled on different nesting levels. Since we are using async/await workflow we need to enable&amp;nbsp;TransactionScopeAsyncFlowOption.Enabled&amp;nbsp;on our transactions. Enable transaction scope Include&amp;nbsp;Enlist=true&amp;nbsp;in your connection string. Call&amp;nbsp;connection.EnlistTransaction(Transaction.Current); Newer versions of Npgsql have enlisting enabled by default.&amp;nbsp; Setup functions and constants used throughout testing private readonly string ConnectionString = &quot;DATABASE=transaction_test;PORT=5432;USER ID=postgres;PASSWORD=postgres;HOST=localhost;&quot;;</summary></entry><entry><title type="html">Custom API version selector</title><link href="https://floatincode.net/2021/08/23/custom-api-version-selector/" rel="alternate" type="text/html" title="Custom API version selector" /><published>2021-08-23T03:08:00+00:00</published><updated>2021-08-23T03:08:00+00:00</updated><id>https://floatincode.net/2021/08/23/custom-api-version-selector</id><content type="html" xml:base="https://floatincode.net/2021/08/23/custom-api-version-selector/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;In this blog post, I will demonstrate how to write a custom .NET CORE API version selector. While it's easy and libraries provided all the necessary information to do that, you should weigh the pros and cons before doing so. The implementation that I will share below is used in API which communicates with the web and two mobile apps (IOS, Android), while at first, this custom version selection seemed a great idea, after some time it looks more like a ticking time bomb. &lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Source code at &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://github.com/FloatInCodeBlog/ApiCustomEndpointVersioning&quot; data-type=&quot;URL&quot; data-id=&quot;https://github.com/FloatInCodeBlog/ApiCustomEndpointVersioning&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Install &lt;code&gt;Microsoft.AspNetCore.Mvc.Versioning&lt;/code&gt; nuget package.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Two identical methods with different api versions for testing.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;        [HttpGet]
        [ApiVersion(&quot;1.0&quot;)]
        public WeatherResponse Get()
        {
            var rng = new Random();
            var respones = new WeatherResponse
            {
                Forecasts = Enumerable.Range(1, 5).Select(index =&amp;gt; new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = Summaries[rng.Next(Summaries.Length)]
                }),
                ApiVersion = &quot;1.0&quot;
            };

            return respones;
        }

        [HttpGet]
        [ApiVersion(&quot;2.0&quot;)]
        public WeatherResponse Get_v2()
        {
            var rng = new Random();
            var respones = new WeatherResponse
            {
                Forecasts = Enumerable.Range(1, 5).Select(index =&amp;gt; new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = Summaries[rng.Next(Summaries.Length)]
                }),
                ApiVersion = &quot;2.0&quot;
            };

            return respones;
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Versioning configuration&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;services.AddApiVersioning(options =&amp;gt;
{
    options.ReportApiVersions = true;
    options.AssumeDefaultVersionWhenUnspecified = true;
    //Important to version reader ALWAYS report version as missing
    options.ApiVersionReader = new HeaderApiVersionReader(&quot;custom-version-selection-works-only-if-api-version-is-not-specified&quot;);

    options.ApiVersionSelector = new HighestUpToSpecifiedIncludedVersionSelector(new ApiVersion(2, 0));
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ApiVersion&lt;/code&gt; has extension to parse version object from string, &lt;code&gt;SelectVersion&lt;/code&gt; method has all the information required to decide which method to select. What's left is for us to make decision and implement our custom version selector.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Custom version selection. Select highest up to specified version&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;    public class HighestUpToSpecifiedIncludedVersionSelector : IApiVersionSelector
    {
        private readonly ApiVersion _defaultVersion;

        public HighestUpToSpecifiedIncludedVersionSelector(ApiVersion defaultVersion)
        {
            _defaultVersion = defaultVersion;
        }

        public ApiVersion SelectVersion(HttpRequest request, ApiVersionModel model)
        {
            if (model == null)
                throw new ArgumentNullException(nameof(model));

            var requestedVersion = ParseVersion(request) ?? _defaultVersion;

            var selectedVersion = model.ImplementedApiVersions.Count switch
            {
                0 =&amp;gt; _defaultVersion,
                1 =&amp;gt; model.ImplementedApiVersions[0].Status == null ? model.ImplementedApiVersions[0] : _defaultVersion,
                _ =&amp;gt; model.ImplementedApiVersions
                   .Where(v =&amp;gt; v.Status == null &amp;amp;&amp;amp; v &amp;lt;= requestedVersion)
                   .Max(v =&amp;gt; v) ?? _defaultVersion
            };

            return selectedVersion;
        }

        private static ApiVersion ParseVersion(HttpRequest request)
        {
            if (!request.Headers.TryGetValue(&quot;api-version&quot;, out var version))
                return null;

            if (string.IsNullOrEmpty(version) || version.Count != 1)
                return null;

            return ApiVersion.TryParse(version[0], out var apiVersion) ? apiVersion : null;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:316,&quot;sizeSlug&quot;:&quot;full&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img src=&quot;/assets/2021/08/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-316&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Sending request without version will execute default version endpoint, which in this case is 2.0&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:317,&quot;width&quot;:645,&quot;height&quot;:326,&quot;sizeSlug&quot;:&quot;full&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img src=&quot;/assets/2021/08/image-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-317&quot; width=&quot;645&quot; height=&quot;326&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Specifying version that doesn't exist we get smallest up to that version, in this case it's 1.0&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;We used this approach in mobile application. Would I use it again ? No. As of right now we don't make any breaking changes to the API, only small bug fixes. With this versioning style, if we already have v2.0 endpoint and mobile app is using it, we can't create new v2.0 endpoint for other controller, if we do, mobile app will start to use it immediately and will break.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;It's good to know that you can change version selection, but it's best to fail if endpoint or version is not found.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term=".NET" /><category term="API" /><category term="C#" /><category term="Versioning" /><summary type="html">In this blog post, I will demonstrate how to write a custom .NET CORE API version selector. While it's easy and libraries provided all the necessary information to do that, you should weigh the pros and cons before doing so. The implementation that I will share below is used in API which communicates with the web and two mobile apps (IOS, Android), while at first, this custom version selection seemed a great idea, after some time it looks more like a ticking time bomb. Source code at GitHub Implementation Install Microsoft.AspNetCore.Mvc.Versioning nuget package. [HttpGet] [ApiVersion(&quot;1.0&quot;)] public WeatherResponse Get() { var rng = new Random(); var respones = new WeatherResponse { Forecasts = Enumerable.Range(1, 5).Select(index =&amp;gt; new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }), ApiVersion = &quot;1.0&quot; };</summary></entry><entry><title type="html">Caprover: best way to deploy .NET and Docker</title><link href="https://floatincode.net/2021/08/09/caprover-best-way-to-deploy-net-and-docker/" rel="alternate" type="text/html" title="Caprover: best way to deploy .NET and Docker" /><published>2021-08-09T02:36:00+00:00</published><updated>2021-08-09T02:36:00+00:00</updated><id>https://floatincode.net/2021/08/09/caprover-best-way-to-deploy-net-and-docker</id><content type="html" xml:base="https://floatincode.net/2021/08/09/caprover-best-way-to-deploy-net-and-docker/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Caprover quickly became my favorite server management tool. If you are a solo developer or working in a smaller team, you should definitely give it a try.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading {&quot;level&quot;:3} --&gt;&lt;/p&gt;
&lt;h3&gt;What's included:&lt;/h3&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker registry - but you can easily connect to any other registry&lt;/li&gt;
&lt;li&gt;Docker build engine - just push your code and Caprover will build and deploy it&lt;/li&gt;
&lt;li&gt;Webhooks - integrate with any Git repository and build\deploy on push&lt;/li&gt;
&lt;li&gt;Server metrics&lt;/li&gt;
&lt;li&gt;Lets Encrypt certificates - Caprover will issue and renew certificates for you&lt;/li&gt;
&lt;li&gt;Custom nginx configs - you are not locked in doing things in only one way, if you need web sockets or extra http headers - you can modify configuration&lt;/li&gt;
&lt;li&gt;One-click-apps - select app from list, enter required variables (name, version ...) and deploy. Similar to  docker-compose where you can run multiple services from single configuration. Also it's easy to create your own one-click-app configurations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading {&quot;level&quot;:3} --&gt;&lt;/p&gt;
&lt;h3&gt;What's missing&lt;/h3&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Logging - to view nginx or other service logs you have to SSH to server&lt;/li&gt;
&lt;li&gt;No build steps - you can't run tests or do anything else, just build and push to registry&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;I have been using Caprover for a half year now and moved all my services to it, so right now I have +10 services running, including web apps, databases, WordPress, and more.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Caprover is too simple to write about and its documentation covers all the details, but at the same time Caprover is too important not to mention it.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;To find more visit &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;http://caprover.com&quot; data-type=&quot;URL&quot; data-id=&quot;caprover.com&quot; target=&quot;_blank&quot;&gt;Caprover.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term=".NET" /><category term="continuous-deployment" /><category term="docker" /><summary type="html">Caprover quickly became my favorite server management tool. If you are a solo developer or working in a smaller team, you should definitely give it a try. What's included: Docker registry - but you can easily connect to any other registry Docker build engine - just push your code and Caprover will build and deploy it Webhooks - integrate with any Git repository and build\deploy on push Server metrics Lets Encrypt certificates - Caprover will issue and renew certificates for you Custom nginx configs - you are not locked in doing things in only one way, if you need web sockets or extra http headers - you can modify configuration One-click-apps - select app from list, enter required variables (name, version ...) and deploy. Similar to docker-compose where you can run multiple services from single configuration. Also it's easy to create your own one-click-app configurations What's missing Logging - to view nginx or other service logs you have to SSH to server No build steps - you can't run tests or do anything else, just build and push to registry I have been using Caprover for a half year now and moved all my services to it, so right now I have +10 services running, including web apps, databases, WordPress, and more. Caprover is too simple to write about and its documentation covers all the details, but at the same time Caprover is too important not to mention it. To find more visit Caprover.com</summary></entry><entry><title type="html">Mapster: generate dto, async after map actions, dependency injection</title><link href="https://floatincode.net/2021/07/26/mapster-generate-dto-async-after-map-actions-dependency-injection/" rel="alternate" type="text/html" title="Mapster: generate dto, async after map actions, dependency injection" /><published>2021-07-26T02:35:00+00:00</published><updated>2021-07-26T02:35:00+00:00</updated><id>https://floatincode.net/2021/07/26/mapster-generate-dto-async-after-map-actions-dependency-injection</id><content type="html" xml:base="https://floatincode.net/2021/07/26/mapster-generate-dto-async-after-map-actions-dependency-injection/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://github.com/MapsterMapper/Mapster&quot; data-type=&quot;URL&quot; data-id=&quot;https://github.com/MapsterMapper/Mapster&quot; target=&quot;_blank&quot;&gt;Mapster &lt;/a&gt;brings some new ideas to object mapping world. Model generation, async custom actions after map, dependency injection. In this post, I will try to explore these new ideas. Source code can be found on &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://github.com/floatas/MapsterTest&quot; data-type=&quot;URL&quot; data-id=&quot;https://github.com/floatas/MapsterTest&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Getting started&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;In your solution folder run the following commands to enable dotnet tools and install mapster code generator.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Enable dotnet tools in solution directory.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;dotnet new tool-manifest&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Enabling tool manifest in the solution directory will create a local configuration file, which will help other team members to install the same tools for the project.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Mapster code generation dotnet tool.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;dotnet tool install Mapster.Tool&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Mapster provides several ways to &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://github.com/MapsterMapper/Mapster/wiki/Mapster.Tool&quot; data-type=&quot;URL&quot; data-id=&quot;https://github.com/MapsterMapper/Mapster/wiki/Mapster.Tool&quot; target=&quot;_blank&quot;&gt;generate mapping files&lt;/a&gt;, for this example, let's generate automatically after build.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Clean generated files.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;xml&quot; class=&quot;language-xml&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ItemGroup&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Generated&amp;nbsp;Include=&quot;**\*.g.cs&quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/ItemGroup&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Target&amp;nbsp;Name=&quot;CleanGenerated&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Delete&amp;nbsp;Files=&quot;@(Generated)&quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Target&amp;gt;&lt;/code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Generate Mapster mapping files after build.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;xml&quot; class=&quot;language-xml&quot;&gt;&amp;lt;Target&amp;nbsp;Name=&quot;Mapster&quot;&amp;nbsp;AfterTargets=&quot;AfterBuild&quot;&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;tool&amp;nbsp;restore&quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;mapster&amp;nbsp;model&amp;nbsp;-a&amp;nbsp;&amp;amp;quot;$(TargetDir)$(ProjectName).dll&amp;amp;quot;&quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;mapster&amp;nbsp;extension&amp;nbsp;-a&amp;nbsp;&amp;amp;quot;$(TargetDir)$(ProjectName).dll&amp;amp;quot;&quot;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;mapster&amp;nbsp;mapper&amp;nbsp;-a&amp;nbsp;&amp;amp;quot;$(TargetDir)$(ProjectName).dll&amp;amp;quot;&quot;&amp;nbsp;/&amp;gt;
&amp;lt;/Target&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;One thing to keep in mind, code generation is done &lt;strong&gt;after build&lt;/strong&gt;. If you change mapster configs and start the project, nothing will change. Correct flow is &lt;strong&gt;build project and then start it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Mapster.Tool will scan assembly and use config files to generate models.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;class&amp;nbsp;MapsterConfig&amp;nbsp;:&amp;nbsp;ICodeGenerationRegister
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;Register(CodeGenerationConfig&amp;nbsp;config)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.AdaptTo(&quot;[name]Dto&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.ForType&amp;lt;WeatherForecast&amp;gt;();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Advanced model generation&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Ignore and change property name.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;public&amp;nbsp;class&amp;nbsp;MapsterConfig&amp;nbsp;:&amp;nbsp;ICodeGenerationRegister
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;Register(CodeGenerationConfig&amp;nbsp;config)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.AdaptTo(&quot;[name]Dto&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.ForType&amp;lt;WeatherForecast&amp;gt;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cfg&amp;nbsp;=&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cfg.Ignore(poco&amp;nbsp;=&amp;gt;&amp;nbsp;poco.TemperatureC);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cfg.Map(poco&amp;nbsp;=&amp;gt;&amp;nbsp;poco.Summary,&amp;nbsp;&quot;MappedSummary&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;The model can be modified by ignoring, renaming, changing the type of the property.   &lt;strong&gt;When you change the property name, you MUST map that property manually.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Map property explicitly.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;TypeAdapterConfig&amp;lt;WeatherForecast,&amp;nbsp;WeatherForecastDto&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.NewConfig()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Map(dest&amp;nbsp;=&amp;gt;&amp;nbsp;dest.MappedSummary,&amp;nbsp;src&amp;nbsp;=&amp;gt;&amp;nbsp;src.Summary);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Type safety&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RequireExplicitMapping&lt;/code&gt; will make sure that all mappings should be registered. &lt;code&gt;RequireDestinationMemberSource&lt;/code&gt; checks if all destination properties have mappings. &lt;code&gt;.Compile()&lt;/code&gt; will perform all checks at compile time and throw exceptions if there are any issues.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Runtime and compile time mapping validation.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;TypeAdapterConfig.GlobalSettings.RequireExplicitMapping&amp;nbsp;=&amp;nbsp;true;
TypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource&amp;nbsp;=&amp;nbsp;true;
TypeAdapterConfig.GlobalSettings.Compile();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;After map actions&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;AfterMapping extension allows you to execute code after mapping is done and do final modifications to result if needed.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;AfterMapping function.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;TypeAdapterConfig&amp;lt;WeatherForecast,&amp;nbsp;WeatherForecastDto&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.NewConfig()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Map(dest&amp;nbsp;=&amp;gt;&amp;nbsp;dest.MappedSummary,&amp;nbsp;src&amp;nbsp;=&amp;gt;&amp;nbsp;src.Summary)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.AfterMapping((dest,&amp;nbsp;d)&amp;nbsp;=&amp;gt;&amp;nbsp;{&amp;nbsp;d.MappedSummary&amp;nbsp;=&amp;nbsp;&quot;AfterMapping&amp;nbsp;&quot;&amp;nbsp;+&amp;nbsp;d.MappedSummary;&amp;nbsp;});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Dependency Injection and async after map actions&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;For dependency injection to work we need to change how mapper is used. Configuration and mapping must be switched from static instances to services. First, we must configure required services by adding singleton for all mapping configurations and scoped mapping service.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Configure Mapster DI&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;public&amp;nbsp;void&amp;nbsp;ConfigureServices(IServiceCollection&amp;nbsp;services)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//configure&amp;nbsp;mapster
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;config&amp;nbsp;=&amp;nbsp;new&amp;nbsp;TypeAdapterConfig();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;services.AddSingleton(config);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;services.AddScoped&amp;lt;IMapper,&amp;nbsp;ServiceMapper&amp;gt;();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TypeAdapterConfig.GlobalSettings.RequireExplicitMapping&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TypeAdapterConfig.GlobalSettings.Compile();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//-------
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;For testing purposes, I created three services all of them return time when they were created.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Mapping definitions must be also declared using DI&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;public&amp;nbsp;void&amp;nbsp;Configure(IApplicationBuilder&amp;nbsp;app,&amp;nbsp;IWebHostEnvironment&amp;nbsp;env,&amp;nbsp;TypeAdapterConfig&amp;nbsp;config)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Mapping&amp;nbsp;configurations
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.NewConfig&amp;lt;WeatherForecast,&amp;nbsp;WeatherForecastDto&amp;gt;()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Map(dest&amp;nbsp;=&amp;gt;&amp;nbsp;dest.MappedSummary,&amp;nbsp;src&amp;nbsp;=&amp;gt;&amp;nbsp;src.Summary)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.AfterMappingAsync(async&amp;nbsp;(dest)&amp;nbsp;=&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Thread.Sleep(1000);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;transient&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MapContext.Current.GetService&amp;lt;TransientService&amp;gt;().DateAsync();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;scoped&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MapContext.Current.GetService&amp;lt;ScopedService&amp;gt;().DateAsync();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;singleton&amp;nbsp;=&amp;nbsp;await&amp;nbsp;MapContext.Current.GetService&amp;lt;SingletonService&amp;gt;().DateAsync();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dest.MappedSummary&amp;nbsp;=&amp;nbsp;$&quot;{transient},&amp;nbsp;{scoped},&amp;nbsp;{singleton}&quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//--------&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Mapping function itself also change to async version.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Using IMapper service.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;private&amp;nbsp;readonly&amp;nbsp;IMapper&amp;nbsp;_mapper;

public&amp;nbsp;WeatherForecastController(IMapper&amp;nbsp;mapper)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_mapper&amp;nbsp;=&amp;nbsp;mapper;
}

[HttpGet]
public&amp;nbsp;async&amp;nbsp;Task&amp;lt;IEnumerable&amp;lt;WeatherForecastDto&amp;gt;&amp;gt;&amp;nbsp;Get()
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;result&amp;nbsp;=&amp;nbsp;new&amp;nbsp;List&amp;lt;WeatherForecastDto&amp;gt;();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach&amp;nbsp;(var&amp;nbsp;forecast&amp;nbsp;in&amp;nbsp;Forecasts())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result.Add(await&amp;nbsp;_mapper.From(forecast)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.AdaptToTypeAsync&amp;lt;WeatherForecastDto&amp;gt;());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Now that we have all the required services, we can do a simple test. Execute endpoint twice and compare dates to see if service instances were created as expected.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:292,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-292&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;First-run results.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:293,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-293&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Second run results.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Transient service results change for each temperature value, scoped service time is the same for request and singleton always shows the same date. From this simple test we see that DI and service scope in mapping works as we expect.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Mapster brings really great additions to otherwise mundane mapping. Code generation, after map actions, dependency injection are things that more and more often come to mind while working on a large legacy project, and from the initial look, Mapster handles these cases pretty well.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;There are still some questions unanswered: how does it handle complex objects? testing I saw in github that some people had issues with concurrency. Code maintainability, since part of logic, would be moved to mapping.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;I'm looking forward to using this library in my next project.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term=".NET" /><category term="C#" /><category term="code-generation" /><category term="DI" /><category term="mapper" /><summary type="html">Mapster brings some new ideas to object mapping world. Model generation, async custom actions after map, dependency injection. In this post, I will try to explore these new ideas. Source code can be found on GitHub. Getting started In your solution folder run the following commands to enable dotnet tools and install mapster code generator. dotnet new tool-manifest Enabling tool manifest in the solution directory will create a local configuration file, which will help other team members to install the same tools for the project. dotnet tool install Mapster.Tool Mapster provides several ways to generate mapping files, for this example, let's generate automatically after build. &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ItemGroup&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Generated&amp;nbsp;Include=&quot;**\*.g.cs&quot;&amp;nbsp;/&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/ItemGroup&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Target&amp;nbsp;Name=&quot;CleanGenerated&quot;&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Delete&amp;nbsp;Files=&quot;@(Generated)&quot;&amp;nbsp;/&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Target&amp;gt; &amp;lt;Target&amp;nbsp;Name=&quot;Mapster&quot;&amp;nbsp;AfterTargets=&quot;AfterBuild&quot;&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;tool&amp;nbsp;restore&quot;&amp;nbsp;/&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;mapster&amp;nbsp;model&amp;nbsp;-a&amp;nbsp;&amp;amp;quot;$(TargetDir)$(ProjectName).dll&amp;amp;quot;&quot;&amp;nbsp;/&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;mapster&amp;nbsp;extension&amp;nbsp;-a&amp;nbsp;&amp;amp;quot;$(TargetDir)$(ProjectName).dll&amp;amp;quot;&quot;&amp;nbsp;/&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Exec&amp;nbsp;WorkingDirectory=&quot;$(ProjectDir)&quot;&amp;nbsp;Command=&quot;dotnet&amp;nbsp;mapster&amp;nbsp;mapper&amp;nbsp;-a&amp;nbsp;&amp;amp;quot;$(TargetDir)$(ProjectName).dll&amp;amp;quot;&quot;&amp;nbsp;/&amp;gt; &amp;lt;/Target&amp;gt; One thing to keep in mind, code generation is done after build. If you change mapster configs and start the project, nothing will change. Correct flow is build project and then start it. &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;class&amp;nbsp;MapsterConfig&amp;nbsp;:&amp;nbsp;ICodeGenerationRegister &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;Register(CodeGenerationConfig&amp;nbsp;config) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.AdaptTo(&quot;[name]Dto&quot;) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.ForType&amp;lt;WeatherForecast&amp;gt;(); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} Advanced model generation public&amp;nbsp;class&amp;nbsp;MapsterConfig&amp;nbsp;:&amp;nbsp;ICodeGenerationRegister { &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;Register(CodeGenerationConfig&amp;nbsp;config) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.AdaptTo(&quot;[name]Dto&quot;) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.ForType&amp;lt;WeatherForecast&amp;gt;( &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cfg&amp;nbsp;=&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cfg.Ignore(poco&amp;nbsp;=&amp;gt;&amp;nbsp;poco.TemperatureC); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cfg.Map(poco&amp;nbsp;=&amp;gt;&amp;nbsp;poco.Summary,&amp;nbsp;&quot;MappedSummary&quot;); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} } The model can be modified by ignoring, renaming, changing the type of the property. When you change the property name, you MUST map that property manually. TypeAdapterConfig&amp;lt;WeatherForecast,&amp;nbsp;WeatherForecastDto&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.NewConfig() &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Map(dest&amp;nbsp;=&amp;gt;&amp;nbsp;dest.MappedSummary,&amp;nbsp;src&amp;nbsp;=&amp;gt;&amp;nbsp;src.Summary); Type safety RequireExplicitMapping will make sure that all mappings should be registered. RequireDestinationMemberSource checks if all destination properties have mappings. .Compile() will perform all checks at compile time and throw exceptions if there are any issues. TypeAdapterConfig.GlobalSettings.RequireExplicitMapping&amp;nbsp;=&amp;nbsp;true; TypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource&amp;nbsp;=&amp;nbsp;true; TypeAdapterConfig.GlobalSettings.Compile(); After map actions AfterMapping extension allows you to execute code after mapping is done and do final modifications to result if needed. TypeAdapterConfig&amp;lt;WeatherForecast,&amp;nbsp;WeatherForecastDto&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.NewConfig() &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Map(dest&amp;nbsp;=&amp;gt;&amp;nbsp;dest.MappedSummary,&amp;nbsp;src&amp;nbsp;=&amp;gt;&amp;nbsp;src.Summary) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.AfterMapping((dest,&amp;nbsp;d)&amp;nbsp;=&amp;gt;&amp;nbsp;{&amp;nbsp;d.MappedSummary&amp;nbsp;=&amp;nbsp;&quot;AfterMapping&amp;nbsp;&quot;&amp;nbsp;+&amp;nbsp;d.MappedSummary;&amp;nbsp;}); Dependency Injection and async after map actions For dependency injection to work we need to change how mapper is used. Configuration and mapping must be switched from static instances to services. First, we must configure required services by adding singleton for all mapping configurations and scoped mapping service. public&amp;nbsp;void&amp;nbsp;ConfigureServices(IServiceCollection&amp;nbsp;services) { &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//configure&amp;nbsp;mapster &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;config&amp;nbsp;=&amp;nbsp;new&amp;nbsp;TypeAdapterConfig(); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;services.AddSingleton(config); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;services.AddScoped&amp;lt;IMapper,&amp;nbsp;ServiceMapper&amp;gt;();</summary></entry><entry><title type="html">Pro Windows Subsystem for Linux (WSL) book “review”</title><link href="https://floatincode.net/2021/07/12/pro-windows-subsystem-for-linux-wsl-book-review/" rel="alternate" type="text/html" title="Pro Windows Subsystem for Linux (WSL) book “review”" /><published>2021-07-12T14:16:00+00:00</published><updated>2021-07-12T14:16:00+00:00</updated><id>https://floatincode.net/2021/07/12/pro-windows-subsystem-for-linux-wsl-book-review</id><content type="html" xml:base="https://floatincode.net/2021/07/12/pro-windows-subsystem-for-linux-wsl-book-review/">&lt;p&gt;&lt;!-- wp:media-text {&quot;mediaId&quot;:219,&quot;mediaLink&quot;:&quot;https://floatincode.net/?attachment_id=219&quot;,&quot;mediaType&quot;:&quot;image&quot;,&quot;mediaWidth&quot;:18} --&gt;&lt;/p&gt;
&lt;div class=&quot;wp-block-media-text alignwide is-stacked-on-mobile&quot; style=&quot;grid-template-columns:18% auto&quot;&gt;
&lt;figure class=&quot;wp-block-media-text__media&quot;&gt;&lt;img src=&quot;/assets/2021/07/ProWindowsSubsystemForLinuxWSLCover-767x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-219 size-full&quot; /&gt;&lt;/figure&gt;
&lt;div class=&quot;wp-block-media-text__content&quot;&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a rel=&quot;noreferrer noopener&quot; target=&quot;_blank&quot; href=&quot;https://www.amazon.com/gp/product/1484268725/ref=as_li_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1484268725&amp;amp;linkCode=as2&amp;amp;tag=blogofthoth-20&amp;amp;linkId=62857a01d0b7be3c9e9dcf19a6a63ef1&quot;&gt;Pro Windows Subsystem for Linux (WSL)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;!-- /wp:media-text --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Review is in quotation marks because this is not a full review, this is a summary and tips of what I learned from this book. When reading it my main focus was to improve my Kubernetes, terraform script workflow. Which involve windows file/directory navigation, editing files on WSL, managing WSL distributions.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Default parameters&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;First lets identify which distributions are installed, which are default and make sure we starting them with correct user.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Change default WSL version&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;wsl.exe --set-default-version 2 &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;List all distributions&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;wsl.exe --list --verbose --all&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;All distribution list, asterisk (*) indicates default&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt; NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop-data    Running         2
  docker-desktop         Running         2 &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Name  - &lt;em&gt;&amp;lt;wsl distro name&amp;gt;&lt;/em&gt; in following commands&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Set default WSL distro&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;wsl.exe --set-default &amp;lt;wsl distro name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Change default WSL distribution&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;wsl.exe --set-version &amp;lt;wsl distro name&amp;gt; 2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Change default user&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;&amp;lt;wsl distro name&amp;gt; config --default-user &amp;lt;new user name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;File permissions&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Even though file permissions doesn't really fit into what I was looking in this book, wanted to write this down for future reference:&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Three groups (&amp;lt;user&amp;gt;&amp;lt;group&amp;gt;&amp;lt;other&amp;gt;):&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User - by default user who created&lt;/li&gt;
&lt;li&gt;Group - users in a group with assigned access to files&lt;/li&gt;
&lt;li&gt;Other - all other users&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading {&quot;level&quot;:3} --&gt;&lt;/p&gt;
&lt;h3&gt;Symbolic form:&lt;/h3&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;r - Read&lt;/li&gt;
&lt;li&gt;w - Write&lt;/li&gt;
&lt;li&gt;x - Execute&lt;/li&gt;
&lt;li&gt;- (just dash) for no permission&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Example: rwx-r-xr-&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rwx - for user&lt;/li&gt;
&lt;li&gt;-r- -for group&lt;/li&gt;
&lt;li&gt;xr- - for other&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading {&quot;level&quot;:3} --&gt;&lt;/p&gt;
&lt;h3&gt;Numeric form&lt;/h3&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:list --&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 - No permissions, ---&lt;/li&gt;
&lt;li&gt;1 - Execute only, --x&lt;/li&gt;
&lt;li&gt;2 - Write only, -w-&lt;/li&gt;
&lt;li&gt;3 - Write and execute, -wx&lt;/li&gt;
&lt;li&gt;4 - Read, r--&lt;/li&gt;
&lt;li&gt;5 - Read and execute, r-x&lt;/li&gt;
&lt;li&gt;6 - Read and write, rw-&lt;/li&gt;
&lt;li&gt;7 - Read, write and execute, rwx&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!-- /wp:list --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Previous example can be written: 745&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Convert between Linux and Windows paths&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;One of the biggest issue for me right now are navigating windows directories in Linux and vice versa.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Convert to windows path (C:\Users\sarun)&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;wslpath -w /mnt/c/Users/sarun&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Convert to Linux path (/mnt/c/Users/sarun)&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;wslpath &quot;C:\Users\sarun&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Open explorer in current directory from linux.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;explorer.exe .&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;It's also possible to browse all WSL distribution files using File Explorer, navigate to: &lt;code&gt;\\wsl$&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Windows X server&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Install x server&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;configuration:&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/a/61110604&quot;&gt;https://stackoverflow.com/a/61110604&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading {&quot;level&quot;:3} --&gt;&lt;/p&gt;
&lt;h3&gt;WSL distribution settings&lt;/h3&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Install required packages&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install xfce4 xfce4-goodies&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Append following lines to &amp;nbsp;&lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Display forwarding settings&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2&amp;gt;/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Reboot WSL distribution.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading {&quot;level&quot;:3} --&gt;&lt;/p&gt;
&lt;h3&gt;Windows settings&lt;/h3&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Install X Server: &lt;a href=&quot;https://sourceforge.net/projects/vcxsrv/&quot;&gt;VcXsrv Windows X Server download | SourceForge.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:209,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-8.png&quot; alt=&quot;&quot; class=&quot;wp-image-209&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Change VcXsrv launcher DPI settings.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Start &lt;code&gt;xLaunch.exe&lt;/code&gt; and select display settings, most of them are optional and you can choose what you like. &quot;Disable access control&quot; is required, without it WSL distribution can't communicate with host.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:239,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-11.png&quot; alt=&quot;&quot; class=&quot;wp-image-239&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Display settings, I found that multiple windows works best for me.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:240,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-12.png&quot; alt=&quot;&quot; class=&quot;wp-image-240&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;When new WSL distribution connects, you can execute or start some default applications.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:213,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-10.png&quot; alt=&quot;&quot; class=&quot;wp-image-213&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Disable access control must be enabled.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Running applications&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Now that we have everything set up we can run some applications.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;You can run individual applications, like &lt;code&gt;xCalc&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:241,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-13.png&quot; alt=&quot;&quot; class=&quot;wp-image-241&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Run individual applications.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Or you can start full desktop experience by running &lt;code&gt;startxfce4&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:243,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/07/image-14-1024x537.png&quot; alt=&quot;&quot; class=&quot;wp-image-243&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Full desktop experience in WSL 2.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Please note that not all applications will start, some of them might have issues or crash.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Considering my initial goal and what this book provided, I'm really happy and would recommend this book. I took only small portion what it provides and will definitely come back to it when my needs increase.  &lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term="bash" /><category term="book-review" /><category term="docker" /><category term="tips" /><category term="wsl-2" /><summary type="html">Pro Windows Subsystem for Linux (WSL) Review is in quotation marks because this is not a full review, this is a summary and tips of what I learned from this book. When reading it my main focus was to improve my Kubernetes, terraform script workflow. Which involve windows file/directory navigation, editing files on WSL, managing WSL distributions. Default parameters First lets identify which distributions are installed, which are default and make sure we starting them with correct user. wsl.exe --set-default-version 2 wsl.exe --list --verbose --all NAME STATE VERSION * Ubuntu Running 2 docker-desktop-data Running 2 docker-desktop Running 2 Name - &amp;lt;wsl distro name&amp;gt; in following commands wsl.exe --set-default &amp;lt;wsl distro name&amp;gt; wsl.exe --set-version &amp;lt;wsl distro name&amp;gt; 2 &amp;lt;wsl distro name&amp;gt; config --default-user &amp;lt;new user name&amp;gt; File permissions Even though file permissions doesn't really fit into what I was looking in this book, wanted to write this down for future reference: Three groups (&amp;lt;user&amp;gt;&amp;lt;group&amp;gt;&amp;lt;other&amp;gt;): User - by default user who created Group - users in a group with assigned access to files Other - all other users Symbolic form: r - Read w - Write x - Execute - (just dash) for no permission Example: rwx-r-xr- rwx - for user -r- -for group xr- - for other Numeric form 0 - No permissions, --- 1 - Execute only, --x 2 - Write only, -w- 3 - Write and execute, -wx 4 - Read, r-- 5 - Read and execute, r-x 6 - Read and write, rw- 7 - Read, write and execute, rwx Previous example can be written: 745 Convert between Linux and Windows paths One of the biggest issue for me right now are navigating windows directories in Linux and vice versa. wslpath -w /mnt/c/Users/sarun wslpath &quot;C:\Users\sarun&quot; explorer.exe . It's also possible to browse all WSL distribution files using File Explorer, navigate to: \\wsl$ Windows X server Install x server configuration: https://stackoverflow.com/a/61110604 WSL distribution settings sudo apt update sudo apt install xfce4 xfce4-goodies Append following lines to &amp;nbsp;~/.bashrc: export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2&amp;gt;/dev/null):0 export LIBGL_ALWAYS_INDIRECT=1 Reboot WSL distribution. Windows settings Install X Server: VcXsrv Windows X Server download | SourceForge.net Change VcXsrv launcher DPI settings. Start xLaunch.exe and select display settings, most of them are optional and you can choose what you like. &quot;Disable access control&quot; is required, without it WSL distribution can't communicate with host. Display settings, I found that multiple windows works best for me. When new WSL distribution connects, you can execute or start some default applications. Disable access control must be enabled. Running applications Now that we have everything set up we can run some applications. You can run individual applications, like xCalc Run individual applications. Or you can start full desktop experience by running startxfce4 Full desktop experience in WSL 2. Please note that not all applications will start, some of them might have issues or crash. Summary Considering my initial goal and what this book provided, I'm really happy and would recommend this book. I took only small portion what it provides and will definitely come back to it when my needs increase.</summary></entry><entry><title type="html">ASP.NET CORE Required property validation</title><link href="https://floatincode.net/2021/06/26/asp-net-core-required-property-validation/" rel="alternate" type="text/html" title="ASP.NET CORE Required property validation" /><published>2021-06-26T10:07:58+00:00</published><updated>2021-06-26T10:07:58+00:00</updated><id>https://floatincode.net/2021/06/26/asp-net-core-required-property-validation</id><content type="html" xml:base="https://floatincode.net/2021/06/26/asp-net-core-required-property-validation/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;System.ComponentModel.DataAnnotations.&lt;strong&gt;Required&lt;/strong&gt; validation doesn't work how most people imagine it working. Required - it does have value, if the property is nullable and value is null - this validation will fail. However, if we have value type property - then we always have value, and required validation never fails.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:191,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/06/JsonAndDataAnnotationPropertyValidation.png&quot; alt=&quot;Data annotation validation is invoked after model binder, which means that if property is value type will be created with default value and required validation never fails.&quot; class=&quot;wp-image-191&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Model binder creates an empty model and assigns values from JSON. If a JSON value is missing for enum or integer - we will get default value, and sometimes this is not desired behavior. We can approach this problem from two sides, we can make value types nullable or we can use JSON validation and fail inside the model binder.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Lets explore these two validation types by creating small project, start with empty ASP.NET core API project.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Validation with System.ComponentModel.DataAnnotations&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Property validation with DataAnnotation &quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;using&amp;nbsp;System.ComponentModel.DataAnnotations;

namespace&amp;nbsp;RequiredValidation
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;class&amp;nbsp;WeatherModel
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Required]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;int&amp;nbsp;Temperature&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Required]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;string&amp;nbsp;Title&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Validation with NewtonsoftJson&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Install Newtonsoft Json nuget package&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;xml&quot; class=&quot;language-xml&quot;&gt;&amp;nbsp;Microsoft.AspNetCore.Mvc.NewtonsoftJson&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code {&quot;lineNumbers&quot;:false} --&gt;&lt;/p&gt;
&lt;pre title=&quot;Register Newtonsof Json as default serializer.&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;ConfigureServices(IServiceCollection&amp;nbsp;services)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;services
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.AddControllers()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.AddNewtonsoftJson();

&lt;/code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Apply JsonProperty validation attribute&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;using&amp;nbsp;Newtonsoft.Json;

namespace&amp;nbsp;RequiredValidation
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;class&amp;nbsp;Weather2Model
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[JsonProperty(Required&amp;nbsp;=&amp;nbsp;Required.Always)]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;int&amp;nbsp;Temperature&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[JsonProperty(Required&amp;nbsp;=&amp;nbsp;Required.Always)]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;string&amp;nbsp;Title&amp;nbsp;{&amp;nbsp;get;&amp;nbsp;set;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Endpoints&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Controller endpoints in both cases are identical, no additional changes are needed. To make testing easier I just return same model.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Endpoints for both test cases&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[HttpPost]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Route(&quot;Update&quot;)]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;IActionResult&amp;nbsp;UpdateWeather(WeatherModel&amp;nbsp;weather)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;Ok(weather);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[HttpPost]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Route(&quot;Update2&quot;)]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;IActionResult&amp;nbsp;UpdateWeather2(Weather2Model&amp;nbsp;weather)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;Ok(weather);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Testing DataAnnotations validation&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Lets start by testing DataAnnotations validation &quot;Update&quot; endpoint.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:193,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/06/image-713x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-193&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;If we ignore value type property, it will get default value.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:194,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/06/image-1-577x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-194&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;If we ignore string property with required attribute, we get error message, as expected.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Testing JSON property validation&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:195,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/06/image-2-528x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-195&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;We get error message when integer is not present in request.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:image {&quot;id&quot;:196,&quot;sizeSlug&quot;:&quot;large&quot;,&quot;linkDestination&quot;:&quot;none&quot;} --&gt;&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;/assets/2021/06/image-3-503x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-196&quot; /&gt;&lt;br /&gt;
&lt;figcaption&gt;Same as above, when string is not present in request we get error message.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;!-- /wp:image --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Back to C# basics, value types always have a default value - unless they are nullable. Adding required on value type property doesn't make sense since it will be with default value either it's zero or first enum value.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term="API" /><category term="C#" /><category term="validation" /><summary type="html">System.ComponentModel.DataAnnotations.Required validation doesn't work how most people imagine it working. Required - it does have value, if the property is nullable and value is null - this validation will fail. However, if we have value type property - then we always have value, and required validation never fails. Model binder creates an empty model and assigns values from JSON. If a JSON value is missing for enum or integer - we will get default value, and sometimes this is not desired behavior. We can approach this problem from two sides, we can make value types nullable or we can use JSON validation and fail inside the model binder. Lets explore these two validation types by creating small project, start with empty ASP.NET core API project. Validation with System.ComponentModel.DataAnnotations using&amp;nbsp;System.ComponentModel.DataAnnotations;</summary></entry><entry><title type="html">ASP.NET CORE Integration tests: Entity framework DB first</title><link href="https://floatincode.net/2021/05/10/asp-net-core-integration-tests-entity-framework-db-first/" rel="alternate" type="text/html" title="ASP.NET CORE Integration tests: Entity framework DB first" /><published>2021-05-10T03:10:52+00:00</published><updated>2021-05-10T03:10:52+00:00</updated><id>https://floatincode.net/2021/05/10/asp-net-core-integration-tests-entity-framework-db-first</id><content type="html" xml:base="https://floatincode.net/2021/05/10/asp-net-core-integration-tests-entity-framework-db-first/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;In this short blog post I want to show how useful EF DB first approach is when testing. While working with legacy project you might now have endpoints to set all data in DB for test, also validating exact data in DB get easier.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Generate code from the database&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Install two Nuget packages in a project that will contain DB files: &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Design/&quot; data-type=&quot;URL&quot; data-id=&quot;https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Design/&quot; target=&quot;_blank&quot;&gt;Microsoft.EntityFrameworkCore.Design&lt;/a&gt; and &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL/6.0.0-preview3&quot; data-type=&quot;URL&quot; data-id=&quot;https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL/6.0.0-preview3&quot; target=&quot;_blank&quot;&gt;Npgsql.EntityFrameworkCore.PostgreSQL&lt;/a&gt; don't forget to rebuild the solution.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Next install &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://docs.microsoft.com/en-us/ef/core/cli/dotnet&quot; data-type=&quot;URL&quot; data-id=&quot;https://docs.microsoft.com/en-us/ef/core/cli/dotnet&quot; target=&quot;_blank&quot;&gt;dotnet-ef&lt;/a&gt; global tool and invoke it with following configuration. Tool has variety of configuration parameters, but for the sake of simplicity we will use only minimal set.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;generate.cmd&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;bash&quot; class=&quot;language-bash&quot;&gt;dotnet&amp;nbsp;ef&amp;nbsp;dbcontext&amp;nbsp;scaffold&amp;nbsp;&quot;Server=127.0.0.1;Port=6444;Database=weather;User&amp;nbsp;Id=admin_user;Password=secretPassword123!;&quot;&amp;nbsp;Npgsql.EntityFrameworkCore.PostgreSQL&amp;nbsp;--output-dir&amp;nbsp;Weather&amp;nbsp;--no-onconfiguring&amp;nbsp;--force&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;At this point we should have all necessary files to change dapper into EF.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Only a few changes are needed, create DataAccess inject database string, and use an entity framework in your project or tests. Source code is always available at &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://github.com/FloatInCodeBlog/ApiIntegrationTests/tree/entity-framework-db-first&quot; data-type=&quot;URL&quot; data-id=&quot;https://github.com/FloatInCodeBlog/ApiIntegrationTests/tree/entity-framework-db-first&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;In memory&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Why ? If someone is using EF code first on enterprise, please let me know how it's going.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;I find Entity Framework is really helpful in tests, you can easily add data to DB and validate if tests performed correct changes to DB. When the database changes, you only need to run &lt;code&gt;generate.cmd&lt;/code&gt; script to update all code and if there are issues, they are in compile-time, which makes maintenance and updates easy. &lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term="API" /><category term="C#" /><category term="database" /><category term="DB-First" /><category term="EntityFramework" /><category term="testing" /><summary type="html">In this short blog post I want to show how useful EF DB first approach is when testing. While working with legacy project you might now have endpoints to set all data in DB for test, also validating exact data in DB get easier. Generate code from the database Install two Nuget packages in a project that will contain DB files: Microsoft.EntityFrameworkCore.Design and Npgsql.EntityFrameworkCore.PostgreSQL don't forget to rebuild the solution. Next install dotnet-ef global tool and invoke it with following configuration. Tool has variety of configuration parameters, but for the sake of simplicity we will use only minimal set. dotnet&amp;nbsp;ef&amp;nbsp;dbcontext&amp;nbsp;scaffold&amp;nbsp;&quot;Server=127.0.0.1;Port=6444;Database=weather;User&amp;nbsp;Id=admin_user;Password=secretPassword123!;&quot;&amp;nbsp;Npgsql.EntityFrameworkCore.PostgreSQL&amp;nbsp;--output-dir&amp;nbsp;Weather&amp;nbsp;--no-onconfiguring&amp;nbsp;--force At this point we should have all necessary files to change dapper into EF. Only a few changes are needed, create DataAccess inject database string, and use an entity framework in your project or tests. Source code is always available at GitHub In memory Why ? If someone is using EF code first on enterprise, please let me know how it's going. Summary I find Entity Framework is really helpful in tests, you can easily add data to DB and validate if tests performed correct changes to DB. When the database changes, you only need to run generate.cmd script to update all code and if there are issues, they are in compile-time, which makes maintenance and updates easy.</summary></entry><entry><title type="html">ASP.NET CORE Integration tests: Database with API</title><link href="https://floatincode.net/2021/04/26/integration-testing-database-with-api/" rel="alternate" type="text/html" title="ASP.NET CORE Integration tests: Database with API" /><published>2021-04-26T01:56:54+00:00</published><updated>2021-04-26T01:56:54+00:00</updated><id>https://floatincode.net/2021/04/26/integration-testing-database-with-api</id><content type="html" xml:base="https://floatincode.net/2021/04/26/integration-testing-database-with-api/">&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;Now that we have database migrations and API integration tests set up we can combine them together. In this post, I will go through some tips and tools that proved to be really helpful. &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://github.com/FloatInCodeBlog/ApiIntegrationTests/tree/with-db&quot; data-type=&quot;URL&quot; data-id=&quot;https://github.com/FloatInCodeBlog/ApiIntegrationTests/tree/with-db&quot; target=&quot;_blank&quot;&gt;Source code.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Double-check that you are using test DB&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;The first thing that you should be doing is make sure you are running tests in test environment. Usually when working we switch our connection strings to our QA or even one of our production databases, the least that we want is to corrupt these databases.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;This check will vary from project to project, I usually check client or user count in DB, for tests, there shouldn't be that many, at least for our tests.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Check if tests are using test DB&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;var&amp;nbsp;maxAllowedEntries&amp;nbsp;=&amp;nbsp;100;

using&amp;nbsp;var&amp;nbsp;conn&amp;nbsp;=&amp;nbsp;new&amp;nbsp;NpgsqlConnection(settings.Value.ConnectionString);

var&amp;nbsp;entries&amp;nbsp;=&amp;nbsp;await&amp;nbsp;conn.ExecuteScalarAsync&amp;lt;int&amp;gt;(&quot;select&amp;nbsp;count(*)&amp;nbsp;from&amp;nbsp;weather_predictions.predictions&quot;);

return&amp;nbsp;entries&amp;nbsp;&amp;lt;&amp;nbsp;maxAllowedEntries;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Disable test concurrency&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;We have one test DB, logically we can only run one test at a time. This can be controlled with collections.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Disable concurrency with attribute&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;[Collection(nameof(NotThreadSafeResourceCollection))]
public class WeatherForecastControllerDatabaseTests
{&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Attribute to disable concurrency&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;[CollectionDefinition(nameof(NotThreadSafeResourceCollection),&amp;nbsp;DisableParallelization&amp;nbsp;=&amp;nbsp;true)]
public&amp;nbsp;class&amp;nbsp;NotThreadSafeResourceCollection
{
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Clear database after each test with Respawn&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;It is possible to restart docker and rebuild the entire database after each test but that would take a lot of time. &lt;a href=&quot;https://www.nuget.org/packages/Respawn/&quot; data-type=&quot;URL&quot; data-id=&quot;https://www.nuget.org/packages/Respawn/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Respawn &lt;/a&gt;NuGet allows us to clear the database, either full or partial with initialization scripts.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Clear database data before each test&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;var&amp;nbsp;checkpoint&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Checkpoint
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TablesToIgnore&amp;nbsp;=&amp;nbsp;new&amp;nbsp;string[]&amp;nbsp;{&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SchemasToInclude&amp;nbsp;=&amp;nbsp;new&amp;nbsp;string[]&amp;nbsp;{&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DbAdapter&amp;nbsp;=&amp;nbsp;DbAdapter.Postgres
};
using&amp;nbsp;var&amp;nbsp;conn&amp;nbsp;=&amp;nbsp;new&amp;nbsp;NpgsqlConnection(settings.Value.ConnectionString);
await&amp;nbsp;conn.OpenAsync();

await&amp;nbsp;checkpoint.Reset(conn);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Comparing objects&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;For object comparison, I highly recommend using &lt;a rel=&quot;noreferrer noopener&quot; href=&quot;https://www.nuget.org/packages/CompareNETObjects&quot; data-type=&quot;URL&quot; data-id=&quot;https://www.nuget.org/packages/CompareNETObjects&quot; target=&quot;_blank&quot;&gt;Compare-Net-Objects&lt;/a&gt;, this NuGet will cover all the use cases that you need.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Ignore order when comparing lists&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;//When&amp;nbsp;we&amp;nbsp;ignore&amp;nbsp;collection&amp;nbsp;order&amp;nbsp;we&amp;nbsp;must&amp;nbsp;specify&amp;nbsp;key&amp;nbsp;which&amp;nbsp;will&amp;nbsp;be&amp;nbsp;used&amp;nbsp;to&amp;nbsp;match&amp;nbsp;actual&amp;nbsp;with&amp;nbsp;expected
comparer.Config.IgnoreCollectionOrder&amp;nbsp;=&amp;nbsp;true;
comparer.Config.CollectionMatchingSpec.Add(typeof(WeatherForecast),&amp;nbsp;new&amp;nbsp;List&amp;lt;string&amp;gt;&amp;nbsp;{&amp;nbsp;nameof(WeatherForecast.Date)&amp;nbsp;});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:code --&gt;&lt;/p&gt;
&lt;pre title=&quot;Custom comparer for one object property&quot; class=&quot;wp-block-code&quot;&gt;&lt;code lang=&quot;csharp&quot; class=&quot;language-csharp&quot;&gt;//Summary&amp;nbsp;will&amp;nbsp;be&amp;nbsp;random,&amp;nbsp;we&amp;nbsp;don't&amp;nbsp;really&amp;nbsp;care&amp;nbsp;about&amp;nbsp;in&amp;nbsp;this&amp;nbsp;test.&amp;nbsp;Check&amp;nbsp;if&amp;nbsp;it's&amp;nbsp;not&amp;nbsp;null.
comparer.Config.CustomPropertyComparer&amp;lt;WeatherForecast&amp;gt;(obj&amp;nbsp;=&amp;gt;&amp;nbsp;obj.Summary,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new&amp;nbsp;CustomComparer&amp;lt;string,&amp;nbsp;string&amp;gt;((expected,&amp;nbsp;actual)&amp;nbsp;=&amp;gt;&amp;nbsp;!string.IsNullOrEmpty(actual)));&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- /wp:code --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:heading --&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;!-- /wp:heading --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- wp:paragraph --&gt;&lt;/p&gt;
&lt;p&gt;In order to run tests fluently some gluing is needed. The first thing should be security, make sure you are using test DB and not production or another shared database. Since only one test can be running at any given time - make sure to configure concurrency, otherwise, you will have to debug a lot of random failing tests due to multiple tests writing data to DB. Lastly comparing objects should be easy, instead of writing tons of helpers invest some time and look into Compare-Net-Objects it's highly customizable and will cover all your cases.&lt;/p&gt;
&lt;p&gt;&lt;!-- /wp:paragraph --&gt;&lt;/p&gt;</content><author><name>{&quot;login&quot;=&gt;&quot;Floatas&quot;, &quot;email&quot;=&gt;&quot;floatas@outlook.com&quot;, &quot;display_name&quot;=&gt;&quot;Floatas&quot;, &quot;first_name&quot;=&gt;&quot;&quot;, &quot;last_name&quot;=&gt;&quot;&quot;}</name><email>floatas@outlook.com</email></author><category term="Software Development" /><category term="API" /><category term="C#" /><category term="database" /><category term="testing" /><summary type="html">Now that we have database migrations and API integration tests set up we can combine them together. In this post, I will go through some tips and tools that proved to be really helpful. Source code. Double-check that you are using test DB The first thing that you should be doing is make sure you are running tests in test environment. Usually when working we switch our connection strings to our QA or even one of our production databases, the least that we want is to corrupt these databases. This check will vary from project to project, I usually check client or user count in DB, for tests, there shouldn't be that many, at least for our tests. var&amp;nbsp;maxAllowedEntries&amp;nbsp;=&amp;nbsp;100;</summary></entry></feed>