Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Warning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Important
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Den här artikeln förklarar vad modellbindning är, hur den fungerar och hur du anpassar dess beteende.
Vad är modellbindning
Kontrollanter och Razor sidor fungerar med data som kommer från HTTP-begäranden. Routningsdata kan till exempel ge en postnyckel, och publicerade formulärfält kan ge värden för modellens egenskaper. Att skriva kod för att hämta vart och ett av dessa värden och konvertera dem från strängar till .NET-typer skulle vara omständligt och felbenäget. Modellbindning automatiserar den här processen. Modellbindningssystemet:
- Hämtar data från olika källor, till exempel routningsdata, formulärfält och frågesträngar.
- Tillhandahåller data till kontroller och Razor sidor i metodparametrar och publika egenskaper.
- Konverterar strängdata till .NET-typer.
- Uppdaterar egenskaper för komplexa typer.
Example
Anta att du har följande åtgärdsmetod:
[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)
Och appen får en begäran med den här URL:en:
https://contoso.com/api/pets/2?DogsOnly=true
Modellbindningen går igenom följande steg när routningssystemet har valt åtgärdsmetoden:
- Hittar den första parametern i GetById, ett heltal med namnetid.
- Söker igenom de tillgängliga källorna i HTTP-begäran och hittar id= "2" i routningsdata.
- Konverterar strängen "2" till heltal 2.
- Hittar nästa parameter i GetById, ett booleskt värde med namnetdogsOnly.
- Söker igenom källorna och hittar "DogsOnly=true" i frågesträngen. Namnmatchning är inte skiftlägeskänsligt.
- Konverterar strängen "true" till boolesk true.
Ramverket anropar GetById sedan metoden och skickar in 2 för parametern id och true för parametern dogsOnly .
I föregående exempel är modellbindningsmålen metodparametrar som är enkla typer. Mål kan också vara egenskaper för en komplex typ. När varje egenskap har bundits sker modellverifiering för den egenskapen. Posten för vilka data som är bundna till modellen och eventuella bindnings- eller valideringsfel lagras i ControllerBase.ModelState eller PageModel.ModelState. För att ta reda på om den här processen lyckades kontrollerar appen flaggan ModelState.IsValid .
Targets
Modellbindning försöker hitta värden för följande typer av mål:
- Parametrar för den kontrollantåtgärdsmetod som en begäran dirigeras till.
- Parametrar för den Razor sidhanterarmetod som en begäran dirigeras till.
- Offentliga egenskaper för en kontrollant eller PageModelklass, om de anges av attribut.
[BindProperty]-attribut
Kan tillämpas på en offentlig egenskap hos en kontroller eller PageModel klass för att modellbindning ska rikta sig mot den egenskapen.
public class EditModel : PageModel
{
    [BindProperty]
    public Instructor? Instructor { get; set; }
    // ...
}
[BindProperties]-attribut
Kan tillämpas på en kontroller eller PageModel klass för att ange modellbindning att rikta in sig på alla offentliga egenskaper i klassen.
[BindProperties]
public class CreateModel : PageModel
{
    public Instructor? Instructor { get; set; }
    // ...
}
Modellbindning för HTTP GET-begäranden
Som standard är egenskaperna inte bundna till HTTP GET-begäranden. Vanligtvis är allt du behöver för en GET-begäran en post-ID-parameter. Post-ID:t används för att leta upp objektet i databasen. Därför behöver du inte binda en egenskap som innehåller en instans av modellen. I scenarier där du vill att egenskaper ska bindas till data från GET-begäranden anger du SupportsGet egenskapen till true:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
Modellbindning av enkla och komplexa typer
Modellbindning använder specifika definitioner för de typer som den fungerar på. En enkel typ konverteras från en enda sträng med hjälp av TypeConverter eller en TryParse metod. En komplex typ konverteras från flera indatavärden. Ramverket avgör skillnaden baserat på förekomsten av en TypeConverter eller TryParse. Vi rekommenderar att du skapar en typkonverterare eller använder TryParse för en string till-konvertering SomeType som inte kräver externa resurser eller flera indata.
Sources
Som standard hämtar modellbindningen data i form av nyckel/värde-par från följande källor i en HTTP-begäran:
- Formulärfält
- Begärandetexten (för kontrollanter som har attributet [ApiController].)
- Ruttdata
- Frågesträngsparametrar
- Ladda upp filer
För varje målparameter eller egenskap genomsöks källorna i den ordning som anges i föregående lista. Det finns några undantag:
- Routningsdata och frågesträngsvärden används endast för enkla typer.
- Uppladdade filer är endast bundna till måltyper som implementerar IFormFileellerIEnumerable<IFormFile>.
Om standardkällan inte är korrekt använder du något av följande attribut för att ange källan:
- 
              [FromQuery]– Hämtar värden från frågesträngen.
- 
              [FromRoute]– Hämtar värden från vägdata.
- 
              [FromForm]– Hämtar värden från publicerade formulärfält.
- 
              [FromBody]– Hämtar värden från begärandetexten.
- 
              [FromHeader]– Hämtar värden från HTTP-huvuden.
Följande attribut:
- Läggs till i modellegenskaper individuellt och inte i modellklassen, som i följande exempel: - public class Instructor { public int Id { get; set; } [FromQuery(Name = "Note")] public string? NoteFromQueryString { get; set; } // ... }
- Det är valfritt att acceptera ett modellnamnsvärde i konstruktorn. Det här alternativet anges om egenskapsnamnet inte matchar värdet i begäran. Till exempel kan värdet i begäran vara en rubrik med ett bindestreck i namnet, som i följande exempel: - public void OnGet([FromHeader(Name = "Accept-Language")] string language)
[FromBody]-attribut
              [FromBody] Använd attributet för en parameter för att fylla i dess egenskaper från brödtexten i en HTTP-begäran. ASP.NET Core-körningen delegerar ansvaret för att läsa brödtexten till en indataformaterare. Indataformaterare beskrivs senare i den här artikeln.
När [FromBody] tillämpas på en komplex typparameter ignoreras alla bindningskällaattribut som tillämpas på dess egenskaper. Följande åtgärd anger till exempel Create att parametern pet är ifylld från brödtexten:
public ActionResult<Pet> Create([FromBody] Pet pet)
Klassen Pet anger att dess Breed egenskap fylls i från en frågesträngsparameter:
public class Pet
{
    public string Name { get; set; } = null!;
    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; } = null!;
}
I föregående exempel:
- Attributet [FromQuery]ignoreras.
- Egenskapen Breedfylls inte i från en frågesträngsparameter.
Indataformaterare läser endast brödtexten och förstår inte bindningskällans attribut. Om ett lämpligt värde hittas i brödtexten används det värdet för att fylla i Breed egenskapen.
Gäller [FromBody] inte för fler än en parameter per åtgärdsmetod. När begärandeströmmen har lästs av en indataformaterare är den inte längre tillgänglig för att läsas igen för bindning av andra [FromBody] parametrar.
Ytterligare källor
Källdata tillhandahålls till modellbindningssystemet av värdeprovidrar. Du kan skriva och registrera anpassade värdeprovidrar som hämtar data för modellbindning från andra källor. Du kanske till exempel vill ha data från cookies eller sessionstillstånd. Så här hämtar du data från en ny källa:
- Skapa en klass som implementerar IValueProvider.
- Skapa en klass som implementerar IValueProviderFactory.
- Registrera fabriksklassen i Program.cs.
Exemplet innehåller en värdeprovider och ett fabriksexempel som hämtar värden från cookies. Registrera anpassade värdeproviderfabriker i Program.cs:
builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
});
Föregående kod placerar den anpassade värdeprovidern efter alla inbyggda värdeprovidrar. Om du vill göra den till den första i listan anropar du Insert(0, new CookieValueProviderFactory()) i stället Addför .
Ingen källa för en modells egenskap
Som standard skapas inte ett modelltillståndsfel om inget värde hittas för en modellegenskap. Egenskapen är inställd på null eller ett standardvärde:
- Nullbara enkla typer är inställda på null.
- Värdetyper som inte kan vara null är inställda på default(T). En parameterint idär till exempel inställd på 0.
- För komplexa typer skapar modellbindning en instans med hjälp av standardkonstruktorn, utan att ange egenskaper.
- Matriser är inställda på Array.Empty<T>(), förutom attbyte[]matriser är inställda pånull.
Om modelltillståndet ska ogiltigförklaras när inget hittas i formulärfält för en modellegenskap använder du attributet [BindRequired] .
Observera att det här [BindRequired] beteendet gäller för modellbindning från publicerade formulärdata, inte från JSON- eller XML-data i en begärandetext. Brödtextdata för begäran hanteras av indataformaterare.
Typkonverteringsfel
Om en källa hittas men inte kan konverteras till måltypen flaggas modelltillståndet som ogiltigt. Målparametern eller -egenskapen är inställd på null eller ett standardvärde, enligt beskrivningen i föregående avsnitt.
I en API-kontrollant som har [ApiController] attributet resulterar ogiltigt modelltillstånd i ett automatiskt HTTP 400-svar.
Visa sidan igen med ett felmeddelande på en Razor sida.
public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }
    // ...
    return RedirectToPage("./Index");
}
När sidan spelas upp av föregående kod visas inte ogiltiga indata i formulärfältet. Det beror på att modellegenskapen har angetts till null eller ett standardvärde. Ogiltiga indata visas i ett felmeddelande. Om du vill redigera om felaktiga data i formulärfältet kan du överväga att göra modellegenskapen till en sträng och göra datakonverteringen manuellt.
Samma strategi rekommenderas om du inte vill att typkonverteringsfel ska resultera i modelltillståndsfel. I så fall gör du modellegenskapen till en sträng.
Enkla typer
Se Modellbindning av enkla och komplexa typer för förklaring av enkla och komplexa typer.
De enkla typer som modellbindningen kan konvertera källsträngar till innehåller följande:
- Boolean
- Byte, SByte
- Char
- DateOnly
- DateTime
- DateTimeOffset
- Decimal
- Double
- Enum
- Guid
- Int16, Int32, Int64
- Single
- TimeOnly
- TimeSpan
- UInt16, UInt32, UInt64
- Uri
- Version
Bind med IParsable<T>.TryParse
API:et IParsable<TSelf>.TryParse stöder parametervärden för bindningskontrollantåtgärd:
public static bool TryParse (string? s, IFormatProvider? provider, out TSelf result);
Följande DateRange-klass implementerar IParsable<TSelf> för att binda ett datumintervall.
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;
    }
}
Föregående kod:
- Konverterar en sträng som representerar två datum till ett DateRangeobjekt
- Modellbindningen använder IParsable<TSelf>.TryParsemetoden för att bindaDateRange.
Följande kontrollantåtgärd använder DateRange klassen för att binda ett datumintervall:
// 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);
}
Följande Locale klass implementerar IParsable<TSelf> för att stödja bindning till CultureInfo:
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;
        }
    }
}
Följande kontrollantåtgärd använder Locale klassen för att binda en CultureInfo sträng:
// 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);
}
Följande kontrollantåtgärd använder klasserna DateRange och Locale för att binda ett datumintervall med CultureInfo:
// 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);
}
API-exempelappen på GitHub visar föregående exempel för en API-kontrollant.
Bind med TryParse
API:et TryParse stöder parametervärden för bindningskontrollantåtgärd:
public static bool TryParse(string value, T out result);
public static bool TryParse(string value, IFormatProvider provider, T out result);
              IParsable<T>.TryParse är den rekommenderade metoden för parameterbindning eftersom den till skillnad från TryParse, inte beror på reflektion.
Följande DateRangeTP klass implementerar 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;
    }
}
Följande kontrollantåtgärd använder DateRangeTP klassen för att binda ett datumintervall:
// 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);
}
Komplexa typer
En komplex typ måste ha en offentlig standardkonstruktor och offentliga skrivbara egenskaper för bindning. När modellbindningen inträffar instansieras klassen med hjälp av den offentliga standardkonstruktorn.
För varje egenskap av den komplexa typen söker modellbindningen igenom källorna efter namnmönstretprefix.property_name. Om inget hittas letar den efter bara property_name utan prefixet. Beslutet att använda prefixet fattas inte per egenskap. Med till exempel en fråga som innehåller ?Instructor.Id=100&Name=foo, bunden till -metoden OnGet(Instructor instructor), innehåller det resulterande objektet av typen Instructor :
- 
              Idinställt på100.
- 
              Nameinställt pånull. Modellbindningen förväntar sigInstructor.NameeftersomInstructor.Idanvändes i föregående frågeparameter.
Note
Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Välj bland grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).
För bindning till en parameter är prefixet parameternamnet. För bindning till en PageModel offentlig egenskap är prefixet namnet på den offentliga egenskapen. Vissa attribut har en Prefix egenskap som gör att du kan åsidosätta standardanvändningen av parametern eller egenskapsnamnet.
Anta till exempel att den komplexa typen är följande Instructor klass:
public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}
Prefix = parameternamn
Om modellen som ska bindas är en parameter med namnet instructorToUpdate:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln instructorToUpdate.ID. Om det inte hittas söker den efter ID utan ett prefix.
Prefix = egenskapsnamn
Om modellen som ska bindas är en egenskap med namnet Instructor på kontrollanten eller PageModel klassen:
[BindProperty]
public Instructor Instructor { get; set; }
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Anpassat prefix
Om modellen som ska bindas är en parameter med namnet instructorToUpdate och ett Bind attribut anger Instructor som prefix:
public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Attribut för komplexa typmål
Flera inbyggda attribut är tillgängliga för att styra modellbindning av komplexa typer:
Warning
Dessa attribut påverkar modellbindningen när publicerade formulärdata är källan till värden. De påverkar inte indataformaterare, som bearbetar publicerade JSON- och XML-begärandeorgan. Indataformaterare beskrivs senare i den här artikeln.
Attributet [Bind]
Kan tillämpas på en klass eller en metodparameter. Anger vilka egenskaper för en modell som ska ingå i modellbindningen. 
              [Bind] påverkar inte indataformaterare.
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när någon hanterare eller åtgärdsmetod anropas:
[Bind("LastName,FirstMidName,HireDate")]
public class Instructor
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när OnPost metoden anropas:
[HttpPost]
public IActionResult OnPost(
    [Bind("LastName,FirstMidName,HireDate")] Instructor instructor)
Attributet [Bind] kan användas för att skydda mot överpublicering i skapa scenarier. Det fungerar inte bra i redigeringsscenarier eftersom exkluderade egenskaper är inställda på null eller ett standardvärde i stället för att lämnas oförändrade. För skydd mot överpublicering rekommenderas visningsmodeller i stället för attributet [Bind] . Mer information finns i Säkerhetsanteckning om överpublicering.
[ModelBinder]-attribut
ModelBinderAttribute kan tillämpas på typer, egenskaper eller parametrar. Det gör det möjligt att ange vilken typ av modellbindning som används för att binda den specifika instansen eller typen. Till exempel:
[HttpPost]
public IActionResult OnPost(
    [ModelBinder<MyInstructorModelBinder>] Instructor instructor)
Attributet [ModelBinder] kan också användas för att ändra namnet på en egenskap eller parameter när det är modellbundet:
public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }
    // ...
}
[BindRequired]-attribut
Orsakar modellbindning för att lägga till ett modelltillståndsfel om bindningen inte kan ske för en modells egenskap. Här är ett exempel:
public class InstructorBindRequired
{
    // ...
    [BindRequired]
    public DateTime HireDate { get; set; }
}
Se även diskussionen om attributet [Required] i Modellverifiering.
[BindNever]-attribut
Kan tillämpas på en egenskap eller en typ. Förhindrar modellbindning från att bestämma en modells egenskap. När det tillämpas på en typ exkluderar modellbindningssystemet alla egenskaper som typen definierar. Här är ett exempel:
public class InstructorBindNever
{
    [BindNever]
    public int Id { get; set; }
    // ...
}
Collections
För mål som är samlingar av enkla typer letar modellbindningen efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att parametern som ska bindas är en matris med namnet - selectedCourses:- public IActionResult OnPost(int? id, int[] selectedCourses)
- Formulär- eller frågesträngsdata kan vara i något av följande format: - 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- Undvik att binda en parameter eller en egenskap med namnet - indexeller- Indexom den ligger i anslutning till ett samlingsvärde. Modellbindning försöker använda- indexsom index för samlingen, vilket kan leda till felaktig bindning. Tänk till exempel på följande åtgärd:- public IActionResult Post(string index, List<Product> products)- I föregående kod binder frågesträngsparametern - indextill- indexmetodparametern och används även för att binda produktsamlingen. Om du byter namn på parametern- indexeller använder ett modellbindningsattribut för att konfigurera bindning undviks det här problemet:- public IActionResult Post(string productIndex, List<Product> products)
- Följande format stöds endast i formulärdata: - selectedCourses[]=1050&selectedCourses[]=2000
- För alla föregående exempelformat skickar modellbindningen en matris med två objekt till parametern - selectedCourses:- selectedCourses[0]=1050
- selectedCourses[1]=2000
 - Dataformat som använder nedsänkta siffror (... [0] ... [1] ...) måste se till att de numreras sekventiellt med början på noll. Om det finns några luckor i siffernummer ignoreras alla objekt efter luckan. Om de till exempel är 0 och 2 i stället för 0 och 1 ignoreras det andra objektet. 
Dictionaries
För Dictionary mål söker modellbindning efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att målparametern heter - Dictionary<int, string>- selectedCourses:- public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
- Publicerade formulär- eller frågesträngsdata kan se ut som något av följande exempel: - 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
- För alla föregående exempelformat skickar modellbindningen en ordlista med två objekt till parametern - selectedCourses:- selectedCourses["1050"]="Chemistry"
- selectedCourses["2000"]="Economics"
 
Konstruktorbindning och rekordtyper
Modellbindning kräver att komplexa typer har en parameterlös konstruktor. Både System.Text.Json och Newtonsoft.Json baserade indataformaterare stöder deserialisering av klasser som inte har en parameterlös konstruktor.
Posttyper är ett bra sätt att kortfattat representera data på nätverket. ASP.NET Core stöder modellbindning och validering av posttyper med en enda konstruktor:
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>
Vid validering av posttyper söker körningsmiljön efter bindnings- och valideringsmetadata specifikt på parametrar i stället för på egenskaper.
Ramverket tillåter bindning till och validering av posttyper:
public record Person([Required] string Name, [Range(0, 100)] int Age);
För att det föregående ska fungera, måste typen:
- Vara en posttyp.
- Ha exakt en offentlig konstruktor.
- Innehåller parametrar som har en egenskap med samma namn och typ. Namnen får inte skilja sig åt från fall till fall.
POCOs utan parameterfria konstruktorer
POCO:er som inte har parameterlösa konstruktorer kan inte bindas.
Följande kod resulterar i ett undantag som säger att typen måste ha en parameterlös konstruktor:
public class Person {
    public Person(string Name) { }
}
public record Person([Required] string Name, [Range(0, 100)] int Age)
{
    public Person(string Name) : this (Name, 0)
    {
    }
}
Registrera typer med manuellt skapade konstruktorer
Posttyper med manuellt skapade konstruktorer som ser ut som primära konstruktorer fungerar
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; }
}
Posttyper, validering och bindningsmetadata
För posttyper används validering och bindning av metadata för parametrar. Metadata för egenskaper ignoreras
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; }
}
Validering och metadata
Validering använder metadata för parametern men använder egenskapen för att läsa värdet. I vanliga fall med primära konstruktorer skulle de två vara identiska. Det finns dock sätt att besegra det:
public record Person([Required] string Name)
{
    private readonly string _name;
    // The following property is never null.
    // However this object could have been constructed as "new Person(null)".
    public string Name { get; init => _name = value ?? string.Empty; }
}
TryUpdateModel uppdaterar inte parametrar för en posttyp
public record Person(string Name)
{
    public int Age { get; set; }
}
var person = new Person("initial-name");
TryUpdateModel(person, ...);
I det här fallet försöker MVC inte binda Name igen. Kan dock Age uppdateras
Globaliseringsbeteende för modellbindningsvägsdata och frågesträngar
ASP.NET Core leverantör för routvärden och leverantör för frågesträngsvärden:
- Behandla värden som invariant kultur.
- Förvänta dig att URL:er är kulturinvarianta.
Däremot genomgår värden som kommer från formulärdata en kulturkänslig konvertering. Detta är avsiktligt så att URL:er kan delas oberoende av språkversion.
Så här gör du så att ASP.NET Core-routningsvärdeprovidern och frågesträngsvärdeprovidern genomgår en kulturkänslig konvertering:
- Ärv från IValueProviderFactory
- Kopiera koden från QueryStringValueProviderFactory eller RouteValueValueProviderFactory
- Ersätt kulturvärdet som skickas till värdeproviderns konstruktor med CultureInfo.CurrentCulture
- Ersätt standardvärdeproviderfabriken i MVC-alternativen med din nya:
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();
});
Särskilda datatyper
Det finns vissa särskilda datatyper som modellbindning kan hantera.
IFormFile och IFormFileCollection
En uppladdad fil som ingår i HTTP-begäran.  
              IEnumerable<IFormFile> stöds också för flera filer.
CancellationToken
Åtgärder kan valfritt binda en CancellationToken som en parameter. Detta binder RequestAborted som signalerar när anslutningen som ligger till grund för HTTP-begäran avbryts. Åtgärder kan använda den här parametern för att avbryta långvariga asynkrona åtgärder som körs som en del av kontrollantåtgärderna.
FormCollection
Används för att hämta alla värden från publicerade formulärdata.
Indataformaterare
Data i begärandetexten kan vara i JSON, XML eller något annat format. För att parsa dessa data använder modellbindningen en indataformaterare som är konfigurerad för att hantera en viss innehållstyp. Som standard innehåller ASP.NET Core JSON-baserade indataformaterare för hantering av JSON-data med .System.Text.Json Du kan lägga till andra formaterare för andra innehållstyper.
Standardformaterare för JSON-indata kan konfigureras med hjälp av AddJsonOptions metoden:
builder.Services.AddControllers().AddJsonOptions(options =>
{
    // Configure property naming policy (camelCase)
    options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    // Add enum converter to serialize enums as strings
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    // Configure other JSON options
    options.JsonSerializerOptions.WriteIndented = true;
    options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
Vanliga konfigurationsalternativ är:
- Namngivningsprincip för egenskaper – Konfigurera camelCase eller andra namngivningskonventioner
- Enum-konverterare – Hantera enum-serialisering som strängar
- Anpassade konverterare – Lägg till typspecifik serialiseringslogik
ASP.NET Core väljer indataformaterare baserat på attributet Förbrukar . Om det inte finns något attribut används rubriken Innehållstyp.
Så här använder du de inbyggda XML-indataformatrarna:
- I - Program.csanropar AddXmlSerializerFormatters eller AddXmlDataContractSerializerFormatters.- builder.Services.AddControllers() .AddXmlSerializerFormatters();
- ConsumesAnvänd attributet för kontrollantklasser eller åtgärdsmetoder som bör förvänta sig XML i begärandetexten.- [HttpPost] [Consumes("application/xml")] public ActionResult<Pet> Create(Pet pet)- Mer information finns i Introduktion till XML-serialisering. 
Anpassa modellbindning med indataformaterare
En indataformaterare tar fullt ansvar för att läsa data från begärandetexten. Om du vill anpassa den här processen konfigurerar du de API:er som används av indataformaterare. I det här avsnittet beskrivs hur du anpassar den System.Text.Json-baserade indataformateren för att förstå en anpassad typ med namnet ObjectId.
Tänk på följande modell, som innehåller en anpassad ObjectId egenskap:
public class InstructorObjectId
{
    [Required]
    public ObjectId ObjectId { get; set; } = null!;
}
Om du vill anpassa modellbindningsprocessen när du använder System.Text.Jsonskapar du en klass som härletts från JsonConverter<T>:
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);
}
Använd attributet JsonConverterAttribute för typen för att använda en anpassad konverterare. I följande exempel konfigureras ObjectId-typen med ObjectIdConverter som sin egen anpassade konverterare.
[JsonConverter(typeof(ObjectIdConverter))]
public record ObjectId(int Id);
Mer information finns i Skriva anpassade konverterare.
Undanta angivna typer från modellbindning
Modellens bindnings- och valideringssystems beteende styrs av ModelMetadata. Du kan anpassa ModelMetadata genom att lägga till en informationsprovider i MvcOptions.ModelMetadataDetailsProviders. Inbyggda informationsprovidrar är tillgängliga för inaktivering av modellbindning eller validering för angivna typer.
Om du vill inaktivera modellbindning för alla modeller av en angiven typ lägger du till en ExcludeBindingMetadataProvider i Program.cs. Om du till exempel vill inaktivera modellbindning för alla modeller av typen System.Version:
builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });
Om du vill inaktivera validering av egenskaper för en angiven typ lägger du till en SuppressChildValidationMetadataProvider i Program.cs. Om du till exempel vill inaktivera validering av egenskaper av typen System.Guid:
builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });
Anpassade modellbindare
Du kan utöka modellbindningen genom att skriva en anpassad modellbindning och använda [ModelBinder] attributet för att välja den för ett visst mål. Läs mer om bindning av anpassade modeller.
Manuell modellbindning
Modellbindning kan anropas manuellt genom att använda metoden TryUpdateModelAsync. Metoden definieras för båda ControllerBase klasserna och PageModel . Med metodöverlagringar kan du ange prefixet och värdeprovidern som ska användas. Metoden returnerar false om modellbindningen misslyckas. Här är ett exempel:
if (await TryUpdateModelAsync(
    newInstructor,
    "Instructor",
    x => x.Name, x => x.HireDate!))
{
    _instructorStore.Add(newInstructor);
    return RedirectToPage("./Index");
}
return Page();
              TryUpdateModelAsync använder värdeleverantörer för att hämta data från formulärets data, frågesträngen och routningsdata. 
              TryUpdateModelAsync är vanligtvis:
- Används med Razor Pages- och MVC-appar med hjälp av kontrollanter och vyer för att förhindra överpublicering.
- Används inte med ett webb-API förutom när det hämtas från formulärdata, frågesträngar och routdata. Webb-API-slutpunkter som använder JSON använder indataformatrar för att deserialisera begärandetexten till ett objekt.
Mer information finns i TryUpdateModelAsync.
[FromServices]-attribut
Det här attributets namn följer mönstret för modellbindningsattribut som anger en datakälla. Men det handlar inte om att binda data från en värdeprovider. Den hämtar en instans av en typ från containern för beroendeinmatning . Syftet är att tillhandahålla ett alternativ till konstruktorinmatning för när du behöver en tjänst endast om en viss metod anropas.
Om en instans av typen inte är registrerad i containern för beroendeinmatning genererar appen ett undantag när parametern försöker bindas. Om du vill göra parametern valfri använder du någon av följande metoder:
- Gör parametern nullbar.
- Ange ett standardvärde för parametern.
För null-parametrar kontrollerar du att parametern inte null är innan du kommer åt den.
Json+PipeReader-deserialisering i MVC
Från och med .NET 10 använder följande funktionella områden i ASP.NET Core överbelastningar av JsonSerializer.DeserializeAsync som är baserade på PipeReader istället för Stream.
- Minimala API:er (parameterbindning, brödtext för läsbegäran)
- MVC (indataformaterare, modell)
- Tilläggsmetoderna HttpRequestJsonExtensions för att läsa begärandetexten som JSON.
För de flesta program ger en övergång från Stream till PipeReader bättre prestanda utan att kräva ändringar i programkoden. Men om ditt program har en anpassad konverterare kanske konverteraren inte hanterar Utf8JsonReader.HasValueSequence korrekt. Om den inte gör det kan resultatet bli fel som ArgumentOutOfRangeException eller saknade data vid deserialisering. Du har följande alternativ för att få konverteraren att fungera utan PipeReader-relaterade fel.
Alternativ 1: Tillfällig lösning
Den snabba lösningen är att gå tillbaka till att använda Stream utan PipeReader-stöd. Om du vill implementera det här alternativet anger du "Microsoft.AspNetCore.UseStreamBasedJsonParsing" AppContext-växeln till "true". Vi rekommenderar att du endast gör detta som en tillfällig lösning och uppdaterar konverteraren så att den stöder HasValueSequence det så snart som möjligt. Växeln kan tas bort i .NET 11. Det enda syftet var att ge utvecklare tid att få sina konverterare uppdaterade.
Alternativ 2: En snabbkorrigering för JsonConverter implementeringar
För den här korrigeringen allokerar du en matris från ReadOnlySequence. Det här exemplet visar hur koden skulle se ut:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
    // previous code
}
Alternativ 3: En mer komplicerad men bättre presterande korrigering
Den här korrigeringen innebär att du konfigurerar en separat kodsökväg för ReadOnlySequence hanteringen:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    if (reader.HasValueSequence)
    {
        reader.ValueSequence;
        // ReadOnlySequence optimized path
    }
    else
    {
        reader.ValueSpan;
        // ReadOnlySpan optimized path
    }
}
Mer information finns i
Ytterligare resurser
Den här artikeln förklarar vad modellbindning är, hur den fungerar och hur du anpassar dess beteende.
Vad är modellbindning
Kontrollanter och Razor sidor fungerar med data som kommer från HTTP-begäranden. Routningsdata kan till exempel ge en postnyckel, och publicerade formulärfält kan ge värden för modellens egenskaper. Att skriva kod för att hämta vart och ett av dessa värden och konvertera dem från strängar till .NET-typer skulle vara omständligt och felbenäget. Modellbindning automatiserar den här processen. Modellbindningssystemet:
- Hämtar data från olika källor, till exempel routningsdata, formulärfält och frågesträngar.
- Tillhandahåller data till kontroller och Razor sidor i metodparametrar och publika egenskaper.
- Konverterar strängdata till .NET-typer.
- Uppdaterar egenskaper för komplexa typer.
Example
Anta att du har följande åtgärdsmetod:
[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)
Och appen får en begäran med den här URL:en:
https://contoso.com/api/pets/2?DogsOnly=true
Modellbindningen går igenom följande steg när routningssystemet har valt åtgärdsmetoden:
- Hittar den första parametern i GetById, ett heltal med namnetid.
- Söker igenom de tillgängliga källorna i HTTP-begäran och hittar id= "2" i routningsdata.
- Konverterar strängen "2" till heltal 2.
- Hittar nästa parameter i GetById, ett booleskt värde med namnetdogsOnly.
- Söker igenom källorna och hittar "DogsOnly=true" i frågesträngen. Namnmatchning är inte skiftlägeskänsligt.
- Konverterar strängen "true" till boolesk true.
Ramverket anropar GetById sedan metoden och skickar in 2 för parametern id och true för parametern dogsOnly .
I föregående exempel är modellbindningsmålen metodparametrar som är enkla typer. Mål kan också vara egenskaper för en komplex typ. När varje egenskap har bundits sker modellverifiering för den egenskapen. Posten för vilka data som är bundna till modellen och eventuella bindnings- eller valideringsfel lagras i ControllerBase.ModelState eller PageModel.ModelState. För att ta reda på om den här processen lyckades kontrollerar appen flaggan ModelState.IsValid .
Targets
Modellbindning försöker hitta värden för följande typer av mål:
- Parametrar för den kontrollantåtgärdsmetod som en begäran dirigeras till.
- Parametrar för den Razor sidhanterarmetod som en begäran dirigeras till.
- Offentliga egenskaper för en kontrollant eller PageModelklass, om de anges av attribut.
[BindProperty]-attribut
Kan tillämpas på en offentlig egenskap hos en kontroller eller PageModel klass för att modellbindning ska rikta sig mot den egenskapen.
public class EditModel : PageModel
{
    [BindProperty]
    public Instructor? Instructor { get; set; }
    // ...
}
[BindProperties]-attribut
Kan tillämpas på en kontroller eller PageModel klass för att ange modellbindning att rikta in sig på alla offentliga egenskaper i klassen.
[BindProperties]
public class CreateModel : PageModel
{
    public Instructor? Instructor { get; set; }
    // ...
}
Modellbindning för HTTP GET-begäranden
Som standard är egenskaperna inte bundna till HTTP GET-begäranden. Vanligtvis är allt du behöver för en GET-begäran en post-ID-parameter. Post-ID:t används för att leta upp objektet i databasen. Därför behöver du inte binda en egenskap som innehåller en instans av modellen. I scenarier där du vill att egenskaper ska bindas till data från GET-begäranden anger du SupportsGet egenskapen till true:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
Modellbindning av enkla och komplexa typer
Modellbindning använder specifika definitioner för de typer som den fungerar på. En enkel typ konverteras från en enda sträng med hjälp av TypeConverter eller en TryParse metod. En komplex typ konverteras från flera indatavärden. Ramverket avgör skillnaden baserat på förekomsten av en TypeConverter eller TryParse. Vi rekommenderar att du skapar en typkonverterare eller använder TryParse för en string till-konvertering SomeType som inte kräver externa resurser eller flera indata.
Sources
Som standard hämtar modellbindningen data i form av nyckel/värde-par från följande källor i en HTTP-begäran:
- Formulärfält
- Begärandetexten (för kontrollanter som har attributet [ApiController].)
- Ruttdata
- Frågesträngsparametrar
- Ladda upp filer
För varje målparameter eller egenskap genomsöks källorna i den ordning som anges i föregående lista. Det finns några undantag:
- Routningsdata och frågesträngsvärden används endast för enkla typer.
- Uppladdade filer är endast bundna till måltyper som implementerar IFormFileellerIEnumerable<IFormFile>.
Om standardkällan inte är korrekt använder du något av följande attribut för att ange källan:
- 
              [FromQuery]– Hämtar värden från frågesträngen.
- 
              [FromRoute]– Hämtar värden från vägdata.
- 
              [FromForm]– Hämtar värden från publicerade formulärfält.
- 
              [FromBody]– Hämtar värden från begärandetexten.
- 
              [FromHeader]– Hämtar värden från HTTP-huvuden.
Följande attribut:
- Läggs till i modellegenskaper individuellt och inte i modellklassen, som i följande exempel: - public class Instructor { public int Id { get; set; } [FromQuery(Name = "Note")] public string? NoteFromQueryString { get; set; } // ... }
- Det är valfritt att acceptera ett modellnamnsvärde i konstruktorn. Det här alternativet anges om egenskapsnamnet inte matchar värdet i begäran. Till exempel kan värdet i begäran vara en rubrik med ett bindestreck i namnet, som i följande exempel: - public void OnGet([FromHeader(Name = "Accept-Language")] string language)
[FromBody]-attribut
              [FromBody] Använd attributet för en parameter för att fylla i dess egenskaper från brödtexten i en HTTP-begäran. ASP.NET Core-körningen delegerar ansvaret för att läsa brödtexten till en indataformaterare. Indataformaterare beskrivs senare i den här artikeln.
När [FromBody] tillämpas på en komplex typparameter ignoreras alla bindningskällaattribut som tillämpas på dess egenskaper. Följande åtgärd anger till exempel Create att parametern pet är ifylld från brödtexten:
public ActionResult<Pet> Create([FromBody] Pet pet)
Klassen Pet anger att dess Breed egenskap fylls i från en frågesträngsparameter:
public class Pet
{
    public string Name { get; set; } = null!;
    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; } = null!;
}
I föregående exempel:
- Attributet [FromQuery]ignoreras.
- Egenskapen Breedfylls inte i från en frågesträngsparameter.
Indataformaterare läser endast brödtexten och förstår inte bindningskällans attribut. Om ett lämpligt värde hittas i brödtexten används det värdet för att fylla i Breed egenskapen.
Gäller [FromBody] inte för fler än en parameter per åtgärdsmetod. När begärandeströmmen har lästs av en indataformaterare är den inte längre tillgänglig för att läsas igen för bindning av andra [FromBody] parametrar.
Ytterligare källor
Källdata tillhandahålls till modellbindningssystemet av värdeprovidrar. Du kan skriva och registrera anpassade värdeprovidrar som hämtar data för modellbindning från andra källor. Du kanske till exempel vill ha data från cookies eller sessionstillstånd. Så här hämtar du data från en ny källa:
- Skapa en klass som implementerar IValueProvider.
- Skapa en klass som implementerar IValueProviderFactory.
- Registrera fabriksklassen i Program.cs.
Exemplet innehåller en värdeprovider och ett fabriksexempel som hämtar värden från cookies. Registrera anpassade värdeproviderfabriker i Program.cs:
builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
});
Föregående kod placerar den anpassade värdeprovidern efter alla inbyggda värdeprovidrar. Om du vill göra den till den första i listan anropar du Insert(0, new CookieValueProviderFactory()) i stället Addför .
Ingen källa för en modells egenskap
Som standard skapas inte ett modelltillståndsfel om inget värde hittas för en modellegenskap. Egenskapen är inställd på null eller ett standardvärde:
- Nullbara enkla typer är inställda på null.
- Värdetyper som inte kan vara null är inställda på default(T). En parameterint idär till exempel inställd på 0.
- För komplexa typer skapar modellbindning en instans med hjälp av standardkonstruktorn, utan att ange egenskaper.
- Matriser är inställda på Array.Empty<T>(), förutom attbyte[]matriser är inställda pånull.
Om modelltillståndet ska ogiltigförklaras när inget hittas i formulärfält för en modellegenskap använder du attributet [BindRequired] .
Observera att det här [BindRequired] beteendet gäller för modellbindning från publicerade formulärdata, inte för JSON- eller XML-data i en begärandetext. Brödtextdata för begäran hanteras av indataformaterare.
Typkonverteringsfel
Om en källa hittas men inte kan konverteras till måltypen flaggas modelltillståndet som ogiltigt. Målparametern eller -egenskapen är inställd på null eller ett standardvärde, enligt beskrivningen i föregående avsnitt.
I en API-kontrollant som har [ApiController] attributet resulterar ogiltigt modelltillstånd i ett automatiskt HTTP 400-svar.
Visa sidan igen med ett felmeddelande på en Razor sida.
public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }
    // ...
    return RedirectToPage("./Index");
}
När sidan spelas upp av föregående kod visas inte ogiltiga indata i formulärfältet. Det beror på att modellegenskapen har angetts till null eller ett standardvärde. Ogiltiga indata visas i ett felmeddelande. Om du vill redigera om felaktiga data i formulärfältet kan du överväga att göra modellegenskapen till en sträng och göra datakonverteringen manuellt.
Samma strategi rekommenderas om du inte vill att typkonverteringsfel ska resultera i modelltillståndsfel. I så fall gör du modellegenskapen till en sträng.
Enkla typer
Se Modellbindning av enkla och komplexa typer för förklaring av enkla och komplexa typer.
De enkla typer som modellbindningen kan konvertera källsträngar till innehåller följande:
- Boolean
- Byte, SByte
- Char
- DateOnly
- DateTime
- DateTimeOffset
- Decimal
- Double
- Enum
- Guid
- Int16, Int32, Int64
- Single
- TimeOnly
- TimeSpan
- UInt16, UInt32, UInt64
- Uri
- Version
Bind med IParsable<T>.TryParse
API:et IParsable<TSelf>.TryParse stöder parametervärden för bindningskontrollantåtgärd:
public static bool TryParse (string? s, IFormatProvider? provider, out TSelf result);
Följande DateRange-klass implementerar IParsable<TSelf> för att binda ett datumintervall.
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;
    }
}
Föregående kod:
- Konverterar en sträng som representerar två datum till ett DateRangeobjekt
- Modellbindningen använder IParsable<TSelf>.TryParsemetoden för att bindaDateRange.
Följande kontrollantåtgärd använder DateRange klassen för att binda ett datumintervall:
// 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);
}
Följande Locale klass implementerar IParsable<TSelf> för att stödja bindning till CultureInfo:
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;
        }
    }
}
Följande kontrollantåtgärd använder Locale klassen för att binda en CultureInfo sträng:
// 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);
}
Följande kontrollantåtgärd använder klasserna DateRange och Locale för att binda ett datumintervall med CultureInfo:
// 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);
}
API-exempelappen på GitHub visar föregående exempel för en API-kontrollant.
Bind med TryParse
API:et TryParse stöder parametervärden för bindningskontrollantåtgärd:
public static bool TryParse(string value, T out result);
public static bool TryParse(string value, IFormatProvider provider, T out result);
              IParsable<T>.TryParse är den rekommenderade metoden för parameterbindning eftersom den till skillnad från TryParse, inte beror på reflektion.
Följande DateRangeTP klass implementerar 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;
    }
}
Följande kontrollantåtgärd använder DateRangeTP klassen för att binda ett datumintervall:
// 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);
}
Komplexa typer
En komplex typ måste ha en offentlig standardkonstruktor och offentliga skrivbara egenskaper för bindning. När modellbindningen inträffar instansieras klassen med hjälp av den offentliga standardkonstruktorn.
För varje egenskap av den komplexa typen söker modellbindningen igenom källorna efter namnmönstretprefix.property_name. Om inget hittas letar den efter bara property_name utan prefixet. Beslutet att använda prefixet fattas inte per egenskap. Med till exempel en fråga som innehåller ?Instructor.Id=100&Name=foo, bunden till -metoden OnGet(Instructor instructor), innehåller det resulterande objektet av typen Instructor :
- 
              Idinställt på100.
- 
              Nameinställt pånull. Modellbindningen förväntar sigInstructor.NameeftersomInstructor.Idanvändes i föregående frågeparameter.
Note
Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Välj bland grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).
För bindning till en parameter är prefixet parameternamnet. För bindning till en PageModel offentlig egenskap är prefixet namnet på den offentliga egenskapen. Vissa attribut har en Prefix egenskap som gör att du kan åsidosätta standardanvändningen av parametern eller egenskapsnamnet.
Anta till exempel att den komplexa typen är följande Instructor klass:
public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}
Prefix = parameternamn
Om modellen som ska bindas är en parameter med namnet instructorToUpdate:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln instructorToUpdate.ID. Om det inte hittas söker den efter ID utan ett prefix.
Prefix = egenskapsnamn
Om modellen som ska bindas är en egenskap med namnet Instructor på kontrollanten eller PageModel klassen:
[BindProperty]
public Instructor Instructor { get; set; }
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Anpassat prefix
Om modellen som ska bindas är en parameter med namnet instructorToUpdate och ett Bind attribut anger Instructor som prefix:
public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Attribut för komplexa typmål
Flera inbyggda attribut är tillgängliga för att styra modellbindning av komplexa typer:
Warning
Dessa attribut påverkar modellbindningen när publicerade formulärdata är källan till värden. De påverkar inte indataformaterare, som bearbetar publicerade JSON- och XML-begärandeorgan. Indataformaterare beskrivs senare i den här artikeln.
Attributet [Bind]
Kan tillämpas på en klass eller en metodparameter. Anger vilka egenskaper för en modell som ska ingå i modellbindningen. 
              [Bind] påverkar inte indataformaterare.
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när någon hanterare eller åtgärdsmetod anropas:
[Bind("LastName,FirstMidName,HireDate")]
public class Instructor
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när OnPost metoden anropas:
[HttpPost]
public IActionResult OnPost(
    [Bind("LastName,FirstMidName,HireDate")] Instructor instructor)
Attributet [Bind] kan användas för att skydda mot överpublicering i skapa scenarier. Det fungerar inte bra i redigeringsscenarier eftersom exkluderade egenskaper är inställda på null eller ett standardvärde i stället för att lämnas oförändrade. För skydd mot överpublicering rekommenderas visningsmodeller i stället för attributet [Bind] . Mer information finns i Säkerhetsanteckning om överpublicering.
[ModelBinder]-attribut
ModelBinderAttribute kan tillämpas på typer, egenskaper eller parametrar. Det gör det möjligt att ange vilken typ av modellbindning som används för att binda den specifika instansen eller typen. Till exempel:
[HttpPost]
public IActionResult OnPost(
    [ModelBinder(typeof(MyInstructorModelBinder))] Instructor instructor)
Attributet [ModelBinder] kan också användas för att ändra namnet på en egenskap eller parameter när det är modellbundet:
public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }
    // ...
}
[BindRequired]-attribut
Orsakar modellbindning för att lägga till ett modelltillståndsfel om bindningen inte kan ske för en modells egenskap. Här är ett exempel:
public class InstructorBindRequired
{
    // ...
    [BindRequired]
    public DateTime HireDate { get; set; }
}
Se även diskussionen om attributet [Required] i Modellverifiering.
[BindNever]-attribut
Kan tillämpas på en egenskap eller en typ. Förhindrar modellbindning från att bestämma en modells egenskap. När det tillämpas på en typ exkluderar modellbindningssystemet alla egenskaper som typen definierar. Här är ett exempel:
public class InstructorBindNever
{
    [BindNever]
    public int Id { get; set; }
    // ...
}
Collections
För mål som är samlingar av enkla typer letar modellbindningen efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att parametern som ska bindas är en matris med namnet - selectedCourses:- public IActionResult OnPost(int? id, int[] selectedCourses)
- Formulär- eller frågesträngsdata kan vara i något av följande format: - 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- Undvik att binda en parameter eller en egenskap med namnet - indexeller- Indexom den ligger i anslutning till ett samlingsvärde. Modellbindning försöker använda- indexsom index för samlingen, vilket kan leda till felaktig bindning. Tänk till exempel på följande åtgärd:- public IActionResult Post(string index, List<Product> products)- I föregående kod binder frågesträngsparametern - indextill- indexmetodparametern och används även för att binda produktsamlingen. Om du byter namn på parametern- indexeller använder ett modellbindningsattribut för att konfigurera bindning undviks det här problemet:- public IActionResult Post(string productIndex, List<Product> products)
- Följande format stöds endast i formulärdata: - selectedCourses[]=1050&selectedCourses[]=2000
- För alla föregående exempelformat skickar modellbindningen en matris med två objekt till parametern - selectedCourses:- selectedCourses[0]=1050
- selectedCourses[1]=2000
 - Dataformat som använder nedsänkta siffror (... [0] ... [1] ...) måste se till att de numreras sekventiellt med början på noll. Om det finns några luckor i siffernummer ignoreras alla objekt efter luckan. Om de till exempel är 0 och 2 i stället för 0 och 1 ignoreras det andra objektet. 
Dictionaries
För Dictionary mål söker modellbindning efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att målparametern heter - Dictionary<int, string>- selectedCourses:- public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
- Publicerade formulär- eller frågesträngsdata kan se ut som något av följande exempel: - 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
- För alla föregående exempelformat skickar modellbindningen en ordlista med två objekt till parametern - selectedCourses:- selectedCourses["1050"]="Chemistry"
- selectedCourses["2000"]="Economics"
 
Konstruktorbindning och rekordtyper
Modellbindning kräver att komplexa typer har en parameterlös konstruktor. Både System.Text.Json och Newtonsoft.Json baserade indataformaterare stöder deserialisering av klasser som inte har en parameterlös konstruktor.
Posttyper är ett bra sätt att kortfattat representera data på nätverket. ASP.NET Core stöder modellbindning och validering av posttyper med en enda konstruktor:
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>
Vid validering av posttyper söker körningsmiljön efter bindnings- och valideringsmetadata specifikt på parametrar i stället för på egenskaper.
Ramverket tillåter bindning till och validering av posttyper:
public record Person([Required] string Name, [Range(0, 100)] int Age);
För att det föregående ska fungera, måste typen:
- Vara en posttyp.
- Ha exakt en offentlig konstruktor.
- Innehåller parametrar som har en egenskap med samma namn och typ. Namnen får inte skilja sig åt från fall till fall.
POCOs utan parameterfria konstruktorer
POCO:er som inte har parameterlösa konstruktorer kan inte bindas.
Följande kod resulterar i ett undantag som säger att typen måste ha en parameterlös konstruktor:
public class Person(string Name)
public record Person([Required] string Name, [Range(0, 100)] int Age)
{
    public Person(string Name) : this (Name, 0);
}
Registrera typer med manuellt skapade konstruktorer
Posttyper med manuellt skapade konstruktorer som ser ut som primära konstruktorer fungerar
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; }
}
Posttyper, validering och bindningsmetadata
För posttyper används validering och bindning av metadata för parametrar. Metadata för egenskaper ignoreras
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; }
}
Validering och metadata
Validering använder metadata för parametern men använder egenskapen för att läsa värdet. I vanliga fall med primära konstruktorer skulle de två vara identiska. Det finns dock sätt att besegra det:
public record Person([Required] string Name)
{
    private readonly string _name;
    // The following property is never null.
    // However this object could have been constructed as "new Person(null)".
    public string Name { get; init => _name = value ?? string.Empty; }
}
TryUpdateModel uppdaterar inte parametrar för en posttyp
public record Person(string Name)
{
    public int Age { get; set; }
}
var person = new Person("initial-name");
TryUpdateModel(person, ...);
I det här fallet försöker MVC inte binda Name igen. Kan dock Age uppdateras
Globaliseringsbeteende för modellbindningsvägsdata och frågesträngar
ASP.NET Core leverantör för routvärden och leverantör för frågesträngsvärden:
- Behandla värden som invariant kultur.
- Förvänta dig att URL:er är kulturinvarianta.
Däremot genomgår värden som kommer från formulärdata en kulturkänslig konvertering. Detta är avsiktligt så att URL:er kan delas oberoende av språkversion.
Så här gör du så att ASP.NET Core-routningsvärdeprovidern och frågesträngsvärdeprovidern genomgår en kulturkänslig konvertering:
- Ärv från IValueProviderFactory
- Kopiera koden från QueryStringValueProviderFactory eller RouteValueValueProviderFactory
- Ersätt kulturvärdet som skickas till värdeproviderns konstruktor med CultureInfo.CurrentCulture
- Ersätt standardvärdeproviderfabriken i MVC-alternativen med din nya:
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();
});
Särskilda datatyper
Det finns vissa särskilda datatyper som modellbindning kan hantera.
IFormFile och IFormFileCollection
En uppladdad fil som ingår i HTTP-begäran.  
              IEnumerable<IFormFile> stöds också för flera filer.
CancellationToken
Åtgärder kan valfritt binda en CancellationToken som en parameter. Detta binder RequestAborted som signalerar när anslutningen som ligger till grund för HTTP-begäran avbryts. Åtgärder kan använda den här parametern för att avbryta långvariga asynkrona åtgärder som körs som en del av kontrollantåtgärderna.
FormCollection
Används för att hämta alla värden från publicerade formulärdata.
Indataformaterare
Data i begärandetexten kan vara i JSON, XML eller något annat format. För att parsa dessa data använder modellbindningen en indataformaterare som är konfigurerad för att hantera en viss innehållstyp. Som standard innehåller ASP.NET Core JSON-baserade indataformaterare för hantering av JSON-data. Du kan lägga till andra formaterare för andra innehållstyper.
ASP.NET Core väljer indataformaterare baserat på attributet Förbrukar . Om det inte finns något attribut används rubriken Innehållstyp.
Så här använder du de inbyggda XML-indataformatrarna:
- I - Program.csanropar AddXmlSerializerFormatters eller AddXmlDataContractSerializerFormatters.- builder.Services.AddControllers() .AddXmlSerializerFormatters();
- ConsumesAnvänd attributet för kontrollantklasser eller åtgärdsmetoder som bör förvänta sig XML i begärandetexten.- [HttpPost] [Consumes("application/xml")] public ActionResult<Pet> Create(Pet pet)- Mer information finns i Introduktion till XML-serialisering. 
Anpassa modellbindning med indataformaterare
En indataformaterare tar fullt ansvar för att läsa data från begärandetexten. Om du vill anpassa den här processen konfigurerar du de API:er som används av indataformaterare. I det här avsnittet beskrivs hur du anpassar den System.Text.Json-baserade indataformateren för att förstå en anpassad typ med namnet ObjectId.
Tänk på följande modell, som innehåller en anpassad ObjectId egenskap:
public class InstructorObjectId
{
    [Required]
    public ObjectId ObjectId { get; set; } = null!;
}
Om du vill anpassa modellbindningsprocessen när du använder System.Text.Jsonskapar du en klass som härletts från JsonConverter<T>:
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);
}
Använd attributet JsonConverterAttribute för typen för att använda en anpassad konverterare. I följande exempel konfigureras ObjectId-typen med ObjectIdConverter som sin egen anpassade konverterare.
[JsonConverter(typeof(ObjectIdConverter))]
public record ObjectId(int Id);
Mer information finns i Skriva anpassade konverterare.
Undanta angivna typer från modellbindning
Modellens bindnings- och valideringssystems beteende styrs av ModelMetadata. Du kan anpassa ModelMetadata genom att lägga till en informationsprovider i MvcOptions.ModelMetadataDetailsProviders. Inbyggda informationsprovidrar är tillgängliga för inaktivering av modellbindning eller validering för angivna typer.
Om du vill inaktivera modellbindning för alla modeller av en angiven typ lägger du till en ExcludeBindingMetadataProvider i Program.cs. Om du till exempel vill inaktivera modellbindning för alla modeller av typen System.Version:
builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });
Om du vill inaktivera validering av egenskaper för en angiven typ lägger du till en SuppressChildValidationMetadataProvider i Program.cs. Om du till exempel vill inaktivera validering av egenskaper av typen System.Guid:
builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });
Anpassade modellbindare
Du kan utöka modellbindningen genom att skriva en anpassad modellbindning och använda [ModelBinder] attributet för att välja den för ett visst mål. Läs mer om bindning av anpassade modeller.
Manuell modellbindning
Modellbindning kan anropas manuellt genom att använda metoden TryUpdateModelAsync. Metoden definieras för båda ControllerBase klasserna och PageModel . Med metodöverlagringar kan du ange prefixet och värdeprovidern som ska användas. Metoden returnerar false om modellbindningen misslyckas. Här är ett exempel:
if (await TryUpdateModelAsync(
    newInstructor,
    "Instructor",
    x => x.Name, x => x.HireDate!))
{
    _instructorStore.Add(newInstructor);
    return RedirectToPage("./Index");
}
return Page();
              TryUpdateModelAsync använder värdeleverantörer för att hämta data från formulärets data, frågesträngen och routningsdata. 
              TryUpdateModelAsync är vanligtvis:
- Används med Razor Pages- och MVC-appar med hjälp av kontrollanter och vyer för att förhindra överpublicering.
- Används inte med ett webb-API förutom när det hämtas från formulärdata, frågesträngar och routdata. Webb-API-slutpunkter som använder JSON använder indataformatrar för att deserialisera begärandetexten till ett objekt.
Mer information finns i TryUpdateModelAsync.
[FromServices]-attribut
Det här attributets namn följer mönstret för modellbindningsattribut som anger en datakälla. Men det handlar inte om att binda data från en värdeprovider. Den hämtar en instans av en typ från containern för beroendeinmatning . Syftet är att tillhandahålla ett alternativ till konstruktorinmatning för när du behöver en tjänst endast om en viss metod anropas.
Om en instans av typen inte är registrerad i containern för beroendeinmatning genererar appen ett undantag när parametern försöker bindas. Om du vill göra parametern valfri använder du någon av följande metoder:
- Gör parametern nullbar.
- Ange ett standardvärde för parametern.
För null-parametrar kontrollerar du att parametern inte null är innan du kommer åt den.
Ytterligare resurser
Den här artikeln förklarar vad modellbindning är, hur den fungerar och hur du anpassar dess beteende.
Vad är modellbindning
Kontrollanter och Razor sidor fungerar med data som kommer från HTTP-begäranden. Routningsdata kan till exempel ge en postnyckel, och publicerade formulärfält kan ge värden för modellens egenskaper. Att skriva kod för att hämta vart och ett av dessa värden och konvertera dem från strängar till .NET-typer skulle vara omständligt och felbenäget. Modellbindning automatiserar den här processen. Modellbindningssystemet:
- Hämtar data från olika källor, till exempel routningsdata, formulärfält och frågesträngar.
- Tillhandahåller data till kontroller och Razor sidor i metodparametrar och publika egenskaper.
- Konverterar strängdata till .NET-typer.
- Uppdaterar egenskaper för komplexa typer.
Example
Anta att du har följande åtgärdsmetod:
[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)
Och appen får en begäran med den här URL:en:
https://contoso.com/api/pets/2?DogsOnly=true
Modellbindningen går igenom följande steg när routningssystemet har valt åtgärdsmetoden:
- Hittar den första parametern i GetById, ett heltal med namnetid.
- Söker igenom de tillgängliga källorna i HTTP-begäran och hittar id= "2" i routningsdata.
- Konverterar strängen "2" till heltal 2.
- Hittar nästa parameter i GetById, ett booleskt värde med namnetdogsOnly.
- Söker igenom källorna och hittar "DogsOnly=true" i frågesträngen. Namnmatchning är inte skiftlägeskänsligt.
- Konverterar strängen "true" till boolesk true.
Ramverket anropar GetById sedan metoden och skickar in 2 för parametern id och true för parametern dogsOnly .
I föregående exempel är modellbindningsmålen metodparametrar som är enkla typer. Mål kan också vara egenskaper för en komplex typ. När varje egenskap har bundits sker modellverifiering för den egenskapen. Posten för vilka data som är bundna till modellen och eventuella bindnings- eller valideringsfel lagras i ControllerBase.ModelState eller PageModel.ModelState. För att ta reda på om den här processen lyckades kontrollerar appen flaggan ModelState.IsValid .
Targets
Modellbindning försöker hitta värden för följande typer av mål:
- Parametrar för den kontrollantåtgärdsmetod som en begäran dirigeras till.
- Parametrar för den Razor sidhanterarmetod som en begäran dirigeras till.
- Offentliga egenskaper för en kontrollant eller PageModelklass, om de anges av attribut.
[BindProperty]-attribut
Kan tillämpas på en offentlig egenskap hos en kontroller eller PageModel klass för att modellbindning ska rikta sig mot den egenskapen.
public class EditModel : PageModel
{
    [BindProperty]
    public Instructor? Instructor { get; set; }
    // ...
}
[BindProperties]-attribut
Kan tillämpas på en kontroller eller PageModel klass för att ange modellbindning att rikta in sig på alla offentliga egenskaper i klassen.
[BindProperties]
public class CreateModel : PageModel
{
    public Instructor? Instructor { get; set; }
    // ...
}
Modellbindning för HTTP GET-begäranden
Som standard är egenskaperna inte bundna till HTTP GET-begäranden. Vanligtvis är allt du behöver för en GET-begäran en post-ID-parameter. Post-ID:t används för att leta upp objektet i databasen. Därför behöver du inte binda en egenskap som innehåller en instans av modellen. I scenarier där du vill att egenskaper ska bindas till data från GET-begäranden anger du SupportsGet egenskapen till true:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
Sources
Som standard hämtar modellbindningen data i form av nyckel/värde-par från följande källor i en HTTP-begäran:
- Formulärfält
- Begärandetexten (för kontrollanter som har attributet [ApiController].)
- Ruttdata
- Frågesträngsparametrar
- Ladda upp filer
För varje målparameter eller egenskap genomsöks källorna i den ordning som anges i föregående lista. Det finns några undantag:
- Routningsdata och frågesträngsvärden används endast för enkla typer.
- Uppladdade filer är endast bundna till måltyper som implementerar IFormFileellerIEnumerable<IFormFile>.
Om standardkällan inte är korrekt använder du något av följande attribut för att ange källan:
- 
              [FromQuery]– Hämtar värden från frågesträngen.
- 
              [FromRoute]– Hämtar värden från vägdata.
- 
              [FromForm]– Hämtar värden från publicerade formulärfält.
- 
              [FromBody]– Hämtar värden från begärandetexten.
- 
              [FromHeader]– Hämtar värden från HTTP-huvuden.
Följande attribut:
- Läggs till i modellegenskaper individuellt och inte i modellklassen, som i följande exempel: - public class Instructor { public int Id { get; set; } [FromQuery(Name = "Note")] public string? NoteFromQueryString { get; set; } // ... }
- Det är valfritt att acceptera ett modellnamnsvärde i konstruktorn. Det här alternativet anges om egenskapsnamnet inte matchar värdet i begäran. Till exempel kan värdet i begäran vara en rubrik med ett bindestreck i namnet, som i följande exempel: - public void OnGet([FromHeader(Name = "Accept-Language")] string language)
[FromBody]-attribut
              [FromBody] Använd attributet för en parameter för att fylla i dess egenskaper från brödtexten i en HTTP-begäran. ASP.NET Core-körningen delegerar ansvaret för att läsa brödtexten till en indataformaterare. Indataformaterare beskrivs senare i den här artikeln.
När [FromBody] tillämpas på en komplex typparameter ignoreras alla bindningskällaattribut som tillämpas på dess egenskaper. Följande åtgärd anger till exempel Create att parametern pet är ifylld från brödtexten:
public ActionResult<Pet> Create([FromBody] Pet pet)
Klassen Pet anger att dess Breed egenskap fylls i från en frågesträngsparameter:
public class Pet
{
    public string Name { get; set; } = null!;
    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; } = null!;
}
I föregående exempel:
- Attributet [FromQuery]ignoreras.
- Egenskapen Breedfylls inte i från en frågesträngsparameter.
Indataformaterare läser endast brödtexten och förstår inte bindningskällans attribut. Om ett lämpligt värde hittas i brödtexten används det värdet för att fylla i Breed egenskapen.
Gäller [FromBody] inte för fler än en parameter per åtgärdsmetod. När begärandeströmmen har lästs av en indataformaterare är den inte längre tillgänglig för att läsas igen för bindning av andra [FromBody] parametrar.
Ytterligare källor
Källdata tillhandahålls till modellbindningssystemet av värdeprovidrar. Du kan skriva och registrera anpassade värdeprovidrar som hämtar data för modellbindning från andra källor. Du kanske till exempel vill ha data från cookies eller sessionstillstånd. Så här hämtar du data från en ny källa:
- Skapa en klass som implementerar IValueProvider.
- Skapa en klass som implementerar IValueProviderFactory.
- Registrera fabriksklassen i Program.cs.
Exemplet innehåller en värdeprovider och ett fabriksexempel som hämtar värden från cookies. Registrera anpassade värdeproviderfabriker i Program.cs:
builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
});
Föregående kod placerar den anpassade värdeprovidern efter alla inbyggda värdeprovidrar. Om du vill göra den till den första i listan anropar du Insert(0, new CookieValueProviderFactory()) i stället Addför .
Ingen källa för en modells egenskap
Som standard skapas inte ett modelltillståndsfel om inget värde hittas för en modellegenskap. Egenskapen är inställd på null eller ett standardvärde:
- Enkla typer som kan ogiltigförklaras är inställda på null.
- Värdetyper som inte kan vara null är inställda på default(T). En parameterint idär till exempel inställd på 0.
- För komplexa typer skapar modellbindning en instans med hjälp av standardkonstruktorn, utan att ange egenskaper.
- Matriser är inställda på Array.Empty<T>(), förutom attbyte[]matriser är inställda pånull.
Om modelltillståndet ska ogiltigförklaras när inget hittas i formulärfält för en modellegenskap använder du attributet [BindRequired] .
Observera att det här [BindRequired] beteendet gäller för modellbindning från publicerade formulärdata, inte för JSON- eller XML-data i en begärandetext. Brödtextdata för begäran hanteras av indataformaterare.
Typkonverteringsfel
Om en källa hittas men inte kan konverteras till måltypen flaggas modelltillståndet som ogiltigt. Målparametern eller -egenskapen är inställd på null eller ett standardvärde, enligt beskrivningen i föregående avsnitt.
I en API-kontrollant som har [ApiController] attributet resulterar ogiltigt modelltillstånd i ett automatiskt HTTP 400-svar.
Visa sidan igen med ett felmeddelande på en Razor sida.
public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }
    // ...
    return RedirectToPage("./Index");
}
När sidan spelas upp av föregående kod visas inte ogiltiga indata i formulärfältet. Det beror på att modellegenskapen har angetts till null eller ett standardvärde. Ogiltiga indata visas i ett felmeddelande. Om du vill redigera om felaktiga data i formulärfältet kan du överväga att göra modellegenskapen till en sträng och göra datakonverteringen manuellt.
Samma strategi rekommenderas om du inte vill att typkonverteringsfel ska resultera i modelltillståndsfel. I så fall gör du modellegenskapen till en sträng.
Enkla typer
De enkla typer som modellbindningen kan konvertera källsträngar till innehåller följande:
- Boolean
- Byte, SByte
- Char
- DateTime
- DateTimeOffset
- Decimal
- Double
- Enum
- Guid
- Int16, Int32, Int64
- Single
- TimeSpan
- UInt16, UInt32, UInt64
- Uri
- Version
Komplexa typer
En komplex typ måste ha en offentlig standardkonstruktor och offentliga skrivbara egenskaper för bindning. När modellbindningen inträffar instansieras klassen med hjälp av den offentliga standardkonstruktorn.
För varje egenskap av den komplexa typen söker modellbindningen igenom källorna efter namnmönstretprefix.property_name. Om inget hittas letar den efter bara property_name utan prefixet. Beslutet att använda prefixet fattas inte per egenskap. Med till exempel en fråga som innehåller ?Instructor.Id=100&Name=foo, bunden till -metoden OnGet(Instructor instructor), innehåller det resulterande objektet av typen Instructor :
- 
              Idinställt på100.
- 
              Nameinställt pånull. Modellbindningen förväntar sigInstructor.NameeftersomInstructor.Idanvändes i föregående frågeparameter.
Note
Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Välj bland grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).
För bindning till en parameter är prefixet parameternamnet. För bindning till en PageModel offentlig egenskap är prefixet namnet på den offentliga egenskapen. Vissa attribut har en Prefix egenskap som gör att du kan åsidosätta standardanvändningen av parametern eller egenskapsnamnet.
Anta till exempel att den komplexa typen är följande Instructor klass:
public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}
Prefix = parameternamn
Om modellen som ska bindas är en parameter med namnet instructorToUpdate:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln instructorToUpdate.ID. Om det inte hittas söker den efter ID utan ett prefix.
Prefix = egenskapsnamn
Om modellen som ska bindas är en egenskap med namnet Instructor på kontrollanten eller PageModel klassen:
[BindProperty]
public Instructor Instructor { get; set; }
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Anpassat prefix
Om modellen som ska bindas är en parameter med namnet instructorToUpdate och ett Bind attribut anger Instructor som prefix:
public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Attribut för komplexa typmål
Flera inbyggda attribut är tillgängliga för att styra modellbindning av komplexa typer:
Warning
Dessa attribut påverkar modellbindningen när publicerade formulärdata är källan till värden. De påverkar inte indataformaterare, som bearbetar publicerade JSON- och XML-begärandeorgan. Indataformaterare beskrivs senare i den här artikeln.
Attributet [Bind]
Kan tillämpas på en klass eller en metodparameter. Anger vilka egenskaper för en modell som ska ingå i modellbindningen. 
              [Bind] påverkar inte indataformaterare.
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när någon hanterare eller åtgärdsmetod anropas:
[Bind("LastName,FirstMidName,HireDate")]
public class Instructor
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när OnPost metoden anropas:
[HttpPost]
public IActionResult OnPost(
    [Bind("LastName,FirstMidName,HireDate")] Instructor instructor)
Attributet [Bind] kan användas för att skydda mot överpublicering i skapa scenarier. Det fungerar inte bra i redigeringsscenarier eftersom exkluderade egenskaper är inställda på null eller ett standardvärde i stället för att lämnas oförändrade. För skydd mot överpublicering rekommenderas visningsmodeller i stället för attributet [Bind] . Mer information finns i Säkerhetsanteckning om överpublicering.
[ModelBinder]-attribut
ModelBinderAttribute kan tillämpas på typer, egenskaper eller parametrar. Det gör det möjligt att ange vilken typ av modellbindning som används för att binda den specifika instansen eller typen. Till exempel:
[HttpPost]
public IActionResult OnPost(
    [ModelBinder(typeof(MyInstructorModelBinder))] Instructor instructor)
Attributet [ModelBinder] kan också användas för att ändra namnet på en egenskap eller parameter när det är modellbundet:
public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }
    // ...
}
[BindRequired]-attribut
Orsakar modellbindning för att lägga till ett modelltillståndsfel om bindningen inte kan ske för en modells egenskap. Här är ett exempel:
public class InstructorBindRequired
{
    // ...
    [BindRequired]
    public DateTime HireDate { get; set; }
}
Se även diskussionen om attributet [Required] i Modellverifiering.
[BindNever]-attribut
Kan tillämpas på en egenskap eller en typ. Förhindrar modellbindning från att bestämma en modells egenskap. När det tillämpas på en typ exkluderar modellbindningssystemet alla egenskaper som typen definierar. Här är ett exempel:
public class InstructorBindNever
{
    [BindNever]
    public int Id { get; set; }
    // ...
}
Collections
För mål som är samlingar av enkla typer letar modellbindningen efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att parametern som ska bindas är en matris med namnet - selectedCourses:- public IActionResult OnPost(int? id, int[] selectedCourses)
- Formulär- eller frågesträngsdata kan vara i något av följande format: - 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- Undvik att binda en parameter eller en egenskap med namnet - indexeller- Indexom den ligger i anslutning till ett samlingsvärde. Modellbindning försöker använda- indexsom index för samlingen, vilket kan leda till felaktig bindning. Tänk till exempel på följande åtgärd:- public IActionResult Post(string index, List<Product> products)- I föregående kod binder frågesträngsparametern - indextill- indexmetodparametern och används även för att binda produktsamlingen. Om du byter namn på parametern- indexeller använder ett modellbindningsattribut för att konfigurera bindning undviks det här problemet:- public IActionResult Post(string productIndex, List<Product> products)
- Följande format stöds endast i formulärdata: - selectedCourses[]=1050&selectedCourses[]=2000
- För alla föregående exempelformat skickar modellbindningen en matris med två objekt till parametern - selectedCourses:- selectedCourses[0]=1050
- selectedCourses[1]=2000
 - Dataformat som använder nedsänkta siffror (... [0] ... [1] ...) måste se till att de numreras sekventiellt med början på noll. Om det finns några luckor i siffernummer ignoreras alla objekt efter luckan. Om de till exempel är 0 och 2 i stället för 0 och 1 ignoreras det andra objektet. 
Dictionaries
För Dictionary mål söker modellbindning efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att målparametern heter - Dictionary<int, string>- selectedCourses:- public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
- Publicerade formulär- eller frågesträngsdata kan se ut som något av följande exempel: - 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
- För alla föregående exempelformat skickar modellbindningen en ordlista med två objekt till parametern - selectedCourses:- selectedCourses["1050"]="Chemistry"
- selectedCourses["2000"]="Economics"
 
Konstruktorbindning och rekordtyper
Modellbindning kräver att komplexa typer har en parameterlös konstruktor. Både System.Text.Json och Newtonsoft.Json baserade indataformaterare stöder deserialisering av klasser som inte har en parameterlös konstruktor.
Posttyper är ett bra sätt att kortfattat representera data på nätverket. ASP.NET Core stöder modellbindning och validering av posttyper med en enda konstruktor:
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>
Vid validering av posttyper söker körningsmiljön efter bindnings- och valideringsmetadata specifikt på parametrar i stället för på egenskaper.
Ramverket tillåter bindning till och validering av posttyper:
public record Person([Required] string Name, [Range(0, 100)] int Age);
För att det föregående ska fungera, måste typen:
- Vara en posttyp.
- Ha exakt en offentlig konstruktor.
- Innehåller parametrar som har en egenskap med samma namn och typ. Namnen får inte skilja sig åt från fall till fall.
POCOs utan parameterfria konstruktorer
POCO:er som inte har parameterlösa konstruktorer kan inte bindas.
Följande kod resulterar i ett undantag som säger att typen måste ha en parameterlös konstruktor:
public class Person(string Name)
public record Person([Required] string Name, [Range(0, 100)] int Age)
{
    public Person(string Name) : this (Name, 0);
}
Registrera typer med manuellt skapade konstruktorer
Posttyper med manuellt skapade konstruktorer som ser ut som primära konstruktorer fungerar
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; }
}
Posttyper, validering och bindningsmetadata
För posttyper används validering och bindning av metadata för parametrar. Metadata för egenskaper ignoreras
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; }
}
Validering och metadata
Validering använder metadata för parametern men använder egenskapen för att läsa värdet. I vanliga fall med primära konstruktorer skulle de två vara identiska. Det finns dock sätt att besegra det:
public record Person([Required] string Name)
{
    private readonly string _name;
    // The following property is never null.
    // However this object could have been constructed as "new Person(null)".
    public string Name { get; init => _name = value ?? string.Empty; }
}
TryUpdateModel uppdaterar inte parametrar för en posttyp
public record Person(string Name)
{
    public int Age { get; set; }
}
var person = new Person("initial-name");
TryUpdateModel(person, ...);
I det här fallet försöker MVC inte binda Name igen. Kan dock Age uppdateras
Globaliseringsbeteende för modellbindningsvägsdata och frågesträngar
ASP.NET Core leverantör för routvärden och leverantör för frågesträngsvärden:
- Behandla värden som invariant kultur.
- Förvänta dig att URL:er är kulturinvarianta.
Däremot genomgår värden som kommer från formulärdata en kulturkänslig konvertering. Detta är avsiktligt så att URL:er kan delas oberoende av språkversion.
Så här gör du så att ASP.NET Core-routningsvärdeprovidern och frågesträngsvärdeprovidern genomgår en kulturkänslig konvertering:
- Ärv från IValueProviderFactory
- Kopiera koden från QueryStringValueProviderFactory eller RouteValueValueProviderFactory
- Ersätt kulturvärdet som skickas till värdeproviderns konstruktor med CultureInfo.CurrentCulture
- Ersätt standardvärdeproviderfabriken i MVC-alternativen med din nya:
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();
});
Särskilda datatyper
Det finns vissa särskilda datatyper som modellbindning kan hantera.
IFormFile och IFormFileCollection
En uppladdad fil som ingår i HTTP-begäran.  
              IEnumerable<IFormFile> stöds också för flera filer.
CancellationToken
Åtgärder kan valfritt binda en CancellationToken som en parameter. Detta binder RequestAborted som signalerar när anslutningen som ligger till grund för HTTP-begäran avbryts. Åtgärder kan använda den här parametern för att avbryta långvariga asynkrona åtgärder som körs som en del av kontrollantåtgärderna.
FormCollection
Används för att hämta alla värden från publicerade formulärdata.
Indataformaterare
Data i begärandetexten kan vara i JSON, XML eller något annat format. För att parsa dessa data använder modellbindningen en indataformaterare som är konfigurerad för att hantera en viss innehållstyp. Som standard innehåller ASP.NET Core JSON-baserade indataformaterare för hantering av JSON-data. Du kan lägga till andra formaterare för andra innehållstyper.
ASP.NET Core väljer indataformaterare baserat på attributet Förbrukar . Om det inte finns något attribut används rubriken Innehållstyp.
Så här använder du de inbyggda XML-indataformatrarna:
- I - Program.csanropar AddXmlSerializerFormatters eller AddXmlDataContractSerializerFormatters.- builder.Services.AddControllers() .AddXmlSerializerFormatters();
- ConsumesAnvänd attributet för kontrollantklasser eller åtgärdsmetoder som bör förvänta sig XML i begärandetexten.- [HttpPost] [Consumes("application/xml")] public ActionResult<Pet> Create(Pet pet)- Mer information finns i Introduktion till XML-serialisering. 
Anpassa modellbindning med indataformaterare
En indataformaterare tar fullt ansvar för att läsa data från begärandetexten. Om du vill anpassa den här processen konfigurerar du de API:er som används av indataformaterare. I det här avsnittet beskrivs hur du anpassar den System.Text.Json-baserade indataformateren för att förstå en anpassad typ med namnet ObjectId.
Tänk på följande modell, som innehåller en anpassad ObjectId egenskap:
public class InstructorObjectId
{
    [Required]
    public ObjectId ObjectId { get; set; } = null!;
}
Om du vill anpassa modellbindningsprocessen när du använder System.Text.Jsonskapar du en klass som härletts från JsonConverter<T>:
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);
}
Använd attributet JsonConverterAttribute för typen för att använda en anpassad konverterare. I följande exempel konfigureras ObjectId-typen med ObjectIdConverter som sin egen anpassade konverterare.
[JsonConverter(typeof(ObjectIdConverter))]
public record ObjectId(int Id);
Mer information finns i Skriva anpassade konverterare.
Undanta angivna typer från modellbindning
Modellens bindnings- och valideringssystems beteende styrs av ModelMetadata. Du kan anpassa ModelMetadata genom att lägga till en informationsprovider i MvcOptions.ModelMetadataDetailsProviders. Inbyggda informationsprovidrar är tillgängliga för inaktivering av modellbindning eller validering för angivna typer.
Om du vill inaktivera modellbindning för alla modeller av en angiven typ lägger du till en ExcludeBindingMetadataProvider i Program.cs. Om du till exempel vill inaktivera modellbindning för alla modeller av typen System.Version:
builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });
Om du vill inaktivera validering av egenskaper för en angiven typ lägger du till en SuppressChildValidationMetadataProvider i Program.cs. Om du till exempel vill inaktivera validering av egenskaper av typen System.Guid:
builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(Guid)));
    });
Anpassade modellbindare
Du kan utöka modellbindningen genom att skriva en anpassad modellbindning och använda [ModelBinder] attributet för att välja den för ett visst mål. Läs mer om bindning av anpassade modeller.
Manuell modellbindning
Modellbindning kan anropas manuellt genom att använda metoden TryUpdateModelAsync. Metoden definieras för båda ControllerBase klasserna och PageModel . Med metodöverlagringar kan du ange prefixet och värdeprovidern som ska användas. Metoden returnerar false om modellbindningen misslyckas. Här är ett exempel:
if (await TryUpdateModelAsync(
    newInstructor,
    "Instructor",
    x => x.Name, x => x.HireDate!))
{
    _instructorStore.Add(newInstructor);
    return RedirectToPage("./Index");
}
return Page();
              TryUpdateModelAsync använder värdeleverantörer för att hämta data från formulärets data, frågesträngen och routningsdata. 
              TryUpdateModelAsync är vanligtvis:
- Används med Razor Pages- och MVC-appar med hjälp av kontrollanter och vyer för att förhindra överpublicering.
- Används inte med ett webb-API förutom när det hämtas från formulärdata, frågesträngar och routdata. Webb-API-slutpunkter som använder JSON använder indataformatrar för att deserialisera begärandetexten till ett objekt.
Mer information finns i TryUpdateModelAsync.
[FromServices]-attribut
Det här attributets namn följer mönstret för modellbindningsattribut som anger en datakälla. Men det handlar inte om att binda data från en värdeprovider. Den hämtar en instans av en typ från containern för beroendeinmatning . Syftet är att tillhandahålla ett alternativ till konstruktorinmatning för när du behöver en tjänst endast om en viss metod anropas.
Om en instans av typen inte är registrerad i containern för beroendeinmatning genererar appen ett undantag när parametern försöker bindas. Om du vill göra parametern valfri använder du någon av följande metoder:
- Gör parametern nullbar.
- Ange ett standardvärde för parametern.
För null-parametrar kontrollerar du att parametern inte null är innan du kommer åt den.
Ytterligare resurser
Den här artikeln förklarar vad modellbindning är, hur den fungerar och hur du anpassar dess beteende.
Visa eller ladda ned exempelkod (hur du laddar ned).
Vad är modellbindning
Kontrollanter och Razor sidor fungerar med data som kommer från HTTP-begäranden. Routningsdata kan till exempel ge en postnyckel, och publicerade formulärfält kan ge värden för modellens egenskaper. Att skriva kod för att hämta vart och ett av dessa värden och konvertera dem från strängar till .NET-typer skulle vara omständligt och felbenäget. Modellbindning automatiserar den här processen. Modellbindningssystemet:
- Hämtar data från olika källor, till exempel routningsdata, formulärfält och frågesträngar.
- Tillhandahåller data till kontroller och Razor sidor i metodparametrar och publika egenskaper.
- Konverterar strängdata till .NET-typer.
- Uppdaterar egenskaper för komplexa typer.
Example
Anta att du har följande åtgärdsmetod:
[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)
Och appen får en begäran med den här URL:en:
http://contoso.com/api/pets/2?DogsOnly=true
Modellbindningen går igenom följande steg när routningssystemet har valt åtgärdsmetoden:
- Hittar den första parametern i GetById, ett heltal med namnetid.
- Söker igenom de tillgängliga källorna i HTTP-begäran och hittar id= "2" i routningsdata.
- Konverterar strängen "2" till heltal 2.
- Hittar nästa parameter i GetById, ett booleskt värde med namnetdogsOnly.
- Söker igenom källorna och hittar "DogsOnly=true" i frågesträngen. Namnmatchning är inte skiftlägeskänsligt.
- Konverterar strängen "true" till boolesk true.
Ramverket anropar GetById sedan metoden och skickar in 2 för parametern id och true för parametern dogsOnly .
I föregående exempel är modellbindningsmålen metodparametrar som är enkla typer. Mål kan också vara egenskaper för en komplex typ. När varje egenskap har bundits sker modellverifiering för den egenskapen. Posten för vilka data som är bundna till modellen och eventuella bindnings- eller valideringsfel lagras i ControllerBase.ModelState eller PageModel.ModelState. För att ta reda på om den här processen lyckades kontrollerar appen flaggan ModelState.IsValid .
Targets
Modellbindning försöker hitta värden för följande typer av mål:
- Parametrar för den kontrollantåtgärdsmetod som en begäran dirigeras till.
- Parametrar för den Razor sidhanterarmetod som en begäran dirigeras till.
- Offentliga egenskaper för en kontrollant eller PageModelklass, om de anges av attribut.
[BindProperty]-attribut
Kan tillämpas på en offentlig egenskap hos en kontroller eller PageModel klass för att modellbindning ska rikta sig mot den egenskapen.
public class EditModel : InstructorsPageModel
{
    [BindProperty]
    public Instructor Instructor { get; set; }
[BindProperties]-attribut
Finns i ASP.NET Core 2.1 eller senare.  Kan tillämpas på en kontroller eller PageModel klass för att ange modellbindning att rikta in sig på alla offentliga egenskaper i klassen.
[BindProperties(SupportsGet = true)]
public class CreateModel : InstructorsPageModel
{
    public Instructor Instructor { get; set; }
Modellbindning för HTTP GET-begäranden
Som standard är egenskaperna inte bundna till HTTP GET-begäranden. Vanligtvis är allt du behöver för en GET-begäran en post-ID-parameter. Post-ID:t används för att leta upp objektet i databasen. Därför behöver du inte binda en egenskap som innehåller en instans av modellen. I scenarier där du vill att egenskaper ska bindas till data från GET-begäranden anger du SupportsGet egenskapen till true:
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string ApplicationInsightsCookie { get; set; }
Sources
Som standard hämtar modellbindningen data i form av nyckel/värde-par från följande källor i en HTTP-begäran:
- Formulärfält
- Begärandetexten (för kontrollanter som har attributet [ApiController].)
- Ruttdata
- Frågesträngsparametrar
- Ladda upp filer
För varje målparameter eller egenskap genomsöks källorna i den ordning som anges i föregående lista. Det finns några undantag:
- Routningsdata och frågesträngsvärden används endast för enkla typer.
- Uppladdade filer är endast bundna till måltyper som implementerar IFormFileellerIEnumerable<IFormFile>.
Om standardkällan inte är korrekt använder du något av följande attribut för att ange källan:
- 
              [FromQuery]– Hämtar värden från frågesträngen.
- 
              [FromRoute]– Hämtar värden från vägdata.
- 
              [FromForm]– Hämtar värden från publicerade formulärfält.
- 
              [FromBody]– Hämtar värden från begärandetexten.
- 
              [FromHeader]– Hämtar värden från HTTP-huvuden.
Följande attribut:
- Läggs till i modellegenskaper individuellt (inte i modellklassen), som i följande exempel: - public class Instructor { public int ID { get; set; } [FromQuery(Name = "Note")] public string NoteFromQueryString { get; set; }
- Det är valfritt att acceptera ett modellnamnsvärde i konstruktorn. Det här alternativet anges om egenskapsnamnet inte matchar värdet i begäran. Till exempel kan värdet i begäran vara en rubrik med ett bindestreck i namnet, som i följande exempel: - public void OnGet([FromHeader(Name = "Accept-Language")] string language)
[FromBody]-attribut
              [FromBody] Använd attributet för en parameter för att fylla i dess egenskaper från brödtexten i en HTTP-begäran. ASP.NET Core-körningen delegerar ansvaret för att läsa brödtexten till en indataformaterare. Indataformaterare beskrivs senare i den här artikeln.
När [FromBody] tillämpas på en komplex typparameter ignoreras alla bindningskällaattribut som tillämpas på dess egenskaper. Följande åtgärd anger till exempel Create att parametern pet är ifylld från brödtexten:
public ActionResult<Pet> Create([FromBody] Pet pet)
Klassen Pet anger att dess Breed egenskap fylls i från en frågesträngsparameter:
public class Pet
{
    public string Name { get; set; }
    [FromQuery] // Attribute is ignored.
    public string Breed { get; set; }
}
I föregående exempel:
- Attributet [FromQuery]ignoreras.
- Egenskapen Breedfylls inte i från en frågesträngsparameter.
Indataformaterare läser endast brödtexten och förstår inte bindningskällans attribut. Om ett lämpligt värde hittas i brödtexten används det värdet för att fylla i Breed egenskapen.
Gäller [FromBody] inte för fler än en parameter per åtgärdsmetod. När begärandeströmmen har lästs av en indataformaterare är den inte längre tillgänglig för att läsas igen för bindning av andra [FromBody] parametrar.
Ytterligare källor
Källdata tillhandahålls till modellbindningssystemet av värdeprovidrar. Du kan skriva och registrera anpassade värdeprovidrar som hämtar data för modellbindning från andra källor. Du kanske till exempel vill ha data från cookies eller sessionstillstånd. Så här hämtar du data från en ny källa:
- Skapa en klass som implementerar IValueProvider.
- Skapa en klass som implementerar IValueProviderFactory.
- Registrera fabriksklassen i Startup.ConfigureServices.
Exempelappen innehåller en värdeprovider och ett fabriksexempel som hämtar värden från cookies. Här är registreringskoden i 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();
Koden som visas placerar den anpassade värdeprovidern efter alla inbyggda värdeprovidrar.  Om du vill göra den till den första i listan anropar du Insert(0, new CookieValueProviderFactory()) i stället Addför .
Ingen källa för en modells egenskap
Som standard skapas inte ett modelltillståndsfel om inget värde hittas för en modellegenskap. Egenskapen är inställd på null eller ett standardvärde:
- Enkla typer som kan ogiltigförklaras är inställda på null.
- Värdetyper som inte kan vara null är inställda på default(T). En parameterint idär till exempel inställd på 0.
- För komplexa typer skapar modellbindning en instans med hjälp av standardkonstruktorn, utan att ange egenskaper.
- Matriser är inställda på Array.Empty<T>(), förutom attbyte[]matriser är inställda pånull.
Om modelltillståndet ska ogiltigförklaras när inget hittas i formulärfält för en modellegenskap använder du attributet [BindRequired] .
Observera att det här [BindRequired] beteendet gäller för modellbindning från publicerade formulärdata, inte för JSON- eller XML-data i en begärandetext. Brödtextdata för begäran hanteras av indataformaterare.
Typkonverteringsfel
Om en källa hittas men inte kan konverteras till måltypen flaggas modelltillståndet som ogiltigt. Målparametern eller -egenskapen är inställd på null eller ett standardvärde, enligt beskrivningen i föregående avsnitt.
I en API-kontrollant som har [ApiController] attributet resulterar ogiltigt modelltillstånd i ett automatiskt HTTP 400-svar.
Visa sidan igen med ett felmeddelande på en Razor sida.
public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }
    _instructorsInMemoryStore.Add(Instructor);
    return RedirectToPage("./Index");
}
Validering på klientsidan fångar upp de flesta felaktiga data som annars skulle skickas till ett Razor sidformulär. Den här valideringen gör det svårt att utlösa den ovan markerade koden. Exempelappen innehåller knappen Skicka med ogiltigt datum som placerar felaktiga data i fältet Anställningsdatum och skickar formuläret. Den här knappen visar hur koden för att redigera sidan fungerar när datakonverteringsfel inträffar.
När sidan spelas upp av föregående kod visas inte ogiltiga indata i formulärfältet. Det beror på att modellegenskapen har angetts till null eller ett standardvärde. Ogiltiga indata visas i ett felmeddelande. Men om du vill redigera om felaktiga data i formulärfältet kan du överväga att göra modellegenskapen till en sträng och göra datakonverteringen manuellt.
Samma strategi rekommenderas om du inte vill att typkonverteringsfel ska resultera i modelltillståndsfel. I så fall gör du modellegenskapen till en sträng.
Enkla typer
De enkla typer som modellbindningen kan konvertera källsträngar till innehåller följande:
- Boolean
- Byte, SByte
- Char
- DateTime
- DateTimeOffset
- Decimal
- Double
- Enum
- Guid
- Int16, Int32, Int64
- Single
- TimeSpan
- UInt16, UInt32, UInt64
- Uri
- Version
Komplexa typer
En komplex typ måste ha en offentlig standardkonstruktor och offentliga skrivbara egenskaper för bindning. När modellbindningen inträffar instansieras klassen med hjälp av den offentliga standardkonstruktorn.
För varje egenskap av den komplexa typen söker modellbindningen igenom källorna efter namnmönstret prefix.property_name. Om inget hittas letar den efter bara property_name utan prefixet.
För bindning till en parameter är prefixet parameternamnet. För bindning till en PageModel offentlig egenskap är prefixet namnet på den offentliga egenskapen. Vissa attribut har en Prefix egenskap som gör att du kan åsidosätta standardanvändningen av parametern eller egenskapsnamnet.
Anta till exempel att den komplexa typen är följande Instructor klass:
public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}
Prefix = parameternamn
Om modellen som ska bindas är en parameter med namnet instructorToUpdate:
public IActionResult OnPost(int? id, Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln instructorToUpdate.ID. Om det inte hittas söker den efter ID utan ett prefix.
Prefix = egenskapsnamn
Om modellen som ska bindas är en egenskap med namnet Instructor på kontrollanten eller PageModel klassen:
[BindProperty]
public Instructor Instructor { get; set; }
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Anpassat prefix
Om modellen som ska bindas är en parameter med namnet instructorToUpdate och ett Bind attribut anger Instructor som prefix:
public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)
Modellbindningen börjar med att titta igenom källorna för nyckeln Instructor.ID. Om det inte hittas söker den efter ID utan ett prefix.
Attribut för komplexa typmål
Flera inbyggda attribut är tillgängliga för att styra modellbindning av komplexa typer:
- [Bind]
- [BindRequired]
- [BindNever]
Warning
Dessa attribut påverkar modellbindningen när publicerade formulärdata är källan till värden. De påverkar inte indataformaterare, som bearbetar publicerade JSON- och XML-begärandeorgan. Indataformaterare beskrivs senare i den här artikeln.
Attributet [Bind]
Kan tillämpas på en klass eller en metodparameter. Anger vilka egenskaper för en modell som ska ingå i modellbindningen. 
              [Bind] påverkar inte indataformaterare.
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när någon hanterare eller åtgärdsmetod anropas:
[Bind("LastName,FirstMidName,HireDate")]
public class Instructor
I följande exempel är endast de angivna egenskaperna för Instructor modellen bundna när OnPost metoden anropas:
[HttpPost]
public IActionResult OnPost([Bind("LastName,FirstMidName,HireDate")] Instructor instructor)
Attributet [Bind] kan användas för att skydda mot överpublicering i skapa scenarier. Det fungerar inte bra i redigeringsscenarier eftersom exkluderade egenskaper är inställda på null eller ett standardvärde i stället för att lämnas oförändrade. För skydd mot överpublicering rekommenderas visningsmodeller i stället för attributet [Bind] . Mer information finns i Säkerhetsanteckning om överpublicering.
[ModelBinder]-attribut
ModelBinderAttribute kan tillämpas på typer, egenskaper eller parametrar. Det gör det möjligt att ange vilken typ av modellbindning som används för att binda den specifika instansen eller typen. Till exempel:
[HttpPost]
public IActionResult OnPost([ModelBinder(typeof(MyInstructorModelBinder))] Instructor instructor)
Attributet [ModelBinder] kan också användas för att ändra namnet på en egenskap eller parameter när det är modellbundet:
public class Instructor
{
    [ModelBinder(Name = "instructor_id")]
    public string Id { get; set; }
    public string Name { get; set; }
}
[BindRequired]-attribut
Kan endast tillämpas på modellegenskaper, inte på metodparametrar. Orsakar modellbindning för att lägga till ett modelltillståndsfel om bindningen inte kan ske för en modells egenskap. Här är ett exempel:
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; }
Se även diskussionen om attributet [Required] i Modellverifiering.
[BindNever]-attribut
Kan endast tillämpas på modellegenskaper, inte på metodparametrar. Förhindrar modellbindning från att bestämma en modells egenskap. Här är ett exempel:
public class InstructorWithDictionary
{
    [BindNever]
    public int ID { get; set; }
Collections
För mål som är samlingar av enkla typer letar modellbindningen efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att parametern som ska bindas är en matris med namnet - selectedCourses:- public IActionResult OnPost(int? id, int[] selectedCourses)
- Formulär- eller frågesträngsdata kan vara i något av följande format: - 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- Undvik att binda en parameter eller en egenskap med namnet - indexeller- Indexom den ligger i anslutning till ett samlingsvärde. Modellbindning försöker använda- indexsom index för samlingen, vilket kan leda till felaktig bindning. Tänk till exempel på följande åtgärd:- public IActionResult Post(string index, List<Product> products)- I föregående kod binder frågesträngsparametern - indextill- indexmetodparametern och används även för att binda produktsamlingen. Om du byter namn på parametern- indexeller använder ett modellbindningsattribut för att konfigurera bindning undviks det här problemet:- public IActionResult Post(string productIndex, List<Product> products)
- Följande format stöds endast i formulärdata: - selectedCourses[]=1050&selectedCourses[]=2000
- För alla föregående exempelformat skickar modellbindningen en matris med två objekt till parametern - selectedCourses:- selectedCourses[0]=1050
- selectedCourses[1]=2000
 - Dataformat som använder nedsänkta siffror (... [0] ... [1] ...) måste se till att de numreras sekventiellt med början på noll. Om det finns några luckor i siffernummer ignoreras alla objekt efter luckan. Om de till exempel är 0 och 2 i stället för 0 och 1 ignoreras det andra objektet. 
Dictionaries
För Dictionary mål söker modellbindning efter matchningar till parameter_name eller property_name. Om ingen matchning hittas letar den efter ett av de format som stöds utan prefixet. Till exempel:
- Anta att målparametern heter - Dictionary<int, string>- selectedCourses:- public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
- Publicerade formulär- eller frågesträngsdata kan se ut som något av följande exempel: - 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
- För alla föregående exempelformat skickar modellbindningen en ordlista med två objekt till parametern - selectedCourses:- selectedCourses["1050"]="Chemistry"
- selectedCourses["2000"]="Economics"
 
Konstruktorbindning och rekordtyper
Modellbindning kräver att komplexa typer har en parameterlös konstruktor. Både System.Text.Json och Newtonsoft.Json baserade indataformaterare stöder deserialisering av klasser som inte har en parameterlös konstruktor.
C# 9 introducerar recordtyper, som är ett utmärkt sätt att kortfattat representera data över nätverket. ASP.NET Core lägger till stöd för modellbindning och validering av posttyper med en enda konstruktor:
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>
Vid validering av posttyper söker körningsmiljön efter bindnings- och valideringsmetadata specifikt på parametrar i stället för på egenskaper.
Ramverket tillåter bindning till och validering av posttyper:
public record Person([Required] string Name, [Range(0, 100)] int Age);
För att det föregående ska fungera, måste typen:
- Vara en posttyp.
- Ha exakt en offentlig konstruktor.
- Innehåller parametrar som har en egenskap med samma namn och typ. Namnen får inte skilja sig åt från fall till fall.
POCOs utan parameterfria konstruktorer
POCO:er som inte har parameterlösa konstruktorer kan inte bindas.
Följande kod resulterar i ett undantag som säger att typen måste ha en parameterlös konstruktor:
public class Person(string Name)
public record Person([Required] string Name, [Range(0, 100)] int Age)
{
   public Person(string Name) : this (Name, 0);
}
Registrera typer med manuellt skapade konstruktorer
Posttyper med manuellt skapade konstruktorer som ser ut som primära konstruktorer fungerar
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; }
}
Posttyper, validering och bindningsmetadata
För posttyper används validering och bindning av metadata för parametrar. Metadata för egenskaper ignoreras
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; }
}
Validering och metadata
Validering använder metadata för parametern men använder egenskapen för att läsa värdet. I vanliga fall med primära konstruktorer skulle de två vara identiska. Det finns dock sätt att besegra det:
public record Person([Required] string Name)
{
   private readonly string _name;
   public Name { get; init => _name = value ?? string.Empty; } // Now this property is never null. However this object could have been constructed as `new Person(null);`
}
TryUpdateModel uppdaterar inte parametrar för en posttyp
public record Person(string Name)
{
   public int Age { get; set; }
}
var person = new Person("initial-name");
TryUpdateModel(person, ...);
I det här fallet försöker MVC inte binda Name igen. Kan dock Age uppdateras
Globaliseringsbeteende för modellbindningsvägsdata och frågesträngar
ASP.NET Core leverantör för routvärden och leverantör för frågesträngsvärden:
- Behandla värden som invariant kultur.
- Förvänta dig att URL:er är kulturinvarianta.
Däremot genomgår värden som kommer från formulärdata en kulturkänslig konvertering. Detta är avsiktligt så att URL:er kan delas oberoende av språkversion.
Så här gör du så att ASP.NET Core-routningsvärdeprovidern och frågesträngsvärdeprovidern genomgår en kulturkänslig konvertering:
- Ärv från IValueProviderFactory
- Kopiera koden från QueryStringValueProviderFactory eller RouteValueValueProviderFactory
- Ersätt kulturvärdet som skickas till värdeproviderns konstruktor med CultureInfo.CurrentCulture
- Ersätt standardvärdeproviderfabriken i MVC-alternativen med din nya:
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;
    }
}
Särskilda datatyper
Det finns vissa särskilda datatyper som modellbindning kan hantera.
IFormFile och IFormFileCollection
En uppladdad fil som ingår i HTTP-begäran.  
              IEnumerable<IFormFile> stöds också för flera filer.
CancellationToken
Åtgärder kan valfritt binda en CancellationToken som en parameter. Detta binder RequestAborted som signalerar när anslutningen som ligger till grund för HTTP-begäran avbryts. Åtgärder kan använda den här parametern för att avbryta långvariga asynkrona åtgärder som körs som en del av kontrollantåtgärderna.
FormCollection
Används för att hämta alla värden från publicerade formulärdata.
Indataformaterare
Data i begärandetexten kan vara i JSON, XML eller något annat format. För att parsa dessa data använder modellbindningen en indataformaterare som är konfigurerad för att hantera en viss innehållstyp. Som standard innehåller ASP.NET Core JSON-baserade indataformaterare för hantering av JSON-data. Du kan lägga till andra formaterare för andra innehållstyper.
ASP.NET Core väljer indataformaterare baserat på attributet Förbrukar . Om det inte finns något attribut används rubriken Innehållstyp.
Så här använder du de inbyggda XML-indataformatrarna:
- Installera NuGet-paketet - Microsoft.AspNetCore.Mvc.Formatters.Xml.
- I - Startup.ConfigureServicesanropar AddXmlSerializerFormatters eller AddXmlDataContractSerializerFormatters.- 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();
- ConsumesAnvänd attributet för kontrollantklasser eller åtgärdsmetoder som bör förvänta sig XML i begärandetexten.- [HttpPost] [Consumes("application/xml")] public ActionResult<Pet> Create(Pet pet)- Mer information finns i Introduktion till XML-serialisering. 
Anpassa modellbindning med indataformaterare
En indataformaterare tar fullt ansvar för att läsa data från begärandetexten. Om du vill anpassa den här processen konfigurerar du de API:er som används av indataformaterare. I det här avsnittet beskrivs hur du anpassar den System.Text.Json-baserade indataformateren för att förstå en anpassad typ med namnet ObjectId.
Tänk på följande modell, som innehåller en anpassad ObjectId egenskap med namnet Id:
public class ModelWithObjectId
{
    public ObjectId Id { get; set; }
}
Om du vill anpassa modellbindningsprocessen när du använder System.Text.Jsonskapar du en klass som härletts från JsonConverter<T>:
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);
    }
}
Använd attributet JsonConverterAttribute för typen för att använda en anpassad konverterare. I följande exempel konfigureras ObjectId-typen med ObjectIdConverter som sin egen anpassade konverterare.
[JsonConverter(typeof(ObjectIdConverter))]
public struct ObjectId
{
    public ObjectId(int id) =>
        Id = id;
    public int Id { get; }
}
Mer information finns i Skriva anpassade konverterare.
Undanta angivna typer från modellbindning
Modellens bindnings- och valideringssystems beteende styrs av ModelMetadata. Du kan anpassa ModelMetadata genom att lägga till en informationsprovider i MvcOptions.ModelMetadataDetailsProviders. Inbyggda informationsprovidrar är tillgängliga för inaktivering av modellbindning eller validering för angivna typer.
Om du vill inaktivera modellbindning för alla modeller av en angiven typ lägger du till en ExcludeBindingMetadataProvider i Startup.ConfigureServices. Om du till exempel vill inaktivera modellbindning för alla modeller av typen System.Version:
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();
Om du vill inaktivera validering av egenskaper för en angiven typ lägger du till en SuppressChildValidationMetadataProvider i Startup.ConfigureServices. Om du till exempel vill inaktivera validering av egenskaper av typen System.Guid:
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();
Anpassade modellbindare
Du kan utöka modellbindningen genom att skriva en anpassad modellbindning och använda [ModelBinder] attributet för att välja den för ett visst mål. Läs mer om bindning av anpassade modeller.
Manuell modellbindning
Modellbindning kan anropas manuellt genom att använda metoden TryUpdateModelAsync. Metoden definieras för båda ControllerBase klasserna och PageModel . Med metodöverlagringar kan du ange prefixet och värdeprovidern som ska användas. Metoden returnerar false om modellbindningen misslyckas. Här är ett exempel:
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 använder värdeleverantörer för att hämta data från formulärets data, frågesträngen och routningsdata. 
              TryUpdateModelAsync är vanligtvis:
- Används med Razor Pages- och MVC-appar med hjälp av kontrollanter och vyer för att förhindra överpublicering.
- Används inte med ett webb-API förutom när det hämtas från formulärdata, frågesträngar och routdata. Webb-API-slutpunkter som använder JSON använder indataformatrar för att deserialisera begärandetexten till ett objekt.
Mer information finns i TryUpdateModelAsync.
[FromServices]-attribut
Det här attributets namn följer mönstret för modellbindningsattribut som anger en datakälla. Men det handlar inte om att binda data från en värdeprovider. Den hämtar en instans av en typ från containern för beroendeinmatning . Syftet är att tillhandahålla ett alternativ till konstruktorinmatning för när du behöver en tjänst endast om en viss metod anropas.
Ytterligare resurser
ASP.NET Core