A reference list of best practices;
https://abdulrwahab.medium.com/api-architecture-best-practices-for-designing-rest-apis-bf907025f5f
https://zonito.medium.com/best-practice-and-cheat-sheet-for-rest-api-design-6a6e12dfa89f
Source, Ingest, Prepare, Analyze and Consume
All about application services for example, Azure App Service. Angular application, Microsoft .NET Core and EF
I was trying to reference a DLL targeting FW 4.6 in a host application targeting .NET Core 2.1. I started getting this error;
This is where I started to wonder, What’s the difference? How they can co-exist? How the host application can use them?
Microsoft recommend to target .NET Standard 2.0 when building reusable libraries, unless you need to support an earlier version. Most general-purpose libraries should not need APIs outside of .NET Standard 2.0. .NET Standard 2.0 is supported by all modern platforms and is the recommended way to support multiple platforms with one target.
.NET Core 2.1 and later versions support .NET Standard 2.0 and earlier versions.
There will be no new .NET Standard versions after 2.1. For more information, see .NET 5 and .NET Standard later in this article.
.NET Standard libraries and Visual Studio
In order to build .NET Standard libraries in Visual Studio, make sure you have Visual Studio 2019 or Visual Studio 2017 version 15.3 or later installed on Windows, or Visual Studio for Mac version 7.1 or later installed on macOS.
A good explanation about libraries
Resources
Generally, when people talk about reflection, the main concern is the performance. Because it runs on runtime, so theoretically, it is a little bit slower than the normal application. But it is flexible for many scenarios, especially if you develop the framework. If it is acceptable to spend a few seconds (or only hundreds of milliseconds) to load assemblies, then feel free to use it.
Let’s walk through an example; We are going to use an interface called “ISpeaker”.
internal interface ISpeaker
{
string SayHello();
}
Create three implementation classes:
English Speakers
internal class EnglishSpeaker : ISpeaker
{
public string Name => this.GetType().ToString();
public string SayHello()
{
return "Hello!";
}
}
Urdu Speakers
internal class UrduSpeaker : ISpeaker
{
public string Name => this.GetType().ToString();
public string SayHello()
{
return "as-salaam-alaikum";
}
}
Chinese Speakers
internal class ChineseSpeaker : ISpeaker
{
public string Name => this.GetType().ToString();
public string SayHello()
{
return "Nihao";
}
}
Now we can use reflection to find all the implementations of ISpeaker
interface and call their methods or properties.
internal class ReflectionHelper
{
public static List<Type> GetAvailableSpeakers()
{
// You can also use AppDomain.CurrentDomain.GetAssemblies() to load all assemblies in the current domain.
// Get the specified assembly.
var assembly =
Assembly.LoadFrom(Path.Combine(Directory.GetCurrentDirectory(), "ReflectionDemo.dll"));
// Find all the types in the assembly.
var types = assembly.GetTypes();
// Apply the filter to find the implementations of ISayHello interface.
var result = types.Where(x => x.IsClass && typeof(ISpeaker).IsAssignableFrom(x)).ToList();
// Or you can use types.Where(x => x.IsClass && x.GetInterfaces().Contains(typeof(ISpeaker))).ToList();
return result;
}
}
In this class, we load the specified dll file that contains types we need. Then we can apply the LINQ query to find all the implementations of ISpeaker
interface using Reflection.
Test the program output. we can output the name and call SayHello
method of each speaker:
using ReflectionDemo;
using System.Reflection;
Console.WriteLine("Hello, World!");
Console.WriteLine("Here is the Reflection sample:");
// Find all the speakers in the current domain
var availableSpeakers = ReflectionHelper.GetAvailableSpeakers();
foreach (var availableSpeaker in availableSpeakers)
{
// Create the instance of the type
var speaker = Activator.CreateInstance(availableSpeaker);
// Get the property info of the given property name
PropertyInfo namePropertyInfo = availableSpeaker.GetProperty("Name");
// Then you can get the value of the property
var name = namePropertyInfo?.GetValue(speaker)?.ToString();
Console.WriteLine($"I am {name}");
// Invoke the method of the instance
Console.WriteLine(availableSpeaker.InvokeMember("SayHello", BindingFlags.InvokeMethod, null, speaker, null));
}
Console.WriteLine();
Console.ReadKey();
Run the program, you will see the below output:
If we need to add other speakers in other languages, just add the implementation classes in the same project. .NET reflection can automatically find out all the required classes and call the methods correctly.
It is extremely useful when we create the plugin-type applications. First we make the interfaces and call the methods from the client by reflection. Then we can create plugins following the interface for the client, which can be loaded as the *.dll files dynamically and executed.
Another scenario is for the framework development. As a framework developer, you will not be able to know what implementations the users will create, so you can only use reflection to create these instances. One example is in some MVVM frameworks, if you create the classes following the conventions, eg. xxxViewModel, the framework can find all the ViewModels and load them automatically using reflection.
The main namespaces we need to use for reflection are System.Reflection and System.Type. You may also need to know the below terms:
Resources
Dynamically Loading and Using Types
https://docs.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support
REST architecture allows us to generate hypermedia links in our responses dynamically and thus make navigation much easier. To put this into perspective, think about a website that uses hyperlinks to help you navigate to different parts of it. You can achieve the same effect with HATEOAS in your REST API.
The advantage of the above approach is that hypermedia links returned from the server drive the application’s state and not the other way around.
A REST client hits an initial API URI and uses the server-provided links to access the resources it needs and discover available actions dynamically.
The client need not have prior knowledge of the service or the different steps involved in a workflow. Additionally, the clients no longer have to hardcode the URI structures for various resources. HATEOAS allows the server to make URI changes as the API evolves without breaking the clients.
Let’s say we need to define an API that guides a client through a signature process. In this process after getting a Resource, the resource will include a Link indicating the following elements that are necessary. The plan is to add a signature link in this example:
{
"documentID": 10,
"documentType": "Contract",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
"links": [
{
"href": "10/signatures",
"rel": "approval",
"type" : "POST"
}
]
}
The recommendation is to add a link to xsd/schema document which will define the structure of model attributes. e.g.
"links": [
{
"href": "10/signatures",
"rel": "approval",
"type" : "POST",
"schema" : "/schemas/signature.xsd"
}
]
Now the client can read the XSD document to find out about the model. This approach wouldn’t process the request but return the model XSD/schema document to the client. In this way, when client want to POST on 10/signatures
, it may get the request schema by GET 10/signatures.xsd
.
Resources
https://thereisnorightway.blogspot.com/2012/05/api-example-using-rest.html
https://medium.com/@andreasreiser94/why-hateoas-is-useless-and-what-that-means-for-rest-a65194471bc8
https://netflix.github.io/genie/docs/3.0.0/rest/#_introduction
I wanted to copy DLL files to a network share. I am dynamically loading assemblies in different applications and can not risk changing file paths.
I don’t want to mess up Visual Studio default binary locations. The work around is to do XCOPY in visual studio post build event;
XCOPY "$(TargetDir)*" "\\Netowrk Path\FolderName\" /S /Y
It’s that simple.
Resources