Showing posts with label API. Show all posts
Showing posts with label API. Show all posts

Interfaces.

When it comes to the ability to interact with the inputs and outputs of software, everything is an interface. For those who aren't aware, the Windows OS was originally named "Microsoft Interface Manager". There is interesting info in the Wikipedia entry on the origins of Windows.


The OS that started it all for Microsoft.


"In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information. The exchange can be between software, computer hardware, peripheral devices, humans, and combinations of these."

 

Without getting into the omnipresence of interfaces too much (the keyboard is one, the mouse and cursor are as well, the monitor is an interface, all of the windows on the screen are interfaces, every single OS event is taking place between two endpoints of an interface, programming languages use interfaces as "contracts" that can be adhered to, to allow for different implementations of the same kinds of data structures and methods, our own 👀 are interfaces to the world around us and on and on- and each of these relies on their own software!...), let's take a simple example.

Let's say we have some really neat library of unique functionality we want to share with as many developers as possible called "extRS". We have so many options for how to get this into the hands of other developers. But it requires assembling the working software into different languages/compilations to fulfill the needs of the different interfaces.


This is what Windows 1.01 looked like; 1985 my, my...


  • For an API (the interface for web services), we will want to present our software in the form of an API running on a web server. With a live ASP.NET Web API (esp. one that can respond to XML and JSON) you can allow clients (interfaces) to get live data from an implementation of your library's functionality via something like a simple POST to /ConvertXmlToJson with a body of:
 { <car><passenger></passenger></car> }  
...which then returns the appropriate XML-translated-to-JSON:
 {  
   "car": 
     {  
       "passenger": null  
     }    
 }  

This is an example of an API request and response (FedEx API)


  • There is also ASP.NET CoreWCF for interfacing with legacy XML SOAP-based web services:
If you want to interface with a legacy SOAP service in ASP.NET Core- this is what you can use


  • For getting our logic into the hands of JavaScript and NodeJS developers we can create and host an NPM package:
htmx and hyperform.js for validation are the neatest 2 open source things I've discovered in the past 2 years


  • For Python developers we can publish a python libraries to PyPI which makes it download-able via pip:
This shows the installation for the Python package pandas through the Windows CMD prompt


  • And we could even create a Ruby gem version, and packages for other languages to boot.... and on and on....

The problem is that, the more packages and different types of assembled or executable libraries you create, the more code bases you have to continuously test and maintain. But if your logic is simple enough, it makes sense extend the reach of your software as much as possible. Every interface that could use it, should be able to get it, and use it.

We have not even discussed console interface (CLI) which is required if you want your logic to be utilized in scripting and tooling chains that perform logic by piping the results of processes into subsequent processes all in CLI scripts like bash or PowerShell.

  • Custom CLI .exe - We can expose our extRS functionality through a command line interface. We compile a CLI program, ExtRS.CLI.exe that accepts user input such as ConvertXmlToJson ""<mouse name="Micky"><mouse>"" and performs prompts to present information to the CLI interface. I hate to disappoint, but that hasn't yet been implemented for the extRS project .sln 🤷🏽‍♂️

A simple .NET CLI program using extRS; this can easily be modified to implement virtually all of the extRS functionality


  • PowerShell Module - With a PowerShell module, DevOps and CI/CD devs can easily install the PowerShell modules through the official Microsoft PowerShell Gallery Here is the ReportingServicesTools PowerShell module:

Here is the ReportingServicesTools PS module; as you can see (errors)- I've gotta update some things in extRSAuth to get it to work with this module(!)


  • Nuget Package (compiled, portable ".dll" binaries) - allow clients to easily get your library's code into any .NET project. With this, any .NET project can reference extRS via:

This is my SSRS extension library, "extRS" on Nuget.org

  • WinForms - though a bit antiquated, there are millions of SMB and huge corporate software applications running proprietary .NET Framework code through Windows forms interfaces. It is like COBOL and FORTRAN- some things just work, and so they persist. For things like point-of-sale systems, sometimes the best solution- is something proven and established that won't surprise anyone (a WinForms POS app). An extRS WinForms app looks like this:

A mock of what an extRS interface implementation in WinForms might look like


  • MAUI - my experience is limited here, but from what I have experienced, MAUI is a faster, more capable version of Xamarin (with Xamarin and Mono under the hood). The great thing about MAUI is that, with one project, you can target all manner of mobile form factors (phones, tablets, watches- iOS and Android). An interface for my "tickertapes" Android app on MAUI for an Android phone looks like this: 

An example of one of my apps, "Tickertapes", running in an Android emulator using MAUI



As you can see we have so many ways to expose our unique (extRS, tickertapes) functionality. The only limitation on getting your functional code into operating programs is- the right interface implementation!




PS: A note on physical client interfaces as well... While we have discussed the different software interfaces (API, CLI, .dll, NPM, .psm, etc.), from a UI presentation and experience perspective, we have to consider the different types of physical interfaces that our code will be represented on- particularly the screen dimensions and how that will affect the inclusion vs. exclusion and location of certain content.

Never give short shrift to UI compatibility across devices- it is dang hard to present a "consistent" experience in myriad "different" ways. ('kinda competing, incompatible angles).


Hardware Form Factors

  • Mobile Phones
  • Desktop monitors
  • Laptop monitors
  • Tablets
  • TV monitors
  • LED scoreboards
  • Digital scrolling Marquee signs
  • Digital Billboards
  • "Smart" Watches
  • VR Headsets
  • Earbuds
  • "Smart" Eye Glasses
  • IoT devices with little or no display at all (in BAS equipment for example, typically these are used to start/stop or accelerate/slow down, based on some kind of PLC configuration and to collect and report useful data metrics about the device)



*"On November 20, 1985 (38 years ago), the first retail release, Windows 1.01, was released in the United States at a cost of US$99 (equivalent to about $280.00 in 2023)." -Wikipedia

Social Authentication in ASP.NET Core MVC

A common modern convenience for apps is the ability to choose to authenticate and create an account based on credentials from an existing service that most people have (ie. Google, Twitter, LinkedIn, GitHub, etc.). in this post I will walk through the configuration of social authentication for Google and LinkedIn accounts.

Setting up social authentication in ASP.NET Core is a lot easier than you might think...

Before implementing this feature you will need to register for a Google and a LinkedIn developer account which will then give you access to the 2 values that make the magic of this built-in authentication possible: clientKey and clientSecret.

Important(!): you will also want to register the Callback/Redirect URLs for each social authentication as shown below. This redirect URL below is for my project running on localhost:44396 obviously ("/signin-google" is the path you want to append to your app root for Google and "/signin-linkedin" for LinkedIn):


Once you have this setup, you will be able to wire them up in the Startup.cs ConfigureServices() method of an ASP.NET Core 3 MVC Web Application ie:

  public void ConfigureServices(IServiceCollection services)  
     {  
       services.AddDbContext<ApplicationDbContext>(options =>  
         options.UseSqlServer(  
           Configuration.GetConnectionString("DefaultConnection")));  
       services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)  
         .AddEntityFrameworkStores<ApplicationDbContext>();  
       services.AddControllersWithViews();  
       services.AddRazorPages();  
       services.AddAuthentication()  
       .AddGoogle(o =>  
       {  
         o.ClientId = "[YourGoogleClientId]";  
         o.ClientSecret = "[YourGoogleClientSecret]";  
       })  
       .AddLinkedIn(o =>  
       {  
         o.ClientId = "[YourLinkedInClientId]";  
         o.ClientSecret = "[YourLinkedInClientSecret]";  
       });  
       // Add application services.   
       services.AddMvc();  
     }  


Now you just have to:

  • Create your ASP.NET Core 3 MVC Web Application project with Identity options as below
  • Install a couple Nuget packages for Google OAuth2 and Linked OAuth respectively
  • Call "Update-Database" from Nuget Package Manager Console
  • Modify Startup.cs

To implement this feature for your users you only need follow a couple steps when setting up the project (whether ASP.NET MVC or the newer ASP.NET Core MVC) to enable some builtin identify and authentication handling after which you can configure and customize to fit your app's particular custom authentication needs. Follow the images below for proper installation of the required 2 Nuget packages, the db command, etc.

First, make sure you create your ASP.NET Core MVC project with "Individual User Accounts" radio button selection and "Store user accounts in app" dropdown selection as follows:


Change Authentication to use Individual User Accounts- this sets up the required boilerplate template code



You will add this Nuget package for LinkedIn authentication



You will add this Nuget package for Google authentication


Next you will need to create the database objects (ASPNET app auth db and tables) via "Update-Database" Package Manager Console command


Finally, modify Startup.cs ConfigureServices() method as shown in the snippet above. Compile and give it a whirl.

And that is all there is to it. Strangely there is not a lot of documentation on exactly how to do this and what can cause it to not work; I spent over an hour debugging what turned out to be a not-so-obvious issue (in my case I was following instructions that erroneously suggested I inject unneeded services to the services.AddAuthentication() instantiation in the snippet of Startup.cs above).


If your keys and Callback URLs are correct you will be able to authenticate to Google and LinkedIn



Once you have registered your social account, you can then log in with it and you will see the following (notice "Hello!...." and "Logout")


If you are like me and do not want to keep to adding yet more and more credentials to LastPass, your users probably don't either. Implementing Social Authentication is a powerful tool that you can leverage with relative ease in ASP.NET Core 3 MVC Web apps.

If you have questions on implementing this or just need some help and general guidance, feel free to comment or drop me an email at colin@sonrai.io


GitHub: https://github.com/cfitzg/DotNetSocialAuth


References:

http://codereform.com/blog/post/asp-net-core-2-1-authentication-with-social-logins/

https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on

https://ankitsharmablogs.com/authentication-using-linkedin-asp-net-core-2-0/  

https://stackoverflow.com/questions/53654020/how-to-implement-google-login-in-net-core-without-an-entityframework-provider


TwickrTape

Real-time scrolling Tweets related to financial news alerts and updates. Just enter the Twitter handle you want to see a marquee of live streaming tweets from.

TL;DR - the working app is here: https://twickrtape.azurewebsites.net
..znd here on Google Play Store: https://play.google.com/store/apps/details?id=io.cordova.twicktape

Use button in lower-left to toggle different Twitter handles

The code is a hodgepodge of various references and vestiges of past personal projects. My initial aim was to get something working end-to-end as I envisioned, and I was able to achieve that pretty easily through the Twitter API and .NET.

The process is standard API stuff- first you authenticate and receive a token which you can then subsequently pass to prove that your requests are valid. Then, using simple (REST API) HTTP GET, we get the content (Twitter Timeline information) that we are interested in.

The gist of the code is .NET C# (an ASP.NET Controller method) and listed below:

  public ActionResult GetTwickr(string handle = "business")  
     {  
       // Set your own keys and screen name  
       var oAuthConsumerKey = "XXXXXXXXXXXXX"; // "API key";  
       var oAuthConsumerSecret = "XXXXXXXXXXXXXXXXXXXXX"; // "API secret key";  
       var oAuthUrl = "https://api.twitter.com/oauth2/token";  
       var screenname = "@" + handle; // default Twitter display current status  
       // Authenticate  
       var authHeaderFormat = "Basic {0}";  
       var authHeader = string.Format(authHeaderFormat,  
         Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey) + ":" +  
         Uri.EscapeDataString((oAuthConsumerSecret)))  
       ));  
       var postBody = "grant_type=client_credentials";  
       HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);  
       authRequest.Headers.Add("Authorization", authHeader);  
       authRequest.Method = "POST";  
       authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";  
       authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;  
       using (Stream stream = authRequest.GetRequestStream())  
       {  
         byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);  
         stream.Write(content, 0, content.Length);  
       }  
       authRequest.Headers.Add("Accept-Encoding", "gzip");  
       WebResponse authResponse = authRequest.GetResponse();  
       // deserialize into an object  
       TwitAuthenticateResponse twitAuthResponse;  
       using (authResponse)  
       {  
         using (var reader = new StreamReader(authResponse.GetResponseStream()))  
         {  
           System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();  
           var objectText = reader.ReadToEnd();  
           twitAuthResponse = JsonConvert.DeserializeObject<TwitAuthenticateResponse>(objectText);  
         }  
       }  
       try  
       {  
         // Get timeline info  
         var timelineFormat = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={0}&include_rts=1&exclude_replies=1&count=5";  
         var timelineUrl = string.Format(timelineFormat, screenname);  
         HttpWebRequest timeLineRequest = (HttpWebRequest)WebRequest.Create(timelineUrl);  
         var timelineHeaderFormat = "{0} {1}";  
         timeLineRequest.Headers.Add("Authorization", string.Format(timelineHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token));  
         timeLineRequest.Method = "GET";  
         WebResponse timeLineResponse = timeLineRequest.GetResponse();  
         var timeLineJson = string.Empty;  
         string scrolltxt = string.Empty;  
         using (timeLineResponse)  
         {  
           using (var reader = new StreamReader(timeLineResponse.GetResponseStream()))  
           {  
             timeLineJson = reader.ReadToEnd();  
           }  
         }  
         // deserialize into an object  
         dynamic obj = JsonConvert.DeserializeObject(timeLineJson);  
         foreach (var r in obj.Root)  
         {  
           scrolltxt += " ***** " + r.text;  
         }  
         var model = new LoggedInUserTimelineViewModel { TimelineContent = scrolltxt, Handle = handle };  
         return View("TwickrMain", model);  
       }  
       catch (Exception e) { }  
       return View("TwickrMain");  
     }  

Next, using Newtonsoft,Json JsonConvert() function, we deserialize the JSON response and zero in on the 'text' property of each entity (tweet) in the array of JSON results (tweets).

And finally, using some basic Bootstrap HTML, JavaScript and CSS we are able to wire up a very simple, but effective app that interacts with the Twitter API in real-time.

Reference: https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline.html

Where can we find the data?

There are myriad resources to get data from a variety of domains (insurance, population, health, geography, weather, sports, etc.). You can get the data in .csv form or through API calls.

Here are a few to jump-start your data-oriented application:

Financial: https://fred.stlouisfed.org/search?st=csv

Baseball: http://www.baseball-databank.org/

Soccer: https://www.soccer24.com/team/apia-tigers/84SKUunL/

Government: https://www.data.gov/

Public: https://github.com/awesomedata/awesome-public-datasets

GIS: https://gisgeography.com/best-free-gis-data-sources-raster-vector/

Google Maps API: https://developers.google.com/maps/documentation/directions/


Reference: https://www.quora.com/What-is-the-best-financial-data-source-in-CSV-file-format