Posts

Showing posts with the label dotnet

Yield in C#

Image
The yield keyword is used when the method or accessor is an enumerator. Using yield return returns one element at a time. The thing to remember here is that IEnumerable/IEnumerable<T> is a stream, not a collection. This is where many developers misuse IEnumerable (myself included once upon a time). Consider the following code: This is probably what you are used to seeing, but is actually a misuse of IEnumerable. The code works just fine, but it is not leveraging the benefits of IEnumerable being a stream. Let's refactor to use yield return: What we are doing now is streaming the elements one at a time. Each iteration by the consumer of this method comes back to the point of the yield and executes the next statement, in this case the while. The benefit? We eliminated a loop and an object allocation. Rather than looping through all the records, building up a list, then looping through the list, we just loop through the records once.

Configuration Reload in .Net

The 12 Factor App guidelines suggest separating configuration from code as a best practice. More specifically, it should be deployed separately as well. We shouldn't have to redeploy the entire application in order to make a configuration change. Ideally, we don't want to have to restart our app either.  This eliminates downtime when making configuration changes that don't otherwise require downtime such as timeout values, retry configuration, logging level, and distributed trace sampling rate. For providers that support it, Microsoft.Extensions.Configuration can reload the configuration when it changes. Let's take a look. We'll be using the JSON file provider for these examples with the following configuration: IConfigurationRoot When we change a configuration value, the value in the IConfiguration instance also changes. The key to making it all work is the reloadOnChange parameter. Given a simple console app, we can see the behavior as we modify the appsettin...

AES256 Encryption in C#

Every few years, I find myself having to write an AES256 encryption routine for a project. I always end up having to lookup the specifics, so I thought I would write it down this time. What is AES256 AES--Advanced Encryption Standard--is a symmetrical block cipher standard. Symmetrical meaning it uses the same key to both encrypt and decrypt, as opposed to Asymmetrical (eg. TLS) which uses a public/private key pair--a different key to encrypt than to decrypt. Block cipher meaning the encryption is performed by chunking the plain text into blocks and encrypting each block separately. In the case of AES, each block is 128 bits in length. Chunks smaller than 128 bits are padded to create a 128 bit block. At the time of this writing, bank-grade and government standard uses a 256 bit key (AES256) and a CBC--Cipher Block Chaining--mode. With CBC, each plain text block is XOR with the previous encrypted block before being encrypted itself. This requires an initialization vector--a unique, ran...

Code Coverage for Multiple Projects in a Single Build using Dotnet Test and Coverlet

Most of the time, your solution will have more than one project and a test unit project for each of those. Azure DevOps only, as of this writing, only allows you to update a single code coverage summary. If you upload more than one, each overwrites the next and only the last one remains. To accomplish this, we can use the merge functionality in Coverlet . I use the MSBuild extension, because it is better suited for CI pipelines. In your test project XML, add the package... <PackageReference Include="coverlet.msbuild" Version="2.7.0">     <PrivateAssets>all</PrivateAssets>     <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference> Then, in your dotnet test command or msbuild command, tell it to use Coverlet and to merge results. If you're using Azure DevOps, your test task looks this... (line wrapped for read ability in the article) - task: DotNetCoreCLI@2 displayName: Test i...

.Net Full Framework Tests with the New Project System

I ran into a scenario where my solution had libraries targeting netStandard2.0 and/or net461. For the libraries targeting just net461, I created a “MSTest Unit Test Project (.Net Framework)” project–the “old” project system. The tests ran fine in Visual Studio, but in my CI build, I wanted to keep it simple and run all the tests with dotnet test. However, this tooling cannot see/run the old test project. So, as an experiment, I tried creating a test project in the new project system, and changing the target moniker from NetCoreApp to net461.  It worked! both dotnet test and Visual Studio can run the tests. It’s worth noting that the library is also the new project system. I haven’t tested if that matters. Test Project XML <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net461</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Include="Mic...

NHibernate Releases 5.1 with support for .Net Core and .NetStandard 2.0

The  NHibernate  Team has done it!  Release 5.1  of the famous ORM for .Net supports both the full .Net Framework and .Net Core. Great work! The library is actually cross compiled for net461, netCoreApp2.0 and netStandard2.0 to account for some of the subtle nuances between net461 and core and to support older tooling that doesn’t know how to work with netStandard libraries. Caveats As noted in the release notes, there are a few caveats when running on Core: Binary serialization is not supported - the user shall implement serialization surrogates for System.Type, FieldInfo, PropertyInfo, MethodInfo, ConstructorInfo, Delegate, etc. SqlClient, Odbc, Oledb drivers are converted to ReflectionBasedDriver to avoid the extra dependencies. CallSessionContext uses a static AsyncLocal field to mimic the CallContext behavior. System transactions (transaction scopes) are untested, due to the lack of data providers supporting them. WebSessionContext and ASP.Net Cor...

C# DateTime, DateTimeOffset and the Cloud

One thing to remember,  System.DateTime  has no knowledge of timezone. It’s only aware that the date and time represents UTC or the local timezone of the machine on which the code is running. In the cloud, by default (and it’s best to keep it that way), the “server’s” timezone is set to UTC. So what? Well… The serializers do some magic that can yield undesired results depending on your situation. Take the following… DateTime today = DateTime . Today ; Seems harmless. If you inspect this instance further, you’ll see that the Kind is set to  DateTimeKind.Local . So, when working with the instance, it will behave in the timezone of the machine. If you serialize it on your laptop, and your laptop’s timezone is set to “Easter Standard Time” (America/New York for you Linux/Mac folks)… string json = JsonConvert . SerializeObject ( today ); Console . WriteLine ( json ); …you get… 2018-02-23T00:00:00-05:00 Notice the timezone offset. If  Dat...

The Async/Void Trap

Image
Example Code I’ll start by saying, you should ALWAYS avoid async/void. Now, I’m sure there are edge cases, but the reality is you can get into a lot of trouble with async/void. A good  article in MSDN Magazine  goes over some best practices when using async/await and asynchronous programming patterns. As the article points out, avoid async/void. However, it also states that an exception to that rule is event handlers where the delegate returns void. Even with those event handlers, you need to be extremely careful. Here’s why–await is actually not blocking. I know if feels like it is, but remember, async/await is just syntax sugar for ContinueWith() and context management. Let’s look at some code. Take some method Foo() that returns void and calls an async method Bar() async void Foo () { await Bar (); } Task Bar () { return Task . Delay ( 10000 ); } Now, if we call Foo(), it will return immediately, and Bar() will be executed in backgrou...