Another Reading List

A .NET Manager’s Perspective on F#

Even though the title says it’s a manager’s perspective, the post actually contains elements of functional programming in general. Good read for intro to functional programming.


The beauty of Functional Programming

This post makes argument on why functional programming is good alternative to more mainstream language. I also like how it covers basic functional programming things like pure function, immutability, etc.


Learn all about Distributed Application Runtime (Dapr), Part 1

Dapr is a fairly new open source project that aim to help you to build multi-cloud, platform-agnostics APIs. It has lots of features, such as state management and pub-sub. This Azure Friday video introduces the concept.


Rock, Paper, Scissors, Lizard, Spock – Sample Application

Microsoft code example to demonstrate microservices that use multilanguage and built in Azure.


Bye bye Postman ! Let’s share your REST API calls in team, easily !

In the world of microservices, tools like Postman is a must today. REST Client is Postman-like, but better. With VS Code extension and versioning in your favorite source control, this is going to be replacing my Postman.


Start-of-Week Reading List

Mockadillo

The rise of microservices requires more manageable APIs, including testing them. Mockadillo is a new tool built for this exact purpose.


Series: How YOU can build a Serverless GraphQL API leveraging microservices

I think this is more like a reference-type article. The topic is so broad and rather complex, but only short read. However, it does have links to more details implementation of GraphQL and anything you need to build a serverless GraphQL microservices API.


First World Problems: Very long RMarkdown documents

If you use RMarkdown, this tricks teach you how to manage a very long RMarkdown document. If you haven’t use (or heard) about RMarkdown and you’re doing data visualization and big data stuff, definitely check it out.


How I (Accidentally) Made a Game Engine from Scratch with Vanilla JS

A great way to start learning about game programming. This covers basic game programming and written in pure JavaScript.


Getting started with Azure App Configuration

The journey of centralized configuration is never ending. Azure App Configuration is another attempt at this, seems very promising however. Today’s configuration is not just in an application, it’s everywhere, the VM, the CI/CD pipeline, etc, and it spans across different cloud provider. Azure App Configuration is built to handle this.


SQL Server and CI/CD Reading List

SQL SERVER – 5 Important Steps When Query Runs Slow Occasionally

Obviously, this is generalized and YMMV (your mileage may vary) -kinda experience. But at the least, if you don’t know where to start, this is the right place to look into.


HOW TO SAVE MONEY ON AZURE USING AZURE RESERVATIONS

Exactly as the title suggest, it’s using Azure Reservations. You reserve the resources for 1 or 3 year terms. The saving could go up to > 50% in some instances. Only available for few resources however, including Virtual Machine, SQL Data Warehouse, Cosmos DB, SQL Database, Azure Databricks.


What are SQL Database instance pools (preview)?

This is not to be confused with Azure SQL Database’s Elastic Pool. Instance pools is a little bit different, in the sense that its main purpose is to migrate (lift-and-shift or otherwise) multiple smaller databases. Instance Pools make it easier to handle this scenario by simplify many things like IP address allocation and deployment time.


Nice tests to run in CI before deploying any website

Not all the tests are created equally. Andy Li gives her perspective what to test in your Continuous Integration pipelines before the deployment.


Build a CI/CD pipeline for API Management, Part 1

Management of APIs can easily go out of control if it’s not done right. In this video, Miao Jiang talks about CI/CD part of API Management. The result is a clean, manageable CI/CD pipeline that can be deployed in any environment.


Sunday Reading List

gRPC + ASP.NET Core as a Migration Path for WCFs in .NET Core

It was fun while it lasts, now with .NET Core development ramping up, WCF and its services library have slowly become technical debt. This articles a guideline to migrate to ASP.NET Web API and gRPC..


System memory health check for ASP.NET Core

If you’re already deploying your application to Azure App Services, you’re familiar with memory health check that comes with it for free. But, let’s say for some reason you need to deploy to other services, like containers or VMs, this article will walk through how to implement memory health check in ASP.NET Core application.


Logging in C# .NET Modern-day Practices: The Complete Guide

A truly complete and comprehensive guide to logging in C# / .NET. Michael walks us through from target types, structured logging, frameworks and best practices around logging. The three frameworks discussed are: Serilog, NLog and log4net. I’m glad I’m not the only one thinking we have too many loggin options in .NET!


Developers: This cute 8-bit RPG game wants to teach you new coding skills

What’s the best way to teach developer your API? Create a game, of course! Twilio does just that. It’s pretty good game too!


What exactly is Kubernetes?

For Container / Kubernetes beginner, this is a really good article to get your started. It covers the basic of Kubernetes, all different parts of Kubernetes, what Kubernetes is NOT and how it actually works.


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.

Invoke Google Apps Script with HTTP GET/POST

To be able to invoke Google Apps Script (GAS) through HTTP, the GAS must be deployed as web app, follow guidelines below.

  1. In script editing screen, add `doGet` and `doPost` functions. This following sample functions take a request parameter and simply check for query string parameter `name` if it’s HTTP GET and request body parameter `name` if it’s HTTP POST. Then return JSON object. The functions’s name `doGet` and `doPost` is mandatory Google conventions in order to accept HTTP GET and HTTP POST. For `ContentService` reference see Google docs.
  2. function doGet(request) {
      // Un-comment to see request output
      // return ContentService.createTextOutput(JSON.stringify(request));
    
      // HTTP GET
      var requestContent = request.parameter;
      var responseContent = '{"response": "' + requestContent.name + '"}';
      var response = ContentService.createTextOutput(responseContent);
      // Set return data type
      response.setMimeType(ContentService.MimeType.JSON);
    
      return response;
    }
    
    function doPost(request) {
      // Un-comment to see request output
      // return ContentService.createTextOutput(JSON.stringify(request));
    
      // HTTP POST
      var requestContent = JSON.parse(request.postData.contents);
      var responseContent = '{"response": "' + requestContent.name + '"}';
      var response = ContentService.createTextOutput(responseContent);
      // Set return data type
      response.setMimeType(ContentService.MimeType.JSON);
    
      return response;
    }
    
  3. In script editing screen, click `Publish` menu and `Deploy as web app…`
  4. apps script 1

  5. Configuration window will pop up. Current web app URL is the URL where the GAS can be invoked. Who has access to the app determine authorization setting on who can invoke the URL, the least restricted setting is `Anyone, even anonymous`.
  6. apps script 2

  7. The first time you publish the GAS, Google will ask for authorization.
  8. apps script 5

  9. Google automatically scan the script to identify authorization scopes. Google requires GAS that need sensitive authorization scopes (any scopes that access user data) to be verified by Google. If your GAS is not verified, Google will display warning message (see screen shot below). Simply click `Advanced` and proceed. However, if you plan to distribute your GAS to public it’s good idea to have Google verify your GAS (not discussed in this article).
  10. apps script 6

  11. Invoke GAS like REST API, here is example of HTTP GET invocation of functions we wrote earlier. Notice I pass in parameter `name` in query string which correspond to my code that look for parameter `name`. I use Postman.
  12. apps script 4

  13. And example of HTTP POST.
  14. apps script 3

Facebook Login Integration in ASP.NET MVC

  1. Obtain App Id from Facebook site.
    http://developers.facebook.com/apps
  2. Create new ASP.NET MVC 4 Web Application project (with Internet Application template).

  3. Open the _LoginPartial.cshtml file under Views\Shared folder.
    b
  4. Comment out all code and insert the following:
    <div id="fb-root"></div>
    <script>
        // Load the SDK Asynchronously
        (function(d){
            var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
            if (d.getElementById(id)) {return;}
            js = d.createElement('script'); js.id = id; js.async = true;
            js.src = "//connect.facebook.net/en_US/all.js";
            ref.parentNode.insertBefore(js, ref);
        }(document));
    
        // Init the SDK upon load
        window.fbAsyncInit = function() {
            FB.init({
                appId      : '<app_id>', // App ID
                channelUrl : '//' + window.location.hostname + '<port>/Home/Channel', // Path to your Channel File
                status     : true, // check login status
                cookie     : true, // enable cookies to allow the server to access the session
                xfbml      : true  // parse XFBML
            });
    
            // listen for and handle auth.statusChange events
            FB.Event.subscribe('auth.statusChange', function(response) {
                if (response.authResponse) {
                    // user has auth'd your app and is logged into Facebook
                    FB.api('/me', function(me){
                        if (me.name) {
                            document.getElementById('auth-displayname').innerHTML = me.name;
                        }
                    })
                    document.getElementById('auth-loggedout').style.display = 'none';
                    document.getElementById('auth-loggedin').style.display = 'block';
                } else {
                    // user has not auth'd your app, or is not logged into Facebook
                    document.getElementById('auth-loggedout').style.display = 'block';
                    document.getElementById('auth-loggedin').style.display = 'none';
                }
            });
    
            // respond to clicks on the login and logout links
            document.getElementById('auth-loginlink').addEventListener('click', function(){
                FB.login();
            });
            document.getElementById('auth-logoutlink').addEventListener('click', function(){
                FB.logout();
            });
        }
    </script>
    
    <div id="auth-status">
        <div id="auth-loggedout">
            <a href="#" id="auth-loginlink">Login</a>
        </div>
        <div id="auth-loggedin" style="display:none">
            Hi, <span id="auth-displayname"></span>
            (<a href="#" id="auth-logoutlink">logout</a>)
        </div>
    </div>
    
  5. Replace <app_id> in above code with your own app id.
  6. Replace <port> in above code with your application’s port.
    You can get application’s port under Project’s properties window. In the screenshot, it’s 6270.

  7. Create new Action in Home controller, name it Channel.
  8. Add the view for Channel action with no layout or master page (uncheck “Use a layout or master page”).
  9. Edit Channel.cshtml to look as following.
    <script type="text/javascript" src="//connect.facebook.net/en_US/all.js"></script>
    

  10. On Facebook Developer App Settings, set the app to interact with Website. Then set the site’s URL to your application full URL.
  11. Compile and run your ASP.NET MVC application.
  12. Login button on the top right corner should take your users to Facebook login page.
Resource and more readings: