Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

.NET 8 – Minimal API’lar da Form Binding İşlemi

Merhaba,

Bu içeriğimizde .NET 8 ile Asp.NET Core mimarisinde minimal api’ler de form binding’e yönelik gelen yeniliğe dair odaklanacak ve bu destekle birlikte form kullanımı açısından MVC controller’larına olan bağımlılığın ortadan kaldırılması temellerinin nasıl atıldığını inceliyor olacağız.

Malumunuz, minimal api’ler HTML ile çalışmak için herhangi bir olanak sağlamamakta ve odak noktası olarak JSON türünden verileri üretmek ve tüketmek üzerine kurgulanmaktadır. Tabi bu şartlarda minimal api’ler de illa HTML içerikleri oluşturmak istiyor yahut böyle bir ihtiyaç doğrultusunda hareket etmeniz gerekiyorsa işte bu taktirde aşağıdaki gibi bir string tanımlamasıyla ihtiyacınızı giderebilirsiniz.

using System.Net.Mime;

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/", () =>
{
    string html = """
                  <!DOCTYPE html>
                  <html>
                      <head>
                        <title>Page Title</title>
                      </head>
                  <body>
                      <h1>This is a Heading</h1>
                      <p>This is a paragraph.</p>
                  </body>
                  </html>
                  """;

    return Results.Content(html, MediaTypeNames.Text.Html);
});

app.Run();

Amma velakin gelin görün ki, minimal api’ler de POST edilmiş olan form verilerini yakalamak(bind olmak) .NET 7 ve öncesinde pek mümkün değildir. Evet, post edilmiş olan form verilerini Razor Page ve controller’lar da rahatlıkla kullanabilirken, minimal api’ler de kullanamıyorduk. Tabi form’lardan gelecek olan multipart/form-data içerik türünden olan verileri IFormFile referansıyla bind edebiliyor ve hatta IFormFileCollection referansıyla da çoğul olarak karşılayabiliyorduk. Yani form binding yapılanması minimal api’ler açısından kısmen geçerlilik gösteriyordu.

Bunu hemen örneklendirmemiz gerekirse eğer;

using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
using System.Net.Mime;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAntiforgery();

var app = builder.Build();
app.UseAntiforgery();

app.MapGet("/", (IAntiforgery antiforgery, HttpContext context) =>
{
    var token = antiforgery.GetAndStoreTokens(context);
    string html = $"""
                      <form action="/upload-file" method="post" enctype="multipart/form-data">
                          <input name="{token.FormFieldName}" type="hidden" value="{token.RequestToken}" />
                          <input type="file" name="file">
                          <input type="submit" value="Gönder">
                      </form>
                  """;

    return Results.Content(html, MediaTypeNames.Text.Html, Encoding.UTF8);
});

app.MapPost("/upload-file", async ([FromForm] IFormFile file) =>
{
    return TypedResults.Ok(file);
});

app.Run();

Yukarıdaki kod bloğunu incelerseniz eğer 11 ile 23. satır aralığında form yapısı oluşturulurken bir yandan da CSRF/XSRF(Cross-Site Request Forgery) saldırılarına karşı Anti-forgery önlemi alınmaktadır. Bunun nedeni form submit edildiğinde bunu karşılayacak olan ‘upload-file’ endpoint’inin bu olası saldırılardan korunması için Asp.NET Core mimarisi tarafından alınan varsayılan bir koruma mekanizmasıdır. Dolayısıyla burada Anti-forgery önlemi için 6. satırda AddAntiforgery servisi eklenmekte ve 9. satırda da endpoint’lere gelen isteklerde anti-forgery koruma kontrolünün yapılabilmesi için UseAntiforgery middleware’i çağrılmaktadır. Ardından yine 11 ile 23. satır aralığında IAntiforgery arayüzüne karşılık instance IoC Container’dan dependency injection ile talep edilmekte ve gerekli güvenlik token’ı oluşturulup form içerisindeki 16. satırdaki ‘hidden’ input’una verilmektedir. Tabi burada token.FormFieldName komutu neticesinde ‘__RequestVerificationToken’ değerinin geleceğini bilmenizde fayda vardır.


Asp.NET Core mimarisinde varsayılan olarak aktif gelen Anti-forgery önlemini kaldırmak istiyorsanız aşağıdaki gibi DisableAntiforgery() metodunu kullanabilirsiniz.

app.MapPost("/upload-file", async ([FromForm] IFormFile file) =>
{
    return TypedResults.Ok(file);
}).DisableAntiforgery();

Velhasıl kelam, yapılan tüm bu çalışmalar neticesinde tarayıcı üzerinden form’u submit ettiğimizde dosya bilgileri ‘upload-file’ endpoint’inde elde edilecektir..NET 8 - Minimal API'lar da Form Binding İşlemiŞimdi bu çalışma üzerine aşağıdaki gibi bir form’un da post edilmesinde herhangi bir sakınca görülmemektedir, öyle değil mi?

<form action="/upload-file" method="post" enctype="multipart/form-data">
    <input name="{token.FormFieldName}" type="hidden" value="{token.RequestToken}" />
    <input type="file" name="file">
    <input type="text" name="fileName">
    <input type="text" name="description">
    <input type="submit" value="Gönder">
</form>

Bu formdaki file dışında kalan ekstra verileri .NET 8 öncesinde aşağıdaki gibi elde edebiliyorduk;

app.MapPost("/upload-file", async ([FromForm] IFormFile file, HttpRequest request) =>
{
    IFormCollection formCollection = await request.ReadFormAsync();
    var fileName = formCollection["fileName"];
    var description = formCollection["description"];
    return TypedResults.Ok(file);
});

.NET 8 ile ise şöyle elde edebiliyoruz;

app.MapPost("/upload-file", async ([FromForm] IFormFile file, [FromForm] string fileName, [FromForm] string description) =>
{
    return TypedResults.Ok(file);
});

ya da aşağıdaki gibi complex type olarak da karşılayabiliyoruz;

app.MapPost("/upload-file", async ([FromForm] UploadFileInfo model) =>
{
    return TypedResults.Ok(model);
});
    public class UploadFileInfo
    {
        public IFormFile File { get; set; }
        public string FileName { get; set; }
        public string Description { get; set; }
    }

.NET 8’den itibaren, IFormFile ve IFormFileCollection referanslarında [FromForm] attribute’unu uygulamanıza gerek yoktur!

Nihai olarak,
.NET 8’de minimal api’ler için HTML form yapılanmalarına karşın binding mekanizmasının şekillendiğini ve bunların dışında Anti-forgery önlemine karşın gerekli çalışmaların nasıl yapılabileceğini incelemiş olduk.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir