A Reading List

Creating PWA Using Angular 7 – Step-by-Step Guide

A rather long and detailed post about Angular and PWA (Progressive Web App), but worth the read, especially if you haven’t heard about PWA. It covers the 101 stuff and goes on to creating PWA using Angular.


How to use Azure Bastion to connect securely to your Azure VMs

Great new offering from Azure. If you always RDP to your VM in Azure, or use a _’jump box’_, you will have a new, better, more secure way to RDP now. I really like the name too!


Lessons from Design School for Software Engineers

They are great lessons software engineers can adopt to become better. Not a technical post, but related to technical. It’s more of philosophical-type post, which is always good to know.


The Battle of C# to JSON Serializers in .NET Core 3

There’s a new kid in town, it’s called `System.Text.Json`. Michael goes over how the comparison between this new .NET Core 3 feature and other JSON libraries, including the infamous Json.NET. And yes, it cover performance test as well.


How to resolve .NET reference and NuGet package version conflicts

Have you ever got one of those annoying, `Could not load file or assembly or one of its dependencies` error when running .NET locally? Not only Michael explains why, but he also tell you how to resolve it. Mystery solved.


Parse JSON in SQL Server

I have following rows in database.

2019-07-17 17_33_37-SQLQuery45.sql - (local)_.Infinity (ENERGY_sutet (53))_ - Microsoft SQL Server M

Here is the full json:

{
    "FirstName": "Paul",
    "LastName": "Goodman",
    "Occupations": [
        {
            "Title": "Senior Manager",
            "Company": "Purple Ocean",
            "YearOfService": 9
        },
        {
            "Title": "Manager",
            "Company": "Blue Ocean",
            "YearOfService": 4
        }
    ]
}
{
    "FirstName": "Tom",
    "LastName": "Badman",
    "Occupations": [
        {
            "Title": "Supervisor",
            "Company": "Red Sky",
            "YearOfService": 1
        },
        {
            "Title": "Janitor",
            "Company": "Yellow Sky",
            "YearOfService": 7
        }
    ]
}

Here is how I can use JSON_VALUE to parse `Data` column.

2019-07-17 17_34_04-SQLQuery45.sql - (local)_.Infinity (ENERGY_sutet (53))_ - Microsoft SQL Server M

I can also use JSON_VALUE in WHERE clause.

2019-07-17 17_34_38-SQLQuery45.sql - (local)_.Infinity (ENERGY_sutet (53))_ - Microsoft SQL Server M

WebApi .Net – Add DelegatingHandler to Get Request Body

Out of the box, WebApi pipeline bind request body to parameter, therefore WebApi Controller (which inherit from ApiController) `Request.Content` object is empty.

For example, passing this json in the request body:

[
    {
        "Name": "Test",
        "Status": "C",
    }
]

Will bind it to WebApi Controller’s parameter, however, `Request.Content` object is empty.

screenshot message handler

Overcome this issue by creating `DelegatingHandler` to add request body back.

RequestHandler.cs

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace QC
{
    public class RequestHandler : DelegatingHandler
    {
        protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // Request body stream is emptied when WebApi bind request body to parameter, here we add original request body back so we can access it
            if (request.Content != null)
            {
                string body = await request.Content.ReadAsStringAsync();
                request.Properties["body"] = body;
            }

            return await base.SendAsync(request, cancellationToken);
        }
    }
}

Register in WebApiConfig.

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MessageHandlers.Add(new RequestHandler());
    }
}

Viola! `Request.Content` contains request body.

screenshot message handler2

Code is from here.

More Comprehensive Naming Convention

Indentation

Indentation

Indentation must be used if the line is associated with the previous line. When indentation is needed, use conventional indentation (one “Tab”).

Example 1:

<div id="content">
    <table>
        <tr>
            <td class="control_title">
            </td>
        </tr>
    </table>
</div>

Example 2:

public string indentation
{
    get
    {
        return _indentation;
    }
    set
    {
        _indentation = value;
    }
}

Wrapping Lines

Avoid lines longer than 120 characters. When an expression will not fit on a single line, break it with conventional indentation in new line.

Example:

string _xmlData = "<?xml version=\"1.0\"?>" + "\r\n" +
    "<!DOCTYPE ddtp=\"http://dtd.wctp.org/wctp-dtd-v1r1.dtd\">" + "\r\n" +
    "<wctp-Operation wctpVersion=\"wctp-dtd-v1r1\">" + "\r\n" +
    "<wctp-SubmitRequest>" + "\r\n" +
    "<wctp-SubmitHeader submitTimestamp=\"" + _timestamp + "\">" + "\r\n" +
    "<wctp-Originator senderID=\"application@chron.com\"/>" + "\r\n" +
    "<wctp-MessageControl messageID=\"001\"/>" + "\r\n" +
    "<wctp-Recipient recipientID=\"" + recipient + "@arch.com\"/>" + "\r\n";

 

Naming Convention (Server Code)

Identifier Naming Convention

Identifier Case Examples Rules
Comment Clear, short and descriptive.
Class PascalCase Person
BankVault
ImageSprite
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
Keep names simple and descriptive.
No underscores.
Nouns.
Method(Private) PascalCase with “_” prefix _UpdateScore(…)
_UpdateUrl(…)
_UpdateID(…)
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Verbs.
Method(Public) PascalCase UpdateScore(…)
UpdateUrl(…)
UpdateID(…)
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Verbs.
Method for Ajax (Private and public) PascalCase following text “Ajax” SavePeopleAjax
GetPropertyAjax
_DeleteGroupAjax
Method for ajax is a method that only called with ajax.
For private, prefix with “_”.
Common Method (Private and public) PascalCase following text “Common” GetStateCommon
_GetAnswerCommon
_SaveStateCommon
Common method is a method that could be use in different controllers/pages.
For private, prefix with “_”.
Namespace PascalCase Chronicle.IT.BasicFunctions
Chronicle.IT.Ftp
Chronicle.IT.Xml
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Use $lt;company_name$gt; as root.
Interface PascalCase with “I” prefix IDisposable
IWidgetXml
IUserID
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Parameter camelCase recordID
personName
previousUrl
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Optional object type can be added. See “Object Type Naming Convention” section.
Property / Variable (Private) camelCase with “_” prefix _backColor
_internalXml
_userID
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores (except the prefix).
Optional object type can be added. See “Object Type Naming Convention” section.
Property / Variable (Public) PascalCase BackColor
InternalXml
UserID
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Optional object type can be added. See “Object Type Naming Convention” section.

Object Type Naming Convention

Additional object’s type can be added to precede some identifiers in order to distinguish the object type. If the object’s type is added, abbreviate the object type according to the following rules:

Object Type Abbreviated Object Type Examples
Array arr _arrBackColors
_arrInternalXml
arrUserID
String str _strBackColor
_strInternalXml
strUserID

 

Naming Convention (Client Code)

CSS & HTML

Identifier Case Examples Rules
Class dash-separated sort-column
portlet-header
portlet-content
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
Keep names simple and descriptive.
No underscores.
Nouns.
All lowercase.
HTML Element camelCase ddlPropertyType
txtName
Start with 3 letters of specified element.
HTML Element (For) PascalCase Group
Property
People.FirstName
For is html element generated by mvc html helper that bound to the specific property.

JavaScript

Identifier Case Examples Rules
Comment Clear, short and descriptive.
Parameter camelCase dashboardResult
peopleResult
currentUrl
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores.
Optional object type can be added. See “Object Type Naming Convention” section.
Nouns.
Property / Variable (Private) camelCase with “_” prefix _savePreference
_currentUrl
_parent
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores (except the prefix).
Optional object type can be added. See “Object Type Naming Convention” section.
Nouns.
Property / Variable (Public) PascalCase SavePreference
CurrentUrl
Parent
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
No underscores (except the prefix).
Optional object type can be added. See “Object Type Naming Convention” section.
Nouns.

Json

Identifier Case Examples Rules
Name PascalCase Person
Status
Parent
Children
Acronyms of 3 or more letters should use pascal case instead of all caps.
Avoid abbreviations (unless it is widely used, like URL, HTML).
Keep names simple and descriptive.
No underscores.
Nouns.
Avoid using two words or more.

ASP.NET Web API and OData’s Verbose JSON

OData v3 and Verbose JSON

Whenever you work with OData in ASP.NET Web API, the return result will be JSON format. It’s noteworthy to know that by default Web API will return new OData JSON format specified in OData version 3. For older OData, the JSON format is different. It has more ‘unnecessary’ placeholders. This old OData JSON is also referred as ‘Verbose JSON’. In short, there are two types of OData JSON:

  • OData v3 has new JSON format
  • Verbose JSON is used in older OData versions.

ASP.NET Web API (.Net 4.5) and Verbose JSON

As mentioned before, by default Web API will return new OData JSON.

To change this behavior, you can request Web API to return old OData JSON format by specifying ‘odata=verbose’ in Accept header. Below is the sample of jQuery Ajax call specifying verbose JSON:

$.ajax({
    url: "/api/Products",
    dataType: "json",
    accepts: { json: "application/json;odata=verbose" }
}).done(function() {
    // do work ...
});

How it Looks Like?

For the curious:

Verbose JSON

{
    "d" : {
        "results": [
            {
                "__metadata": {
                    "uri": "http://demos/Orders(10248)",
                    "type": "SampleModel.Order"
                },
                "ProductId": 10248,
                "Name": "Vgnon"
            }
        ],
        "__count": "1"
    }
}

OData v3 (and above) JSON

{
    "odata.metadata":"http://localhost:43111/api/$metadata#Products",
    "odata.count":"1",
    "value":
    [
        {
            "ProductId":2,
            "CreatedDate":"2013-06-10T23:53:26",
            "CreatedBy":0,"Name":"Camera"
        }
    ]
}

JSON And C# Object Serialization Quick Reference

With JavaScriptSerializer, you can pretty much serialize / deserialize json-formatted string to any object and vice versa. Some of example below use class object, you can find this class object at the very bottom.

Here’s the quick reference:

string[] _testJsonStringArray = new string[8];
_testJsonStringArray[0] = "Id";
_testJsonStringArray[1] = "Firstname";
_testJsonStringArray[2] = "Lastname";
_testJsonStringArray[3] = "Age";
_testJsonStringArray[4] = "Job Description";
_testJsonStringArray[5] = "Address";
_testJsonStringArray[6] = "Email";
_testJsonStringArray[7] = "Hometown";

// Serialize Output:
// ["Id","Firstname","Lastname","Age","Job Description","Address","Email","Hometown"]
IEnumerable _testJsonList = new List() {
    "Id", "Firstname", "Lastname", "Age", "Job Description", "Address", "Email", "Hometown"
};

// Serialize Output:
// ["Id","Firstname","Lastname","Age","Job Description","Address","Email","Hometown"]
IEnumerable> _testJsonNestedList = new List>()
{
    new List()  {
        "31", "Test"
    },
    new List(){
        "12", "Also Test"
    }
};

// Serialize Output:
// [["31","Test"],["12","Also Test"]]
Person _testJsonClass = new Person()
{
    Firstname = "Alexander",
    Lastname = "The Great",
    Age = 99,
    JobDescription = "Eat and sleep",
    Address = "11 NoAddress St",
    Email = "alexander.thegreat@thegreat.com",
    Birthday = new DateTime(1999, 1, 1),
    Hometown = "Nowhere"
};

// Serialize Output:
// {"Firstname":"Alexander","Lastname":"The Great","Age":99,"JobDescription":"Eat and sleep","Address":"11 NoAddress St","Email":"alexander.thegreat@thegreat.com","Birthday":"\/Date(915170400000)\/","Hometown":"Nowhere"}
IEnumerable _testJsonClassCollection = new List()
{
    new Person() {
        Firstname = "Alexander",
        Lastname = "The Great",
        Age = 99,
        JobDescription = "Eat and sleep",
        Address = "11 NoAddress St",
        Email = "alexander.thegreat@thegreat.com",
        Birthday = new DateTime(1999, 1, 1),
        Hometown = "Nowhere"
    },
    new Person() {
        Firstname = "Smith",
        Lastname = "The Great",
        Age = 88,
        JobDescription = "Shopping and coding",
        Address = "12 NoAddress St",
        Email = "smith.thegreate@thegreate.com",
        Birthday = new DateTime(1980, 1, 1),
        Hometown = "Somewhere"
    }
};

// Serialize Output:
// [{"Firstname":"Alexander","Lastname":"The Great","Age":99,"JobDescription":"Eat and sleep","Address":"11 NoAddress St","Email":"alexander.thegreat@thegreat.com","Birthday":"\/Date(915170400000)\/","Hometown":"Nowhere"},{"Firstname":"Smith","Lastname":"The Great","Age":88,"JobDescription":"Shopping and coding","Address":"12 NoAddress St","Email":"smith.thegreate@thegreate.com","Birthday":"\/Date(315554400000)\/","Hometown":"Somewhere"}]
Building _testJsonClassContainCollection = new Building()
{
    Rooms = new List() {
        "401",
        "213",
        "523"
    }
};

// Serialize Output:
// {"Rooms":["401","213","523"]}
IEnumerable _testJsonClassCollectionContainCollection = new List()
{
    new Building() {
        Rooms = new List() { "White", "Blue", "Red" }
    },
    new Building() {
        Rooms = new List() { "A23", "23C", "G34" }
    }
};

// Serialize Output:
// [{"Rooms":["White","Blue","Red"]},{"Rooms":["A23","23C","G34"]}]
NestedBuilding _testJsonClassNestedList = new NestedBuilding()
{
    Rooms = new List>() {
        new List() { "Blue Room", "Orange Room", "Gray Room" },
        new List() { "Hot Room", "Cold Room", "Warm Room" }
    }
};

// Serialize Output:
// {"Rooms":[["Blue Room","Orange Room","Gray Room"],["Hot Room","Cold Room","Warm Room"]]}

And here’s the classes I used:

public class Person
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public int Age { get; set; }
    public string JobDescription { get; set; }
    public string Address { get; set; }
    public string Email { get; set; }
    public DateTime Birthday { get; set; }
    public string Hometown { get; set; }
}

public class Building
{
    public IEnumerable Rooms { get; set; }
}

public class NestedBuilding
{
    public IEnumerable> Rooms { get; set; }
}

System.Web.Script.Serialization.JavaScriptSerializer

In my earlier post and here, I make use of System.Web.Script namespace for its JavaScript serialization. Worth noting that in order to use the namespace, we will need to add the following references:

  • System.Web
  • System.Web.Extensions