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.

Adding byte to byte array

There are two methods. either to create a new array or resize the existing array;

To resize existing array, do this;

Array.Resize(ref fileBytesArray, fileBytesArray.Length + 1);

To create a new array from existing one and resize, do this;

bArray = AddByteToArray(bArray,  newByte);

Here is the method;

public byte[] AddByteToArray(byte[] bArray, byte newByte)
{
    byte[] newArray = new byte[bArray.Length + 1];
    bArray.CopyTo(newArray, 1);
    newArray[0] = newByte;
    return newArray;
}

Reference

c# how to add byte to byte array

Executing Raw SQL Queries using EF Core

Here are some methods;

DbSet.FromSqlRaw

The DbSet.FromSqlRaw method (DbSet.FromSql prior to Entity Framework Core 3.0) enables you to pass in a SQL command to be executed against the database to return instances of the type represented by the DbSet:

public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public Author Author { get; set; }
    public int AuthorId{ get; set; }
    public string Isbn { get; set; }
}
...
public class SampleContext : DbContext
{
    public DbSet<Book> Books { get; set; }
}
using (var context = new SampleContext())
{
    var books = context.Books.FromSqlRaw("SELECT BookId, Title, AuthorId, Isbn FROM Books").ToList();
}

The DbSet must be included in the model (i.e. it can not be configured as Ignored). All columns in the target table that map to properties on the entity must be included in the SQL statement. The column names must match those that the properties are mapped to. Property names are not taken into account when the results are hydrated into instances of the entity.

If any columns are missing, or are returned with names not mapped to properties, an InvalidOperationException will be raised .

Parameterized Queries

It’s always advised to parameterize user input to prevent the possibility of a SQL injection attack being successful. Entity Framework Core will parameterize SQL if you use format strings with FromSqlRaw or string interpolation with the FromSqlInterpolated method:

// Format string
var author = db.Authors.FromSqlRaw("SELECT * From Authors Where AuthorId = {0}", id).FirstOrDefault();
// String interpolation
var author = db.Authors.FromSqlInterpolated($"SELECT * From Authors Where AuthorId = {id}").FirstOrDefault();

Both of these approaches result in the following SQL being generated;

SELECT "a"."AuthorId", "a"."FirstName", "a"."LastName"
FROM (
    SELECT * From Authors Where AuthorId = @p0
) AS "a"
LIMIT 1

Entity Framework Core will only parameterize format strings if they are supplied inline to the FromSqlRaw method call. Format strings declared outside of the FromSqlRaw method call will not be parsed for parameter placeholders. In effect, you will be passing a concatenated string directly to the database, which is a SQL injection risk.

The following example is dangerous and should not be used:

var sql = string.Format("SELECT * From Authors Where AuthorId = {0}", id);
var author = db.Authors.FromSqlRaw(sql).FirstOrDefault(); 

The generated SQL is unparameterized:

SELECT "a"."AuthorId", "a"."FirstName", "a"."LastName"
FROM (
  SELECT * From Authors Where AuthorId = 2
) AS "a"
LIMIT 1

Stored Procedures

The SQL command can be any valid SQL statement that returns all the required fields of data. It is possible to call stored procedures via the FromSqlRaw method:

using (var context = new SampleContext())
{
    var books = context.Books
        .FromSqlRaw("EXEC GetAllBooks")
        .ToList();
}

It is also possible to pass in values to named parameters:

using (var context = new SampleContext())
{
    var authorId = new SqlParameter("@AuthorId", 1);
    var books = context.Books
        .FromSqlRaw("EXEC GetBooksByAuthor @AuthorId" , authorId)
        .ToList();
}

Non-Entity Types and Projections

In versions of EF Core prior to 2.1, it is not possible to use the FromSqlRaw method to return a subset of properties (a projection) directly from the database. Using the Books DbSet above as an example, the following will not work:

using(var context = new SampleContext())
{
    var books = context.Books.FromSqlRaw("SELECT BookId, Title FROM Books").ToList();
}

You must project the result of the FromSqlRaw method call to return a subset of properties:

using(var context = new SampleContext())
{
    var books = context.Books
        .FromSql("SELECT * FROM Books")
        .Select(b => new {
            BookId = b.BookId,
            Title = b.Title 
            }).ToList();
}

However, this may prove inefficient as all columns from the mapped table will be returned by the FromSql method call.

Support for returning ad hoc (not DbSet) types from direct SQL calls is possible from EF Core 2.1.

Database.ExecuteSqlCommand

The DbContext exposes a Database property which includes a method called ExecuteSqlCommand. This method returns an integer specifying the number of rows affected by the SQL statement passed to it. Valid operations are INSERTUPDATE and DELETE. The method is not used for returning entities.

using(var context = new SampleContext())
{
    var commandText = "INSERT Categories (CategoryName) VALUES (@CategoryName)";
    var name = new SqlParameter("@CategoryName", "Test");
    context.Database.ExecuteSqlCommand(commandText, name);
}

Note: You will need to add using Microsoft.Data.SqlClient; to make the SqlParameter type available to your code.

The ExecuteSqlCommand method can also be used to execute stored procedures:

using(var context = new SampleContext())
{
    var name = new SqlParameter("@CategoryName", "Test");
    context.Database.ExecuteSqlCommand("EXEC AddCategory @CategoryName", name);
}

Leveraging ADO.NET via the Context.Database property

In addition to the ExecuteSqlCommand method, the DbContext.Database property provides an API that allows you to perform ADO.NET operations directly. The GetDbConnection method returns a DbConnection object representing the context’s underlying connection. From that point, you can revert to the familiar ADO.NET APIs:

using (var context = new SampleContext())
using (var command = context.Database.GetDbConnection().CreateCommand())
{
    command.CommandText = "SELECT * From Table1";
    context.Database.OpenConnection();
    using (var result = command.ExecuteReader())
    {
        // do something with result
    }
}

EF CORE..

Get file path in .net core from wwwroot folder

This is how;

public class HomeController : Controller {
    private IWebHostEnvironment _hostEnvironment;

    public HomeController(IWebHostEnvironment environment) {
        _hostEnvironment = environment;
    }

    [HttpGet]
    public IActionResult Get() {
        string path = Path.Combine(_hostEnvironment.WebRootPath, "Sample.PNG");
        return View();
    }
}

References

https://weblog.west-wind.com/posts/2020/Feb/26/Working-with-IWebHostEnvironment-and-IHostingEnvironment-in-dual-targeted-NET-Core-Projects#out-with-old-in-with-the-new-iwebhostenvironment