# Developing the API endpoints

# START FROM PREVIOUS MODULE'S END

Developing the API Data access

# ADD APIMODELS TO DOMAIN

namespace ChinookASPNETWebAPI.Domain.ApiModels;

public class AlbumApiModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int ArtistId { get; set; }
    public string ArtistName { get; set; }

    public ArtistApiModel Artist { get; set; }

    public IList<TrackApiModel> Tracks { get; set; }
}

# ADD IConvertModel TO DOMAIN

namespace Chinook.Domain.Converters;

public interface IConvertModel<out TTarget>
{
    TTarget Convert();
}

# ADD ConvertExtensions TO DOMAIN

using Chinook.Domain.Converters;

namespace Chinook.Domain.Extensions;

public static class ConvertExtensions
{
    public static IEnumerable<TTarget> ConvertAll<TTarget>(
        this IEnumerable<IConvertModel<TTarget>> values)
        => values.Select(value => value.Convert());
}

# ADD CONVERT CODE APIMODELS IN DOMAIN

using Chinook.Domain.Converters;
using Chinook.Domain.Entities;

namespace ChinookASPNETWebAPI.Domain.ApiModels;

public class AlbumApiModel : IConvertModel<Album>
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int ArtistId { get; set; }
    public string ArtistName { get; set; }

    public ArtistApiModel Artist { get; set; }

    public IList<TrackApiModel> Tracks { get; set; }

    public Album Convert() =>
        new()
        {
            Id = Id,
            ArtistId = ArtistId,
            Title = Title ?? string.Empty
        };
}

# ADD CONVERT CODE ENTITIES IN DOMAIN

using Chinook.Domain.Converters;
using ChinookASPNETWebAPI.Domain.ApiModels;

namespace Chinook.Domain.Entities;

public partial class Album : IConvertModel<AlbumApiModel>
{
    public Album()
    {
        Tracks = new HashSet<Track>();
    }

    public int Id { get; set; }
    public string Title { get; set; } = null!;
    public int ArtistId { get; set; }

    public virtual Artist Artist { get; set; } = null!;
    public virtual ICollection<Track> Tracks { get; set; }

    public AlbumApiModel Convert() =>
        new()
        {
            Id = Id,
            ArtistId = ArtistId,
            Title = Title
        };
}

# ADD SUPERVISOR TO DOMAIN

Take a look at the code here for the logic of the Supervisor

# ADD APPSETTINGS TO API PROJECT

# ADD SERVICESCONFIGURATION TO API PROJECT

using Chinook.Domain.Repositories;
using Chinook.Domain.Supervisor;
using Chinook.Data.Repositories;

namespace Chinook.API.Configurations;

public static class ServicesConfiguration
{
    public static void ConfigureRepositories(this IServiceCollection services)
    {
        services.AddScoped<IAlbumRepository, AlbumRepository>()
            .AddScoped<IArtistRepository, ArtistRepository>()
            .AddScoped<ICustomerRepository, CustomerRepository>()
            .AddScoped<IEmployeeRepository, EmployeeRepository>()
            .AddScoped<IGenreRepository, GenreRepository>()
            .AddScoped<IInvoiceRepository, InvoiceRepository>()
            .AddScoped<IInvoiceLineRepository, InvoiceLineRepository>()
            .AddScoped<IMediaTypeRepository, MediaTypeRepository>()
            .AddScoped<IPlaylistRepository, PlaylistRepository>()
            .AddScoped<ITrackRepository, TrackRepository>();
    }

    public static void ConfigureSupervisor(this IServiceCollection services)
    {
        services.AddScoped<IChinookSupervisor, ChinookSupervisor>();
    }
}

# ADD ConfigureRepositories() AND ConfigureSupervisor() TO CONFIGURESERVICES IN API PROJECT

builder.Services.ConfigureRepositories();
builder.Services.ConfigureSupervisor();

# ADD CONTROLLERS TO API

# ADD ACTIONS TO CONTROLLERS

using System.Net;
using Chinook.Domain.ApiModels;
using Chinook.Domain.Supervisor;
using Microsoft.AspNetCore.Mvc;

namespace Chinook.API.Controllers;

//[Authorize]
[Route("api/[controller]")]
[ApiController]
public class AlbumController : ControllerBase
{
    private readonly IChinookSupervisor _chinookSupervisor;
    private readonly ILogger<AlbumController> _logger;

    public AlbumController(IChinookSupervisor chinookSupervisor, ILogger<AlbumController> logger)
    {
        _chinookSupervisor = chinookSupervisor;
        _logger = logger;
    }

    [HttpGet]
    [Produces(typeof(List<AlbumApiModel>))]
    public async Task<ActionResult<List<AlbumApiModel>>> Get()
    {
        var albums = await _chinookSupervisor.GetAllAlbum();

        if (albums.Any())
        {
            return Ok(albums);
        }
        else
        {
            return StatusCode((int)HttpStatusCode.NotFound, "No Albums Could Be Found");
        }
    }

    [HttpGet("{id}", Name = "GetAlbumById")]
    public async Task<ActionResult<AlbumApiModel>> Get(int id)
    {
        var album = await _chinookSupervisor.GetAlbumById(id);

        if (album != null)
        {
            return Ok(album);
        }
        else
        {
            return StatusCode((int)HttpStatusCode.NotFound, "Album Not Found");
        }
    }

    [HttpPost]
    [Produces("application/json")]
    [Consumes("application/json")]
    public async Task<ActionResult<AlbumApiModel>> Post([FromBody] AlbumApiModel input)
    {
        if (input == null)
        {
            return StatusCode((int)HttpStatusCode.BadRequest, "Given Album is null");
        }
        else
        {
            return Ok(await _chinookSupervisor.AddAlbum(input));
        }
    }

    [HttpPut("{id}")]
    [Produces("application/json")]
    [Consumes("application/json")]
    public async Task<ActionResult<AlbumApiModel>> Put(int id, [FromBody] AlbumApiModel input)
    {
        if (input == null)
        {
            return StatusCode((int)HttpStatusCode.BadRequest, "Given Album is null");
        }
        else
        {
            return Ok(await _chinookSupervisor.UpdateAlbum(input));
        }
    }

    [HttpDelete("{id}")]
    public async Task<ActionResult> Delete(int id)
    {
        return Ok(await _chinookSupervisor.DeleteAlbum(id));
    }

    [HttpGet("artist/{id}")]
    public async Task<ActionResult<List<AlbumApiModel>>> GetByArtistId(int id)
    {
        var albums = await _chinookSupervisor.GetAlbumByArtistId(id);

        if (albums.Any())
        {
            return Ok(albums);
        }
        else
        {
            return StatusCode((int)HttpStatusCode.NotFound, "No Albums Could Be Found for the Artist");
        }
    }
}

# ADD LOGGING TO API PROJECT Add Logging to API Project ServicesConfiguration class

public static void AddAPILogging(this IServiceCollection services)
{
    services.AddLogging(builder => builder
        .AddConsole()
        .AddFilter(level => level >= LogLevel.Information)
    );
    
    services.AddHttpLogging(logging =>
    {
        // Customize HTTP logging.
        logging.LoggingFields = HttpLoggingFields.All;
        logging.RequestHeaders.Add("My-Request-Header");
        logging.ResponseHeaders.Add("My-Response-Header");
        logging.MediaTypeOptions.AddText("application/javascript");
        logging.RequestBodyLogLimit = 4096;
        logging.ResponseBodyLogLimit = 4096;
    });
}

# ADD AddAPILogging TO PROGRAM IN API PROJECT

builder.Services.AddAPILogging();

# CHANGE LAUNCHSETTINGS

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:46460",
      "sslPort": 44369
    }
  },
  "profiles": {
    "Chinook.API": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "api/",
      "applicationUrl": "https://localhost:7211;http://localhost:5211",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}