Ekinlikler
19 Kas 23 - 21 Kas 23
Becerilerinizi genişletmek ve günümüzün karmaşık sorunlarını çözmenize yardımcı olmak için oluşturulan Microsoft Ignite'daki çevrimiçi oturumlara katılın.
Hemen kaydolunBu tarayıcı artık desteklenmiyor.
En son özelliklerden, güvenlik güncelleştirmelerinden ve teknik destekten faydalanmak için Microsoft Edge’e yükseltin.
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 9 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.
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:
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:
id
bir tamsayının GetById
ilk parametresini bulur.id
.dogsOnly
bir boole değerinin GetById
sonraki parametresini bulur.true
dönüştürür.Çerçeve daha sonra parametresi için true
dogsOnly
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.
Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:
PageModel
sınıfın genel özellikleri.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; }
// ...
}
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; }
// ...
}
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 true
ayarlayınSupportsGet
:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
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 TypeConverter
TryParse
varlığı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 string
SomeType
dönüştürme için kullanmanızı TryParse
öneririz.
Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:
Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:
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)
Ö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.
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, tanımlama bilgilerinden veya oturum durumundan veri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:
IValueProvider
uygulayan bir sınıf oluşturun.IValueProviderFactory
uygulayan bir sınıf oluşturun.Program.cs
kaydedin.Örnek, tanımlama bilgilerinden değer alan bir değer sağlayıcısı ve fabrika örneği içerir. özel değer sağlayıcısı fabrikalarını içinde Program.cs
kaydedin:
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
.
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
ayarlanır.default(T)
ayarlanır. Örneğin, bir parametre int id
0 olarak ayarlanır.Array.Empty<T>()
ayarlanır, ancak byte[]
diziler olarak null
ayarlanı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, bir istek gövdesindeki JSON veya XML verilerine değil, gönderilen form verilerinden model bağlama için geçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.
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 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:
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:
DateRange
dönüştürürIParsable<TSelf>.TryParse
, bağlamak için DateRange
yö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 CultureInfo
uygularIParsable<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ı CultureInfo
bağ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.
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 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=foo
ile yöntemine OnGet(Instructor instructor)
bağlı olarak, türünde Instructor
elde edilen nesne şunları içerir:
Id
olarak 100
ayarlayın.Name
olarak null
ayarlayın. Önceki sorgu parametresinde kullanıldığından model bağlamasının beklediği Instructor.Name
Instructor.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; }
}
Bağlanacak model adlı instructorToUpdate
bir parametreyse:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Model bağlama, anahtarının instructorToUpdate.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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, gönderilen JSON ve XML istek gövdelerini işleyen giriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.
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. Fazla paylaşıma karşı koruma 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.
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; }
// ...
}
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ı.
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; }
// ...
}
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ı selectedCourses
bir 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:
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.
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ı selectedCourses
bir 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:
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
<label>Name: <input asp-for="Name" /></label>
<br />
<label>Age: <input asp-for="Age" /></label>
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:
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);
}
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 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 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; }
}
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
ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:
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();
});
Model bağlamanın işleyebileceği bazı özel veri türleri vardır.
HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile>
desteklenir.
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.
Gönderilen form verilerinden tüm değerleri almak için kullanılır.
İstek gövdesindeki veriler JSON, XML veya başka bir biçimde olabilir. 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, JSON verilerini işlemek için JSON tabanlı giriş biçimlendiricileri içerir. 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ç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.Json
nası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.Json
model 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.
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 ExcludeBindingMetadataProvider Program.cs
ekleyin. Örneğin, türündeki System.Version
tü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 SuppressChildValidationMetadataProvider Program.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 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.
Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBase
PageModel
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:
Daha fazla bilgi için bkz . TryUpdateModelAsync.
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:
Null atanabilir parametreler için, parametreye erişmeden önce bu parametrenin olmadığından null
emin olun.
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.
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:
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:
id
bir tamsayının GetById
ilk parametresini bulur.id
.dogsOnly
bir boole değerinin GetById
sonraki parametresini bulur.true
dönüştürür.Çerçeve daha sonra parametresi için true
dogsOnly
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.
Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:
PageModel
sınıfın genel özellikleri.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; }
// ...
}
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; }
// ...
}
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 true
ayarlayınSupportsGet
:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
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 TypeConverter
TryParse
varlığı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 string
SomeType
dönüştürme için kullanmanızı TryParse
öneririz.
Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:
Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:
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)
Ö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.
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, tanımlama bilgilerinden veya oturum durumundan veri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:
IValueProvider
uygulayan bir sınıf oluşturun.IValueProviderFactory
uygulayan bir sınıf oluşturun.Program.cs
kaydedin.Örnek, tanımlama bilgilerinden değer alan bir değer sağlayıcısı ve fabrika örneği içerir. özel değer sağlayıcısı fabrikalarını içinde Program.cs
kaydedin:
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
.
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
ayarlanır.default(T)
ayarlanır. Örneğin, bir parametre int id
0 olarak ayarlanır.Array.Empty<T>()
ayarlanır, ancak byte[]
diziler olarak null
ayarlanı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, bir istek gövdesindeki JSON veya XML verilerine değil, gönderilen form verilerinden model bağlama için geçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.
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 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:
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:
DateRange
dönüştürürIParsable<TSelf>.TryParse
, bağlamak için DateRange
yö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 CultureInfo
uygularIParsable<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ı CultureInfo
bağ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.
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 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=foo
ile yöntemine OnGet(Instructor instructor)
bağlı olarak, türünde Instructor
elde edilen nesne şunları içerir:
Id
olarak 100
ayarlayın.Name
olarak null
ayarlayın. Önceki sorgu parametresinde kullanıldığından model bağlamasının beklediği Instructor.Name
Instructor.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; }
}
Bağlanacak model adlı instructorToUpdate
bir parametreyse:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Model bağlama, anahtarının instructorToUpdate.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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, gönderilen JSON ve XML istek gövdelerini işleyen giriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.
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. Fazla paylaşıma karşı koruma 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.
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; }
// ...
}
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ı.
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; }
// ...
}
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ı selectedCourses
bir 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:
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.
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ı selectedCourses
bir 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:
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
<label>Name: <input asp-for="Name" /></label>
<br />
<label>Age: <input asp-for="Age" /></label>
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:
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);
}
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 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 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; }
}
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
ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:
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();
});
Model bağlamanın işleyebileceği bazı özel veri türleri vardır.
HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile>
desteklenir.
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.
Gönderilen form verilerinden tüm değerleri almak için kullanılır.
İstek gövdesindeki veriler JSON, XML veya başka bir biçimde olabilir. 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, JSON verilerini işlemek için JSON tabanlı giriş biçimlendiricileri içerir. 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ç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.Json
nası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.Json
model 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.
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 ExcludeBindingMetadataProvider Program.cs
ekleyin. Örneğin, türündeki System.Version
tü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 SuppressChildValidationMetadataProvider Program.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 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.
Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBase
PageModel
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:
Daha fazla bilgi için bkz . TryUpdateModelAsync.
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:
Null atanabilir parametreler için, parametreye erişmeden önce bu parametrenin olmadığından null
emin olun.
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.
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:
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:
id
bir tamsayının GetById
ilk parametresini bulur.id
.dogsOnly
bir boole değerinin GetById
sonraki parametresini bulur.true
dönüştürür.Çerçeve daha sonra parametresi için true
dogsOnly
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.
Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:
PageModel
sınıfın genel özellikleri.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; }
// ...
}
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; }
// ...
}
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 true
ayarlayınSupportsGet
:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:
Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:
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)
Ö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.
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, tanımlama bilgilerinden veya oturum durumundan veri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:
IValueProvider
uygulayan bir sınıf oluşturun.IValueProviderFactory
uygulayan bir sınıf oluşturun.Program.cs
kaydedin.Örnek, tanımlama bilgilerinden değer alan bir değer sağlayıcısı ve fabrika örneği içerir. özel değer sağlayıcısı fabrikalarını içinde Program.cs
kaydedin:
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
.
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
ayarlanır.default(T)
ayarlanır. Örneğin, bir parametre int id
0 olarak ayarlanır.Array.Empty<T>()
ayarlanır, ancak byte[]
diziler olarak null
ayarlanı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, bir istek gövdesindeki JSON veya XML verilerine değil, gönderilen form verilerinden model bağlama için geçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.
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.
Model bağlayıcısının kaynak dizeleri dönüştürebileceği basit türler şunlardır:
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=foo
ile yöntemine OnGet(Instructor instructor)
bağlı olarak, türünde Instructor
elde edilen nesne şunları içerir:
Id
olarak 100
ayarlayın.Name
olarak null
ayarlayın. Önceki sorgu parametresinde kullanıldığından model bağlamasının beklediği Instructor.Name
Instructor.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; }
}
Bağlanacak model adlı instructorToUpdate
bir parametreyse:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Model bağlama, anahtarının instructorToUpdate.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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, gönderilen JSON ve XML istek gövdelerini işleyen giriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.
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. Fazla paylaşıma karşı koruma 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.
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; }
// ...
}
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ı.
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; }
// ...
}
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ı selectedCourses
bir 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:
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.
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ı selectedCourses
bir 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:
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
<label>Name: <input asp-for="Name" /></label>
<br />
<label>Age: <input asp-for="Age" /></label>
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:
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);
}
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 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 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; }
}
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
ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:
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();
});
Model bağlamanın işleyebileceği bazı özel veri türleri vardır.
HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile>
desteklenir.
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.
Gönderilen form verilerinden tüm değerleri almak için kullanılır.
İstek gövdesindeki veriler JSON, XML veya başka bir biçimde olabilir. 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, JSON verilerini işlemek için JSON tabanlı giriş biçimlendiricileri içerir. 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ç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.Json
nası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.Json
model 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.
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 ExcludeBindingMetadataProvider Program.cs
ekleyin. Örneğin, türündeki System.Version
tü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 SuppressChildValidationMetadataProvider Program.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 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.
Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBase
PageModel
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:
Daha fazla bilgi için bkz . TryUpdateModelAsync.
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:
Null atanabilir parametreler için, parametreye erişmeden önce bu parametrenin olmadığından null
emin olun.
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).
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:
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:
id
bir tamsayının GetById
ilk parametresini bulur.id
.dogsOnly
bir boole değerinin GetById
sonraki parametresini bulur.true
dönüştürür.Çerçeve daha sonra parametresi için true
dogsOnly
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.
Model bağlama, aşağıdaki hedef türleri için değerleri bulmaya çalışır:
PageModel
sınıfın genel özellikleri.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; }
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; }
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 true
ayarlayınSupportsGet
:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string ApplicationInsightsCookie { get; set; }
Varsayılan olarak, model bağlama bir HTTP isteğinde aşağıdaki kaynaklardan anahtar-değer çiftleri biçiminde veri alır:
Her hedef parametre veya özellik için kaynaklar, önceki listede belirtilen sırayla taranır. Birkaç özel durum vardır:
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)
Ö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.
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, tanımlama bilgilerinden veya oturum durumundan veri isteyebilirsiniz. Yeni bir kaynaktan veri almak için:
IValueProvider
uygulayan bir sınıf oluşturun.IValueProviderFactory
uygulayan bir sınıf oluşturun.Startup.ConfigureServices
kaydedin.Örnek uygulama, tanımlama bilgilerinden değer alan bir değer sağlayıcısı ve fabrika örneği içerir. 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
.
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
ayarlanır.default(T)
ayarlanır. Örneğin, bir parametre int id
0 olarak ayarlanır.Array.Empty<T>()
ayarlanır, ancak byte[]
diziler olarak null
ayarlanı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, bir istek gövdesindeki JSON veya XML verilerine değil, gönderilen form verilerinden model bağlama için geçerli olduğunu unutmayın. İstek gövdesi verileri giriş biçimlendiricileri tarafından işlenir.
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.
Model bağlayıcısının kaynak dizeleri dönüştürebileceği basit türler şunlardır:
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; }
}
Bağlanacak model adlı instructorToUpdate
bir parametreyse:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Model bağlama, anahtarının instructorToUpdate.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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.ID
kaynaklarına bakarak başlar. Bu bulunamazsa, ön ek olmadan arar ID
.
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, gönderilen JSON ve XML istek gövdelerini işleyen giriş biçimlendiricilerini etkilemez. Giriş biçimlendiricileri bu makalenin ilerleyen bölümlerinde açıklanmıştır.
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. Fazla paylaşıma karşı koruma 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.
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; }
}
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ı.
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; }
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ı selectedCourses
bir 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:
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.
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ı selectedCourses
bir 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:
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
<label>Name: <input asp-for="Name" /></label>
...
<label>Age: <input asp-for="Age" /></label>
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:
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);
}
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 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 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);`
}
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
ASP.NET Core yol değeri sağlayıcısı ve sorgu dizesi değer sağlayıcısı:
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;
}
}
Model bağlamanın işleyebileceği bazı özel veri türleri vardır.
HTTP isteğine eklenen karşıya yüklenen bir dosya. Ayrıca, birden çok dosya için de IEnumerable<IFormFile>
desteklenir.
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.
Gönderilen form verilerinden tüm değerleri almak için kullanılır.
İstek gövdesindeki veriler JSON, XML veya başka bir biçimde olabilir. 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, JSON verilerini işlemek için JSON tabanlı giriş biçimlendiricileri içerir. 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ç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.Json
nası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.Json
model 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.
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 ExcludeBindingMetadataProvider Startup.ConfigureServices
ekleyin. Örneğin, türündeki System.Version
tü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 SuppressChildValidationMetadataProvider Startup.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 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.
Model bağlama yöntemi kullanılarak TryUpdateModelAsync el ile çağrılabilir. yöntemi hem hem de ControllerBase
PageModel
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:
Daha fazla bilgi için bkz . TryUpdateModelAsync.
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.
ASP.NET Core geri bildirimi
ASP.NET Core, açık kaynak bir projedir. Geri bildirim sağlamak için bir bağlantı seçin:
Ekinlikler
19 Kas 23 - 21 Kas 23
Becerilerinizi genişletmek ve günümüzün karmaşık sorunlarını çözmenize yardımcı olmak için oluşturulan Microsoft Ignite'daki çevrimiçi oturumlara katılın.
Hemen kaydolunEğitim
Modül
.NET MAUI'de veri bağlama kullanan bir kullanıcı arabirimi oluşturun. - Training
Veri bağlama ile bir kullanıcı arabirimi oluşturun. Kullanıcı arabiriminiz en son verilere göre otomatik olarak güncelleştirilirken, veriler kullanıcı arabirimindeki değişikliklere yanıt olarak güncelleştirilir.