Veebirakenduste loomine API päringute abil

Saame valida, millist juba valmismalli kasutame. Võtame juba loodud kontrolleri koos API otspunktiga.

Paneme nimeks “veeb“.

Loome kontrolleri malli ning võimaldame kasutada ka Swaggerit (OpenAPI).

Käivitamine

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherController> _logger;

        public WeatherController(ILogger<WeatherController> logger)
        {
            _logger = logger;
        }

        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

Näide

Esmaste API päringute tegemine

Teeme esimesi päringuid.

Tee esimene avalik API otspunkt, milleks on “hello-world”.

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class PrimitiividController : ControllerBase
    {

        // GET: primitiivid/hello-world
        [HttpGet("hello-world")]
        public string HelloWorld()
        {
            return "Hello world at " + DateTime.Now;
        }

    }
}

Näited API meetoditest

1. Lihtne meetod ilma parameetriteta

[HttpGet("hello-world")]
public string HelloWorld()
{
    return "Hello world at " + DateTime.Now;
}

  • Tagastab tervituse koos jooksva kuupäevaga.

2. Meetod ühe string-parameetriga

[HttpGet("hello-variable/{nimi}")]
public string HelloVariable(string nimi)
{
    return "Hello " + nimi;
}

  • Võtab URL-ist parameetri nimi ja tagastab isikliku tervituse.

3. Meetod mitme arvulise parameetriga

[HttpGet("add/{nr1}/{nr2}")]
public int AddNumbers(int nr1, int nr2)
{
    return nr1 + nr2;
}

[HttpGet("multiply/{nr1}/{nr2}")]
public int Multiply(int nr1, int nr2)
{
    return nr1 * nr2;
}

  • Teostab liitmise ja korrutamise.

4. Meetod ilma tagastust väärtuseta (void)

[HttpGet("do-logs/{arv}")]
public void DoLogs(int arv)
{
    for (int i = 0; i &lt; arv; i++)
    {
        Console.WriteLine("See on logi nr " + i);
    }
}

  • Väljastab konsooli logisõnumeid määratud arv kordi.

Tagastus uue avanenud terminali aknas (avaneb peale käivitamist automaatselt):

Mudeli koostamine

Pane kausta nimeks “Models”

  1. Äsjaloodud kausta parem klõps
  2. Vali “Add”
  3. Avanenud vaates vali “New item…”
  4. Vali C# class (paremal on kirjas An empty class declaration)

Lisa uude mudelisse järgnev kood:

namespace veeb.models;

public class Toode
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public bool IsActive { get; set; }

    public Toode(int id, string name, double price, bool isActive)
    {
        Id = id;
        Name = name;
        Price = price;
        IsActive = isActive;
    }
}

API päringud mudeliga

Uue faili loomiseks vajuta kausta “Controllers” kausta peal parema klõpsuga, vali “add” ning võta “New Item…”. Pane loodud faili nimeks ToodeController.cs ning vali tühja API kontrolleri mall (API Controller – Empty).

Faili sisu on alguses järgnev:

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ToodeController : ControllerBase
    {
    }
}

Loo siia klassi uus toode, imiteerimaks andmebaasist kättesaadavat toodet.

using Microsoft.AspNetCore.Mvc;
using veeb.models;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ToodeController : ControllerBase
    {
        private static Toode _toode = new Toode(1, "Koola", 1.5, true);

    }
}

Teeme kontrollerile API otspunkti, mis annab eerakendusele (meie mõistes brauseris kättesaadavaks) vastloodud toote.

using Microsoft.AspNetCore.Mvc;
using veeb.models;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ToodeController : ControllerBase
    {
        private static Toode _toode = new Toode(1, "Koola", 1.5, true);

        // GET: toode
        [HttpGet]
        public Toode GetToode()
        {
            return _toode;
        }
    }
}

Näide (toode):

Tee uus API otspunkt, millega on võimalik hinda 1 euro võrra suurendada.

using Microsoft.AspNetCore.Mvc;
using veeb.models;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ToodeController : ControllerBase
    {
        private static Toode _toode = new Toode(1, "Koola", 1.5, true);

        // GET: toode
        [HttpGet]
        public Toode GetToode()
        {
            return _toode;
        }

        // GET: toode/suurenda-hinda
        [HttpGet("suurenda-hinda")]
        public Toode SuurendaHinda()
        {
            _toode.Price = _toode.Price + 1;
            return _toode;
        }
    }
}

Näide (toode/suurenda-hinda):

API päringud mudeli ja listiga

Kui varasemalt tegelesime ühe mudeliga, siis võtame seekord kasutusele mudelite listi. Teeme valmis toote kontrolleri, millele paneme nimeks “TootedController“.

Uue faili loomiseks vajuta kausta “Controllers” kausta peal parema klõpsuga, vali “add” ning võta “New Item…”. Pane loodud faili nimeks ToodeController.cs ning vali tühja API kontrolleri mall (API Controller – Empty).

using Microsoft.AspNetCore.Mvc;
using veebirakendus.models;

namespace veebirakendus.Controllers;

[ApiController]
[Route("[controller]")]
public class TootedController
{
    private static List<Toode> _tooted = new List<Toode>{
        new Toode(1,"Koola", 1.5, true),
        new Toode(2,"Fanta", 1.0, false),
        new Toode(3,"Sprite", 1.7, true),
        new Toode(4,"Vichy", 2.0, true),
        new Toode(5,"Vitamin well", 2.5, true)
        };
    

    // https://localhost:7052/tooted
    [HttpGet]
    public List<Toode> Get()
    {
        return _tooted;
    }
    
    [HttpGet("kustuta/{index}")]
    public List<Toode> Delete(int index)
    {
        _tooted.RemoveAt(index);
        return _tooted;
    }
    
    [HttpGet("kustuta2/{index}")]
    public string Delete2(int index)
    {
        _tooted.RemoveAt(index);
        return "Kustutatud!";
    }
    
    [HttpGet("lisa/{id}/{nimi}/{hind}/{aktiivne}")]
    public List<Toode> Add(int id, string nimi, double hind, bool aktiivne)
    {
        Toode toode = new Toode(id, nimi, hind, aktiivne);
        _tooted.Add(toode);
        return _tooted;
    }
    
    [HttpGet("lisa")] // GET /tooted/lisa?id=1&nimi=Koola&hind=1.5&aktiivne=true
    public List<Toode> Add2([FromQuery] int id, [FromQuery] string nimi, [FromQuery] double hind, [FromQuery] bool aktiivne)
    {
        Toode toode = new Toode(id, nimi, hind, aktiivne);
        _tooted.Add(toode);
        return _tooted;
    }
    
    [HttpGet("hind-dollaritesse/{kurss}")] // GET /tooted/hind-dollaritesse/1.5
    public List<Toode> Dollaritesse(double kurss)
    {
        for (int i = 0; i < _tooted.Count; i++)
        {
            _tooted[i].Price = _tooted[i].Price * kurss;
        }
        return _tooted;
    }

    // või foreachina:

    [HttpGet("hind-dollaritesse2/{kurss}")] // GET /tooted/hind-dollaritesse2/1.5
    public List<Toode> Dollaritesse2(double kurss)
    {
        foreach (var t in _tooted)
        {
            t.Price = t.Price * kurss;
        }

        return _tooted;
    }
}

Näide:

Eesliidese implementeerimine

App.js faili kirjuta järgnev sisu:

import { useEffect, useRef, useState } from 'react';
import './App.css';

function App() {
  const [tooted, setTooted] = useState([]);

  useEffect(() => {
    fetch("https://localhost:4444/tooted")
      .then(res => res.json())
      .then(json => setTooted(json));
  }, []);

  return (
    <div className="App">
      {tooted.map(toode => 
        <div>
          <div>{toode.id}</div>
          <div>{toode.name}</div>
          <div>{toode.price.toFixed(2)}</div>
        </div>)}
    </div>
  );
}

export default App;

Lisame järgmised read Program.cs faili

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseCors(options => options
    .WithOrigins("*")
    .AllowAnyMethod()
    .AllowAnyHeader()
);

app.UseAuthorization();

app.MapControllers();

app.Run();

App.js faili kirjuta järgnev sisu:

import { useEffect, useRef, useState } from 'react';
import './App.css';

function App() {
  const [tooted, setTooted] = useState([]);
  const idRef = useRef();
  const nameRef = useRef();
  const priceRef = useRef();
  const isActiveRef = useRef();
  const [isUsd, setUsd] = useState(false);

  useEffect(() => {
    fetch("https://localhost:4444/tooted")
      .then(res => res.json())
      .then(json => setTooted(json));
  }, []);

  function kustuta(index) {
    fetch("https://localhost:4444/tooted/kustuta/" + index)
      .then(res => res.json())
      .then(json => setTooted(json));
  }

  function lisa() {
    fetch(`https://localhost:4444/tooted/lisa/${Number(idRef.current.value)}/${nameRef.current.value}/${Number(priceRef.current.value)}/${isActiveRef.current.checked}`)
      .then(res => res.json())
      .then(json => setTooted(json));
  }

  function dollariteks() {
    const kurss = 1.1;
    setUsd(true);
    fetch("https://localhost:4444/tooted/hind-dollaritesse/" + kurss)
      .then(res => res.json())
      .then(json => setTooted(json));
  }

  function eurodeks() {
    const kurss = 0.9091;
    setUsd(false);
    fetch("https://localhost:4444/tooted/hind-dollaritesse/" + kurss)
      .then(res => res.json())
      .then(json => setTooted(json));
  }

  return (
    <div className="App">
      <label>ID</label> <br />
      <input ref={idRef} type="number" /> <br />
      <label>name</label> <br />
      <input ref={nameRef} type="text" /> <br />
      <label>price</label> <br />
      <input ref={priceRef} type="number" /> <br />
      <label>isActive</label> <br />
      <input ref={isActiveRef} type="checkbox" /> <br />
      <button onClick={() => lisa()}>Lisa</button>
      {tooted.map((toode, index) => 
        <div>
          <div>{toode.id}</div>
          <div>{toode.name}</div>
          <div>{toode.price.toFixed(2)}</div>
          <button onClick={() => kustuta(index)}>x</button>
        </div>)}
      {isUsd === false && <button onClick={() => dollariteks()}>Muuda dollariteks</button>}
      {isUsd === true && <button onClick={() => eurodeks()}>Muuda eurodeks</button>}
    </div>
  );
}

export default App;

Parimad praktikad

Refaktoorime ehk teeme koodi ilusaks.

  1. CORS vaid pordile 3000

Tahame, et meie tagarakenduse koodile pääseme vaid meie oma eesrakendusega ligi. Piirame seda ainult meie pordile(Program.cs).

app.UseCors(options => options
    .WithOrigins("http://localhost:3000")
    .AllowAnyMethod()
    .AllowAnyHeader()
);

Kogu fail on seejärel järgnev(Program.cs):

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseCors(options => options
    .WithOrigins("http://localhost:3000")
    .AllowAnyMethod()
    .AllowAnyHeader()
);

app.UseAuthorization();

app.MapControllers();

app.Run();

TootedControler.cs

using Microsoft.AspNetCore.Mvc;
using veeb.models;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class TootedController : ControllerBase
    {
        private static List<Toode> _tooted = new()
        {
            new Toode(1,"Koola", 1.5, true),
            new Toode(2,"Fanta", 1.0, false),
            new Toode(3,"Sprite", 1.7, true),
            new Toode(4,"Vichy", 2.0, true),
            new Toode(5,"Vitamin well", 2.5, true)
        };

        // GET https://localhost:4444/tooted
        [HttpGet]
        public List<Toode> Get()
        {
            return _tooted;
        }

        // DELETE https://localhost:4444/tooted/kustuta/0
        [HttpDelete("kustuta/{index}")]
        public List<Toode> Delete(int index)
        {
            _tooted.RemoveAt(index);
            return _tooted;
        }

        [HttpDelete("kustuta2/{index}")]
        public string Delete2(int index)
        {
            _tooted.RemoveAt(index);
            return "Kustutatud!";
        }

        // POST https://localhost:4444/tooted/lisa/1/Coca/1.5/true
        [HttpPost("lisa/{id}/{nimi}/{hind}/{aktiivne}")]
        public List<Toode> Add(int id, string nimi, double hind, bool aktiivne)
        {
            Toode toode = new Toode(id, nimi, hind, aktiivne);
            _tooted.Add(toode);
            return _tooted;
        }

        [HttpPost("lisa2")]
        public List<Toode> Add2(int id, string nimi, double hind, bool aktiivne)
        {
            Toode toode = new Toode(id, nimi, hind, aktiivne);
            _tooted.Add(toode);
            return _tooted;
        }

        // PATCH https://localhost:4444/tooted/hind-dollaritesse/1.5
        [HttpPatch("hind-dollaritesse/{kurss}")] 
        public List<Toode> UpdatePrices(double kurss)
        {
            for (int i = 0; i < _tooted.Count; i++)
            {
                _tooted[i].Price = _tooted[i].Price * kurss;
            }
            return _tooted;
        }
    }
}

Peame muutma ka eesrakenduses lisamise korrektseks (tervikuna), muidu enam ühendus ei toimi(App.js)

import { useEffect, useRef, useState } from 'react';
import './App.css';

function App() {
  const [tooted, setTooted] = useState([]);
  const idRef = useRef();
  const nameRef = useRef();
  const priceRef = useRef();
  const isActiveRef = useRef();


  useEffect(() => {
    fetch("https://localhost:4444/tooted")
      .then(res => res.json())
      .then(json => setTooted(json));
  }, []);

  function kustuta(index) {
    fetch("https://localhost:4444/tooted/kustuta/" + index, {"method": "DELETE"})
      .then(res => res.json())
      .then(json => setTooted(json));
  }

  ////////////////////////
  function lisa() {
    const uusToode = {
      "id": Number(idRef.current.value),
      "name": nameRef.current.value,
      "price": Number(priceRef.current.value),
      "isActive": isActiveRef.current.checked
    }
    fetch("https://localhost:4444/tooted/lisa", {"method": "POST", "body": JSON.stringify(uusToode)})
      .then(res => res.json())
      .then(json => setTooted(json));
  }
  ////////////////////////

  function dollariteks() {
    const kurss = 1.1;
    fetch("https://localhost:4444/tooted/hind-dollaritesse/" + kurss, {"method": "PATCH"})
      .then(res => res.json())
      .then(json => setTooted(json));
  }

  return (
    <div className="App">
      <label>ID</label> <br />
      <input ref={idRef} type="number" /> <br />
      <label>Nimi</label> <br />
      <input ref={nameRef} type="text" /> <br />
      <label>Hind</label> <br />
      <input ref={priceRef} type="number" /> <br />
      <label>Aktiivne</label> <br />
      <input ref={isActiveRef} type="checkbox" /> <br />
      <button onClick={() => lisa()}>Lisa</button>
      {tooted.map((toode, index) => 
        <div>
          <div>{toode.id}</div>
          <div>{toode.name}</div>
          <div>{toode.price}</div>
          <button onClick={() => kustuta(index)}>x</button>
        </div>)}
      <button onClick={() => dollariteks()}>Muuda dollariteks</button>
    </div>
  );
}

export default App;

Näide:

Iseseisev harjutus:

  • Tee tagarakendusse uus API otspunkt, mis muudab toodet. Kasuta PUT päringu tüüpi. Eesrakenduses pole midagi lisada vaja.

API päring teise rakendusse: pakiautomaatide kättesaamine

  1. Teeme uue kontrolleri

Pane nimeks ParcelMachineController.

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ParcelMachineController : ControllerBase
    {
        
    }
}
  1. Teeme API otspunkti

Meile tagastatakse sõna “PAKIAUTOMAADID”.

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ParcelMachineController : ControllerBase
    {
        
        [HttpGet]
        public string GetParcelMachines()
        {
            return "PAKIAUTOMAADID";
        }
    }
}
  1. Lisame HttpClienti

Selleks, et võõrasse rakendusse päringuid teha, peame seda tegema HttpClient abil.

Lisa järgnev lõik Program.cs faili, mis võimaldab rakendusega HttpClient võimalused siduda.

builder.Services.AddHttpClient();

Lõplik Program.cs fail on järgnev:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddHttpClient();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseCors(options => options
    .WithOrigins("*")
    .AllowAnyMethod()
    .AllowAnyHeader()
);

app.UseAuthorization();

app.MapControllers();

app.Run();

IActionResult tagastuses tähendab HttpClient päringu vastust.

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ParcelMachineController : ControllerBase
    {
        private readonly HttpClient _httpClient;

        public ParcelMachineController(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }
        
        [HttpGet]
        public async Task<IActionResult> GetParcelMachines()
        {
            var response = await _httpClient.GetAsync("https://www.omniva.ee/locations.json");
            var responseBody = await response.Content.ReadAsStringAsync();
            return Content(responseBody, "application/json");
        }
    }
}

Näita pakiautomaate Reactis

import { useEffect, useState } from 'react';
import './App.css';

function App() {
  const [pakiautomaadid, setPakiautomaadid] = useState([]);

  useEffect(() => {
    fetch("https://localhost:4444/parcelmachine")
      .then(res => res.json())
      .then(json => setPakiautomaadid(json));
  }, []);

  return (
    <div className="App">
      <select>
        {pakiautomaadid.map(automaat => 
            <option>
                {automaat.NAME}
            </option>)}
      </select>
    </div>
  );
}

export default App;

Näide:

API päring teise rakendusse: Elering hindade kättesaamine

  1. Teeme uue kontrolleri

Controllers kaustale parem klõps -> Add -> New Item -> API Controller – Empty

Nimeks paneme NordpoolController

using Microsoft.AspNetCore.Mvc;

namespace veeb.Controllers
{
    [Route("[controller]")]
[ApiController]
public class NordpoolController : ControllerBase
{
    private readonly HttpClient _httpClient;

    public NordpoolController(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    [HttpGet]
    public async Task<IActionResult> GetNordpoolPrices()
    {
        var response = await _httpClient.GetAsync("https://dashboard.elering.ee/api/nps/price");
        var responseBody = await response.Content.ReadAsStringAsync();
        return Content(responseBody, "application/json");
    }
}
}

Näita NordPooli hindu Reactis

import { useEffect, useState } from 'react';
import './App.css';

function App() {
  const [fi, setFi] = useState([]);
  const [ee, setEe] = useState([]);
  const [lv, setLv] = useState([]);
  const [lt, setLt] = useState([]);

  useEffect(() => {
    fetch("https://localhost:4444/nordpool")
      .then(res => res.json())
      .then(json => {
        setFi(json.data.fi);
        setEe(json.data.ee)
        setLv(json.data.lv)
        setLt(json.data.lt)
      });
  }, []);

  return (
    <div>
      <table style={{marginLeft: "100px"}}>
        <thead>
          <th style={{border: "1px solid #ddd", padding: "12px", backgroundColor: "#04AA6D"}}>Ajatempel</th>
          <th style={{border: "1px solid #ddd", padding: "12px", backgroundColor: "#04AA6D"}}>Hind</th>
        </thead>
        <tbody>
          <div style={{position: "absolute", left: "30px"}}>Soome</div>
          {fi.map(data => 
          <tr key={data.timestamp}>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{new Date(data.timestamp * 1000).toISOString()}</td>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{data.price}</td>
          </tr>)}
          <div style={{position: "absolute", left: "30px"}}>Eesti</div>
          {ee.map(data => 
          <tr key={data.timestamp}>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{new Date(data.timestamp * 1000).toISOString()}</td>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{data.price}</td>
          </tr>)}
          <div style={{position: "absolute", left: "30px"}}>Läti</div>
          {lv.map(data => 
          <tr key={data.timestamp}>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{new Date(data.timestamp * 1000).toISOString()}</td>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{data.price}</td>
          </tr>)}
          <div style={{position: "absolute", left: "30px"}}>Leedu</div>
          {lt.map(data => 
          <tr key={data.timestamp}>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{new Date(data.timestamp * 1000).toISOString()}</td>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{data.price}</td>
          </tr>)}
        </tbody>
      </table>
    </div>
  );
}

export default App;

Näide:

API päring teise rakendusse: Elering päringu modifitseerimine

  1. Eesrakendus soovib API otspunkti konfigureerida selliseks, et saadetakse kaasa “ee”, “lv”, “lt” või “fi” parameeter ning näidatakse selle riigi hindasid. Teeme.

Eesrakendus on järgnev:

import { useEffect, useState } from 'react';
import './App.css';

function App() {
  const [prices, setPrices] = useState([]);
  const [chosenCountry, setChosenCountry] = useState("ee");

  useEffect(() => {
    fetch("https://localhost:4444/nordpool/" + chosenCountry)
      .then(res => res.json())
      .then(json => {
        setPrices(json);
      });
  }, [chosenCountry]);

  return (
    <div>
      <button onClick={() => setChosenCountry("fi")}>Soome</button>
      <button onClick={() => setChosenCountry("ee")}>Eesti</button>
      <button onClick={() => setChosenCountry("lv")}>Läti</button>
      <button onClick={() => setChosenCountry("lt")}>Leedu</button>
      <table style={{marginLeft: "100px"}}>
        <thead>
          <th style={{border: "1px solid #ddd", padding: "12px", backgroundColor: "#04AA6D"}}>Ajatempel</th>
          <th style={{border: "1px solid #ddd", padding: "12px", backgroundColor: "#04AA6D"}}>Hind</th>
        </thead>
        <tbody>
          <div style={{position: "absolute", left: "30px"}}>{chosenCountry}</div>
          {prices.map(data => 
          <tr key={data.timestamp}>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{new Date(data.timestamp * 1000).toISOString()}</td>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{data.price}</td>
          </tr>)}
        </tbody>
      </table>
    </div>
  );
}

export default App;

Seega tagarakenduse peame tegema selliseks, mis parameetri kaasa võtaks:

using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class NordpoolController : ControllerBase
    {

        private readonly HttpClient _httpClient;

        public NordpoolController(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        [HttpGet("{country}")]
        public async Task<IActionResult> GetNordPoolPrices(string country)
        {
            var response = await _httpClient.GetAsync("https://dashboard.elering.ee/api/nps/price");
            var responseBody = await response.Content.ReadAsStringAsync();
            var jsonDoc = JsonDocument.Parse(responseBody);
            var dataProperty = jsonDoc.RootElement.GetProperty("data");

            string prices;

            switch (country)
            {
                case "ee":
                    prices = dataProperty.GetProperty("ee").ToString();
                    return Content(prices, "application/json");

                case "lv":
                    prices = dataProperty.GetProperty("lv").ToString();
                    return Content(prices, "application/json");

                case "lt":
                    prices = dataProperty.GetProperty("lt").ToString();
                    return Content(prices, "application/json");

                case "fi":
                    prices = dataProperty.GetProperty("fi").ToString();
                    return Content(prices, "application/json");

                default:
                    return BadRequest("Invalid country code.");
            }
        }
    }
}

Näide:

2. Eesrakendus näitab kuupäevasid peale vajutades näidatakse selle kuupäeva hindasid. Meie ülesanne on eesrakendusel seda võimaldada, võttes eesrakendusest vastu kuupäeva ning saate selle Elering API otspunktile.

import { useRef } from 'react';
import { useEffect, useState } from 'react';
import './App.css';

function App() {
  const [prices, setPrices] = useState([]);
  const [chosenCountry, setChosenCountry] = useState("ee");
  const [start, setStart] = useState("");
  const [end, setEnd] = useState("");
  const startRef = useRef();
  const endRef = useRef();

  useEffect(() => {
    if (start !== "" && end !== "") {
      fetch("https://localhost:4444/nordpool/" + chosenCountry + "/" + start + "/" + end)
        .then(res => res.json())
        .then(json => {
          setPrices(json);
        });
    }
  }, [chosenCountry, start, end]);

  function updateStart() {
    const startIso = new Date(startRef.current.value).toISOString();
    setStart(startIso);
  }

  function updateEnd() {
    const endIso = new Date(endRef.current.value).toISOString();
    setEnd(endIso);
  }

  return (
    <div>
      <button onClick={() => setChosenCountry("fi")}>Soome</button>
      <button onClick={() => setChosenCountry("ee")}>Eesti</button>
      <button onClick={() => setChosenCountry("lv")}>Läti</button>
      <button onClick={() => setChosenCountry("lt")}>Leedu</button>
      <input ref={startRef} onChange={updateStart} type="datetime-local" />
      <input ref={endRef} onChange={updateEnd} type="datetime-local" />
      {prices.length > 0 && 
      <table style={{marginLeft: "100px"}}>
        <thead>
          <th style={{border: "1px solid #ddd", padding: "12px", backgroundColor: "#04AA6D"}}>Ajatempel</th>
          <th style={{border: "1px solid #ddd", padding: "12px", backgroundColor: "#04AA6D"}}>Hind</th>
        </thead>
        <tbody>
          <td style={{position: "absolute", left: "30px"}}>{chosenCountry}</td>
          {prices.map(data => 
          <tr key={data.timestamp}>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{new Date(data.timestamp * 1000).toISOString()}</td>
            <td style={{border: "1px solid #ddd", padding: "8px"}}>{data.price}</td>
          </tr>)}
        </tbody>
      </table>}
    </div>
  );
}

export default App;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

namespace veeb.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class NordpoolController : ControllerBase
    {

        private readonly HttpClient _httpClient;

        public NordpoolController(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        [HttpGet("{country}/{start}/{end}")]
        public async Task<IActionResult> GetNordPoolPrices(
            string country,
            string start,
            string end)
        {
            var response = await _httpClient.GetAsync(
                $"https://dashboard.elering.ee/api/nps/price?start={start}&end={end}");
            var responseBody = await response.Content.ReadAsStringAsync();
            Console.WriteLine(responseBody);

            var jsonDoc = JsonDocument.Parse(responseBody);
            var dataProperty = jsonDoc.RootElement.GetProperty("data");

            string prices;

            switch (country)
            {
                case "ee":
                    prices = dataProperty.GetProperty("ee").ToString();
                    Console.WriteLine(responseBody);

                    return Content(prices, "application/json");

                case "lv":
                    prices = dataProperty.GetProperty("lv").ToString();
                    return Content(prices, "application/json");

                case "lt":
                    prices = dataProperty.GetProperty("lt").ToString();
                    return Content(prices, "application/json");

                case "fi":
                    prices = dataProperty.GetProperty("fi").ToString();
                    return Content(prices, "application/json");

                default:
                    return BadRequest("Invalid country code.");
            }
        }
    }
}

Näide:

API päring teise rakendusse: Makse

Loome Controllers/PaymentController.cs ja kirjutame sinna sisse näiteks:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

namespace VeebTARpv23.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class PaymentController : ControllerBase
    {
        private readonly HttpClient _httpClient;

        public PaymentController(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        [HttpGet("{sum}")]
        public async Task<IActionResult> MakePayment(string sum)
        {
            var paymentData = new
            {
                api_username = "e36eb40f5ec87fa2",
                account_name = "EUR3D1",
                amount = sum,
                order_reference = Math.Ceiling(new Random().NextDouble() * 999999),
                nonce = $"a9b7f7e7as{DateTime.Now}{new Random().NextDouble() * 999999}",
                timestamp = DateTime.Now,
                customer_url = "https://maksmine.web.app/makse"
            };

            var json = JsonSerializer.Serialize(paymentData);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "ZTM2ZWI0MGY1ZWM4N2ZhMjo3YjkxYTNiOWUxYjc0NTI0YzJlOWZjMjgyZjhhYzhjZA==");

            var response = await client.PostAsync("https://igw-demo.every-pay.com/api/v4/payments/oneoff", content);

            if (response.IsSuccessStatusCode)
            {
                var responseContent = await response.Content.ReadAsStringAsync();
                var jsonDoc = JsonDocument.Parse(responseContent);
                var paymentLink = jsonDoc.RootElement.GetProperty("payment_link");
                return Ok(paymentLink);
            }
            else
            {
                return BadRequest("Payment failed.");
            }
        }
    }
}

Näide:

Läheme Postman sisse ja teeme GET päring

Saame näiteks sellis URL: https://payment.sandbox.lhv.ee/lp/q2zaxyd8q6/nXjxSePYOG

Läheme selle URL siise ja saame:

Võtame mis tahes panga, ma võttan LHV:

Siit me näeme, et on Sandbox võttame seda:

Võtame mis tahes kasutaja ja ma võttan Smart-ID ja siis lihtsalt klikkime Confirm

Ootame kuni ta töötleb selle tulemuse:

Tulemuseks me saame:

postman