• Featured post

C# Async ops

El nucleo de la programacion asincrona son los objetos Task y Task<T>. Son compatibles con las palabras clave async y await.

Primero hay que reconocer si el codigo se usa para trabajos enlazados a I/O o si son CPU intensivos.

  • Si el codigo espera algo como una BBDD o una response de un servidor, es codigo I/O. En este caso hay que usar async y await
  • Si el codigo realiza un calculo costoso, es CPU intensivo. Use await para esperar una operacion que se ha comenzado en background con Task.run

Async / Await (Operaciones I/O)

La palabra clave importante aqui es await. Lo que hace es suspender la ejecucion del metodo actual y devolver el control hasta que está lista para seguir.

public async Task Main()
{
	string contenido = await LeerPaginaWebAsync("http://example.com");
}

private async Task<string> LeerPaginaWebAsync(string url)
{
	using (HttpClient client = new HttpClient())
	{
		return await client.GetStringAsync(url);
	}
}

Read More

Data Models Entity Framework Core

You can easily mark fields for a model which are primary key or are required.

public class User
{
	[Key]
	public int Id { get; set; }
	
	[Required(ErrorMessage = "Name is mandatory")]
	public string Name { get; set; }
	
	public string Telephone { get; set; }
	
	public string Mobile { get; set; }
	
	[Required(ErrorMessage = "Email is mandatory")]
	public string Email { get; set; }
}

Nullables C#

Tipos Nullable (?)

El operador ? se usa para convertir un tipo de valor en un tipo de valor nullable, el cual puede contener un valor nulo.

int? numeroNullable = null;
if(numeroNullable.HasValue)
{
	Console.WriteLine(numeroNullable);
}

Acceso condicional nulo a miembros (?. o ?[])

Este operador permite acceder a un miembro de un objeto solo si el objeto no es nulo, evitando asi una NullReferenceException. Si no se cumple, devuelve null.

  • si a es nulo, el resultado de a?.x o a?[x] es null
  • si a no es nulo, el resultado de a?.x o a?[x] es el mismo que a.x o a[x]
string[] nombres = null;
int? longitud = nombres?.Length; // asigna null en lugar de lanzar una excepcion

(!) (revisar como usarlo mejor junto al operador ??) (!)

Coalescencia de Nulos (??)

Se usa para proporcionar un valor por defecto en caso de que una expresion nullable contenga un null.

sin este operador

string name = GetName();
if(name == null)
{
	name = "unknown";
}

se reemplaza por esto usando el operador

string name = GetName() ?? "unknown";

Se recomienda usar ?? en vez de expresiones ternarias para comprobar un null

// no usar esto
var v = x != null ? x : y; // or 
var v = x == null ? x : y;

// y usar esto en su lugar
var v = x ?? y;

(!) También se puede usar junto al operador ?. para asignar un valor por defecto en caso de que sea nulo (!)

string[] nombres = ...; // whatever 
string nombre = nombres?[index] ?? "NotFound"; // array is null or name not found

Se puede usar junto a un throw para hacer más concisa la asignación de valores.

public string Name
{
	get => name;
	set => name = value ?? throw new ArgumentNullException(nameof(value), "Name cannot be null");
}

Asignacion de coalescencia de nulos (??=)

reemplaza este formato de código

if (variable is null) 
{
	variable = "something";
}

por esto. lo hace más conciso

variable ??= "something";

Reference(s)

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0029-ide0030-ide0270
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators–and-

Linq examples

Retrieve a simple subset of properties for all items in list

Usually, anon data types are used in the select clause to return a specific subset of properties for each object in the collection.

we have the employee class

public class Employee
{
	public int ID { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }
	public string Address { get; set; }
}
List<Employee> employees = // whatever ...
// we convert an Employee into an anon object type with a subset of properties
var employeeDetails = from emp in employees
	select new { Id = emp.ID, Name = emp.Name };

How to map List of classes

// Method to show call usage. 
public List<MappedUser> MapListOfUsers(List<User> users)
{
	// option 1
	List<MappedUser> mappedUsers = users.Select(user => MapSingleUser(user))
		.ToList();
	
	// option 2
	List<MappedUser> mappedUsers2 = 
		(from user in users select MapSingleUser(user)).ToList();
}

method to encapsulate mapping itself

private MappedUser MapSingleUser(User user)
{
 var mapped = new MappedUser
 {
	 Id = user.Id,
	 Name = user.Name,
	 Email = user.Email
 };
 return mapped;
}

This provides easier and more legible than doing a foreach to iterate everything.

How to filter list per properties (Where)

var adminUserTask = users
	.AsParallel()
	.Where(user => "admin".Equals(user.type.ToLower()))
	.Select(async user => { return await ProcessAdmin(user);});
List<UserResults> results = (await Task.WhenAll(adminUserTask)).ToList();

How to select records based on another list (ids)

This is how to select a list of items, selecting them by id, based on another list of items

List<string> idList = // ...
var profiles = _context.UserProfiles
		.Where(userProf => idList.Contains(userProf.Id));

How to order based on a dynamic parameter

// Direction is an Enum w. values ASC or DESC
private List<Person> SortPersons(Direction direction, List<Person> persons, Func<Person, string> sortBy)
{
	if(direction.DESC)
	{
		return persons.OrderByDescending(sortBy.Invoke).ToList();
	} else 
	{
		return persons.OrderBy(sortBy.Invoke).ToList();
	}
}

How to use it

var sortedPersons = SortPersons(direction, persons, person => person.Name);

How to use in async await env

We separate the linq query into Task and Execution. This executes this Task concurrently.

Single param lambda

remember that for lambdas with a single param where it comes from the same query, you don’t need to explicitely set it

this transforms

public List<int> FilterList(List<int> listToFilter, List<int> filterintList)
{
	return listToFilter.Where(number => filteringList.Contains(number)).ToList();
}

How to filter list per properties (Where)

filter by properties in a nullable list and return true if there’s any row that match. If the list is null, it returns false.

return response.results?.rows
	.Where(row => row.id == requestId && (row.owner == requestOwner || row.responsible == requestResponsible))
	.Any() ?? false;

another example

var task = response.results.rows
	.AsParallel()
	.Where(row => "specifictype".Equals(row.type.ToLower()))
	.Select(async row => {
		if(row.type.Equals("specificType"))
		{
			return await Something(row, id, log);
		} else 
		{
			return row;
		}
	});

Methods worth a mention

Remove duplicates Distinct()

var task = response.results.rows
	.AsParallel()
	.Where(row => "specificType".Equals(row.type.ToLower()))
	.Select(async row => { return await Something(row, id, log);});

Get the difference of two lists Except()

var distinctList = listToFilter
	.Except(filteringList)
	.ToList();

Validaciones C#

C# tiene los DataAnnotation

[Required] hace que sea un campo obligatorio

[Required(ErrorMessage = "Nombre es obligatorio")]
public string NombreCategoria { get; set; }

[Required(ErrorMessage = "Orden es obligatorio")]
[Range(1, int.MaxValue, ErrorMessage = "El orden debe de ser mayor a cero")]
public int Orden {get; set; }

Se controla mediante el siguiente codigo en el controller. El código de ModelState es código base de un Controller.

if(ModelState.IsValid) 
{
	// code if everything's valid
}

Nomenclatura C#

class Program 
{
	// private variables start with _
	private readonly string _estaEsMiCadena;

	// constantes
	const int IVA = 7;

	// fields
	public int Name { get; private set; }

	static void Main(string[] args)
	{
		// camel case
		var thisIsMyVariable = "Camel";
	}

	// pascal case
	public void ThisIsAMethod()
	{
	
	}
}

Todas las Interfaces deben comenzar su nombre por I.

public interface IEjemplo
{

}

Introducción a .NET

CLR (Common language runtime)

Entorno de ejecucion para .NET. En tiempo de ejecucion el compilador de CLR convierte el codigo CIL en codigo nativo para el SO. Facilita la integración entre lenguajes.

CLR es la MV en la que se ejecutan nuestras apps. CLR se hizo para tener una capa de abstraccion entre las propias apps y el SO donde se ejecutaban.

El CLI se puede ejecutar en otros SO. El CLR se ejecuta solo en Windows.

.NET intro

Read More

.NET launchsettings vs appsettings

launchSettings

Tiene más que ver con el despliegue. Establece los perfiles con los que ejecutaremos nuestro proyecto. Configura la forma en la que se inicia la aplicación durante el desarrollo.

No se utiliza en entornos de producción.

appsettings

Se utiliza para almacenar la configuración de la aplicación, como cadenas de conexión de BBDD.

Se utiliza tanto en entornos de desarrollo como de producción.

.NET Middleware

Middleware is software assembled into a pipeline to handle request and responses. Each component:

  • Chooses if he passes the request to the next component.
  • Can perform work before and after the next component.

(an example can be an authorization middleware)

.NET middleware

Test APIs with Postman - Scripting

We can set pre-request scripts (run before the request) & tests (after execution) at several levels:

  • Collection
  • Folder
  • Request

Snippets

Inside pre-request Script and Tests we have a SNIPPETS column with templates we may use for our code.

postman scripting

Get / Set variables

console.log("Hello world");

// work with local vars
let urlVar = pm.variables.get("protocol");
console.log("value for protocol: " + urlVar);

pm.variables.set("protocol", "http");
console.log(pm.variables.get("protocol"));  

// work with global vars
let globalVar = pm.globals.get("env");
console.log(globalVar);

Read More