avatarsimbu

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

6056

Abstract

class="hljs-keyword">record</span> <span class="hljs-title">Recipe</span>(<span class="hljs-params"><span class="hljs-built_in">string</span> Title, <span class="hljs-built_in">string</span> Link, <span class="hljs-built_in">string</span> Source, TimeSpan Duration, <span class="hljs-built_in">string</span> Thumbnail</span>)</span> { }</pre></div><p id="a0bb">Fix the local port number in the docker launch settings</p><figure id="7bbf"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*Ds4ESUOGhQbnW3BW0e_5uA.png"><figcaption>Set a static port number in launch settings.</figcaption></figure><p id="1710">Run it with docker and test it works</p><figure id="76c0"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ifzECoR-rAMCUzGoUs3e4A.png"><figcaption>Swagger UI for local recipes API</figcaption></figure><p id="f112">If it does, click on the API link to view the swagger.json file and save it to disk.</p><h2 id="b8b1">Ta Da</h2><figure id="42d7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*cjTL7F3JZmWRE3E2fPwQNg.png"><figcaption>Listing recipes with Swagger</figcaption></figure><h2 id="ea31">Swagger OpenAPI Definition</h2><div id="92c3"><pre>{ <span class="hljs-string">"openapi"</span>: <span class="hljs-string">"3.0.1"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"info"</span>: { <span class="hljs-string">"title"</span>: <span class="hljs-string">"Recipies Api"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"description"</span>: <span class="hljs-string">"Recipe Management"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"version"</span>: <span class="hljs-string">"v1"</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"paths"</span>: { <span class="hljs-string">"/recipes"</span>: { <span class="hljs-string">"get"</span>: { <span class="hljs-string">"tags"</span>: [ <span class="hljs-string">"Recipes"</span> ]<span class="hljs-punctuation">,</span> <span class="hljs-string">"summary"</span>: <span class="hljs-string">"List Recipes."</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"description"</span>: <span class="hljs-string">"Gets a list of all Recipes."</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"operationId"</span>: <span class="hljs-string">"GetRecipes"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"responses"</span>: { <span class="hljs-string">"200"</span>: { <span class="hljs-string">"description"</span>: <span class="hljs-string">"Success"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"content"</span>: { <span class="hljs-string">"application/json"</span>: { <span class="hljs-string">"schema"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"array"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"items"</span>: { <span class="hljs-string">"ref"</span>: <span class="hljs-string">"#/components/schemas/Recipe"</span> } } } } } } } } }<span class="hljs-punctuation">,</span> <span class="hljs-string">"components"</span>: { <span class="hljs-string">"schemas"</span>: { <span class="hljs-string">"Recipe"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"object"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"properties"</span>: { <span class="hljs-string">"title"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"nullable"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"link"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"nullable"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"source"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"nullable"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"duration"</span>: { <span class="hljs-string">"ref"</span>: <span class="hljs-string">"#/components/schemas/TimeSpan"</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"thumbnail"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"nullable"</span>: <span class="hljs-literal">true</span> } }<span class="hljs-punctuation">,</span> <span class="hljs-string">"additionalProperties"</span>: <span class="hljs-literal">false</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"TimeSpan"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"object"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"properties"</span>: { <span class="hljs-string">"ticks"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"integer"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"int64"</span> }<span class="hljs-

Options

punctuation">,</span> <span class="hljs-string">"days"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"integer"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"int32"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"hours"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"integer"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"int32"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"milliseconds"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"integer"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"int32"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"minutes"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"integer"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"int32"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"seconds"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"integer"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"int32"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"totalDays"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"number"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"double"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"totalHours"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"number"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"double"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"totalMilliseconds"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"number"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"double"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"totalMinutes"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"number"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"double"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> }<span class="hljs-punctuation">,</span> <span class="hljs-string">"totalSeconds"</span>: { <span class="hljs-string">"type"</span>: <span class="hljs-string">"number"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"format"</span>: <span class="hljs-string">"double"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"readOnly"</span>: <span class="hljs-literal">true</span> } }<span class="hljs-punctuation">,</span> <span class="hljs-string">"additionalProperties"</span>: <span class="hljs-literal">false</span> } } } }</pre></div><h2 id="131e">BackBurner</h2><p id="30f3">I took a brief stab at looking at ways to scaffold .net core Web API’s and found <a href="https://wrapt.dev/docs/all-about-auth-in-dotnet-core">Wrapt</a>, but discounted for now after seeing the amount of code generated.</p><p id="f14f">I may be tempted to come back to it but want to experiment with other ways to scaffold API’s including using EF.</p><p id="79e2">The aim is to make adding new API endpoints easy whilst ensuring consistency and avoiding limiting the capabilities, more on this another time.</p><h2 id="b7d2">Links</h2><ul><li><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/overview?view=aspnetcore-7.0">Minimal API’s</a></li><li><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-7.0">Minimal API’s Quick Reference</a></li><li><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/openapi?view=aspnetcore-7.0">OpenAPI Support</a></li><li><a href="https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X">Swagger Annotations</a></li></ul></article></body>

Join Medium to view all my articles.

Flutter — Microsoft API Management secured with AD — Web API

In the previous article Flutter — Authentication we added support for an authentication service.

Now we turn our attention to implementing an authentication service starting with support for Microsoft technologies.

It is only the tip of the iceberg, the start of your journey; security configuration is always changing, has many parts and rarely has comprehensive guides.

Due to the complexity of the setup I’ve broken it into eight parts:

  1. Web API — Setting up your Web API with Visual Studio.
  2. APIM Service — Creating an API management service in Azure.
  3. Secure Gateway — Securing requests through the API gateway.
  4. MSAL — Authenticating your Flutter app on iOS.
  5. MSAL — Authenticating your Flutter app on Android.
  6. MSAL — Authenticating your Flutter app on the Web.
  7. Hosted API — Hosting your Web API’s in Azure.
  8. Secure Hosted API — Secure requests with the APIM Gateway

In this first article in the series we will create a minimal .Net API that returns a list of recipes.

Recipes API

You can use Visual Studio to create a minimal Web API without security.

Selecting c# Web API in Visual Studio
Naming web api
Additional Info used to create web api.

Add the Swashbuckle Annotations nugget package

Swashbuckle Annotations package.

Replace the program.cs file code with this:

using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Annotations;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddEndpointsApiExplorer();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Description = "Recipe Management",
        Title = "Recipies Api",
        Version = "v1"
    });
    options.EnableAnnotations();
});

var app = builder.Build();

// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Recipes Minimal API v1");

    });
}

app.UseHttpsRedirection();

// Recipes API

app.MapGet("/recipes", [SwaggerOperation(summary: "List Recipes.", description: "Gets a list of all Recipes.")] () =>
    {
        var recipes = new Recipe[]
        {
            new Recipe(
                "How to boil an egg", 
                "https://www.theguardian.com/lifeandstyle/2014/nov/11/how-to-boil-an-egg-the-heston-blumenthal-way", 
                "Heston Blumenthal", 
                TimeSpan.FromSeconds(630), 
                "https://i.guim.co.uk/img/static/sys-images/Guardian/Pix/pictures/2014/11/5/1415205733799/4bfbd71a-6cd0-4494-833f-eaaed20a15b3-1020x612.jpeg?width=620&quality=45&auto=format&fit=max&dpr=2&s=ca3a95d7e761d267eff1b79b58cc4849" )
        };
        return recipes;
    })
    .WithName("GetRecipes")
    .WithTags("Recipes");

app.Run();

internal record Recipe(string Title, string Link, string Source, TimeSpan Duration, string Thumbnail)
{
}

Fix the local port number in the docker launch settings

Set a static port number in launch settings.

Run it with docker and test it works

Swagger UI for local recipes API

If it does, click on the API link to view the swagger.json file and save it to disk.

Ta Da

Listing recipes with Swagger

Swagger OpenAPI Definition

{
  "openapi": "3.0.1",
  "info": {
    "title": "Recipies Api",
    "description": "Recipe Management",
    "version": "v1"
  },
  "paths": {
    "/recipes": {
      "get": {
        "tags": [
          "Recipes"
        ],
        "summary": "List Recipes.",
        "description": "Gets a list of all Recipes.",
        "operationId": "GetRecipes",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Recipe"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Recipe": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "nullable": true
          },
          "link": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "type": "string",
            "nullable": true
          },
          "duration": {
            "$ref": "#/components/schemas/TimeSpan"
          },
          "thumbnail": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "TimeSpan": {
        "type": "object",
        "properties": {
          "ticks": {
            "type": "integer",
            "format": "int64"
          },
          "days": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "hours": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "milliseconds": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "minutes": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "seconds": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "totalDays": {
            "type": "number",
            "format": "double",
            "readOnly": true
          },
          "totalHours": {
            "type": "number",
            "format": "double",
            "readOnly": true
          },
          "totalMilliseconds": {
            "type": "number",
            "format": "double",
            "readOnly": true
          },
          "totalMinutes": {
            "type": "number",
            "format": "double",
            "readOnly": true
          },
          "totalSeconds": {
            "type": "number",
            "format": "double",
            "readOnly": true
          }
        },
        "additionalProperties": false
      }
    }
  }
}

BackBurner

I took a brief stab at looking at ways to scaffold .net core Web API’s and found Wrapt, but discounted for now after seeing the amount of code generated.

I may be tempted to come back to it but want to experiment with other ways to scaffold API’s including using EF.

The aim is to make adding new API endpoints easy whilst ensuring consistency and avoiding limiting the capabilities, more on this another time.

Links

Flutter
Mobile App Development
Programming
Software Engineering
Technology
Recommended from ReadMedium