.NET Core REST API Notes

In the realm of enterprise software, two programming languages have dominated: C# (c sharp) and Java. Java has a runtime environment – which must be installed on computers that want to run Java code – called the JVM, and likewise C# has a runtime environment called .NET. I have a lot of experience with Java/JVM, but not as much with C#/.NET. Of the two languages, Java is probably more popular. This is likely (at least in part) due to the fact that Java and the JVM were open source while C#/.NET’s source code had been Microsoft’s property and closed to the public.

Since June 2016, a version of .NET has been available as open source software. That version is .NET Core (.NET Framework is the closed source relative). After learning about the open source release, I wanted to work with the C#/.NET system. Here, I’m going to document my notes on building a simple REST API connected to an SQL database – in this case, PostgreSQL (which is case sensitive, and that matters).

Installation

Installation of .NET Core is pretty easy. Here’s a link to Microsoft’s website with details for different operation systems:

https://docs.microsoft.com/en-us/dotnet/core/install

Starting the Project

To start a new .NET Core REST API, we can issue a single command. After the command runs, we’ll have a C#/.NET project scaffold in our project directory.

dotnet new webapi -o [project-name]
ls [project-name]
appsettings.Development.json
bin
[project-name].csproj
Program.cs
Startup.cs
appsettings.json
Controllers
obj
Properties
WeatherForecast.cs

To start the application, we can issue this command:

dotnet run
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to https://localhost:5001 on the IPv6 loopback interface: 'Cannot assign requested address'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Cannot assign requested address'.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app

HTTPS/HTTP and CORS

By default the application is configured for HTTPS. I’ll be hosting my project from a container service which will provide the HTTPS. So to make things easier, I’ll turn off HTTPS. To do this first specify the listen addresses (with port number), then tell the program not to redirect to HTTPS in Startup.cs.

Specify Listen Addresses

In Program.cs, call the UseUrls method on the WebBuilder object to specify the server’s listen addresses.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseUrls("http://+:5000");
                webBuilder.UseStartup<Startup>();
            });
}

In Startup.cs, simply comment out or remove the line in the Configure method with the call to app.UseHttpsRedirection.

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "lists_api v1"));
    }

    // app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Add CORS Policy

Add the following policy to the ConfigureService method in the Startup.cs class.

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "VtagApi", Version = "v1" });
            });

            services.AddCors(o => o.AddPolicy("AllowAll", builder =>
            {
                builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
            }));
        }

Apply CORS Policy

Call app.UseCors method to use AllowAll policy.

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "VtagApi v1"));
            }
            // app.UseHttpsRedirection();

            app.UseCors("AllowAll");

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

HTTP Requests and Responses

Entity Framework Core

Entity Framework Core is an Object Relational Mapping (ORM) tool that maps database entities to C# objects.

Case Sensitive Table Column Names

Install MongoDB Driver

dotnet add [ProjectName].csproj package MongoDB.Driver

Column/Property Value Converters

Often times, our C# and database data types don’t quite match up. Using a string for a VARCHAR, works “out of the box” with the EF, but matching enumerated types from the database is a bit trickier. We’ll also look at converting a TEXT type from the database into a C# List<string>. With this conversion in place we can store and work with CSV strings.

Namespaces

This section contains information about important Namespaces using in the creation of the REST API application.

Annotations

System.ComponentModel.DataAnnotations.Schema

  • Table – directs a Model class to use specified database table.
namespace MyApi
{
    [Table("entities")]
    public class Entity
    {
        // Model class defined here.
    }
}
  • Column – specify which column the Model property is mapped to.
namespace MyApi
{
    [Table("entities")]
    public class Entity
    {
        [Column("size")]
        public int Size { get; set; }

        // Model class defined here.
    }
}
  • NotMapped – tell Entity Framework not to map a property/column.
namespace MyApi
{
    [Table("entities")]
    public class Entity
    {
        [NotMapped]
        public int Name { get; set; }

        // Model class defined here.
    }
}

Docker

Using Docker with .NET Core apps is pretty simple.

Leave a Reply

Your email address will not be published. Required fields are marked *