URL Matching in C#

To start, let’s define what the internals of a URL looks like:

For our purposes, we care about the scheme, authority, path, query, and fragment. You can think of the scheme as the protocol, i.e., HTTP or HTTPS. The authority is the root or domain, for example, mycompany.com. The path, query, and fragment make up the rest of the URL. The URL spec defines each segment in this specific order. For example, the scheme always comes before the authority. The path comes after the scheme and authority. The query and fragment come after the path if there is one in the URL.

Read this, if thinking about using fragment in URL.

Alice runs a web site, Bob visits it, authenticates and receives a session cookie. (Some time might pass here, Bob might even close his browser.) Charlie sends Bob a mail saying “check out this cool link!”. Bob opens the link, which leads to a site controlled by Charlie. The page redirects Bob’s browser to a page on Alice’s site with an attack payload in the hash. The payload is executed, and since the browser still remembers the cookies, it can just send them to Charlie

https://stackoverflow.com/questions/1822598/getting-url-hash-location-and-using-it-in-jquery

Read more here

Possible values of empty json

An empty string is not a valid json;

string json = "";

While an empty string is not valid JSON two quotes is valid JSON. This is an important distinction.

Which is to say a string that contains two quotes is not the same thing as an empty string.

string json = "{}";
string json = "[]";

Valid minimal JSON strings are

The empty object '{}'

The empty array '[]'

The string that is empty '""'

A number e.g. '123.4'

The boolean value true 'true'

The boolean value false 'false'

The null value 'null'

Resource

https://stackoverflow.com/questions/30621802/why-does-json-parse-fail-with-the-empty-string

Convert Json String to C# object

Let’s say we have this json string in Ajax post method;

let groupObject = '[{ "Key": "Commercial", "IsMember": "true" }, { "Key": "Corporate", "IsMember": "false" }, { "Key": "Consumer", "IsMember": "false" }]';

Make sure this is a valid json. We can use following web site for json validation;

https://jsonlint.com/

We will create a user group class in .NET;

public class UGroupVM
{
    public string? Key { get; set; }
    public string? IsMember { get; set; }
}

We will user JSON Deserialization to get group object (try to use IList or List otherwise deserialization will fail because json is formatted as key/value pair);

var userGroup = JsonSerializer.Deserialize<List<UserGroupVM>>(groupObject);

For Newtonsoft, this is the syntax

var userAdGroup =
 JsonConvert.DeserializeObject<List<UserGroupVM>>(groupObject);

An alternative is this;

JArray jarray = JArray.Parse(groupObject);

foreach (JObject jObject in jArray)
{
    Console.WriteLine($"{(string)jObject["Key"]} -> {(string)jObject["IsMember"]}");
}

Hidden / Invisible Characters

Windows 98 had some tricks using ALT+some integer to add invisible characters. These are normally called  Control Characters.

The control characters U+0000–U+001F and U+007F come from ASCII. Additionally, U+0080–U+009F were used in conjunction with ISO 8859 character sets (among others). They are specified in ISO 6429 and often referred to as C0 and C1 control codes respectively. Most of these characters play no explicit role in Unicode text handling. The characters U+0000 , U+0009 (HT), U+000A (LF), U+000D (CR), and U+0085 (CR+LF) are commonly used in text processing as formatting characters.

This is how we can identify and remove them in a string;

string input; // this is your input string
string output = new string(input.Where(c => !char.IsControl(c)).ToArray());
Console.write(output.Trim());

For testing,

Excel can be used.

Click on the Cell where you want to add character. Click Insert -> Symbols;

Select “Basic Latin” in Subset and add empty space;

This will add a special character in selected cell before or after the value depending on the position.

Notepad++ is another alternative and can be used to add special characters in a string.

  1. Go to Edit > Character Panel to show the ASCII Insertion Panel.
  2. Put the cursor where you want to insert the character.
  3. Double-click the character (in the Character column) to insert.

For more info on NotePad++ special character handling, click here.

Resolve the issue of request matched multiple endpoints in .NET Core Web API

If there are two endpoint with same route, .NET Core Web API will throw request matched multiple endpoints error. Here is an example;

// api/menus/{menuId}/menuitems
[HttpGet("{menuId}/menuitems")]
public IActionResult GetAllMenuItemsByMenuId(int menuId)
{            
    ....
}

// api/menus/{menuId}/menuitems?userId={userId}
[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItemsByMenuAndUser(int menuId, int userId)
{
    ...
}

This is impossible because the actions are dynamically activated. The request data (such as a query string) cannot be bound until the framework knows the action signature. It can’t know the action signature until it follows the route. Therefore, we can’t make routing dependent on things the framework doesn’t even know yet.

Long and short, we need to differentiate the routes in some way: either some other static path or making the userId a route param. However, we don’t actually need separate actions here. All action params are optional by default. Therefore, we can just have:

[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItemsByMenu(int menuId, int userId)

And then we can branch on whether userId == 0 (the default). That should be fine here, because there will never be a user with an id of 0, but we may also consider making the param nullable and then branching on userId.HasValue instead, which is a bit more explicit.

We can also continue to keep the logic separate, if we prefer, by utilizing private methods. For example:

[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItems(int menuId, int userId) =>
    userId == 0 ? GetMenuItemsByMenuId(menuId) : GetMenuItemsByUserId(menuId, userId);

private IActionResult GetMenuItemsByMenuId(int menuId)
{
    ...
}

private IActionResult GetMenuItemsByUserId(int menuId, int userId)
{
    ...
}

Have fun.

Read more here.