Category: .NET Core

Dotnet Try

I have wrote a blog post about DotNet CLI Tools
I did not mention one that is super important: DotNet Try : https://github.com/dotnet/try

You can see at https://github.com/dotnet/try how to install it .

Or ,to use in Docker, check my files to install in Docker https://github.com/ignatandrei/Presentations/tree/master/2019/shorts/NetCoreGlobalTools/dotnetTry   . To edit files in Docker, use Visual Studio Code with Docker and Remote Development and Docker extension.

To see in action on the web, check out Noda Time  or

( for the moment is in preview, but it will work with GitHub and blogs…)

[PostEvent] Talks by Softbinator

The organizers from Talk from Softbinator were kind enough to select me for a presentation. Again , my presentation about .NET Core and Angular Everywhere. Source Code at https://github.com/ignatandrei/angNetCoreDemo/ 

The presentation was supposed to take 1/2 hour – and it took 1 hour with all the explanations.

Video at https://www.facebook.com/softbinator/videos/459024768242391

Correct abstraction–.NET Core IFileProvider

Create the right abstraction and they will implement it. I was delighted by finding that the .NET Core has an IFileProvider : https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.ifileprovider?view=aspnetcore-2.2  .

An obvious implementation is PhysicalFileProvider : https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.physicalfileprovider?view=aspnetcore-2.2 

A not so obvious implementation, but normal from a programmers mind, is NullFileProvider: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.nullfileprovider?view=aspnetcore-2.2 

And, because we have already 2 providers, makes sense a CompositeFileProvider: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.compositefileprovider?view=aspnetcore-2.2

And because we create assemblies, it is normal to have EmbeddedFileProvider: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.embeddedfileprovider?view=aspnetcore-2.2

And , to complicate things, a ManifestEmbeddedFileProvider: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.manifestembeddedfileprovider?view=aspnetcore-2.2

( You can read more details here: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-2.2#physicalfileprovider)

But this is just what Microsoft provides in .NET Framework.

Other creates more, such as :

LongFileProvider: https://github.com/v-kabanov/hdrepository/blob/master/trunk/Common/bfs.Repository.IO.WinNtfs/WinLongFileFrovider.cs 

S3FileProvider: https://github.com/evorine/S3FileProvider/blob/master/src/S3FileProvider.cs, https://github.com/lamondlu/AWSS3FileProvider

AzureBlogFileProvider: https://github.com/filipw/Strathweb.AspNetCore.AzureBlobFileProvider

More Cloud Providers : https://github.com/jiabiao/NCloudFiles

ZipFileProviders: https://github.com/tagcode/Lexical.FileProvider , https://github.com/cloudscribe/cloudscribe/blob/master/src/cloudscribe.Web.Common/StaticFiles/GzipMappingFileProvider.cs 

DatabaseFileProviders: https://github.com/mikebrind/RazorEngineViewOptionsFileProviders

It is interesting how you can find various implementation of an so common thing, like a file / folder. But it is also rewarding to see that you have created the right abstractions – and other will implement !

[PostEvent] CodeCamp Timisoara

I have been a presenter and participant at CodeCamp Timisoara. There are a lot of tracks with good information!

As a participant , I can mention:

Things you did not know about C# and .NET – with Marius Bancila
CALMS in DevOps – with Adrian Suteu
Making E2E tests great again using Cypress – with Omri Ben Ari

My presentation was about Angular and .NET Core Everywhere and you can find the source code at https://github.com/ignatandrei/AngNetCoreDemo

Simple serialize of encoding

My problem was the serialize of the Encoding . Let’s suppose that we have a class that have a property Encoding( maybe to read a file ).


internal class MyTest
{
    public MyTest()
    {
        enc = ASCIIEncoding.ASCII;
    }
    public Encoding enc { get; set; }
}


We want to serialize this class in order to let the administrator/people to decide what will be the encoding.

When we serialize( obvious, with NewtonSoftJson) , we obtain this kind of data:

{
“enc”: {
“IsSingleByte”: true,
“BodyName”: “us-ascii”,
“EncodingName”: “US-ASCII”,
“HeaderName”: “us-ascii”,
WebName“: “us-ascii”,
“WindowsCodePage”: 1252,
“IsBrowserDisplay”: false,
“IsBrowserSave”: false,
“IsMailNewsDisplay”: true,
“IsMailNewsSave”: true,
“EncoderFallback”: {
“DefaultString”: “?”,
“MaxCharCount”: 1
},
“DecoderFallback”: {
“DefaultString”: “?”,
“MaxCharCount”: 1
},
“IsReadOnly”: true,
“CodePage”: 20127
}
}

This is too much for someone to edit . We want a simple string that can be edited easy – and the WebName ,  that is , in fact , a string from https://www.iana.org/assignments/character-sets/character-sets.xhtml seems the obvious choice.

So –  I have done a JSONConverter class just for this property. It is very simple:

public class JsonEncodingConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (typeof(Encoding).IsAssignableFrom(objectType));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string webName = "";
        if (reader.TokenType == JsonToken.String)
        {

            webName = reader.Value?.ToString();
        }
        existingValue = Encoding.GetEncoding(webName);

        return existingValue;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        string webName = (value as Encoding).WebName;
        serializer.Serialize(writer, webName);
    }
}

And can be used very easy:

MyTest m = new MyTest();
JsonEncodingConverter[] conv = new[] { new JsonEncodingConverter() };
string original = JsonConvert.SerializeObject(m, Formatting.Indented);
string data = JsonConvert.SerializeObject(m, Formatting.Indented, conv);
//https://www.iana.org/assignments/character-sets/character-sets.xhtml
Console.WriteLine(data);
Console.WriteLine("and now the original");
Console.WriteLine(original);
MyTest s = JsonConvert.DeserializeObject<MyTest>(data, conv);
Console.WriteLine(s.enc.WebName);

The result of serializing it is now

{
“enc”: “us-ascii”
}

And because it has this code

public override bool CanConvert(Type objectType)
{
    return (typeof(Encoding).IsAssignableFrom(objectType));
}

it means it will serialize just the encoding, not other tools.

And it is more easy to be edited by someone.

Moral: Aim for simple string that can be edited can be achieved when serializing. Do not stay with defaults!

 

( you can easy achieve backwards compatibility for already serialized Encoding by asking

if (reader.TokenType == JsonToken.StartObject)
{
    webName = reader.Value?.ToString();
    //handling old data format for encoding
    while (reader.TokenType != JsonToken.EndObject)
    {
        if (!reader.Read())
            break;
        if (reader.TokenType != JsonToken.PropertyName)
            continue;
        var val = reader.Value?.ToString();
        if (string.Compare("webname", val, StringComparison.InvariantCultureIgnoreCase) == 0)
        {
            webName = reader.ReadAsString();
            //do not break - advance reading to the end
            //break;
        }
    }

}

)

[PostEvent] HackTalks 2019

I have been a presenter and participant at #HackTalks Timisoara. I have seen lots of interesting people that do great stuff. Also lots of programmers interested of how to do better programming. It is a good vibe and lots of knowledge sharing.

As a participant , I can mention:

https://www.facebook.com/hacktalks.ro/posts/823295824708035 : Container Orchestration in the cloud for oncology  – data science and programming together for the greater good

https://www.facebook.com/hacktalks.ro/posts/821329954904622 : Platform revolution in mobility –  very informative and opinionated

 

https://www.facebook.com/hacktalks.ro/posts/820025591701725 : How to #model and #visualize complex conditional logic using a graph that describes a finite state machine in a highly flexible and data-driven way – nice way in JavaScript to describe logic flow with data .

 

My presentation was about Angular and .NET Core Everywhere and you can find the source code at https://github.com/ignatandrei/AngNetCoreDemo

Obtaining list of videos from a youtube playlist with Stankins

Because Stankins has a parser to html, you can have this kind of macro

#see all href

Stankins.HTML.ReceiverHtmlAHref file=https://www.youtube.com/playlist?list=PL4aSKgR4yk4OnmJW6PlBuDOXdYk6zTGps

#retain href column
StankinsObjects.FilterRetainColumnDataContains namecolumn=href stringToHave=PL4aSKgR4yk4OnmJW6PlBuDOXdYk6zTGps

#retain just videos which title contains 5Min

StankinsObjects.FilterRetainColumnDataContains namecolumn=a_text stringToHave=5Min

#remove column a_html

StankinsObjects.FilterRemoveColumn namecolumn=a_html

#transform column to li a href

StankinsObjects.TransformerAddColumnExpressionByTable expression=”‘<li><a href=’+ href+’>’ + a_text+'</a></li>'” newcolumnname=test nametable=TableLinks

#remove column href

StankinsObjects.FilterRemoveColumn namecolumn=href

#remove column a_text

StankinsObjects.FilterRemoveColumn namecolumn=a_text

 

The demo is at

https://azurestankins.azurewebsites.net/recipe/youtubeplaylist

DotNet CLI Tools

There is a revival of CLI tools. And dotnet is going with the wave.

You can find the tools installed with .NET Core here , https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x  and here https://docs.microsoft.com/en-us/dotnet/core/additional-tools/

 

Usually you do not need those – since Visual Studio is good to have all from the GUI.

However, you can make your own tool – and you have the instruction here: https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools-how-to-create

But, before re-inventing the wheel, take a look at the list here https://github.com/natemcmaster/dotnet-tools

I have used for AzureDevOps CI:

  1.  https://github.com/tonerdo/coverlet 
  2. https://github.com/ignatandrei/AOP_With_Roslyn
  3. https://github.com/loresoft/DotNet.Property
  4. https://github.com/SonarSource/sonar-scanner-msbuild
  5. https://github.com/KrystianKolad/DotnetThx
  6. https://github.com/danielpalme/ReportGenerator/
  7. https://github.com/Hubert-Rybak/dotnet-warp
  8. https://github.com/aspnet/AspNetCore/tree/master/src/Tools/dotnet-watch

 

Did you use some CLI tools?

Small Task quiz knowledge

The task and the await /async never ceases to amaze me. That because there is so much under covers( see https://channel9.msdn.com/Events/TechDays/Techdays-2014-the-Netherlands/Async-programming-deep-dive )

Let’s say that we have this code that awaits and throws ( or not ) an exception:


        static async Task<bool> test(int delaySeconds, Exception throwEx)
        {
            Console.WriteLine($"enter {delaySeconds} ");
            await Task.Delay(delaySeconds * 1000);
            Console.WriteLine($"finish waiting {delaySeconds} and throw Exception:  {throwEx.Message}");

            if (throwEx != null)
            {
                throw throwEx;//never do this in production
            }
            return true;
        }

First problem:  Error order

What this code will produce as output for the line Console.WriteLine(“err ” + ex.GetType().Name);  ?


            Console.WriteLine("start");
            var t10Ex = test(delaySeconds: 10, throwEx: new ArgumentException("problem with argument"));
            var t19Ex = test(delaySeconds: 19, throwEx: new DllNotFoundException("not found dll"));
            var t100NotEx = test(delaySeconds: 100, throwEx: null);

            try
            {
                await Task.WhenAll(new Task[] { t19Ex, t10Ex, t100NotEx });
            
            }
            catch (Exception ex)
            {
                Console.WriteLine("err " + ex.GetType().Name);

            }
            finally
            {
                Console.WriteLine("in finally");

            }
            Console.WriteLine("waiting in main");
            await Task.Delay(100 * 1000);
            Console.WriteLine("finish");

Answer: err DllNotFoundException
. That is because the await it produce error for the first  item in the array  , not for the first item in chronological order. More, it will wait for all tasks to finish.

Second problem: Grab all  errors

How do you modify the above code to grab all errors ?
Answer: By introducing a new variable, tAll . Attention: the exception is the same ( dllNotFound), however, the whole AggregateException is in tAll.Exception

            Task tAll=null;
            try
            {
                tAll = Task.WhenAll(new Task[] { t19Ex, t10Ex, t100NotEx });
                await tAll;
            
            }
            catch (Exception ex)
            {
                Console.WriteLine("err " + ex.GetType().Name);
                Console.WriteLine(" all exception here:" + tAll.Exception);

            }
            finally
            {
                Console.WriteLine("in finally");

            }

Third problem: Continue With
Let’s modify slightly the code for using ContinueWith. When the “in continue with ” will be displayed ?


            Console.WriteLine("start");
            var t10Ex = test(delaySeconds: 10, throwEx: new ArgumentException("problem with argument"));
            var t20NotEx = test(delaySeconds: 20, throwEx: null);
            var t10ContinueWith = t10Ex.ContinueWith(async (previousTask) =>
            {
                await Task.Delay(25 * 1000);
                Console.WriteLine("in continue with " + previousTask.IsCompletedSuccessfully);

            }).Unwrap();
            try
            {
                await Task.WhenAll(t10Ex, t20NotEx );
                
            
            }
            catch (Exception ex)
            {
                Console.WriteLine("err " + ex.GetType().Name);

            }
            finally
            {
                Console.WriteLine("in finally");

            }
            Console.WriteLine("waiting in main");
            await Task.Delay(100 * 1000);
            Console.WriteLine("finish");

Answer: : AFTER displaying “waiting in main” . Basically, you do not wait for ContinueWith, you wait for the first task in the ContinueWith construct ( t10Ex in our case)

And a question for you : Why do we need Unwrap ? ( Hint: try the code without and see the exception!)

C# and Null object

There is a lot to talk i n programming that null is bad , for example https://www.yegor256.com/2014/05/13/why-null-is-bad.html   and https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/ .

In C# we have a love-hate relationship with null :

Love : Because  the value type / struct cannot be null, C# creators invented Nullable<T> https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1

Hate: Because  reference types / classes can be null, c# 8.0 invented nullable reference types : https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/nullable-reference-types – no doubt from me that will be in the language

I want to add my 2 cents here : Null is sometime good

1. For databases , a null field is different from a 0 field ( see this toilet paper null vs 0 as a reference : https://pbs.twimg.com/media/C7ojxbSVAAEX9Bt.jpg )

2. For finding if a item exists in an array of value types, how do you find that the value that you want to search exists or not with .FirstOrDefault ? If the array is composed of reference, you can compare with null ….

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.