ASP.NET Core'da Model Bağlama

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin ASP.NET Core 8.0 sürümüne bakın.

Bu makalede model bağlamanın ne olduğu, nasıl çalıştığı ve davranışının nasıl özelleştirileceği açıklanmaktadır.

Model bağlama nedir?

Denetleyiciler ve Razor sayfalar, HTTP isteklerinden gelen verilerle çalışır. Örneğin, yol verileri bir kayıt anahtarı sağlayabilir ve deftere nakledilmiş form alanları modelin özellikleri için değerler sağlayabilir. Bu değerlerin her birini almak ve bunları dizelerden .NET türlerine dönüştürmek için kod yazmak yorucu ve hataya açık olabilir. Model bağlama bu işlemi otomatikleştirir. Model bağlama sistemi:

  • Rota verileri, form alanları ve sorgu dizeleri gibi çeşitli kaynaklardan veri alır.
  • Verileri, yöntem parametrelerinde ve Razor genel özelliklerde denetleyicilere ve sayfalara sağlar.
  • Dize verilerini .NET türlerine dönüştürür.
  • Karmaşık türlerin özelliklerini Güncelleştirmeler.

Örnek

Aşağıdaki eylem yöntemine sahip olduğunuzu varsayalım:

[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)

Uygulama şu URL'ye sahip bir istek alır:

https://contoso.com/api/pets/2?DogsOnly=true

Model bağlama, yönlendirme sistemi eylem yöntemini seçtikten sonra aşağıdaki adımlardan geçer:

  • adlı idbir tamsayının GetByIdilk parametresini bulur.
  • HTTP isteğindeki kullanılabilir kaynakları arar ve yol verilerinde = "2" değerini bulur id .
  • "2" dizesini 2 tamsayısına dönüştürür.
  • adlı dogsOnlybir boole değerinin GetByIdsonraki parametresini bulur.
  • Kaynaklara bakar ve sorgu dizesinde "DogsOnly=true" değerini bulur. Ad eşleştirme büyük/küçük harfe duyarlı değildir.
  • "true" dizesini boole değerine truedönüştürür.

Çerçeve daha sonra parametresi için truedogsOnly ve parametresi için id 2'yi geçirerek yöntemini çağırırGetById.

Yukarıdaki örnekte, model bağlama hedefleri basit türler olan yöntem parametreleridir. Hedefler, karmaşık bir türün özellikleri de olabilir. Her özellik başarıyla bağlandıktan sonra, bu özellik için model doğrulaması gerçekleşir. Modele bağlı verilerin kaydı ve bağlama veya doğrulama hataları ControllerBase.ModelState veya PageModel.ModelState içinde depolanır. Bu işlemin başarılı olup olmadığını öğrenmek için uygulama ModelState.IsValid bayrağını denetler.

Hedefler

Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:

  • bir isteğin yönlendirıldığı denetleyici eylem yönteminin parametreleri.
  • bir isteğin Razor yönlendirıldığı Pages işleyici yönteminin parametreleri.
  • Öznitelikler tarafından belirtilirse, bir denetleyicinin veya PageModel sınıfın genel özellikleri.

[BindProperty] özniteliği

Model bağlamanın bu özelliği hedeflemesine neden olmak için bir denetleyicinin veya PageModel sınıfın ortak özelliğine uygulanabilir:

public class EditModel : PageModel
{
    [BindProperty]
    public Instructor? Instructor { get; set; }

    // ...
}

[BindProperties] özniteliği

Model bağlamasının sınıfın tüm genel özelliklerini hedeflemesini bildirmek için bir denetleyiciye veya PageModel sınıfa uygulanabilir:

[BindProperties]
public class CreateModel : PageModel
{
    public Instructor? Instructor { get; set; }

    // ...
}

HTTP GET istekleri için model bağlama

Varsayılan olarak, özellikler HTTP GET isteklerine bağlı değildir. Genellikle, GET isteği için ihtiyacınız olan tek şey bir kayıt kimliği parametresidir. Kayıt kimliği, veritabanındaki öğeyi aramak için kullanılır. Bu nedenle, modelin bir örneğini tutan bir özelliği bağlamaya gerek yoktur. GET isteklerindeki verilere bağlı özelliklerin olmasını istediğiniz senaryolarda özelliğini olarak trueayarlayınSupportsGet:

[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }

Model bağlama basit ve karmaşık türler

Model bağlama, üzerinde çalıştığı türler için belirli tanımları kullanır. Basit bir tür, veya TryParse yöntemi kullanılarak TypeConverter tek bir dizeden dönüştürülür. Karmaşık bir tür birden çok giriş değerinden dönüştürülür. Çerçeve, veya TypeConverterTryParsevarlığını temel alarak farkı belirler. Bir tür dönüştürücüsü oluşturmanızı veya dış kaynaklar veya birden çok giriş gerektirmeyen bir stringSomeType dönüştürme için kullanmanızı TryParse öneririz.

Kaynaklar

Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:

  1. Form alanları
  2. İstek gövdesi ([ApiController] özniteliğine sahip denetleyiciler için.)
  3. Veri yönlendirme
  4. Sorgu dizesi parametreleri
  5. Karşıya yüklenen dosyalar

Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:

  • Yönlendirme verileri ve sorgu dizesi değerleri yalnızca basit türler için kullanılır.
  • Karşıya yüklenen dosyalar yalnızca veya IEnumerable<IFormFile>uygulayan IFormFile hedef türlerine bağlıdır.

Varsayılan kaynak doğru değilse, kaynağı belirtmek için aşağıdaki özniteliklerden birini kullanın:

  • [FromQuery] - Sorgu dizesinden değerleri alır.
  • [FromRoute] - Rota verilerinden değerleri alır.
  • [FromForm] - Deftere nakledilen form alanlarından değerleri alır.
  • [FromBody] - İstek gövdesinden değerleri alır.
  • [FromHeader] - HTTP üst bilgilerinden değerleri alır.

Bu öznitelikler:

  • Aşağıdaki örnekte olduğu gibi model sınıfına değil model özelliklerine ayrı ayrı eklenir:

    public class Instructor
    {
        public int Id { get; set; }
    
        [FromQuery(Name = "Note")]
        public string? NoteFromQueryString { get; set; }
    
        // ...
    }
    
  • İsteğe bağlı olarak oluşturucuda bir model adı değeri kabul edin. Özellik adının istekteki değerle eşleşmemesi durumunda bu seçenek sağlanır. Örneğin, istekteki değer, aşağıdaki örnekte olduğu gibi adında kısa çizgi bulunan bir üst bilgi olabilir:

    public void OnGet([FromHeader(Name = "Accept-Language")] string language)
    

[FromBody] özniteliği

Özelliklerini bir HTTP isteğinin [FromBody] gövdesinden doldurmak için özniteliğini bir parametreye uygulayın. ASP.NET Core çalışma zamanı, gövdeyi okuma sorumluluğunu bir giriş biçimlendiricisine devreder. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[FromBody] Karmaşık bir tür parametresine uygulandığında, özelliklerine uygulanan bağlama kaynağı öznitelikleri yoksayılır. Örneğin, aşağıdaki Create eylem parametresinin gövdeden doldurulduğunu pet belirtir:

public ActionResult<Pet> Create([FromBody] Pet pet)

sınıfı, Pet özelliğinin Breed bir sorgu dizesi parametresinden doldurulduğunu belirtir:

public class Pet
{
    public string Name { get; set; } = null!;

    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; } = null!;
}

Yukarıdaki örnekte:

  • [FromQuery] Özniteliği yoksayılır.
  • Breed özelliği bir sorgu dizesi parametresinden doldurulmuyor.

Giriş biçimlendiricileri yalnızca gövdeyi okur ve bağlama kaynak özniteliklerini anlamaz. Gövdede uygun bir değer bulunursa, bu değer özelliği doldurmak Breed için kullanılır.

Eylem yöntemi başına birden fazla parametreye uygulamayın [FromBody] . İstek akışı bir giriş biçimlendiricisi tarafından okunduktan sonra, diğer [FromBody] parametreleri bağlamak için yeniden okunamayacaktır.

Ek kaynaklar

Kaynak veriler, değer sağlayıcıları tarafından model bağlama sistemine sağlanır. Diğer kaynaklardan model bağlama için veri alan özel değer sağlayıcıları yazabilir ve kaydedebilirsiniz. Örneğin, s veya oturum durumundan cookieveri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:

  • IValueProvider uygulayan bir sınıf oluşturun.
  • IValueProviderFactory uygulayan bir sınıf oluşturun.
  • fabrika sınıfını'na Program.cskaydedin.

Örnek, s değerlerini alan bir değer sağlayıcısı ve fabrika örneği içerir.cookie özel değer sağlayıcısı fabrikalarını içinde Program.cskaydedin:

builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
});

Yukarıdaki kod, özel değer sağlayıcısını tüm yerleşik değer sağlayıcılarının arkasına yerleştirir. Bunu listede ilk yapmak için yerine öğesini çağırın Insert(0, new CookieValueProviderFactory())Add.

Model özelliği için kaynak yok

Varsayılan olarak, bir model özelliği için değer bulunamazsa model durumu hatası oluşturulmaz. özelliği null veya varsayılan değer olarak ayarlanır:

  • Null atanabilir basit türler olarak nullayarlanır.
  • Null değer atanamayan değer türleri olarak default(T)ayarlanır. Örneğin, bir parametre int id 0 olarak ayarlanır.
  • Karmaşık Türler için model bağlama, özellikleri ayarlamadan varsayılan oluşturucuyu kullanarak bir örnek oluşturur.
  • Diziler olarak Array.Empty<T>()ayarlanır, ancak byte[] diziler olarak nullayarlanır.

Model özelliği için form alanlarında hiçbir şey bulunamazsa model durumu geçersiz kılınmalıdır, özniteliğini [BindRequired] kullanın.

Bu [BindRequired] davranışın, istek gövdesindeki ON veya XML verilerine değil, gönderilen form verilerinden model bağlama için JSgeçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.

Tür dönüştürme hataları

Bir kaynak bulunur ancak hedef türe dönüştürülemezse, model durumu geçersiz olarak işaretlenir. Hedef parametre veya özellik, önceki bölümde belirtildiği gibi null veya varsayılan değer olarak ayarlanır.

Özniteliği olan bir API denetleyicisinde [ApiController] geçersiz model durumu otomatik HTTP 400 yanıtıyla sonuçlandı.

Razor Sayfada, sayfayı bir hata iletisiyle yeniden dağıtın:

public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    // ...

    return RedirectToPage("./Index");
}

Sayfa önceki kod tarafından yeniden görüntülendiğinde, form alanında geçersiz giriş gösterilmez. Bunun nedeni model özelliğinin null veya varsayılan değer olarak ayarlanmış olmasıdır. Geçersiz giriş bir hata iletisinde görünüyor. Form alanındaki hatalı verileri yeniden görüntülemek istiyorsanız model özelliğini bir dize haline getirme ve veri dönüştürme işlemini el ile gerçekleştirmeyi göz önünde bulundurun.

Tür dönüştürme hatalarının model durumu hatalarına neden olmasını istemiyorsanız aynı strateji önerilir. Bu durumda, model özelliğini bir dize yapın.

Basit türler

Basit ve karmaşık türlerin açıklaması için bkz. Model bağlama basit ve karmaşık türler.

Model bağlayıcısının kaynak dizeleri dönüştürebileceği basit türler şunlardır:

Ile bağlama IParsable<T>.TryParse

API, IParsable<TSelf>.TryParse bağlama denetleyicisi eylem parametresi değerlerini destekler:

public static bool TryParse (string? s, IFormatProvider? provider, out TSelf result);

Aşağıdaki DateRange sınıf, bir tarih aralığını bağlamayı desteklemek için uygulanır IParsable<TSelf> :

public class DateRange : IParsable<DateRange>
{
    public DateOnly? From { get; init; }
    public DateOnly? To { get; init; }

    public static DateRange Parse(string value, IFormatProvider? provider)
    {
        if (!TryParse(value, provider, out var result))
        {
           throw new ArgumentException("Could not parse supplied value.", nameof(value));
        }

        return result;
    }

    public static bool TryParse(string? value,
                                IFormatProvider? provider, out DateRange dateRange)
    {
        var segments = value?.Split(',', StringSplitOptions.RemoveEmptyEntries 
                                       | StringSplitOptions.TrimEntries);

        if (segments?.Length == 2
            && DateOnly.TryParse(segments[0], provider, out var fromDate)
            && DateOnly.TryParse(segments[1], provider, out var toDate))
        {
            dateRange = new DateRange { From = fromDate, To = toDate };
            return true;
        }

        dateRange = new DateRange { From = default, To = default };
        return false;
    }
}

Yukarıdaki kod:

  • İki tarihi temsil eden bir dizeyi nesneye DateRange dönüştürür
  • Model bağlayıcısı IParsable<TSelf>.TryParse , bağlamak için DateRangeyöntemini kullanır.

Aşağıdaki denetleyici eylemi, bir tarih aralığını bağlamak için sınıfını DateRange kullanır:

// GET /WeatherForecast/ByRange?range=7/24/2022,07/26/2022
public IActionResult ByRange([FromQuery] DateRange range)
{
    if (!ModelState.IsValid)
        return View("Error", ModelState.Values.SelectMany(v => v.Errors));

    var weatherForecasts = 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)]
        })
        .Where(wf => DateOnly.FromDateTime(wf.Date) >= range.From
                     && DateOnly.FromDateTime(wf.Date) <= range.To)
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d"),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int)(wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View("Index", weatherForecasts);
}

Aşağıdaki Locale sınıf, bağlamayı desteklemek için CultureInfouygularIParsable<TSelf>:

public class Locale : CultureInfo, IParsable<Locale>
{
    public Locale(string culture) : base(culture)
    {
    }

    public static Locale Parse(string value, IFormatProvider? provider)
    {
        if (!TryParse(value, provider, out var result))
        {
           throw new ArgumentException("Could not parse supplied value.", nameof(value));
        }

        return result;
    }

    public static bool TryParse([NotNullWhen(true)] string? value,
                                IFormatProvider? provider, out Locale locale)
    {
        if (value is null)
        {
            locale = new Locale(CurrentCulture.Name);
            return false;
        }
        
        try
        {
            locale = new Locale(value);
            return true;
        }
        catch (CultureNotFoundException)
        {
            locale = new Locale(CurrentCulture.Name);
            return false;
        }
    }
}

Aşağıdaki denetleyici eylemi bir CultureInfo dizeyi bağlamak için sınıfını Locale kullanır:

// GET /en-GB/WeatherForecast
public IActionResult Index([FromRoute] Locale locale)
{
    var weatherForecasts = 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)]
        })
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d", locale),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int)(wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View(weatherForecasts);
}

Aşağıdaki denetleyici eylemi ile bir tarih aralığını CultureInfobağlamak için ve Locale sınıflarını kullanırDateRange:

// GET /af-ZA/WeatherForecast/RangeByLocale?range=2022-07-24,2022-07-29
public IActionResult RangeByLocale([FromRoute] Locale locale, [FromQuery] string range)
{
    if (!ModelState.IsValid)
        return View("Error", ModelState.Values.SelectMany(v => v.Errors));

    if (!DateRange.TryParse(range, locale, out DateRange rangeResult))
    {
        ModelState.TryAddModelError(nameof(range),
            $"Invalid date range: {range} for locale {locale.DisplayName}");

        return View("Error", ModelState.Values.SelectMany(v => v.Errors));
    }

    var weatherForecasts = 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)]
        })
        .Where(wf => DateOnly.FromDateTime(wf.Date) >= rangeResult.From
                     && DateOnly.FromDateTime(wf.Date) <= rangeResult.To)
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d", locale),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int) (wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View("Index", weatherForecasts);
}

GitHub'da API örnek uygulaması, bir API denetleyicisi için önceki örneği gösterir.

Ile bağlama TryParse

API, TryParse bağlama denetleyicisi eylem parametresi değerlerini destekler:

public static bool TryParse(string value, T out result);
public static bool TryParse(string value, IFormatProvider provider, T out result);

IParsable<T>.TryParse parametre bağlaması için önerilen yaklaşımdır çünkü aksine TryParse, yansımaya bağımlı değildir.

Aşağıdaki DateRangeTP sınıf şunu uygular TryParse:

public class DateRangeTP
{
    public DateOnly? From { get; }
    public DateOnly? To { get; }

    public DateRangeTP(string from, string to)
    {
        if (string.IsNullOrEmpty(from))
            throw new ArgumentNullException(nameof(from));
        if (string.IsNullOrEmpty(to))
            throw new ArgumentNullException(nameof(to));

        From = DateOnly.Parse(from);
        To = DateOnly.Parse(to);
    }

    public static bool TryParse(string? value, out DateRangeTP? result)
    {
        var range = value?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        if (range?.Length != 2)
        {
            result = default;
            return false;
        }

        result = new DateRangeTP(range[0], range[1]);
        return true;
    }
}

Aşağıdaki denetleyici eylemi, bir tarih aralığını bağlamak için sınıfını DateRangeTP kullanır:

// GET /WeatherForecast/ByRangeTP?range=7/24/2022,07/26/2022
public IActionResult ByRangeTP([FromQuery] DateRangeTP range)
{
    if (!ModelState.IsValid)
        return View("Error", ModelState.Values.SelectMany(v => v.Errors));

    var weatherForecasts = 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)]
        })
        .Where(wf => DateOnly.FromDateTime(wf.Date) >= range.From
                     && DateOnly.FromDateTime(wf.Date) <= range.To)
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d"),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int)(wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View("Index", weatherForecasts);
}

Karmaşık türler

Karmaşık bir türün, bağlanacak genel bir varsayılan oluşturucuya ve genel yazılabilir özelliklerine sahip olması gerekir. Model bağlama gerçekleştiğinde, sınıfı genel varsayılan oluşturucu kullanılarak örneği oluşturulur.

Karmaşık türün her özelliği için model bağlaması, prefix.property_name ad deseninin kaynaklarına bakar. Hiçbir şey bulunmazsa, ön ek olmadan yalnızca property_name arar. Öneki kullanma kararı özellik başına yapılmaz. Örneğin, içeren bir sorgu ?Instructor.Id=100&Name=fooile yöntemine OnGet(Instructor instructor)bağlı olarak, türünde Instructor elde edilen nesne şunları içerir:

  • Id olarak 100ayarlayın.
  • Name olarak nullayarlayın. Önceki sorgu parametresinde kullanıldığından model bağlamasının beklediği Instructor.NameInstructor.Id bir işlemdir.

Bir parametreye bağlama için ön ek parametre adıdır. Ortak özelliğe PageModel bağlama için ön ek, ortak özellik adıdır. Bazı öznitelikler, parametre veya özellik adının varsayılan kullanımını geçersiz kılmanıza olanak tanıyan bir Prefix özelliğe sahiptir.

Örneğin, karmaşık türün aşağıdaki Instructor sınıf olduğunu varsayalım:

public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Ön ek = parametre adı

Bağlanacak model adlı instructorToUpdatebir parametreyse:

public IActionResult OnPost(int? id, Instructor instructorToUpdate)

Model bağlama, anahtarının instructorToUpdate.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Ön ek = özellik adı

Bağlanacak model denetleyicinin veya PageModel sınıfın adlı Instructor bir özellikse:

[BindProperty]
public Instructor Instructor { get; set; }

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Özel ön ek

Bağlanacak model adlı instructorToUpdate bir parametreyse ve Bind bir öznitelik ön ek olarak belirtiyorsa Instructor :

public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Karmaşık tür hedefleri için öznitelikler

Karmaşık türlerin model bağlamasını denetlemek için çeşitli yerleşik öznitelikler kullanılabilir:

Uyarı

Bu öznitelikler, deftere nakledilmiş form verileri değerlerin kaynağı olduğunda model bağlamayı etkiler. Bunlar, ON ve XML istek gövdelerini işleyen JSgiriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[Bind] özniteliği

Bir sınıfa veya yöntem parametresine uygulanabilir. Modelin hangi özelliklerinin model bağlamaya dahil edilmesi gerektiğini belirtir. [Bind]giriş biçimlendiricilerini etkilemez.

Aşağıdaki örnekte, herhangi bir işleyici veya eylem yöntemi çağrıldığında yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[Bind("LastName,FirstMidName,HireDate")]
public class Instructor

Aşağıdaki örnekte, yöntem çağrıldığında OnPost yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[HttpPost]
public IActionResult OnPost(
    [Bind("LastName,FirstMidName,HireDate")] Instructor instructor)

[Bind] özniteliği, oluşturma senaryolarında aşırı paylaşıma karşı koruma sağlamak için kullanılabilir. Dışlanan özellikler değiştirilmeden bırakılmak yerine null veya varsayılan değer olarak ayarlandığından, düzenleme senaryolarında düzgün çalışmaz. Aşırı paylaşıma karşı savunma için, özniteliği yerine [Bind] görünüm modelleri önerilir. Daha fazla bilgi için bkz . Fazla paylaşımla ilgili güvenlik notu.

[ModelBinder] özniteliği

ModelBinderAttribute türlere, özelliklere veya parametrelere uygulanabilir. Belirli bir örneği veya türü bağlamak için kullanılan model bağlayıcısının türünü belirtmeye olanak tanır. Örneğin:

[HttpPost]
public IActionResult OnPost(
    [ModelBinder<MyInstructorModelBinder>] Instructor instructor)

Özniteliği, [ModelBinder] modele bağlı olduğunda bir özelliğin veya parametrenin adını değiştirmek için de kullanılabilir:

public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }

    // ...
}

[BindRequired] özniteliği

Bir modelin özelliği için bağlama gerçekleşemiyorsa model bağlamanın model durumu hatası eklemesine neden olur. Bir örnek aşağıda verilmiştir:

public class InstructorBindRequired
{
    // ...

    [BindRequired]
    public DateTime HireDate { get; set; }
}

Ayrıca Bkz. Model doğrulamasında özniteliğin [Required] tartışması.

[BindNever] özniteliği

Bir özelliğe veya türe uygulanabilir. Model bağlamanın modelin özelliğini ayarlamasını engeller. Bir türe uygulandığında, model bağlama sistemi türün tanımladığı tüm özellikleri dışlar. Bir örnek aşağıda verilmiştir:

public class InstructorBindNever
{
    [BindNever]
    public int Id { get; set; }

    // ...
}

Koleksiyonlar

Basit tür koleksiyonları olan hedefler için model bağlama, parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Bağlanacak parametrenin adlı selectedCoursesbir dizi olduğunu varsayalım:

    public IActionResult OnPost(int? id, int[] selectedCourses)
    
  • Form veya sorgu dizesi verileri aşağıdaki biçimlerden birinde olabilir:

    selectedCourses=1050&selectedCourses=2000 
    
    selectedCourses[0]=1050&selectedCourses[1]=2000
    
    [0]=1050&[1]=2000
    
    selectedCourses[a]=1050&selectedCourses[b]=2000&selectedCourses.index=a&selectedCourses.index=b
    
    [a]=1050&[b]=2000&index=a&index=b
    

    Bir parametreyi veya adlı index bir özelliği ya da Index bir koleksiyon değerine bitişikse bağlamaktan kaçının. Model bağlaması, koleksiyon için dizin olarak kullanmayı index dener ve bu da yanlış bağlamaya neden olabilir. Örneğin, aşağıdaki eylemi göz önünde bulundurun:

    public IActionResult Post(string index, List<Product> products)
    

    Yukarıdaki kodda index sorgu dizesi parametresi yöntem parametresine index bağlanır ve ayrıca ürün koleksiyonunu bağlamak için kullanılır. Parametrenin yeniden adlandırılması veya bağlamayı index yapılandırmak için bir model bağlama özniteliği kullanılması bu sorunu önler:

    public IActionResult Post(string productIndex, List<Product> products)
    
  • Aşağıdaki biçim yalnızca form verilerinde desteklenir:

    selectedCourses[]=1050&selectedCourses[]=2000
    
  • Önceki tüm örnek biçimler için, model bağlama parametresine selectedCourses iki öğeden oluşan bir dizi geçirir:

    • selectedCourses[0]=1050
    • selectedCourses[1]=2000

    Alt simge numaraları kullanan veri biçimleri (... [0] ... [1] ...) sıfırdan başlayarak sıralı olarak numaralandırıldığından emin olmalıdır. Alt simge numaralandırmasında boşluk varsa, boşluktan sonraki tüm öğeler yoksayılır. Örneğin, alt simgeler 0 ve 1 yerine 0 ve 2 ise, ikinci öğe yoksayılır.

Sözlükler

HedeflerdeDictionary, model bağlama parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Hedef parametrenin adlı selectedCoursesbir Dictionary<int, string> olduğunu varsayalım:

    public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
    
  • Gönderilen form veya sorgu dizesi verileri aşağıdaki örneklerden biri gibi görünebilir:

    selectedCourses[1050]=Chemistry&selectedCourses[2000]=Economics
    
    [1050]=Chemistry&selectedCourses[2000]=Economics
    
    selectedCourses[0].Key=1050&selectedCourses[0].Value=Chemistry&
    selectedCourses[1].Key=2000&selectedCourses[1].Value=Economics
    
    [0].Key=1050&[0].Value=Chemistry&[1].Key=2000&[1].Value=Economics
    
  • Yukarıdaki tüm örnek biçimler için model bağlama parametresine selectedCourses iki öğeden oluşan bir sözlük geçirir:

    • selectedCourses["1050"]="Kimya"
    • selectedCourses["2000"]="Economics"

Oluşturucu bağlama ve kayıt türleri

Model bağlama, karmaşık türlerin parametresiz bir oluşturucuya sahip olmasını gerektirir. Newtonsoft.Json Hem hem de System.Text.Json tabanlı giriş biçimlendiricileri, parametresiz oluşturucuya sahip olmayan sınıfların seri durumdan çıkarıldığını destekler.

Kayıt türleri, ağ üzerinden verileri kısa bir şekilde temsil etmenin harika bir yoludur. ASP.NET Core, tek bir oluşturucuyla model bağlamayı ve kayıt türlerini doğrulamayı destekler:

public record Person(
    [Required] string Name, [Range(0, 150)] int Age, [BindNever] int Id);

public class PersonController
{
    public IActionResult Index() => View();

    [HttpPost]
    public IActionResult Index(Person person)
    {
        // ...
    }
}

Person/Index.cshtml:

@model Person

Name: <input asp-for="Name" />
<br />
Age: <input asp-for="Age" />

Kayıt türleri doğrulanırken çalışma zamanı, özellikle özellikler yerine parametrelerde bağlama ve doğrulama meta verilerini arar.

Çerçeve, kayıt türlerini bağlamaya ve doğrulamaya olanak tanır:

public record Person([Required] string Name, [Range(0, 100)] int Age);

Öncekinin çalışması için türün şunları yapması gerekir:

  • Kayıt türü olun.
  • Tam olarak bir ortak oluşturucuya sahip olun.
  • Aynı ada ve türe sahip bir özelliğe sahip parametreleri içerir. Adların büyük/küçük harfe göre farklılık göstermemesi gerekir.

Parametresiz oluşturucuları olmayan POCO'lar

Parametresiz oluşturucuları olmayan POCO'lar bağlanamaz.

Aşağıdaki kod, türün parametresiz bir oluşturucuya sahip olması gerektiğini belirten bir özel durumla sonuçlar:

public class Person(string Name)

public record Person([Required] string Name, [Range(0, 100)] int Age)
{
    public Person(string Name) : this (Name, 0);
}

El ile yazılmış oluşturucularla kayıt türleri

Birincil oluşturucular gibi görünen el ile yazılmış oluşturucuların çalıştığı kayıt türleri

public record Person
{
    public Person([Required] string Name, [Range(0, 100)] int Age)
        => (this.Name, this.Age) = (Name, Age);

    public string Name { get; set; }
    public int Age { get; set; }
}

Kayıt türleri, doğrulama ve bağlama meta verileri

Kayıt türleri için parametrelerde doğrulama ve bağlama meta verileri kullanılır. Özelliklerdeki meta veriler yoksayılır

public record Person (string Name, int Age)
{
   [BindProperty(Name = "SomeName")] // This does not get used
   [Required] // This does not get used
   public string Name { get; init; }
}

Doğrulama ve meta veriler

Doğrulama parametresinde meta verileri kullanır, ancak değerini okumak için özelliğini kullanır. Birincil oluşturucular ile normal durumda, ikisi aynı olacaktır. Ancak, bunu yenmenin yolları vardır:

public record Person([Required] string Name)
{
    private readonly string _name;

    // The following property is never null.
    // However this object could have been constructed as "new Person(null)".
    public string Name { get; init => _name = value ?? string.Empty; }
}

TryUpdateModel bir kayıt türündeki parametreleri güncelleştirmez

public record Person(string Name)
{
    public int Age { get; set; }
}

var person = new Person("initial-name");
TryUpdateModel(person, ...);

Bu durumda, MVC yeniden bağlamayı Name denemez. Ancak, Age güncelleştirilmeye izin verilir

Model bağlama yönlendirme verilerinin ve sorgu dizelerinin genelleştirme davranışı

ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:

  • Değerleri sabit kültür olarak değerlendirin.
  • URL'lerin kültür sabiti olmasını beklenir.

Buna karşılık, form verilerinden gelen değerler kültüre duyarlı bir dönüştürmeden geçer. Bu, URL'lerin yerel ayarlar arasında paylaşılabilir olması için tasarım gereğidir.

ASP.NET Core yol değeri sağlayıcısının ve sorgu dizesi değer sağlayıcısının kültüre duyarlı bir dönüştürmeden geçirilmesini sağlamak için:

public class CultureQueryStringValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        _ = context ?? throw new ArgumentNullException(nameof(context));

        var query = context.ActionContext.HttpContext.Request.Query;
        if (query?.Count > 0)
        {
            context.ValueProviders.Add(
                new QueryStringValueProvider(
                    BindingSource.Query,
                    query,
                    CultureInfo.CurrentCulture));
        }

        return Task.CompletedTask;
    }
}
builder.Services.AddControllers(options =>
{
    var index = options.ValueProviderFactories.IndexOf(
        options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>()
            .Single());

    options.ValueProviderFactories[index] =
        new CultureQueryStringValueProviderFactory();
});

Özel veri türleri

Model bağlamanın işleyebileceği bazı özel veri türleri vardır.

IFormFile ve IFormFileCollection

HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile> desteklenir.

Cancellationtoken

Eylemler isteğe bağlı olarak parametresini CancellationToken bağlayabilir. Bu, HTTP isteğini temel alan bağlantı durdurulduğunda sinyalleri bağlar RequestAborted . Eylemler, denetleyici eylemlerinin bir parçası olarak yürütülen uzun süre çalışan zaman uyumsuz işlemleri iptal etmek için bu parametreyi kullanabilir.

Formcollection

Gönderilen form verilerinden tüm değerleri almak için kullanılır.

Giriş biçimlendiricileri

İstek gövdesindeki veriler ON, XML veya başka bir biçimde olabilir JS. Model bağlama, bu verileri ayrıştırmak için belirli bir içerik türünü işlemek üzere yapılandırılmış bir giriş biçimlendirici kullanır. varsayılan olarak ASP.NET Core, ON verilerini işlemek JSiçin ON tabanlı giriş biçimlendiricileri içerirJS. Diğer içerik türleri için başka biçimlendiriciler ekleyebilirsiniz.

ASP.NET Core, Consumes özniteliğine göre giriş biçimlendiricilerini seçer. Öznitelik yoksa İçerik Türü üst bilgisini kullanır.

Yerleşik XML giriş biçimlendiricilerini kullanmak için:

  • içindeProgram.cs, veya AddXmlDataContractSerializerFormattersöğesini arayınAddXmlSerializerFormatters.

    builder.Services.AddControllers()
        .AddXmlSerializerFormatters();
    
  • özniteliğini, istek gövdesinde Consumes XML beklenmesi gereken denetleyici sınıflarına veya eylem yöntemlerine uygulayın.

    [HttpPost]
    [Consumes("application/xml")]
    public ActionResult<Pet> Create(Pet pet)
    

    Daha fazla bilgi için bkz . XML Serileştirmeye Giriş.

Giriş biçimlendiricileri ile model bağlamayı özelleştirme

Giriş biçimlendiricisi, istek gövdesinden veri okumanın tüm sorumluluğunu alır. Bu işlemi özelleştirmek için giriş biçimlendiricisi tarafından kullanılan API'leri yapılandırın. Bu bölümde, adlı ObjectIdözel türü anlamak için tabanlı giriş biçimlendiricisinin System.Text.Jsonnasıl özelleştirileceği açıklanmaktadır.

Özel ObjectId bir özellik içeren aşağıdaki modeli göz önünde bulundurun:

public class InstructorObjectId
{
    [Required]
    public ObjectId ObjectId { get; set; } = null!;
}

kullanırken System.Text.Jsonmodel bağlama işlemini özelleştirmek için öğesinden JsonConverter<T>türetilmiş bir sınıf oluşturun:

internal class ObjectIdConverter : JsonConverter<ObjectId>
{
    public override ObjectId Read(
        ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => new(JsonSerializer.Deserialize<int>(ref reader, options));

    public override void Write(
        Utf8JsonWriter writer, ObjectId value, JsonSerializerOptions options)
        => writer.WriteNumberValue(value.Id);
}

Özel dönüştürücü kullanmak için özniteliğini JsonConverterAttribute türüne uygulayın. Aşağıdaki örnekte, ObjectId türü ile özel dönüştürücüsü olarak yapılandırılır ObjectIdConverter :

[JsonConverter(typeof(ObjectIdConverter))]
public record ObjectId(int Id);

Daha fazla bilgi için bkz . Özel dönüştürücüler yazma.

Belirtilen türleri model bağlamasından dışla

Model bağlama ve doğrulama sistemlerinin davranışı tarafından ModelMetadatayönlendirilir. MvcOptions.ModelMetadataDetailsProviders'a bir ayrıntı sağlayıcısı ekleyerek özelleştirebilirsinizModelMetadata. Yerleşik ayrıntılar sağlayıcıları, belirtilen türler için model bağlamasını veya doğrulamayı devre dışı bırakmak için kullanılabilir.

Belirtilen türdeki tüm modellerde model bağlamayı devre dışı bırakmak için içine bir ExcludeBindingMetadataProviderProgram.csekleyin. Örneğin, türündeki System.Versiontüm modellerde model bağlamayı devre dışı bırakmak için:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });

Belirtilen türün özelliklerinde doğrulamayı devre dışı bırakmak için içine ekleyin SuppressChildValidationMetadataProviderProgram.cs. Örneğin, türündeki System.Guidözelliklerde doğrulamayı devre dışı bırakmak için:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });

Özel model bağlayıcıları

Özel bir model bağlayıcısı yazarak ve özniteliğini kullanarak model bağlamayı [ModelBinder] belirli bir hedef için seçerek genişletebilirsiniz. Özel model bağlama hakkında daha fazla bilgi edinin.

El ile model bağlama

Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBasePageModel sınıflarında tanımlanır. Yöntem aşırı yüklemeleri, kullanılacak ön ek ve değer sağlayıcısını belirtmenize olanak sağlar. Yöntem, model bağlama başarısız olursa döndürür false . Bir örnek aşağıda verilmiştir:

if (await TryUpdateModelAsync(
    newInstructor,
    "Instructor",
    x => x.Name, x => x.HireDate!))
{
    _instructorStore.Add(newInstructor);
    return RedirectToPage("./Index");
}

return Page();

TryUpdateModelAsync form gövdesinden, sorgu dizesinden ve yönlendirme verilerinden veri almak için değer sağlayıcılarını kullanır. TryUpdateModelAsync genellikle:

  • Fazla gönderimi önlemek için denetleyiciler ve görünümler kullanılarak Sayfalar ve MVC uygulamalarıyla birlikte Razor kullanılır.
  • Form verilerinden, sorgu dizelerinden ve yönlendirme verilerinden kullanılmadığı sürece web API'siyle kullanılmaz. ON kullanan JSWeb API uç noktaları, istek gövdesini bir nesneye seri durumdan çıkarmak için Giriş biçimlendiricilerini kullanır.

Daha fazla bilgi için bkz . TryUpdateModelAsync.

[FromServices] özniteliği

Bu özniteliğin adı, bir veri kaynağı belirten model bağlama özniteliklerinin desenini izler. Ancak bu, bir değer sağlayıcısından verileri bağlamayla ilgili değildir. Bağımlılık ekleme kapsayıcısından bir türün örneğini alır. Amacı, yalnızca belirli bir yöntem çağrıldığında bir hizmete ihtiyacınız olduğunda oluşturucu eklemeye alternatif sağlamaktır.

Türün bir örneği bağımlılık ekleme kapsayıcısında kayıtlı değilse, uygulama parametresini bağlamaya çalışırken bir özel durum oluşturur. parametresini isteğe bağlı hale getirmek için aşağıdaki yaklaşımlardan birini kullanın:

  • Parametresini null atanabilir hale getirin.
  • parametresi için varsayılan bir değer ayarlayın.

Null atanabilir parametreler için, parametreye erişmeden önce bu parametrenin olmadığından null emin olun.

Ek kaynaklar

Bu makalede model bağlamanın ne olduğu, nasıl çalıştığı ve davranışının nasıl özelleştirileceği açıklanmaktadır.

Model bağlama nedir?

Denetleyiciler ve Razor sayfalar, HTTP isteklerinden gelen verilerle çalışır. Örneğin, yol verileri bir kayıt anahtarı sağlayabilir ve deftere nakledilmiş form alanları modelin özellikleri için değerler sağlayabilir. Bu değerlerin her birini almak ve bunları dizelerden .NET türlerine dönüştürmek için kod yazmak yorucu ve hataya açık olabilir. Model bağlama bu işlemi otomatikleştirir. Model bağlama sistemi:

  • Rota verileri, form alanları ve sorgu dizeleri gibi çeşitli kaynaklardan veri alır.
  • Verileri, yöntem parametrelerinde ve Razor genel özelliklerde denetleyicilere ve sayfalara sağlar.
  • Dize verilerini .NET türlerine dönüştürür.
  • Karmaşık türlerin özelliklerini Güncelleştirmeler.

Örnek

Aşağıdaki eylem yöntemine sahip olduğunuzu varsayalım:

[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)

Uygulama şu URL'ye sahip bir istek alır:

https://contoso.com/api/pets/2?DogsOnly=true

Model bağlama, yönlendirme sistemi eylem yöntemini seçtikten sonra aşağıdaki adımlardan geçer:

  • adlı idbir tamsayının GetByIdilk parametresini bulur.
  • HTTP isteğindeki kullanılabilir kaynakları arar ve yol verilerinde = "2" değerini bulur id .
  • "2" dizesini 2 tamsayısına dönüştürür.
  • adlı dogsOnlybir boole değerinin GetByIdsonraki parametresini bulur.
  • Kaynaklara bakar ve sorgu dizesinde "DogsOnly=true" değerini bulur. Ad eşleştirme büyük/küçük harfe duyarlı değildir.
  • "true" dizesini boole değerine truedönüştürür.

Çerçeve daha sonra parametresi için truedogsOnly ve parametresi için id 2'yi geçirerek yöntemini çağırırGetById.

Yukarıdaki örnekte, model bağlama hedefleri basit türler olan yöntem parametreleridir. Hedefler, karmaşık bir türün özellikleri de olabilir. Her özellik başarıyla bağlandıktan sonra, bu özellik için model doğrulaması gerçekleşir. Modele bağlı verilerin kaydı ve bağlama veya doğrulama hataları ControllerBase.ModelState veya PageModel.ModelState içinde depolanır. Bu işlemin başarılı olup olmadığını öğrenmek için uygulama ModelState.IsValid bayrağını denetler.

Hedefler

Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:

  • bir isteğin yönlendirıldığı denetleyici eylem yönteminin parametreleri.
  • bir isteğin Razor yönlendirıldığı Pages işleyici yönteminin parametreleri.
  • Öznitelikler tarafından belirtilirse, bir denetleyicinin veya PageModel sınıfın genel özellikleri.

[BindProperty] özniteliği

Model bağlamanın bu özelliği hedeflemesine neden olmak için bir denetleyicinin veya PageModel sınıfın ortak özelliğine uygulanabilir:

public class EditModel : PageModel
{
    [BindProperty]
    public Instructor? Instructor { get; set; }

    // ...
}

[BindProperties] özniteliği

Model bağlamasının sınıfın tüm genel özelliklerini hedeflemesini bildirmek için bir denetleyiciye veya PageModel sınıfa uygulanabilir:

[BindProperties]
public class CreateModel : PageModel
{
    public Instructor? Instructor { get; set; }

    // ...
}

HTTP GET istekleri için model bağlama

Varsayılan olarak, özellikler HTTP GET isteklerine bağlı değildir. Genellikle, GET isteği için ihtiyacınız olan tek şey bir kayıt kimliği parametresidir. Kayıt kimliği, veritabanındaki öğeyi aramak için kullanılır. Bu nedenle, modelin bir örneğini tutan bir özelliği bağlamaya gerek yoktur. GET isteklerindeki verilere bağlı özelliklerin olmasını istediğiniz senaryolarda özelliğini olarak trueayarlayınSupportsGet:

[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }

Model bağlama basit ve karmaşık türler

Model bağlama, üzerinde çalıştığı türler için belirli tanımları kullanır. Basit bir tür, veya TryParse yöntemi kullanılarak TypeConverter tek bir dizeden dönüştürülür. Karmaşık bir tür birden çok giriş değerinden dönüştürülür. Çerçeve, veya TypeConverterTryParsevarlığını temel alarak farkı belirler. Bir tür dönüştürücüsü oluşturmanızı veya dış kaynaklar veya birden çok giriş gerektirmeyen bir stringSomeType dönüştürme için kullanmanızı TryParse öneririz.

Kaynaklar

Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:

  1. Form alanları
  2. İstek gövdesi ([ApiController] özniteliğine sahip denetleyiciler için.)
  3. Veri yönlendirme
  4. Sorgu dizesi parametreleri
  5. Karşıya yüklenen dosyalar

Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:

  • Yönlendirme verileri ve sorgu dizesi değerleri yalnızca basit türler için kullanılır.
  • Karşıya yüklenen dosyalar yalnızca veya IEnumerable<IFormFile>uygulayan IFormFile hedef türlerine bağlıdır.

Varsayılan kaynak doğru değilse, kaynağı belirtmek için aşağıdaki özniteliklerden birini kullanın:

  • [FromQuery] - Sorgu dizesinden değerleri alır.
  • [FromRoute] - Rota verilerinden değerleri alır.
  • [FromForm] - Deftere nakledilen form alanlarından değerleri alır.
  • [FromBody] - İstek gövdesinden değerleri alır.
  • [FromHeader] - HTTP üst bilgilerinden değerleri alır.

Bu öznitelikler:

  • Aşağıdaki örnekte olduğu gibi model sınıfına değil model özelliklerine ayrı ayrı eklenir:

    public class Instructor
    {
        public int Id { get; set; }
    
        [FromQuery(Name = "Note")]
        public string? NoteFromQueryString { get; set; }
    
        // ...
    }
    
  • İsteğe bağlı olarak oluşturucuda bir model adı değeri kabul edin. Özellik adının istekteki değerle eşleşmemesi durumunda bu seçenek sağlanır. Örneğin, istekteki değer, aşağıdaki örnekte olduğu gibi adında kısa çizgi bulunan bir üst bilgi olabilir:

    public void OnGet([FromHeader(Name = "Accept-Language")] string language)
    

[FromBody] özniteliği

Özelliklerini bir HTTP isteğinin [FromBody] gövdesinden doldurmak için özniteliğini bir parametreye uygulayın. ASP.NET Core çalışma zamanı, gövdeyi okuma sorumluluğunu bir giriş biçimlendiricisine devreder. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[FromBody] Karmaşık bir tür parametresine uygulandığında, özelliklerine uygulanan bağlama kaynağı öznitelikleri yoksayılır. Örneğin, aşağıdaki Create eylem parametresinin gövdeden doldurulduğunu pet belirtir:

public ActionResult<Pet> Create([FromBody] Pet pet)

sınıfı, Pet özelliğinin Breed bir sorgu dizesi parametresinden doldurulduğunu belirtir:

public class Pet
{
    public string Name { get; set; } = null!;

    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; } = null!;
}

Yukarıdaki örnekte:

  • [FromQuery] Özniteliği yoksayılır.
  • Breed özelliği bir sorgu dizesi parametresinden doldurulmuyor.

Giriş biçimlendiricileri yalnızca gövdeyi okur ve bağlama kaynak özniteliklerini anlamaz. Gövdede uygun bir değer bulunursa, bu değer özelliği doldurmak Breed için kullanılır.

Eylem yöntemi başına birden fazla parametreye uygulamayın [FromBody] . İstek akışı bir giriş biçimlendiricisi tarafından okunduktan sonra, diğer [FromBody] parametreleri bağlamak için yeniden okunamayacaktır.

Ek kaynaklar

Kaynak veriler, değer sağlayıcıları tarafından model bağlama sistemine sağlanır. Diğer kaynaklardan model bağlama için veri alan özel değer sağlayıcıları yazabilir ve kaydedebilirsiniz. Örneğin, s veya oturum durumundan cookieveri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:

  • IValueProvider uygulayan bir sınıf oluşturun.
  • IValueProviderFactory uygulayan bir sınıf oluşturun.
  • fabrika sınıfını'na Program.cskaydedin.

Örnek, s değerlerini alan bir değer sağlayıcısı ve fabrika örneği içerir.cookie özel değer sağlayıcısı fabrikalarını içinde Program.cskaydedin:

builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
});

Yukarıdaki kod, özel değer sağlayıcısını tüm yerleşik değer sağlayıcılarının arkasına yerleştirir. Bunu listede ilk yapmak için yerine öğesini çağırın Insert(0, new CookieValueProviderFactory())Add.

Model özelliği için kaynak yok

Varsayılan olarak, bir model özelliği için değer bulunamazsa model durumu hatası oluşturulmaz. özelliği null veya varsayılan değer olarak ayarlanır:

  • Null atanabilir basit türler olarak nullayarlanır.
  • Null değer atanamayan değer türleri olarak default(T)ayarlanır. Örneğin, bir parametre int id 0 olarak ayarlanır.
  • Karmaşık Türler için model bağlama, özellikleri ayarlamadan varsayılan oluşturucuyu kullanarak bir örnek oluşturur.
  • Diziler olarak Array.Empty<T>()ayarlanır, ancak byte[] diziler olarak nullayarlanır.

Model özelliği için form alanlarında hiçbir şey bulunamazsa model durumu geçersiz kılınmalıdır, özniteliğini [BindRequired] kullanın.

Bu [BindRequired] davranışın, istek gövdesindeki ON veya XML verilerine değil, gönderilen form verilerinden model bağlama için JSgeçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.

Tür dönüştürme hataları

Bir kaynak bulunur ancak hedef türe dönüştürülemezse, model durumu geçersiz olarak işaretlenir. Hedef parametre veya özellik, önceki bölümde belirtildiği gibi null veya varsayılan değer olarak ayarlanır.

Özniteliği olan bir API denetleyicisinde [ApiController] geçersiz model durumu otomatik HTTP 400 yanıtıyla sonuçlandı.

Razor Sayfada, sayfayı bir hata iletisiyle yeniden dağıtın:

public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    // ...

    return RedirectToPage("./Index");
}

Sayfa önceki kod tarafından yeniden görüntülendiğinde, form alanında geçersiz giriş gösterilmez. Bunun nedeni model özelliğinin null veya varsayılan değer olarak ayarlanmış olmasıdır. Geçersiz giriş bir hata iletisinde görünüyor. Form alanındaki hatalı verileri yeniden görüntülemek istiyorsanız model özelliğini bir dize haline getirme ve veri dönüştürme işlemini el ile gerçekleştirmeyi göz önünde bulundurun.

Tür dönüştürme hatalarının model durumu hatalarına neden olmasını istemiyorsanız aynı strateji önerilir. Bu durumda, model özelliğini bir dize yapın.

Basit türler

Basit ve karmaşık türlerin açıklaması için bkz. Model bağlama basit ve karmaşık türler.

Model bağlayıcısının kaynak dizeleri dönüştürebileceği basit türler şunlardır:

Ile bağlama IParsable<T>.TryParse

API, IParsable<TSelf>.TryParse bağlama denetleyicisi eylem parametresi değerlerini destekler:

public static bool TryParse (string? s, IFormatProvider? provider, out TSelf result);

Aşağıdaki DateRange sınıf, bir tarih aralığını bağlamayı desteklemek için uygulanır IParsable<TSelf> :

public class DateRange : IParsable<DateRange>
{
    public DateOnly? From { get; init; }
    public DateOnly? To { get; init; }

    public static DateRange Parse(string value, IFormatProvider? provider)
    {
        if (!TryParse(value, provider, out var result))
        {
           throw new ArgumentException("Could not parse supplied value.", nameof(value));
        }

        return result;
    }

    public static bool TryParse(string? value,
                                IFormatProvider? provider, out DateRange dateRange)
    {
        var segments = value?.Split(',', StringSplitOptions.RemoveEmptyEntries 
                                       | StringSplitOptions.TrimEntries);

        if (segments?.Length == 2
            && DateOnly.TryParse(segments[0], provider, out var fromDate)
            && DateOnly.TryParse(segments[1], provider, out var toDate))
        {
            dateRange = new DateRange { From = fromDate, To = toDate };
            return true;
        }

        dateRange = new DateRange { From = default, To = default };
        return false;
    }
}

Yukarıdaki kod:

  • İki tarihi temsil eden bir dizeyi nesneye DateRange dönüştürür
  • Model bağlayıcısı IParsable<TSelf>.TryParse , bağlamak için DateRangeyöntemini kullanır.

Aşağıdaki denetleyici eylemi, bir tarih aralığını bağlamak için sınıfını DateRange kullanır:

// GET /WeatherForecast/ByRange?range=7/24/2022,07/26/2022
public IActionResult ByRange([FromQuery] DateRange range)
{
    if (!ModelState.IsValid)
        return View("Error", ModelState.Values.SelectMany(v => v.Errors));

    var weatherForecasts = 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)]
        })
        .Where(wf => DateOnly.FromDateTime(wf.Date) >= range.From
                     && DateOnly.FromDateTime(wf.Date) <= range.To)
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d"),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int)(wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View("Index", weatherForecasts);
}

Aşağıdaki Locale sınıf, bağlamayı desteklemek için CultureInfouygularIParsable<TSelf>:

public class Locale : CultureInfo, IParsable<Locale>
{
    public Locale(string culture) : base(culture)
    {
    }

    public static Locale Parse(string value, IFormatProvider? provider)
    {
        if (!TryParse(value, provider, out var result))
        {
           throw new ArgumentException("Could not parse supplied value.", nameof(value));
        }

        return result;
    }

    public static bool TryParse([NotNullWhen(true)] string? value,
                                IFormatProvider? provider, out Locale locale)
    {
        if (value is null)
        {
            locale = new Locale(CurrentCulture.Name);
            return false;
        }
        
        try
        {
            locale = new Locale(value);
            return true;
        }
        catch (CultureNotFoundException)
        {
            locale = new Locale(CurrentCulture.Name);
            return false;
        }
    }
}

Aşağıdaki denetleyici eylemi bir CultureInfo dizeyi bağlamak için sınıfını Locale kullanır:

// GET /en-GB/WeatherForecast
public IActionResult Index([FromRoute] Locale locale)
{
    var weatherForecasts = 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)]
        })
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d", locale),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int)(wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View(weatherForecasts);
}

Aşağıdaki denetleyici eylemi ile bir tarih aralığını CultureInfobağlamak için ve Locale sınıflarını kullanırDateRange:

// GET /af-ZA/WeatherForecast/RangeByLocale?range=2022-07-24,2022-07-29
public IActionResult RangeByLocale([FromRoute] Locale locale, [FromQuery] string range)
{
    if (!ModelState.IsValid)
        return View("Error", ModelState.Values.SelectMany(v => v.Errors));

    if (!DateRange.TryParse(range, locale, out DateRange rangeResult))
    {
        ModelState.TryAddModelError(nameof(range),
            $"Invalid date range: {range} for locale {locale.DisplayName}");

        return View("Error", ModelState.Values.SelectMany(v => v.Errors));
    }

    var weatherForecasts = 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)]
        })
        .Where(wf => DateOnly.FromDateTime(wf.Date) >= rangeResult.From
                     && DateOnly.FromDateTime(wf.Date) <= rangeResult.To)
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d", locale),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int) (wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View("Index", weatherForecasts);
}

GitHub'da API örnek uygulaması, bir API denetleyicisi için önceki örneği gösterir.

Ile bağlama TryParse

API, TryParse bağlama denetleyicisi eylem parametresi değerlerini destekler:

public static bool TryParse(string value, T out result);
public static bool TryParse(string value, IFormatProvider provider, T out result);

IParsable<T>.TryParse parametre bağlaması için önerilen yaklaşımdır çünkü aksine TryParse, yansımaya bağımlı değildir.

Aşağıdaki DateRangeTP sınıf şunu uygular TryParse:

public class DateRangeTP
{
    public DateOnly? From { get; }
    public DateOnly? To { get; }

    public DateRangeTP(string from, string to)
    {
        if (string.IsNullOrEmpty(from))
            throw new ArgumentNullException(nameof(from));
        if (string.IsNullOrEmpty(to))
            throw new ArgumentNullException(nameof(to));

        From = DateOnly.Parse(from);
        To = DateOnly.Parse(to);
    }

    public static bool TryParse(string? value, out DateRangeTP? result)
    {
        var range = value?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        if (range?.Length != 2)
        {
            result = default;
            return false;
        }

        result = new DateRangeTP(range[0], range[1]);
        return true;
    }
}

Aşağıdaki denetleyici eylemi, bir tarih aralığını bağlamak için sınıfını DateRangeTP kullanır:

// GET /WeatherForecast/ByRangeTP?range=7/24/2022,07/26/2022
public IActionResult ByRangeTP([FromQuery] DateRangeTP range)
{
    if (!ModelState.IsValid)
        return View("Error", ModelState.Values.SelectMany(v => v.Errors));

    var weatherForecasts = 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)]
        })
        .Where(wf => DateOnly.FromDateTime(wf.Date) >= range.From
                     && DateOnly.FromDateTime(wf.Date) <= range.To)
        .Select(wf => new WeatherForecastViewModel
        {
            Date = wf.Date.ToString("d"),
            TemperatureC = wf.TemperatureC,
            TemperatureF = 32 + (int)(wf.TemperatureC / 0.5556),
            Summary = wf.Summary
        });

    return View("Index", weatherForecasts);
}

Karmaşık türler

Karmaşık bir türün, bağlanacak genel bir varsayılan oluşturucuya ve genel yazılabilir özelliklerine sahip olması gerekir. Model bağlama gerçekleştiğinde, sınıfı genel varsayılan oluşturucu kullanılarak örneği oluşturulur.

Karmaşık türün her özelliği için model bağlaması, prefix.property_name ad deseninin kaynaklarına bakar. Hiçbir şey bulunmazsa, ön ek olmadan yalnızca property_name arar. Öneki kullanma kararı özellik başına yapılmaz. Örneğin, içeren bir sorgu ?Instructor.Id=100&Name=fooile yöntemine OnGet(Instructor instructor)bağlı olarak, türünde Instructor elde edilen nesne şunları içerir:

  • Id olarak 100ayarlayın.
  • Name olarak nullayarlayın. Önceki sorgu parametresinde kullanıldığından model bağlamasının beklediği Instructor.NameInstructor.Id bir işlemdir.

Bir parametreye bağlama için ön ek parametre adıdır. Ortak özelliğe PageModel bağlama için ön ek, ortak özellik adıdır. Bazı öznitelikler, parametre veya özellik adının varsayılan kullanımını geçersiz kılmanıza olanak tanıyan bir Prefix özelliğe sahiptir.

Örneğin, karmaşık türün aşağıdaki Instructor sınıf olduğunu varsayalım:

public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Ön ek = parametre adı

Bağlanacak model adlı instructorToUpdatebir parametreyse:

public IActionResult OnPost(int? id, Instructor instructorToUpdate)

Model bağlama, anahtarının instructorToUpdate.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Ön ek = özellik adı

Bağlanacak model denetleyicinin veya PageModel sınıfın adlı Instructor bir özellikse:

[BindProperty]
public Instructor Instructor { get; set; }

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Özel ön ek

Bağlanacak model adlı instructorToUpdate bir parametreyse ve Bind bir öznitelik ön ek olarak belirtiyorsa Instructor :

public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Karmaşık tür hedefleri için öznitelikler

Karmaşık türlerin model bağlamasını denetlemek için çeşitli yerleşik öznitelikler kullanılabilir:

Uyarı

Bu öznitelikler, deftere nakledilmiş form verileri değerlerin kaynağı olduğunda model bağlamayı etkiler. Bunlar, ON ve XML istek gövdelerini işleyen JSgiriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[Bind] özniteliği

Bir sınıfa veya yöntem parametresine uygulanabilir. Modelin hangi özelliklerinin model bağlamaya dahil edilmesi gerektiğini belirtir. [Bind]giriş biçimlendiricilerini etkilemez.

Aşağıdaki örnekte, herhangi bir işleyici veya eylem yöntemi çağrıldığında yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[Bind("LastName,FirstMidName,HireDate")]
public class Instructor

Aşağıdaki örnekte, yöntem çağrıldığında OnPost yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[HttpPost]
public IActionResult OnPost(
    [Bind("LastName,FirstMidName,HireDate")] Instructor instructor)

[Bind] özniteliği, oluşturma senaryolarında aşırı paylaşıma karşı koruma sağlamak için kullanılabilir. Dışlanan özellikler değiştirilmeden bırakılmak yerine null veya varsayılan değer olarak ayarlandığından, düzenleme senaryolarında düzgün çalışmaz. Aşırı paylaşıma karşı savunma için, özniteliği yerine [Bind] görünüm modelleri önerilir. Daha fazla bilgi için bkz . Fazla paylaşımla ilgili güvenlik notu.

[ModelBinder] özniteliği

ModelBinderAttribute türlere, özelliklere veya parametrelere uygulanabilir. Belirli bir örneği veya türü bağlamak için kullanılan model bağlayıcısının türünü belirtmeye olanak tanır. Örneğin:

[HttpPost]
public IActionResult OnPost(
    [ModelBinder(typeof(MyInstructorModelBinder))] Instructor instructor)

Özniteliği, [ModelBinder] modele bağlı olduğunda bir özelliğin veya parametrenin adını değiştirmek için de kullanılabilir:

public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }

    // ...
}

[BindRequired] özniteliği

Bir modelin özelliği için bağlama gerçekleşemiyorsa model bağlamanın model durumu hatası eklemesine neden olur. Bir örnek aşağıda verilmiştir:

public class InstructorBindRequired
{
    // ...

    [BindRequired]
    public DateTime HireDate { get; set; }
}

Ayrıca Bkz. Model doğrulamasında özniteliğin [Required] tartışması.

[BindNever] özniteliği

Bir özelliğe veya türe uygulanabilir. Model bağlamanın modelin özelliğini ayarlamasını engeller. Bir türe uygulandığında, model bağlama sistemi türün tanımladığı tüm özellikleri dışlar. Bir örnek aşağıda verilmiştir:

public class InstructorBindNever
{
    [BindNever]
    public int Id { get; set; }

    // ...
}

Koleksiyonlar

Basit tür koleksiyonları olan hedefler için model bağlama, parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Bağlanacak parametrenin adlı selectedCoursesbir dizi olduğunu varsayalım:

    public IActionResult OnPost(int? id, int[] selectedCourses)
    
  • Form veya sorgu dizesi verileri aşağıdaki biçimlerden birinde olabilir:

    selectedCourses=1050&selectedCourses=2000 
    
    selectedCourses[0]=1050&selectedCourses[1]=2000
    
    [0]=1050&[1]=2000
    
    selectedCourses[a]=1050&selectedCourses[b]=2000&selectedCourses.index=a&selectedCourses.index=b
    
    [a]=1050&[b]=2000&index=a&index=b
    

    Bir parametreyi veya adlı index bir özelliği ya da Index bir koleksiyon değerine bitişikse bağlamaktan kaçının. Model bağlaması, koleksiyon için dizin olarak kullanmayı index dener ve bu da yanlış bağlamaya neden olabilir. Örneğin, aşağıdaki eylemi göz önünde bulundurun:

    public IActionResult Post(string index, List<Product> products)
    

    Yukarıdaki kodda index sorgu dizesi parametresi yöntem parametresine index bağlanır ve ayrıca ürün koleksiyonunu bağlamak için kullanılır. Parametrenin yeniden adlandırılması veya bağlamayı index yapılandırmak için bir model bağlama özniteliği kullanılması bu sorunu önler:

    public IActionResult Post(string productIndex, List<Product> products)
    
  • Aşağıdaki biçim yalnızca form verilerinde desteklenir:

    selectedCourses[]=1050&selectedCourses[]=2000
    
  • Önceki tüm örnek biçimler için, model bağlama parametresine selectedCourses iki öğeden oluşan bir dizi geçirir:

    • selectedCourses[0]=1050
    • selectedCourses[1]=2000

    Alt simge numaraları kullanan veri biçimleri (... [0] ... [1] ...) sıfırdan başlayarak sıralı olarak numaralandırıldığından emin olmalıdır. Alt simge numaralandırmasında boşluk varsa, boşluktan sonraki tüm öğeler yoksayılır. Örneğin, alt simgeler 0 ve 1 yerine 0 ve 2 ise, ikinci öğe yoksayılır.

Sözlükler

HedeflerdeDictionary, model bağlama parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Hedef parametrenin adlı selectedCoursesbir Dictionary<int, string> olduğunu varsayalım:

    public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
    
  • Gönderilen form veya sorgu dizesi verileri aşağıdaki örneklerden biri gibi görünebilir:

    selectedCourses[1050]=Chemistry&selectedCourses[2000]=Economics
    
    [1050]=Chemistry&selectedCourses[2000]=Economics
    
    selectedCourses[0].Key=1050&selectedCourses[0].Value=Chemistry&
    selectedCourses[1].Key=2000&selectedCourses[1].Value=Economics
    
    [0].Key=1050&[0].Value=Chemistry&[1].Key=2000&[1].Value=Economics
    
  • Yukarıdaki tüm örnek biçimler için model bağlama parametresine selectedCourses iki öğeden oluşan bir sözlük geçirir:

    • selectedCourses["1050"]="Kimya"
    • selectedCourses["2000"]="Economics"

Oluşturucu bağlama ve kayıt türleri

Model bağlama, karmaşık türlerin parametresiz bir oluşturucuya sahip olmasını gerektirir. Newtonsoft.Json Hem hem de System.Text.Json tabanlı giriş biçimlendiricileri, parametresiz oluşturucuya sahip olmayan sınıfların seri durumdan çıkarıldığını destekler.

Kayıt türleri, ağ üzerinden verileri kısa bir şekilde temsil etmenin harika bir yoludur. ASP.NET Core, tek bir oluşturucuyla model bağlamayı ve kayıt türlerini doğrulamayı destekler:

public record Person(
    [Required] string Name, [Range(0, 150)] int Age, [BindNever] int Id);

public class PersonController
{
    public IActionResult Index() => View();

    [HttpPost]
    public IActionResult Index(Person person)
    {
        // ...
    }
}

Person/Index.cshtml:

@model Person

Name: <input asp-for="Name" />
<br />
Age: <input asp-for="Age" />

Kayıt türleri doğrulanırken çalışma zamanı, özellikle özellikler yerine parametrelerde bağlama ve doğrulama meta verilerini arar.

Çerçeve, kayıt türlerini bağlamaya ve doğrulamaya olanak tanır:

public record Person([Required] string Name, [Range(0, 100)] int Age);

Öncekinin çalışması için türün şunları yapması gerekir:

  • Kayıt türü olun.
  • Tam olarak bir ortak oluşturucuya sahip olun.
  • Aynı ada ve türe sahip bir özelliğe sahip parametreleri içerir. Adların büyük/küçük harfe göre farklılık göstermemesi gerekir.

Parametresiz oluşturucuları olmayan POCO'lar

Parametresiz oluşturucuları olmayan POCO'lar bağlanamaz.

Aşağıdaki kod, türün parametresiz bir oluşturucuya sahip olması gerektiğini belirten bir özel durumla sonuçlar:

public class Person(string Name)

public record Person([Required] string Name, [Range(0, 100)] int Age)
{
    public Person(string Name) : this (Name, 0);
}

El ile yazılmış oluşturucularla kayıt türleri

Birincil oluşturucular gibi görünen el ile yazılmış oluşturucuların çalıştığı kayıt türleri

public record Person
{
    public Person([Required] string Name, [Range(0, 100)] int Age)
        => (this.Name, this.Age) = (Name, Age);

    public string Name { get; set; }
    public int Age { get; set; }
}

Kayıt türleri, doğrulama ve bağlama meta verileri

Kayıt türleri için parametrelerde doğrulama ve bağlama meta verileri kullanılır. Özelliklerdeki meta veriler yoksayılır

public record Person (string Name, int Age)
{
   [BindProperty(Name = "SomeName")] // This does not get used
   [Required] // This does not get used
   public string Name { get; init; }
}

Doğrulama ve meta veriler

Doğrulama parametresinde meta verileri kullanır, ancak değerini okumak için özelliğini kullanır. Birincil oluşturucular ile normal durumda, ikisi aynı olacaktır. Ancak, bunu yenmenin yolları vardır:

public record Person([Required] string Name)
{
    private readonly string _name;

    // The following property is never null.
    // However this object could have been constructed as "new Person(null)".
    public string Name { get; init => _name = value ?? string.Empty; }
}

TryUpdateModel bir kayıt türündeki parametreleri güncelleştirmez

public record Person(string Name)
{
    public int Age { get; set; }
}

var person = new Person("initial-name");
TryUpdateModel(person, ...);

Bu durumda, MVC yeniden bağlamayı Name denemez. Ancak, Age güncelleştirilmeye izin verilir

Model bağlama yönlendirme verilerinin ve sorgu dizelerinin genelleştirme davranışı

ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:

  • Değerleri sabit kültür olarak değerlendirin.
  • URL'lerin kültür sabiti olmasını beklenir.

Buna karşılık, form verilerinden gelen değerler kültüre duyarlı bir dönüştürmeden geçer. Bu, URL'lerin yerel ayarlar arasında paylaşılabilir olması için tasarım gereğidir.

ASP.NET Core yol değeri sağlayıcısının ve sorgu dizesi değer sağlayıcısının kültüre duyarlı bir dönüştürmeden geçirilmesini sağlamak için:

public class CultureQueryStringValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        _ = context ?? throw new ArgumentNullException(nameof(context));

        var query = context.ActionContext.HttpContext.Request.Query;
        if (query?.Count > 0)
        {
            context.ValueProviders.Add(
                new QueryStringValueProvider(
                    BindingSource.Query,
                    query,
                    CultureInfo.CurrentCulture));
        }

        return Task.CompletedTask;
    }
}
builder.Services.AddControllers(options =>
{
    var index = options.ValueProviderFactories.IndexOf(
        options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>()
            .Single());

    options.ValueProviderFactories[index] =
        new CultureQueryStringValueProviderFactory();
});

Özel veri türleri

Model bağlamanın işleyebileceği bazı özel veri türleri vardır.

IFormFile ve IFormFileCollection

HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile> desteklenir.

Cancellationtoken

Eylemler isteğe bağlı olarak parametresini CancellationToken bağlayabilir. Bu, HTTP isteğini temel alan bağlantı durdurulduğunda sinyalleri bağlar RequestAborted . Eylemler, denetleyici eylemlerinin bir parçası olarak yürütülen uzun süre çalışan zaman uyumsuz işlemleri iptal etmek için bu parametreyi kullanabilir.

Formcollection

Gönderilen form verilerinden tüm değerleri almak için kullanılır.

Giriş biçimlendiricileri

İstek gövdesindeki veriler ON, XML veya başka bir biçimde olabilir JS. Model bağlama, bu verileri ayrıştırmak için belirli bir içerik türünü işlemek üzere yapılandırılmış bir giriş biçimlendirici kullanır. varsayılan olarak ASP.NET Core, ON verilerini işlemek JSiçin ON tabanlı giriş biçimlendiricileri içerirJS. Diğer içerik türleri için başka biçimlendiriciler ekleyebilirsiniz.

ASP.NET Core, Consumes özniteliğine göre giriş biçimlendiricilerini seçer. Öznitelik yoksa İçerik Türü üst bilgisini kullanır.

Yerleşik XML giriş biçimlendiricilerini kullanmak için:

  • içindeProgram.cs, veya AddXmlDataContractSerializerFormattersöğesini arayınAddXmlSerializerFormatters.

    builder.Services.AddControllers()
        .AddXmlSerializerFormatters();
    
  • özniteliğini, istek gövdesinde Consumes XML beklenmesi gereken denetleyici sınıflarına veya eylem yöntemlerine uygulayın.

    [HttpPost]
    [Consumes("application/xml")]
    public ActionResult<Pet> Create(Pet pet)
    

    Daha fazla bilgi için bkz . XML Serileştirmeye Giriş.

Giriş biçimlendiricileri ile model bağlamayı özelleştirme

Giriş biçimlendiricisi, istek gövdesinden veri okumanın tüm sorumluluğunu alır. Bu işlemi özelleştirmek için giriş biçimlendiricisi tarafından kullanılan API'leri yapılandırın. Bu bölümde, adlı ObjectIdözel türü anlamak için tabanlı giriş biçimlendiricisinin System.Text.Jsonnasıl özelleştirileceği açıklanmaktadır.

Özel ObjectId bir özellik içeren aşağıdaki modeli göz önünde bulundurun:

public class InstructorObjectId
{
    [Required]
    public ObjectId ObjectId { get; set; } = null!;
}

kullanırken System.Text.Jsonmodel bağlama işlemini özelleştirmek için öğesinden JsonConverter<T>türetilmiş bir sınıf oluşturun:

internal class ObjectIdConverter : JsonConverter<ObjectId>
{
    public override ObjectId Read(
        ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => new(JsonSerializer.Deserialize<int>(ref reader, options));

    public override void Write(
        Utf8JsonWriter writer, ObjectId value, JsonSerializerOptions options)
        => writer.WriteNumberValue(value.Id);
}

Özel dönüştürücü kullanmak için özniteliğini JsonConverterAttribute türüne uygulayın. Aşağıdaki örnekte, ObjectId türü ile özel dönüştürücüsü olarak yapılandırılır ObjectIdConverter :

[JsonConverter(typeof(ObjectIdConverter))]
public record ObjectId(int Id);

Daha fazla bilgi için bkz . Özel dönüştürücüler yazma.

Belirtilen türleri model bağlamasından dışla

Model bağlama ve doğrulama sistemlerinin davranışı tarafından ModelMetadatayönlendirilir. MvcOptions.ModelMetadataDetailsProviders'a bir ayrıntı sağlayıcısı ekleyerek özelleştirebilirsinizModelMetadata. Yerleşik ayrıntılar sağlayıcıları, belirtilen türler için model bağlamasını veya doğrulamayı devre dışı bırakmak için kullanılabilir.

Belirtilen türdeki tüm modellerde model bağlamayı devre dışı bırakmak için içine bir ExcludeBindingMetadataProviderProgram.csekleyin. Örneğin, türündeki System.Versiontüm modellerde model bağlamayı devre dışı bırakmak için:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });

Belirtilen türün özelliklerinde doğrulamayı devre dışı bırakmak için içine ekleyin SuppressChildValidationMetadataProviderProgram.cs. Örneğin, türündeki System.Guidözelliklerde doğrulamayı devre dışı bırakmak için:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });

Özel model bağlayıcıları

Özel bir model bağlayıcısı yazarak ve özniteliğini kullanarak model bağlamayı [ModelBinder] belirli bir hedef için seçerek genişletebilirsiniz. Özel model bağlama hakkında daha fazla bilgi edinin.

El ile model bağlama

Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBasePageModel sınıflarında tanımlanır. Yöntem aşırı yüklemeleri, kullanılacak ön ek ve değer sağlayıcısını belirtmenize olanak sağlar. Yöntem, model bağlama başarısız olursa döndürür false . Bir örnek aşağıda verilmiştir:

if (await TryUpdateModelAsync(
    newInstructor,
    "Instructor",
    x => x.Name, x => x.HireDate!))
{
    _instructorStore.Add(newInstructor);
    return RedirectToPage("./Index");
}

return Page();

TryUpdateModelAsync form gövdesinden, sorgu dizesinden ve yönlendirme verilerinden veri almak için değer sağlayıcılarını kullanır. TryUpdateModelAsync genellikle:

  • Fazla gönderimi önlemek için denetleyiciler ve görünümler kullanılarak Sayfalar ve MVC uygulamalarıyla birlikte Razor kullanılır.
  • Form verilerinden, sorgu dizelerinden ve yönlendirme verilerinden kullanılmadığı sürece web API'siyle kullanılmaz. ON kullanan JSWeb API uç noktaları, istek gövdesini bir nesneye seri durumdan çıkarmak için Giriş biçimlendiricilerini kullanır.

Daha fazla bilgi için bkz . TryUpdateModelAsync.

[FromServices] özniteliği

Bu özniteliğin adı, bir veri kaynağı belirten model bağlama özniteliklerinin desenini izler. Ancak bu, bir değer sağlayıcısından verileri bağlamayla ilgili değildir. Bağımlılık ekleme kapsayıcısından bir türün örneğini alır. Amacı, yalnızca belirli bir yöntem çağrıldığında bir hizmete ihtiyacınız olduğunda oluşturucu eklemeye alternatif sağlamaktır.

Türün bir örneği bağımlılık ekleme kapsayıcısında kayıtlı değilse, uygulama parametresini bağlamaya çalışırken bir özel durum oluşturur. parametresini isteğe bağlı hale getirmek için aşağıdaki yaklaşımlardan birini kullanın:

  • Parametresini null atanabilir hale getirin.
  • parametresi için varsayılan bir değer ayarlayın.

Null atanabilir parametreler için, parametreye erişmeden önce bu parametrenin olmadığından null emin olun.

Ek kaynaklar

Bu makalede model bağlamanın ne olduğu, nasıl çalıştığı ve davranışının nasıl özelleştirileceği açıklanmaktadır.

Model bağlama nedir?

Denetleyiciler ve Razor sayfalar, HTTP isteklerinden gelen verilerle çalışır. Örneğin, yol verileri bir kayıt anahtarı sağlayabilir ve deftere nakledilmiş form alanları modelin özellikleri için değerler sağlayabilir. Bu değerlerin her birini almak ve bunları dizelerden .NET türlerine dönüştürmek için kod yazmak yorucu ve hataya açık olabilir. Model bağlama bu işlemi otomatikleştirir. Model bağlama sistemi:

  • Rota verileri, form alanları ve sorgu dizeleri gibi çeşitli kaynaklardan veri alır.
  • Verileri, yöntem parametrelerinde ve Razor genel özelliklerde denetleyicilere ve sayfalara sağlar.
  • Dize verilerini .NET türlerine dönüştürür.
  • Karmaşık türlerin özelliklerini Güncelleştirmeler.

Örnek

Aşağıdaki eylem yöntemine sahip olduğunuzu varsayalım:

[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)

Uygulama şu URL'ye sahip bir istek alır:

https://contoso.com/api/pets/2?DogsOnly=true

Model bağlama, yönlendirme sistemi eylem yöntemini seçtikten sonra aşağıdaki adımlardan geçer:

  • adlı idbir tamsayının GetByIdilk parametresini bulur.
  • HTTP isteğindeki kullanılabilir kaynakları arar ve yol verilerinde = "2" değerini bulur id .
  • "2" dizesini 2 tamsayısına dönüştürür.
  • adlı dogsOnlybir boole değerinin GetByIdsonraki parametresini bulur.
  • Kaynaklara bakar ve sorgu dizesinde "DogsOnly=true" değerini bulur. Ad eşleştirme büyük/küçük harfe duyarlı değildir.
  • "true" dizesini boole değerine truedönüştürür.

Çerçeve daha sonra parametresi için truedogsOnly ve parametresi için id 2'yi geçirerek yöntemini çağırırGetById.

Yukarıdaki örnekte, model bağlama hedefleri basit türler olan yöntem parametreleridir. Hedefler, karmaşık bir türün özellikleri de olabilir. Her özellik başarıyla bağlandıktan sonra, bu özellik için model doğrulaması gerçekleşir. Modele bağlı verilerin kaydı ve bağlama veya doğrulama hataları ControllerBase.ModelState veya PageModel.ModelState içinde depolanır. Bu işlemin başarılı olup olmadığını öğrenmek için uygulama ModelState.IsValid bayrağını denetler.

Hedefler

Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:

  • bir isteğin yönlendirıldığı denetleyici eylem yönteminin parametreleri.
  • bir isteğin Razor yönlendirıldığı Pages işleyici yönteminin parametreleri.
  • Öznitelikler tarafından belirtilirse, bir denetleyicinin veya PageModel sınıfın genel özellikleri.

[BindProperty] özniteliği

Model bağlamanın bu özelliği hedeflemesine neden olmak için bir denetleyicinin veya PageModel sınıfın ortak özelliğine uygulanabilir:

public class EditModel : PageModel
{
    [BindProperty]
    public Instructor? Instructor { get; set; }

    // ...
}

[BindProperties] özniteliği

Model bağlamasının sınıfın tüm genel özelliklerini hedeflemesini bildirmek için bir denetleyiciye veya PageModel sınıfa uygulanabilir:

[BindProperties]
public class CreateModel : PageModel
{
    public Instructor? Instructor { get; set; }

    // ...
}

HTTP GET istekleri için model bağlama

Varsayılan olarak, özellikler HTTP GET isteklerine bağlı değildir. Genellikle, GET isteği için ihtiyacınız olan tek şey bir kayıt kimliği parametresidir. Kayıt kimliği, veritabanındaki öğeyi aramak için kullanılır. Bu nedenle, modelin bir örneğini tutan bir özelliği bağlamaya gerek yoktur. GET isteklerindeki verilere bağlı özelliklerin olmasını istediğiniz senaryolarda özelliğini olarak trueayarlayınSupportsGet:

[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }

Kaynaklar

Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:

  1. Form alanları
  2. İstek gövdesi ([ApiController] özniteliğine sahip denetleyiciler için.)
  3. Veri yönlendirme
  4. Sorgu dizesi parametreleri
  5. Karşıya yüklenen dosyalar

Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:

  • Yönlendirme verileri ve sorgu dizesi değerleri yalnızca basit türler için kullanılır.
  • Karşıya yüklenen dosyalar yalnızca veya IEnumerable<IFormFile>uygulayan IFormFile hedef türlerine bağlıdır.

Varsayılan kaynak doğru değilse, kaynağı belirtmek için aşağıdaki özniteliklerden birini kullanın:

  • [FromQuery] - Sorgu dizesinden değerleri alır.
  • [FromRoute] - Rota verilerinden değerleri alır.
  • [FromForm] - Deftere nakledilen form alanlarından değerleri alır.
  • [FromBody] - İstek gövdesinden değerleri alır.
  • [FromHeader] - HTTP üst bilgilerinden değerleri alır.

Bu öznitelikler:

  • Aşağıdaki örnekte olduğu gibi model sınıfına değil model özelliklerine ayrı ayrı eklenir:

    public class Instructor
    {
        public int Id { get; set; }
    
        [FromQuery(Name = "Note")]
        public string? NoteFromQueryString { get; set; }
    
        // ...
    }
    
  • İsteğe bağlı olarak oluşturucuda bir model adı değeri kabul edin. Özellik adının istekteki değerle eşleşmemesi durumunda bu seçenek sağlanır. Örneğin, istekteki değer, aşağıdaki örnekte olduğu gibi adında kısa çizgi bulunan bir üst bilgi olabilir:

    public void OnGet([FromHeader(Name = "Accept-Language")] string language)
    

[FromBody] özniteliği

Özelliklerini bir HTTP isteğinin [FromBody] gövdesinden doldurmak için özniteliğini bir parametreye uygulayın. ASP.NET Core çalışma zamanı, gövdeyi okuma sorumluluğunu bir giriş biçimlendiricisine devreder. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[FromBody] Karmaşık bir tür parametresine uygulandığında, özelliklerine uygulanan bağlama kaynağı öznitelikleri yoksayılır. Örneğin, aşağıdaki Create eylem parametresinin gövdeden doldurulduğunu pet belirtir:

public ActionResult<Pet> Create([FromBody] Pet pet)

sınıfı, Pet özelliğinin Breed bir sorgu dizesi parametresinden doldurulduğunu belirtir:

public class Pet
{
    public string Name { get; set; } = null!;

    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; } = null!;
}

Yukarıdaki örnekte:

  • [FromQuery] Özniteliği yoksayılır.
  • Breed özelliği bir sorgu dizesi parametresinden doldurulmuyor.

Giriş biçimlendiricileri yalnızca gövdeyi okur ve bağlama kaynak özniteliklerini anlamaz. Gövdede uygun bir değer bulunursa, bu değer özelliği doldurmak Breed için kullanılır.

Eylem yöntemi başına birden fazla parametreye uygulamayın [FromBody] . İstek akışı bir giriş biçimlendiricisi tarafından okunduktan sonra, diğer [FromBody] parametreleri bağlamak için yeniden okunamayacaktır.

Ek kaynaklar

Kaynak veriler, değer sağlayıcıları tarafından model bağlama sistemine sağlanır. Diğer kaynaklardan model bağlama için veri alan özel değer sağlayıcıları yazabilir ve kaydedebilirsiniz. Örneğin, s veya oturum durumundan cookieveri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:

  • IValueProvider uygulayan bir sınıf oluşturun.
  • IValueProviderFactory uygulayan bir sınıf oluşturun.
  • fabrika sınıfını'na Program.cskaydedin.

Örnek, s değerlerini alan bir değer sağlayıcısı ve fabrika örneği içerir.cookie özel değer sağlayıcısı fabrikalarını içinde Program.cskaydedin:

builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
});

Yukarıdaki kod, özel değer sağlayıcısını tüm yerleşik değer sağlayıcılarının arkasına yerleştirir. Bunu listede ilk yapmak için yerine öğesini çağırın Insert(0, new CookieValueProviderFactory())Add.

Model özelliği için kaynak yok

Varsayılan olarak, bir model özelliği için değer bulunamazsa model durumu hatası oluşturulmaz. özelliği null veya varsayılan değer olarak ayarlanır:

  • Null atanabilir basit türler olarak nullayarlanır.
  • Null değer atanamayan değer türleri olarak default(T)ayarlanır. Örneğin, bir parametre int id 0 olarak ayarlanır.
  • Karmaşık Türler için model bağlama, özellikleri ayarlamadan varsayılan oluşturucuyu kullanarak bir örnek oluşturur.
  • Diziler olarak Array.Empty<T>()ayarlanır, ancak byte[] diziler olarak nullayarlanır.

Model özelliği için form alanlarında hiçbir şey bulunamazsa model durumu geçersiz kılınmalıdır, özniteliğini [BindRequired] kullanın.

Bu [BindRequired] davranışın, istek gövdesindeki ON veya XML verilerine değil, gönderilen form verilerinden model bağlama için JSgeçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.

Tür dönüştürme hataları

Bir kaynak bulunur ancak hedef türe dönüştürülemezse, model durumu geçersiz olarak işaretlenir. Hedef parametre veya özellik, önceki bölümde belirtildiği gibi null veya varsayılan değer olarak ayarlanır.

Özniteliği olan bir API denetleyicisinde [ApiController] geçersiz model durumu otomatik HTTP 400 yanıtıyla sonuçlandı.

Razor Sayfada, sayfayı bir hata iletisiyle yeniden dağıtın:

public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    // ...

    return RedirectToPage("./Index");
}

Sayfa önceki kod tarafından yeniden görüntülendiğinde, form alanında geçersiz giriş gösterilmez. Bunun nedeni model özelliğinin null veya varsayılan değer olarak ayarlanmış olmasıdır. Geçersiz giriş bir hata iletisinde görünüyor. Form alanındaki hatalı verileri yeniden görüntülemek istiyorsanız model özelliğini bir dize haline getirme ve veri dönüştürme işlemini el ile gerçekleştirmeyi göz önünde bulundurun.

Tür dönüştürme hatalarının model durumu hatalarına neden olmasını istemiyorsanız aynı strateji önerilir. Bu durumda, model özelliğini bir dize yapın.

Basit türler

Model bağlayıcısının kaynak dizeleri dönüştürebileceği basit türler şunlardır:

Karmaşık türler

Karmaşık bir türün, bağlanacak genel bir varsayılan oluşturucuya ve genel yazılabilir özelliklerine sahip olması gerekir. Model bağlama gerçekleştiğinde, sınıfı genel varsayılan oluşturucu kullanılarak örneği oluşturulur.

Karmaşık türün her özelliği için model bağlaması, prefix.property_name ad deseninin kaynaklarına bakar. Hiçbir şey bulunmazsa, ön ek olmadan yalnızca property_name arar. Öneki kullanma kararı özellik başına yapılmaz. Örneğin, içeren bir sorgu ?Instructor.Id=100&Name=fooile yöntemine OnGet(Instructor instructor)bağlı olarak, türünde Instructor elde edilen nesne şunları içerir:

  • Id olarak 100ayarlayın.
  • Name olarak nullayarlayın. Önceki sorgu parametresinde kullanıldığından model bağlamasının beklediği Instructor.NameInstructor.Id bir işlemdir.

Bir parametreye bağlama için ön ek parametre adıdır. Ortak özelliğe PageModel bağlama için ön ek, ortak özellik adıdır. Bazı öznitelikler, parametre veya özellik adının varsayılan kullanımını geçersiz kılmanıza olanak tanıyan bir Prefix özelliğe sahiptir.

Örneğin, karmaşık türün aşağıdaki Instructor sınıf olduğunu varsayalım:

public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Ön ek = parametre adı

Bağlanacak model adlı instructorToUpdatebir parametreyse:

public IActionResult OnPost(int? id, Instructor instructorToUpdate)

Model bağlama, anahtarının instructorToUpdate.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Ön ek = özellik adı

Bağlanacak model denetleyicinin veya PageModel sınıfın adlı Instructor bir özellikse:

[BindProperty]
public Instructor Instructor { get; set; }

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Özel ön ek

Bağlanacak model adlı instructorToUpdate bir parametreyse ve Bind bir öznitelik ön ek olarak belirtiyorsa Instructor :

public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Karmaşık tür hedefleri için öznitelikler

Karmaşık türlerin model bağlamasını denetlemek için çeşitli yerleşik öznitelikler kullanılabilir:

Uyarı

Bu öznitelikler, deftere nakledilmiş form verileri değerlerin kaynağı olduğunda model bağlamayı etkiler. Bunlar, ON ve XML istek gövdelerini işleyen JSgiriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[Bind] özniteliği

Bir sınıfa veya yöntem parametresine uygulanabilir. Modelin hangi özelliklerinin model bağlamaya dahil edilmesi gerektiğini belirtir. [Bind]giriş biçimlendiricilerini etkilemez.

Aşağıdaki örnekte, herhangi bir işleyici veya eylem yöntemi çağrıldığında yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[Bind("LastName,FirstMidName,HireDate")]
public class Instructor

Aşağıdaki örnekte, yöntem çağrıldığında OnPost yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[HttpPost]
public IActionResult OnPost(
    [Bind("LastName,FirstMidName,HireDate")] Instructor instructor)

[Bind] özniteliği, oluşturma senaryolarında aşırı paylaşıma karşı koruma sağlamak için kullanılabilir. Dışlanan özellikler değiştirilmeden bırakılmak yerine null veya varsayılan değer olarak ayarlandığından, düzenleme senaryolarında düzgün çalışmaz. Aşırı paylaşıma karşı savunma için, özniteliği yerine [Bind] görünüm modelleri önerilir. Daha fazla bilgi için bkz . Fazla paylaşımla ilgili güvenlik notu.

[ModelBinder] özniteliği

ModelBinderAttribute türlere, özelliklere veya parametrelere uygulanabilir. Belirli bir örneği veya türü bağlamak için kullanılan model bağlayıcısının türünü belirtmeye olanak tanır. Örneğin:

[HttpPost]
public IActionResult OnPost(
    [ModelBinder(typeof(MyInstructorModelBinder))] Instructor instructor)

Özniteliği, [ModelBinder] modele bağlı olduğunda bir özelliğin veya parametrenin adını değiştirmek için de kullanılabilir:

public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }

    // ...
}

[BindRequired] özniteliği

Bir modelin özelliği için bağlama gerçekleşemiyorsa model bağlamanın model durumu hatası eklemesine neden olur. Bir örnek aşağıda verilmiştir:

public class InstructorBindRequired
{
    // ...

    [BindRequired]
    public DateTime HireDate { get; set; }
}

Ayrıca Bkz. Model doğrulamasında özniteliğin [Required] tartışması.

[BindNever] özniteliği

Bir özelliğe veya türe uygulanabilir. Model bağlamanın modelin özelliğini ayarlamasını engeller. Bir türe uygulandığında, model bağlama sistemi türün tanımladığı tüm özellikleri dışlar. Bir örnek aşağıda verilmiştir:

public class InstructorBindNever
{
    [BindNever]
    public int Id { get; set; }

    // ...
}

Koleksiyonlar

Basit tür koleksiyonları olan hedefler için model bağlama, parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Bağlanacak parametrenin adlı selectedCoursesbir dizi olduğunu varsayalım:

    public IActionResult OnPost(int? id, int[] selectedCourses)
    
  • Form veya sorgu dizesi verileri aşağıdaki biçimlerden birinde olabilir:

    selectedCourses=1050&selectedCourses=2000 
    
    selectedCourses[0]=1050&selectedCourses[1]=2000
    
    [0]=1050&[1]=2000
    
    selectedCourses[a]=1050&selectedCourses[b]=2000&selectedCourses.index=a&selectedCourses.index=b
    
    [a]=1050&[b]=2000&index=a&index=b
    

    Bir parametreyi veya adlı index bir özelliği ya da Index bir koleksiyon değerine bitişikse bağlamaktan kaçının. Model bağlaması, koleksiyon için dizin olarak kullanmayı index dener ve bu da yanlış bağlamaya neden olabilir. Örneğin, aşağıdaki eylemi göz önünde bulundurun:

    public IActionResult Post(string index, List<Product> products)
    

    Yukarıdaki kodda index sorgu dizesi parametresi yöntem parametresine index bağlanır ve ayrıca ürün koleksiyonunu bağlamak için kullanılır. Parametrenin yeniden adlandırılması veya bağlamayı index yapılandırmak için bir model bağlama özniteliği kullanılması bu sorunu önler:

    public IActionResult Post(string productIndex, List<Product> products)
    
  • Aşağıdaki biçim yalnızca form verilerinde desteklenir:

    selectedCourses[]=1050&selectedCourses[]=2000
    
  • Önceki tüm örnek biçimler için, model bağlama parametresine selectedCourses iki öğeden oluşan bir dizi geçirir:

    • selectedCourses[0]=1050
    • selectedCourses[1]=2000

    Alt simge numaraları kullanan veri biçimleri (... [0] ... [1] ...) sıfırdan başlayarak sıralı olarak numaralandırıldığından emin olmalıdır. Alt simge numaralandırmasında boşluk varsa, boşluktan sonraki tüm öğeler yoksayılır. Örneğin, alt simgeler 0 ve 1 yerine 0 ve 2 ise, ikinci öğe yoksayılır.

Sözlükler

HedeflerdeDictionary, model bağlama parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Hedef parametrenin adlı selectedCoursesbir Dictionary<int, string> olduğunu varsayalım:

    public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
    
  • Gönderilen form veya sorgu dizesi verileri aşağıdaki örneklerden biri gibi görünebilir:

    selectedCourses[1050]=Chemistry&selectedCourses[2000]=Economics
    
    [1050]=Chemistry&selectedCourses[2000]=Economics
    
    selectedCourses[0].Key=1050&selectedCourses[0].Value=Chemistry&
    selectedCourses[1].Key=2000&selectedCourses[1].Value=Economics
    
    [0].Key=1050&[0].Value=Chemistry&[1].Key=2000&[1].Value=Economics
    
  • Yukarıdaki tüm örnek biçimler için model bağlama parametresine selectedCourses iki öğeden oluşan bir sözlük geçirir:

    • selectedCourses["1050"]="Kimya"
    • selectedCourses["2000"]="Economics"

Oluşturucu bağlama ve kayıt türleri

Model bağlama, karmaşık türlerin parametresiz bir oluşturucuya sahip olmasını gerektirir. Newtonsoft.Json Hem hem de System.Text.Json tabanlı giriş biçimlendiricileri, parametresiz oluşturucuya sahip olmayan sınıfların seri durumdan çıkarıldığını destekler.

Kayıt türleri, ağ üzerinden verileri kısa bir şekilde temsil etmenin harika bir yoludur. ASP.NET Core, tek bir oluşturucuyla model bağlamayı ve kayıt türlerini doğrulamayı destekler:

public record Person(
    [Required] string Name, [Range(0, 150)] int Age, [BindNever] int Id);

public class PersonController
{
    public IActionResult Index() => View();

    [HttpPost]
    public IActionResult Index(Person person)
    {
        // ...
    }
}

Person/Index.cshtml:

@model Person

Name: <input asp-for="Name" />
<br />
Age: <input asp-for="Age" />

Kayıt türleri doğrulanırken çalışma zamanı, özellikle özellikler yerine parametrelerde bağlama ve doğrulama meta verilerini arar.

Çerçeve, kayıt türlerini bağlamaya ve doğrulamaya olanak tanır:

public record Person([Required] string Name, [Range(0, 100)] int Age);

Öncekinin çalışması için türün şunları yapması gerekir:

  • Kayıt türü olun.
  • Tam olarak bir ortak oluşturucuya sahip olun.
  • Aynı ada ve türe sahip bir özelliğe sahip parametreleri içerir. Adların büyük/küçük harfe göre farklılık göstermemesi gerekir.

Parametresiz oluşturucuları olmayan POCO'lar

Parametresiz oluşturucuları olmayan POCO'lar bağlanamaz.

Aşağıdaki kod, türün parametresiz bir oluşturucuya sahip olması gerektiğini belirten bir özel durumla sonuçlar:

public class Person(string Name)

public record Person([Required] string Name, [Range(0, 100)] int Age)
{
    public Person(string Name) : this (Name, 0);
}

El ile yazılmış oluşturucularla kayıt türleri

Birincil oluşturucular gibi görünen el ile yazılmış oluşturucuların çalıştığı kayıt türleri

public record Person
{
    public Person([Required] string Name, [Range(0, 100)] int Age)
        => (this.Name, this.Age) = (Name, Age);

    public string Name { get; set; }
    public int Age { get; set; }
}

Kayıt türleri, doğrulama ve bağlama meta verileri

Kayıt türleri için parametrelerde doğrulama ve bağlama meta verileri kullanılır. Özelliklerdeki meta veriler yoksayılır

public record Person (string Name, int Age)
{
   [BindProperty(Name = "SomeName")] // This does not get used
   [Required] // This does not get used
   public string Name { get; init; }
}

Doğrulama ve meta veriler

Doğrulama parametresinde meta verileri kullanır, ancak değerini okumak için özelliğini kullanır. Birincil oluşturucular ile normal durumda, ikisi aynı olacaktır. Ancak, bunu yenmenin yolları vardır:

public record Person([Required] string Name)
{
    private readonly string _name;

    // The following property is never null.
    // However this object could have been constructed as "new Person(null)".
    public string Name { get; init => _name = value ?? string.Empty; }
}

TryUpdateModel bir kayıt türündeki parametreleri güncelleştirmez

public record Person(string Name)
{
    public int Age { get; set; }
}

var person = new Person("initial-name");
TryUpdateModel(person, ...);

Bu durumda, MVC yeniden bağlamayı Name denemez. Ancak, Age güncelleştirilmeye izin verilir

Model bağlama yönlendirme verilerinin ve sorgu dizelerinin genelleştirme davranışı

ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:

  • Değerleri sabit kültür olarak değerlendirin.
  • URL'lerin kültür sabiti olmasını beklenir.

Buna karşılık, form verilerinden gelen değerler kültüre duyarlı bir dönüştürmeden geçer. Bu, URL'lerin yerel ayarlar arasında paylaşılabilir olması için tasarım gereğidir.

ASP.NET Core yol değeri sağlayıcısının ve sorgu dizesi değer sağlayıcısının kültüre duyarlı bir dönüştürmeden geçirilmesini sağlamak için:

public class CultureQueryStringValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        _ = context ?? throw new ArgumentNullException(nameof(context));

        var query = context.ActionContext.HttpContext.Request.Query;
        if (query?.Count > 0)
        {
            context.ValueProviders.Add(
                new QueryStringValueProvider(
                    BindingSource.Query,
                    query,
                    CultureInfo.CurrentCulture));
        }

        return Task.CompletedTask;
    }
}
builder.Services.AddControllers(options =>
{
    var index = options.ValueProviderFactories.IndexOf(
        options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>()
            .Single());

    options.ValueProviderFactories[index] =
        new CultureQueryStringValueProviderFactory();
});

Özel veri türleri

Model bağlamanın işleyebileceği bazı özel veri türleri vardır.

IFormFile ve IFormFileCollection

HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile> desteklenir.

Cancellationtoken

Eylemler isteğe bağlı olarak parametresini CancellationToken bağlayabilir. Bu, HTTP isteğini temel alan bağlantı durdurulduğunda sinyalleri bağlar RequestAborted . Eylemler, denetleyici eylemlerinin bir parçası olarak yürütülen uzun süre çalışan zaman uyumsuz işlemleri iptal etmek için bu parametreyi kullanabilir.

Formcollection

Gönderilen form verilerinden tüm değerleri almak için kullanılır.

Giriş biçimlendiricileri

İstek gövdesindeki veriler ON, XML veya başka bir biçimde olabilir JS. Model bağlama, bu verileri ayrıştırmak için belirli bir içerik türünü işlemek üzere yapılandırılmış bir giriş biçimlendirici kullanır. varsayılan olarak ASP.NET Core, ON verilerini işlemek JSiçin ON tabanlı giriş biçimlendiricileri içerirJS. Diğer içerik türleri için başka biçimlendiriciler ekleyebilirsiniz.

ASP.NET Core, Consumes özniteliğine göre giriş biçimlendiricilerini seçer. Öznitelik yoksa İçerik Türü üst bilgisini kullanır.

Yerleşik XML giriş biçimlendiricilerini kullanmak için:

  • içindeProgram.cs, veya AddXmlDataContractSerializerFormattersöğesini arayınAddXmlSerializerFormatters.

    builder.Services.AddControllers()
        .AddXmlSerializerFormatters();
    
  • özniteliğini, istek gövdesinde Consumes XML beklenmesi gereken denetleyici sınıflarına veya eylem yöntemlerine uygulayın.

    [HttpPost]
    [Consumes("application/xml")]
    public ActionResult<Pet> Create(Pet pet)
    

    Daha fazla bilgi için bkz . XML Serileştirmeye Giriş.

Giriş biçimlendiricileri ile model bağlamayı özelleştirme

Giriş biçimlendiricisi, istek gövdesinden veri okumanın tüm sorumluluğunu alır. Bu işlemi özelleştirmek için giriş biçimlendiricisi tarafından kullanılan API'leri yapılandırın. Bu bölümde, adlı ObjectIdözel türü anlamak için tabanlı giriş biçimlendiricisinin System.Text.Jsonnasıl özelleştirileceği açıklanmaktadır.

Özel ObjectId bir özellik içeren aşağıdaki modeli göz önünde bulundurun:

public class InstructorObjectId
{
    [Required]
    public ObjectId ObjectId { get; set; } = null!;
}

kullanırken System.Text.Jsonmodel bağlama işlemini özelleştirmek için öğesinden JsonConverter<T>türetilmiş bir sınıf oluşturun:

internal class ObjectIdConverter : JsonConverter<ObjectId>
{
    public override ObjectId Read(
        ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => new(JsonSerializer.Deserialize<int>(ref reader, options));

    public override void Write(
        Utf8JsonWriter writer, ObjectId value, JsonSerializerOptions options)
        => writer.WriteNumberValue(value.Id);
}

Özel dönüştürücü kullanmak için özniteliğini JsonConverterAttribute türüne uygulayın. Aşağıdaki örnekte, ObjectId türü ile özel dönüştürücüsü olarak yapılandırılır ObjectIdConverter :

[JsonConverter(typeof(ObjectIdConverter))]
public record ObjectId(int Id);

Daha fazla bilgi için bkz . Özel dönüştürücüler yazma.

Belirtilen türleri model bağlamasından dışla

Model bağlama ve doğrulama sistemlerinin davranışı tarafından ModelMetadatayönlendirilir. MvcOptions.ModelMetadataDetailsProviders'a bir ayrıntı sağlayıcısı ekleyerek özelleştirebilirsinizModelMetadata. Yerleşik ayrıntılar sağlayıcıları, belirtilen türler için model bağlamasını veya doğrulamayı devre dışı bırakmak için kullanılabilir.

Belirtilen türdeki tüm modellerde model bağlamayı devre dışı bırakmak için içine bir ExcludeBindingMetadataProviderProgram.csekleyin. Örneğin, türündeki System.Versiontüm modellerde model bağlamayı devre dışı bırakmak için:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });

Belirtilen türün özelliklerinde doğrulamayı devre dışı bırakmak için içine ekleyin SuppressChildValidationMetadataProviderProgram.cs. Örneğin, türündeki System.Guidözelliklerde doğrulamayı devre dışı bırakmak için:

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });

Özel model bağlayıcıları

Özel bir model bağlayıcısı yazarak ve özniteliğini kullanarak model bağlamayı [ModelBinder] belirli bir hedef için seçerek genişletebilirsiniz. Özel model bağlama hakkında daha fazla bilgi edinin.

El ile model bağlama

Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBasePageModel sınıflarında tanımlanır. Yöntem aşırı yüklemeleri, kullanılacak ön ek ve değer sağlayıcısını belirtmenize olanak sağlar. Yöntem, model bağlama başarısız olursa döndürür false . Bir örnek aşağıda verilmiştir:

if (await TryUpdateModelAsync(
    newInstructor,
    "Instructor",
    x => x.Name, x => x.HireDate!))
{
    _instructorStore.Add(newInstructor);
    return RedirectToPage("./Index");
}

return Page();

TryUpdateModelAsync form gövdesinden, sorgu dizesinden ve yönlendirme verilerinden veri almak için değer sağlayıcılarını kullanır. TryUpdateModelAsync genellikle:

  • Fazla gönderimi önlemek için denetleyiciler ve görünümler kullanılarak Sayfalar ve MVC uygulamalarıyla birlikte Razor kullanılır.
  • Form verilerinden, sorgu dizelerinden ve yönlendirme verilerinden kullanılmadığı sürece web API'siyle kullanılmaz. ON kullanan JSWeb API uç noktaları, istek gövdesini bir nesneye seri durumdan çıkarmak için Giriş biçimlendiricilerini kullanır.

Daha fazla bilgi için bkz . TryUpdateModelAsync.

[FromServices] özniteliği

Bu özniteliğin adı, bir veri kaynağı belirten model bağlama özniteliklerinin desenini izler. Ancak bu, bir değer sağlayıcısından verileri bağlamayla ilgili değildir. Bağımlılık ekleme kapsayıcısından bir türün örneğini alır. Amacı, yalnızca belirli bir yöntem çağrıldığında bir hizmete ihtiyacınız olduğunda oluşturucu eklemeye alternatif sağlamaktır.

Türün bir örneği bağımlılık ekleme kapsayıcısında kayıtlı değilse, uygulama parametresini bağlamaya çalışırken bir özel durum oluşturur. parametresini isteğe bağlı hale getirmek için aşağıdaki yaklaşımlardan birini kullanın:

  • Parametresini null atanabilir hale getirin.
  • parametresi için varsayılan bir değer ayarlayın.

Null atanabilir parametreler için, parametreye erişmeden önce bu parametrenin olmadığından null emin olun.

Ek kaynaklar

Bu makalede model bağlamanın ne olduğu, nasıl çalıştığı ve davranışının nasıl özelleştirileceği açıklanmaktadır.

Örnek kodu görüntüleme veya indirme (indirme).

Model bağlama nedir?

Denetleyiciler ve Razor sayfalar, HTTP isteklerinden gelen verilerle çalışır. Örneğin, yol verileri bir kayıt anahtarı sağlayabilir ve deftere nakledilmiş form alanları modelin özellikleri için değerler sağlayabilir. Bu değerlerin her birini almak ve bunları dizelerden .NET türlerine dönüştürmek için kod yazmak yorucu ve hataya açık olabilir. Model bağlama bu işlemi otomatikleştirir. Model bağlama sistemi:

  • Rota verileri, form alanları ve sorgu dizeleri gibi çeşitli kaynaklardan veri alır.
  • Verileri, yöntem parametrelerinde ve Razor genel özelliklerde denetleyicilere ve sayfalara sağlar.
  • Dize verilerini .NET türlerine dönüştürür.
  • Karmaşık türlerin özelliklerini Güncelleştirmeler.

Örnek

Aşağıdaki eylem yöntemine sahip olduğunuzu varsayalım:

[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)

Uygulama şu URL'ye sahip bir istek alır:

http://contoso.com/api/pets/2?DogsOnly=true

Model bağlama, yönlendirme sistemi eylem yöntemini seçtikten sonra aşağıdaki adımlardan geçer:

  • adlı idbir tamsayının GetByIdilk parametresini bulur.
  • HTTP isteğindeki kullanılabilir kaynakları arar ve yol verilerinde = "2" değerini bulur id .
  • "2" dizesini 2 tamsayısına dönüştürür.
  • adlı dogsOnlybir boole değerinin GetByIdsonraki parametresini bulur.
  • Kaynaklara bakar ve sorgu dizesinde "DogsOnly=true" değerini bulur. Ad eşleştirme büyük/küçük harfe duyarlı değildir.
  • "true" dizesini boole değerine truedönüştürür.

Çerçeve daha sonra parametresi için truedogsOnly ve parametresi için id 2'yi geçirerek yöntemini çağırırGetById.

Yukarıdaki örnekte, model bağlama hedefleri basit türler olan yöntem parametreleridir. Hedefler, karmaşık bir türün özellikleri de olabilir. Her özellik başarıyla bağlandıktan sonra, bu özellik için model doğrulaması gerçekleşir. Modele bağlı verilerin kaydı ve bağlama veya doğrulama hataları ControllerBase.ModelState veya PageModel.ModelState içinde depolanır. Bu işlemin başarılı olup olmadığını öğrenmek için uygulama ModelState.IsValid bayrağını denetler.

Hedefler

Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:

  • bir isteğin yönlendirıldığı denetleyici eylem yönteminin parametreleri.
  • bir isteğin Razor yönlendirıldığı Pages işleyici yönteminin parametreleri.
  • Öznitelikler tarafından belirtilirse, bir denetleyicinin veya PageModel sınıfın genel özellikleri.

[BindProperty] özniteliği

Model bağlamanın bu özelliği hedeflemesine neden olmak için bir denetleyicinin veya PageModel sınıfın ortak özelliğine uygulanabilir:

public class EditModel : InstructorsPageModel
{
    [BindProperty]
    public Instructor Instructor { get; set; }

[BindProperties] özniteliği

ASP.NET Core 2.1 ve sonraki sürümlerde kullanılabilir. Model bağlamasının sınıfın tüm genel özelliklerini hedeflemesini bildirmek için bir denetleyiciye veya PageModel sınıfa uygulanabilir:

[BindProperties(SupportsGet = true)]
public class CreateModel : InstructorsPageModel
{
    public Instructor Instructor { get; set; }

HTTP GET istekleri için model bağlama

Varsayılan olarak, özellikler HTTP GET isteklerine bağlı değildir. Genellikle, GET isteği için ihtiyacınız olan tek şey bir kayıt kimliği parametresidir. Kayıt kimliği, veritabanındaki öğeyi aramak için kullanılır. Bu nedenle, modelin bir örneğini tutan bir özelliği bağlamaya gerek yoktur. GET isteklerindeki verilere bağlı özelliklerin olmasını istediğiniz senaryolarda özelliğini olarak trueayarlayınSupportsGet:

[BindProperty(Name = "ai_user", SupportsGet = true)]
public string ApplicationInsightsCookie { get; set; }

Kaynaklar

Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:

  1. Form alanları
  2. İstek gövdesi ([ApiController] özniteliğine sahip denetleyiciler için.)
  3. Veri yönlendirme
  4. Sorgu dizesi parametreleri
  5. Karşıya yüklenen dosyalar

Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:

  • Yönlendirme verileri ve sorgu dizesi değerleri yalnızca basit türler için kullanılır.
  • Karşıya yüklenen dosyalar yalnızca veya IEnumerable<IFormFile>uygulayan IFormFile hedef türlerine bağlıdır.

Varsayılan kaynak doğru değilse, kaynağı belirtmek için aşağıdaki özniteliklerden birini kullanın:

  • [FromQuery] - Sorgu dizesinden değerleri alır.
  • [FromRoute] - Rota verilerinden değerleri alır.
  • [FromForm] - Deftere nakledilen form alanlarından değerleri alır.
  • [FromBody] - İstek gövdesinden değerleri alır.
  • [FromHeader] - HTTP üst bilgilerinden değerleri alır.

Bu öznitelikler:

  • Aşağıdaki örnekte olduğu gibi model özelliklerine ayrı ayrı eklenir (model sınıfına eklenmez):

    public class Instructor
    {
        public int ID { get; set; }
    
        [FromQuery(Name = "Note")]
        public string NoteFromQueryString { get; set; }
    
  • İsteğe bağlı olarak oluşturucuda bir model adı değeri kabul edin. Özellik adının istekteki değerle eşleşmemesi durumunda bu seçenek sağlanır. Örneğin, istekteki değer, aşağıdaki örnekte olduğu gibi adında kısa çizgi bulunan bir üst bilgi olabilir:

    public void OnGet([FromHeader(Name = "Accept-Language")] string language)
    

[FromBody] özniteliği

Özelliklerini bir HTTP isteğinin [FromBody] gövdesinden doldurmak için özniteliğini bir parametreye uygulayın. ASP.NET Core çalışma zamanı, gövdeyi okuma sorumluluğunu bir giriş biçimlendiricisine devreder. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[FromBody] Karmaşık bir tür parametresine uygulandığında, özelliklerine uygulanan bağlama kaynağı öznitelikleri yoksayılır. Örneğin, aşağıdaki Create eylem parametresinin gövdeden doldurulduğunu pet belirtir:

public ActionResult<Pet> Create([FromBody] Pet pet)

sınıfı, Pet özelliğinin Breed bir sorgu dizesi parametresinden doldurulduğunu belirtir:

public class Pet
{
    public string Name { get; set; }

    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; }
}

Yukarıdaki örnekte:

  • [FromQuery] Özniteliği yoksayılır.
  • Breed özelliği bir sorgu dizesi parametresinden doldurulmuyor.

Giriş biçimlendiricileri yalnızca gövdeyi okur ve bağlama kaynak özniteliklerini anlamaz. Gövdede uygun bir değer bulunursa, bu değer özelliği doldurmak Breed için kullanılır.

Eylem yöntemi başına birden fazla parametreye uygulamayın [FromBody] . İstek akışı bir giriş biçimlendiricisi tarafından okunduktan sonra, diğer [FromBody] parametreleri bağlamak için yeniden okunamayacaktır.

Ek kaynaklar

Kaynak veriler, değer sağlayıcıları tarafından model bağlama sistemine sağlanır. Diğer kaynaklardan model bağlama için veri alan özel değer sağlayıcıları yazabilir ve kaydedebilirsiniz. Örneğin, s veya oturum durumundan cookieveri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:

  • IValueProvider uygulayan bir sınıf oluşturun.
  • IValueProviderFactory uygulayan bir sınıf oluşturun.
  • fabrika sınıfını'na Startup.ConfigureServiceskaydedin.

Örnek uygulama, s değerlerini alan bir değer sağlayıcısı ve fabrika örneği içerir.cookie kayıt kodu şu şekildedir Startup.ConfigureServices:

services.AddRazorPages()
    .AddMvcOptions(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version)));
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
})
.AddXmlSerializerFormatters();

Gösterilen kod, özel değer sağlayıcısını tüm yerleşik değer sağlayıcılarının arkasına yerleştirir. Bunu listede ilk yapmak için yerine öğesini çağırın Insert(0, new CookieValueProviderFactory())Add.

Model özelliği için kaynak yok

Varsayılan olarak, bir model özelliği için değer bulunamazsa model durumu hatası oluşturulmaz. özelliği null veya varsayılan değer olarak ayarlanır:

  • Null atanabilir basit türler olarak nullayarlanır.
  • Null değer atanamayan değer türleri olarak default(T)ayarlanır. Örneğin, bir parametre int id 0 olarak ayarlanır.
  • Karmaşık Türler için model bağlama, özellikleri ayarlamadan varsayılan oluşturucuyu kullanarak bir örnek oluşturur.
  • Diziler olarak Array.Empty<T>()ayarlanır, ancak byte[] diziler olarak nullayarlanır.

Model özelliği için form alanlarında hiçbir şey bulunamazsa model durumu geçersiz kılınmalıdır, özniteliğini [BindRequired] kullanın.

Bu [BindRequired] davranışın, istek gövdesindeki ON veya XML verilerine değil, gönderilen form verilerinden model bağlama için JSgeçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.

Tür dönüştürme hataları

Bir kaynak bulunur ancak hedef türe dönüştürülemezse, model durumu geçersiz olarak işaretlenir. Hedef parametre veya özellik, önceki bölümde belirtildiği gibi null veya varsayılan değer olarak ayarlanır.

Özniteliği olan bir API denetleyicisinde [ApiController] geçersiz model durumu otomatik HTTP 400 yanıtıyla sonuçlandı.

Razor Sayfada, sayfayı bir hata iletisiyle yeniden dağıtın:

public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _instructorsInMemoryStore.Add(Instructor);
    return RedirectToPage("./Index");
}

İstemci tarafı doğrulama, aksi takdirde Sayfalar Razor formuna gönderilecek çoğu hatalı veriyi yakalar. Bu doğrulama, önceki vurgulanan kodu tetiklemesini zorlaştırır. Örnek uygulama, hatalı verileri İşe Alma Tarihi alanına yerleştiren ve formu gönderen Geçersiz Tarihle Gönder düğmesini içerir. Bu düğme, veri dönüştürme hataları oluştuğunda sayfayı yeniden dağıtma kodunun nasıl çalıştığını gösterir.

Sayfa önceki kod tarafından yeniden görüntülendiğinde, form alanında geçersiz giriş gösterilmez. Bunun nedeni model özelliğinin null veya varsayılan değer olarak ayarlanmış olmasıdır. Geçersiz giriş bir hata iletisinde görünüyor. Ancak, form alanındaki hatalı verileri yeniden görüntülemek istiyorsanız model özelliğini bir dize haline getirme ve veri dönüştürme işlemini el ile gerçekleştirmeyi göz önünde bulundurun.

Tür dönüştürme hatalarının model durumu hatalarına neden olmasını istemiyorsanız aynı strateji önerilir. Bu durumda, model özelliğini bir dize yapın.

Basit türler

Model bağlayıcısının kaynak dizeleri dönüştürebileceği basit türler şunlardır:

Karmaşık türler

Karmaşık bir türün, bağlanacak genel bir varsayılan oluşturucuya ve genel yazılabilir özelliklerine sahip olması gerekir. Model bağlama gerçekleştiğinde, sınıfı genel varsayılan oluşturucu kullanılarak örneği oluşturulur.

Karmaşık türün her özelliği için model bağlaması, prefix.property_name ad deseninin kaynaklarına bakar. Hiçbir şey bulunmazsa, ön ek olmadan yalnızca property_name arar.

Bir parametreye bağlama için ön ek parametre adıdır. Ortak özelliğe PageModel bağlama için ön ek, ortak özellik adıdır. Bazı öznitelikler, parametre veya özellik adının varsayılan kullanımını geçersiz kılmanıza olanak tanıyan bir Prefix özelliğe sahiptir.

Örneğin, karmaşık türün aşağıdaki Instructor sınıf olduğunu varsayalım:

public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Ön ek = parametre adı

Bağlanacak model adlı instructorToUpdatebir parametreyse:

public IActionResult OnPost(int? id, Instructor instructorToUpdate)

Model bağlama, anahtarının instructorToUpdate.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Ön ek = özellik adı

Bağlanacak model denetleyicinin veya PageModel sınıfın adlı Instructor bir özellikse:

[BindProperty]
public Instructor Instructor { get; set; }

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Özel ön ek

Bağlanacak model adlı instructorToUpdate bir parametreyse ve Bind bir öznitelik ön ek olarak belirtiyorsa Instructor :

public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)

Model bağlama, anahtarının Instructor.IDkaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID .

Karmaşık tür hedefleri için öznitelikler

Karmaşık türlerin model bağlamasını denetlemek için çeşitli yerleşik öznitelikler kullanılabilir:

  • [Bind]
  • [BindRequired]
  • [BindNever]

Uyarı

Bu öznitelikler, deftere nakledilmiş form verileri değerlerin kaynağı olduğunda model bağlamayı etkiler. Bunlar, ON ve XML istek gövdelerini işleyen JSgiriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.

[Bind] özniteliği

Bir sınıfa veya yöntem parametresine uygulanabilir. Modelin hangi özelliklerinin model bağlamaya dahil edilmesi gerektiğini belirtir. [Bind]giriş biçimlendiricilerini etkilemez.

Aşağıdaki örnekte, herhangi bir işleyici veya eylem yöntemi çağrıldığında yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[Bind("LastName,FirstMidName,HireDate")]
public class Instructor

Aşağıdaki örnekte, yöntem çağrıldığında OnPost yalnızca modelin Instructor belirtilen özellikleri bağlıdır:

[HttpPost]
public IActionResult OnPost([Bind("LastName,FirstMidName,HireDate")] Instructor instructor)

[Bind] özniteliği, oluşturma senaryolarında aşırı paylaşıma karşı koruma sağlamak için kullanılabilir. Dışlanan özellikler değiştirilmeden bırakılmak yerine null veya varsayılan değer olarak ayarlandığından, düzenleme senaryolarında düzgün çalışmaz. Aşırı paylaşıma karşı savunma için, özniteliği yerine [Bind] görünüm modelleri önerilir. Daha fazla bilgi için bkz . Fazla paylaşımla ilgili güvenlik notu.

[ModelBinder] özniteliği

ModelBinderAttribute türlere, özelliklere veya parametrelere uygulanabilir. Belirli bir örneği veya türü bağlamak için kullanılan model bağlayıcısının türünü belirtmeye olanak tanır. Örneğin:

[HttpPost]
public IActionResult OnPost([ModelBinder(typeof(MyInstructorModelBinder))] Instructor instructor)

Özniteliği, [ModelBinder] modele bağlı olduğunda bir özelliğin veya parametrenin adını değiştirmek için de kullanılabilir:

public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }

    public string Name { get; set; }
}

[BindRequired] özniteliği

Yöntem parametrelerine değil, yalnızca model özelliklerine uygulanabilir. Bir modelin özelliği için bağlama gerçekleşemiyorsa model bağlamanın model durumu hatası eklemesine neden olur. Bir örnek aşağıda verilmiştir:

public class InstructorWithCollection
{
    public int ID { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [Display(Name = "Hire Date")]
    [BindRequired]
    public DateTime HireDate { get; set; }

Ayrıca Bkz. Model doğrulamasında özniteliğin [Required] tartışması.

[BindNever] özniteliği

Yöntem parametrelerine değil, yalnızca model özelliklerine uygulanabilir. Model bağlamanın modelin özelliğini ayarlamasını engeller. Bir örnek aşağıda verilmiştir:

public class InstructorWithDictionary
{
    [BindNever]
    public int ID { get; set; }

Koleksiyonlar

Basit tür koleksiyonları olan hedefler için model bağlama, parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Bağlanacak parametrenin adlı selectedCoursesbir dizi olduğunu varsayalım:

    public IActionResult OnPost(int? id, int[] selectedCourses)
    
  • Form veya sorgu dizesi verileri aşağıdaki biçimlerden birinde olabilir:

    selectedCourses=1050&selectedCourses=2000 
    
    selectedCourses[0]=1050&selectedCourses[1]=2000
    
    [0]=1050&[1]=2000
    
    selectedCourses[a]=1050&selectedCourses[b]=2000&selectedCourses.index=a&selectedCourses.index=b
    
    [a]=1050&[b]=2000&index=a&index=b
    

    Bir parametreyi veya adlı index bir özelliği ya da Index bir koleksiyon değerine bitişikse bağlamaktan kaçının. Model bağlaması, koleksiyon için dizin olarak kullanmayı index dener ve bu da yanlış bağlamaya neden olabilir. Örneğin, aşağıdaki eylemi göz önünde bulundurun:

    public IActionResult Post(string index, List<Product> products)
    

    Yukarıdaki kodda index sorgu dizesi parametresi yöntem parametresine index bağlanır ve ayrıca ürün koleksiyonunu bağlamak için kullanılır. Parametrenin yeniden adlandırılması veya bağlamayı index yapılandırmak için bir model bağlama özniteliği kullanılması bu sorunu önler:

    public IActionResult Post(string productIndex, List<Product> products)
    
  • Aşağıdaki biçim yalnızca form verilerinde desteklenir:

    selectedCourses[]=1050&selectedCourses[]=2000
    
  • Önceki tüm örnek biçimler için, model bağlama parametresine selectedCourses iki öğeden oluşan bir dizi geçirir:

    • selectedCourses[0]=1050
    • selectedCourses[1]=2000

    Alt simge numaraları kullanan veri biçimleri (... [0] ... [1] ...) sıfırdan başlayarak sıralı olarak numaralandırıldığından emin olmalıdır. Alt simge numaralandırmasında boşluk varsa, boşluktan sonraki tüm öğeler yoksayılır. Örneğin, alt simgeler 0 ve 1 yerine 0 ve 2 ise, ikinci öğe yoksayılır.

Sözlükler

HedeflerdeDictionary, model bağlama parameter_name veya property_name eşleşmeleri arar. Eşleşme bulunmazsa, ön ek olmadan desteklenen biçimlerden birini arar. Örneğin:

  • Hedef parametrenin adlı selectedCoursesbir Dictionary<int, string> olduğunu varsayalım:

    public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
    
  • Gönderilen form veya sorgu dizesi verileri aşağıdaki örneklerden biri gibi görünebilir:

    selectedCourses[1050]=Chemistry&selectedCourses[2000]=Economics
    
    [1050]=Chemistry&selectedCourses[2000]=Economics
    
    selectedCourses[0].Key=1050&selectedCourses[0].Value=Chemistry&
    selectedCourses[1].Key=2000&selectedCourses[1].Value=Economics
    
    [0].Key=1050&[0].Value=Chemistry&[1].Key=2000&[1].Value=Economics
    
  • Yukarıdaki tüm örnek biçimler için model bağlama parametresine selectedCourses iki öğeden oluşan bir sözlük geçirir:

    • selectedCourses["1050"]="Kimya"
    • selectedCourses["2000"]="Economics"

Oluşturucu bağlama ve kayıt türleri

Model bağlama, karmaşık türlerin parametresiz bir oluşturucuya sahip olmasını gerektirir. Newtonsoft.Json Hem hem de System.Text.Json tabanlı giriş biçimlendiricileri, parametresiz oluşturucuya sahip olmayan sınıfların seri durumdan çıkarıldığını destekler.

C# 9, ağ üzerinden verileri kısa bir şekilde temsil etmenin harika bir yolu olan kayıt türlerini tanıtır. ASP.NET Core, tek bir oluşturucuyla model bağlama ve kayıt türlerini doğrulama desteği ekler:

public record Person([Required] string Name, [Range(0, 150)] int Age, [BindNever] int Id);

public class PersonController
{
   public IActionResult Index() => View();

   [HttpPost]
   public IActionResult Index(Person person)
   {
       ...
   }
}

Person/Index.cshtml:

@model Person

Name: <input asp-for="Name" />
...
Age: <input asp-for="Age" />

Kayıt türleri doğrulanırken çalışma zamanı, özellikle özellikler yerine parametrelerde bağlama ve doğrulama meta verilerini arar.

Çerçeve, kayıt türlerini bağlamaya ve doğrulamaya olanak tanır:

public record Person([Required] string Name, [Range(0, 100)] int Age);

Öncekinin çalışması için türün şunları yapması gerekir:

  • Kayıt türü olun.
  • Tam olarak bir ortak oluşturucuya sahip olun.
  • Aynı ada ve türe sahip bir özelliğe sahip parametreleri içerir. Adların büyük/küçük harfe göre farklılık göstermemesi gerekir.

Parametresiz oluşturucuları olmayan POCO'lar

Parametresiz oluşturucuları olmayan POCO'lar bağlanamaz.

Aşağıdaki kod, türün parametresiz bir oluşturucuya sahip olması gerektiğini belirten bir özel durumla sonuçlar:

public class Person(string Name)

public record Person([Required] string Name, [Range(0, 100)] int Age)
{
   public Person(string Name) : this (Name, 0);
}

El ile yazılmış oluşturucularla kayıt türleri

Birincil oluşturucular gibi görünen el ile yazılmış oluşturucuların çalıştığı kayıt türleri

public record Person
{
   public Person([Required] string Name, [Range(0, 100)] int Age) => (this.Name, this.Age) = (Name, Age);

   public string Name { get; set; }
   public int Age { get; set; }
}

Kayıt türleri, doğrulama ve bağlama meta verileri

Kayıt türleri için parametrelerde doğrulama ve bağlama meta verileri kullanılır. Özelliklerdeki meta veriler yoksayılır

public record Person (string Name, int Age)
{
   [BindProperty(Name = "SomeName")] // This does not get used
   [Required] // This does not get used
   public string Name { get; init; }
}

Doğrulama ve meta veriler

Doğrulama parametresinde meta verileri kullanır, ancak değerini okumak için özelliğini kullanır. Birincil oluşturucular ile normal durumda, ikisi aynı olacaktır. Ancak, bunu yenmenin yolları vardır:

public record Person([Required] string Name)
{
   private readonly string _name;
   public Name { get; init => _name = value ?? string.Empty; } // Now this property is never null. However this object could have been constructed as `new Person(null);`
}

TryUpdateModel bir kayıt türündeki parametreleri güncelleştirmez

public record Person(string Name)
{
   public int Age { get; set; }
}

var person = new Person("initial-name");
TryUpdateModel(person, ...);

Bu durumda, MVC yeniden bağlamayı Name denemez. Ancak, Age güncelleştirilmeye izin verilir

Model bağlama yönlendirme verilerinin ve sorgu dizelerinin genelleştirme davranışı

ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:

  • Değerleri sabit kültür olarak değerlendirin.
  • URL'lerin kültür sabiti olmasını beklenir.

Buna karşılık, form verilerinden gelen değerler kültüre duyarlı bir dönüştürmeden geçer. Bu, URL'lerin yerel ayarlar arasında paylaşılabilir olması için tasarım gereğidir.

ASP.NET Core yol değeri sağlayıcısının ve sorgu dizesi değer sağlayıcısının kültüre duyarlı bir dönüştürmeden geçirilmesini sağlamak için:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
    {
        var index = options.ValueProviderFactories.IndexOf(
            options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>().Single());
        options.ValueProviderFactories[index] = new CulturedQueryStringValueProviderFactory();
    });
}
public class CulturedQueryStringValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        var query = context.ActionContext.HttpContext.Request.Query;
        if (query != null && query.Count > 0)
        {
            var valueProvider = new QueryStringValueProvider(
                BindingSource.Query,
                query,
                CultureInfo.CurrentCulture);

            context.ValueProviders.Add(valueProvider);
        }

        return Task.CompletedTask;
    }
}

Özel veri türleri

Model bağlamanın işleyebileceği bazı özel veri türleri vardır.

IFormFile ve IFormFileCollection

HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile> desteklenir.

Cancellationtoken

Eylemler isteğe bağlı olarak parametresini CancellationToken bağlayabilir. Bu, HTTP isteğini temel alan bağlantı durdurulduğunda sinyalleri bağlar RequestAborted . Eylemler, denetleyici eylemlerinin bir parçası olarak yürütülen uzun süre çalışan zaman uyumsuz işlemleri iptal etmek için bu parametreyi kullanabilir.

Formcollection

Gönderilen form verilerinden tüm değerleri almak için kullanılır.

Giriş biçimlendiricileri

İstek gövdesindeki veriler ON, XML veya başka bir biçimde olabilir JS. Model bağlama, bu verileri ayrıştırmak için belirli bir içerik türünü işlemek üzere yapılandırılmış bir giriş biçimlendirici kullanır. varsayılan olarak ASP.NET Core, ON verilerini işlemek JSiçin ON tabanlı giriş biçimlendiricileri içerirJS. Diğer içerik türleri için başka biçimlendiriciler ekleyebilirsiniz.

ASP.NET Core, Consumes özniteliğine göre giriş biçimlendiricilerini seçer. Öznitelik yoksa İçerik Türü üst bilgisini kullanır.

Yerleşik XML giriş biçimlendiricilerini kullanmak için:

  • Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet paketini yükleyin.

  • içindeStartup.ConfigureServices, veya AddXmlDataContractSerializerFormattersöğesini arayınAddXmlSerializerFormatters.

    services.AddRazorPages()
        .AddMvcOptions(options =>
    {
        options.ValueProviderFactories.Add(new CookieValueProviderFactory());
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(System.Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
    })
    .AddXmlSerializerFormatters();
    
  • özniteliğini, istek gövdesinde Consumes XML beklenmesi gereken denetleyici sınıflarına veya eylem yöntemlerine uygulayın.

    [HttpPost]
    [Consumes("application/xml")]
    public ActionResult<Pet> Create(Pet pet)
    

    Daha fazla bilgi için bkz . XML Serileştirmeye Giriş.

Giriş biçimlendiricileri ile model bağlamayı özelleştirme

Giriş biçimlendiricisi, istek gövdesinden veri okumanın tüm sorumluluğunu alır. Bu işlemi özelleştirmek için giriş biçimlendiricisi tarafından kullanılan API'leri yapılandırın. Bu bölümde, adlı ObjectIdözel türü anlamak için tabanlı giriş biçimlendiricisinin System.Text.Jsonnasıl özelleştirileceği açıklanmaktadır.

adlı Idözel ObjectId bir özellik içeren aşağıdaki modeli göz önünde bulundurun:

public class ModelWithObjectId
{
    public ObjectId Id { get; set; }
}

kullanırken System.Text.Jsonmodel bağlama işlemini özelleştirmek için öğesinden JsonConverter<T>türetilmiş bir sınıf oluşturun:

internal class ObjectIdConverter : JsonConverter<ObjectId>
{
    public override ObjectId Read(
        ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return new ObjectId(JsonSerializer.Deserialize<int>(ref reader, options));
    }

    public override void Write(
        Utf8JsonWriter writer, ObjectId value, JsonSerializerOptions options)
    {
        writer.WriteNumberValue(value.Id);
    }
}

Özel dönüştürücü kullanmak için özniteliğini JsonConverterAttribute türüne uygulayın. Aşağıdaki örnekte, ObjectId türü ile özel dönüştürücüsü olarak yapılandırılır ObjectIdConverter :

[JsonConverter(typeof(ObjectIdConverter))]
public struct ObjectId
{
    public ObjectId(int id) =>
        Id = id;

    public int Id { get; }
}

Daha fazla bilgi için bkz . Özel dönüştürücüler yazma.

Belirtilen türleri model bağlamasından dışla

Model bağlama ve doğrulama sistemlerinin davranışı tarafından ModelMetadatayönlendirilir. MvcOptions.ModelMetadataDetailsProviders'a bir ayrıntı sağlayıcısı ekleyerek özelleştirebilirsinizModelMetadata. Yerleşik ayrıntılar sağlayıcıları, belirtilen türler için model bağlamasını veya doğrulamayı devre dışı bırakmak için kullanılabilir.

Belirtilen türdeki tüm modellerde model bağlamayı devre dışı bırakmak için içine bir ExcludeBindingMetadataProviderStartup.ConfigureServicesekleyin. Örneğin, türündeki System.Versiontüm modellerde model bağlamayı devre dışı bırakmak için:

services.AddRazorPages()
    .AddMvcOptions(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version)));
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
})
.AddXmlSerializerFormatters();

Belirtilen türün özelliklerinde doğrulamayı devre dışı bırakmak için içine ekleyin SuppressChildValidationMetadataProviderStartup.ConfigureServices. Örneğin, türündeki System.Guidözelliklerde doğrulamayı devre dışı bırakmak için:

services.AddRazorPages()
    .AddMvcOptions(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version)));
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
})
.AddXmlSerializerFormatters();

Özel model bağlayıcıları

Özel bir model bağlayıcısı yazarak ve özniteliğini kullanarak model bağlamayı [ModelBinder] belirli bir hedef için seçerek genişletebilirsiniz. Özel model bağlama hakkında daha fazla bilgi edinin.

El ile model bağlama

Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBasePageModel sınıflarında tanımlanır. Yöntem aşırı yüklemeleri, kullanılacak ön ek ve değer sağlayıcısını belirtmenize olanak sağlar. Yöntem, model bağlama başarısız olursa döndürür false . Bir örnek aşağıda verilmiştir:

if (await TryUpdateModelAsync<InstructorWithCollection>(
    newInstructor,
    "Instructor",
    i => i.FirstMidName, i => i.LastName, i => i.HireDate))
{
    _instructorsInMemoryStore.Add(newInstructor);
    return RedirectToPage("./Index");
}
PopulateAssignedCourseData(newInstructor);
return Page();

TryUpdateModelAsync form gövdesinden, sorgu dizesinden ve yönlendirme verilerinden veri almak için değer sağlayıcılarını kullanır. TryUpdateModelAsync genellikle:

  • Fazla gönderimi önlemek için denetleyiciler ve görünümler kullanılarak Sayfalar ve MVC uygulamalarıyla birlikte Razor kullanılır.
  • Form verilerinden, sorgu dizelerinden ve yönlendirme verilerinden kullanılmadığı sürece web API'siyle kullanılmaz. ON kullanan JSWeb API uç noktaları, istek gövdesini bir nesneye seri durumdan çıkarmak için Giriş biçimlendiricilerini kullanır.

Daha fazla bilgi için bkz . TryUpdateModelAsync.

[FromServices] özniteliği

Bu özniteliğin adı, bir veri kaynağı belirten model bağlama özniteliklerinin desenini izler. Ancak bu, bir değer sağlayıcısından verileri bağlamayla ilgili değildir. Bağımlılık ekleme kapsayıcısından bir türün örneğini alır. Amacı, yalnızca belirli bir yöntem çağrıldığında bir hizmete ihtiyacınız olduğunda oluşturucu eklemeye alternatif sağlamaktır.

Ek kaynaklar