Megosztás a következőn keresztül:


Modellérvényesítés az ASP.NET Core MVC-ben és Razor a Pagesben

Ez a cikk bemutatja, hogyan érvényesítheti a felhasználói bemenetet egy ASP.NET Core MVC- vagy Razor Pages-alkalmazásban.

Mintakód megtekintése vagy letöltése (hogyan töltsük le).

Ellenőrzés a .NET 10-ben

A .NET 10-ben az egyesített érvényesítési API-k át lettek helyezve a Microsoft.Extensions.Validation NuGet-csomagba. Ez a módosítás az érvényesítési API-kat ASP.NET Core HTTP-forgatókönyveken kívül is elérhetővé teszi.

Az Microsoft.Extensions.Validation API-k használata:

  • Adja hozzá a következő csomaghivatkozást:

    <PackageReference Include="Microsoft.Extensions.Validation" Version="10.0.0" />
    

    A funkció változatlan marad, de most explicit csomaghivatkozásra van szükség.

  • Érvényesítési szolgáltatások regisztrálása függőséginjektálással:

    builder.Services.AddValidation();
    

Modell állapota

A modellállapot két alrendszer hibáit jelöli: a modellkötést és a modellérvényesítést. A modellkötésből származó hibák általában adatkonvertálási hibák. Egy "x" például egy egész számmezőbe van beírva. A modell érvényesítése a modellkötés után történik, és olyan hibákat jelez, amelyekben az adatok nem felelnek meg az üzleti szabályoknak. Például egy 0 értéket ad meg egy olyan mezőben, amely 1 és 5 közötti értékelést vár.

A modellkötés és a modell érvényesítése is egy vezérlőművelet vagy egy Razor Pages-kezelő metódus végrehajtása előtt történik. A webalkalmazások esetében az alkalmazás feladata, hogy megvizsgálja ModelState.IsValid, és megfelelően reagáljon. A webalkalmazások általában hibaüzenettel jelenítik meg a lapot, ahogyan az a következő Razor Pages-példában is látható:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

A vezérlőkkel és nézetekkel rendelkező ASP.NET Core MVC esetében az alábbi példa bemutatja, hogyan ellenőrizheti ModelState.IsValid a vezérlőműveleten belül:

public async Task<IActionResult> Create(Movie movie)
{
    if (!ModelState.IsValid)
    {
        return View(movie);
    }

    _context.Movies.Add(movie);
    await _context.SaveChangesAsync();

    return RedirectToAction(nameof(Index));
}

A webes API-vezérlőknek nem kell ellenőrizniük ModelState.IsValid , hogy rendelkeznek-e az [ApiController] attribútummal. Ebben az esetben a rendszer a hibaadatokat tartalmazó automatikus HTTP 400-választ adja vissza, ha a modell állapota érvénytelen. További információ: Automatikus HTTP 400-válaszok.

Újrafuttatás ellenőrzése

Az érvényesítés automatikus, de előfordulhat, hogy manuálisan szeretné megismételni. Előfordulhat például, hogy egy tulajdonság értékét számítja ki, és újra szeretné futtatni az ellenőrzést, miután a tulajdonságot a kiszámított értékre állítja. Az érvényesítés újrafuttatásához először hívja meg a modellre vonatkozó ellenőrzés törléséhez a ModelStateDictionary.ClearValidationState, majd ezt kövesse a TryValidateModel meghívásával.

public async Task<IActionResult> OnPostTryValidateAsync()
{
    var modifiedReleaseDate = DateTime.Now.Date;
    Movie.ReleaseDate = modifiedReleaseDate;

    ModelState.ClearValidationState(nameof(Movie));
    if (!TryValidateModel(Movie, nameof(Movie)))
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Érvényesítési attribútumok

Az érvényesítési attribútumokkal érvényesítési szabályokat adhat meg a modelltulajdonságokhoz. A mintaalkalmazás alábbi példája egy olyan modellosztályt mutat be, amely érvényesítési attribútumokkal van eljegyzve. Az [ClassicMovie] attribútum egy egyéni érvényesítési attribútum, a többi pedig beépített. Az [ClassicMovieWithClientValidator] nem jelenik meg, amely a testreszabott attribútum megvalósításának egy alternatív módját mutatja be.

public class Movie
{
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; } = null!;

    [ClassicMovie(1960)]
    [DataType(DataType.Date)]
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; } = null!;

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }
}

Beépített attribútumok

Az érvényesítési attribútumok teljes listáját a System.ComponentModel.DataAnnotations névtérben találja.

Hibaüzenetek

Az érvényesítési attribútumokkal megadhatja az érvénytelen bemenethez megjelenítendő hibaüzenetet. Például:

[StringLength(8, ErrorMessage = "Name length can't be more than 8.")]

Belsőleg az attribútumok meghívják a String.Format-t, használva a mezőnév helyőrzőjét, és néha további helyőrzőket is. Például:

[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]

Egy tulajdonságra Name alkalmazva az előző kód által létrehozott hibaüzenet a következő: "A névhossznak 6 és 8 között kell lennie".

Annak kiderítéséhez, hogy String.Format egy adott attribútum hibaüzenete mely paramétereknek lesz átadva, tekintse meg a DataAnnotations forráskódját.

JSON-tulajdonságnevek használata érvényesítési hibák esetén

Alapértelmezés szerint, amikor érvényesítési hiba történik, a modell érvényesítése létrehoz egy ModelStateDictionary-t a tulajdonságnévvel, mint hiba kulcs. Egyes alkalmazások, például az egyoldalas alkalmazások, JSON-tulajdonságneveket használhatnak a webes API-kból generált érvényesítési hibákhoz. Az alábbi kód úgy konfigurálja az ellenőrzést, hogy a SystemTextJsonValidationMetadataProvider JSON-tulajdonságneveket használja:

using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new SystemTextJsonValidationMetadataProvider());
});

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Az alábbi kód konfigurálja az ellenőrzést úgy, hogy NewtonsoftJsonValidationMetadataProvider a JSON tulajdonság nevét használja, amikor Json.NET-et használ:

using Microsoft.AspNetCore.Mvc.NewtonsoftJson;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new NewtonsoftJsonValidationMetadataProvider());
}).AddNewtonsoftJson();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Például a camel-casing használatára vonatkozó szabályzatra a GitHubon találnak példátProgram.cs.

Nem null értékű hivatkozástípusok és [Kötelező] attribútum

Az érvényesítési rendszer úgy kezeli a nem null értékű paramétereket vagy kötött tulajdonságokat, mintha attribútummal [Required(AllowEmptyStrings = true)] rendelkeznének. A Nullable kontextusok engedélyezésével az MVC implicit módon megkezdi a nem-null értékű tulajdonságok vagy paraméterek érvényesítését, mintha rendelkeznének az [Required(AllowEmptyStrings = true)] attribútummal. Vegye figyelembe a következő kódot:

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

Ha az alkalmazás <Nullable>enable</Nullable> segítségével készült, akkor a Name számára hiányzó érték a JSON-fájlban vagy az űrlap-bejegyzésben érvényesítési hibát eredményez. Ez ellentmondásosnak tűnhet, mivel az [Required(AllowEmptyStrings = true)] attribútum hallgatólagos, de ez várható viselkedés, mivel az üres sztringek alapértelmezés szerint null értékűre lesznek konvertálva. Nullázható hivatkozástípust használva engedélyezheti a Name tulajdonság számára, hogy null vagy hiányzó értékek legyenek megadva.

public class Person
{
    public string? Name { get; set; }
}

Ez a viselkedés letiltható a következő SuppressImplicitRequiredAttributeForNonNullableReferenceTypesbeállítássalProgram.cs:

builder.Services.AddControllers(
    options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);

[Kötelező] érvényesítés a kiszolgálón

A kiszolgálón a szükséges érték hiányzik, ha a tulajdonság null értékű. A nem null értékű mezők mindig érvényesek, és az [Required] attribútum hibaüzenete soha nem jelenik meg.

A nem null értékű tulajdonság modellkötése azonban meghiúsulhat, ami hibaüzenetet eredményez, például The value '' is invalid: . Ha egyéni hibaüzenetet szeretne megadni a nem null értékű típusok kiszolgálóoldali érvényesítéséhez, a következő lehetőségek közül választhat:

  • Tegye a mezőt nullelláthatóvá (például decimal? helyett decimal). Nullázható<A T> értéktípusokat a rendszer standard null értékű típusokként kezeli.

  • Adja meg a modellkötés által használandó alapértelmezett hibaüzenetet az alábbi példában látható módon:

    builder.Services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    builder.Services.AddSingleton
        <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
    

    További információ a modellkötési hibákról, amelyekhez alapértelmezett üzeneteket állíthat be, lásd: DefaultModelBindingMessageProvider.

[Kötelező] ellenőrzés az ügyfélen

A nem null értékű típusok és sztringek eltérően vannak kezelve az ügyfélen a kiszolgálóhoz képest. Az ügyfél oldalán

  • Egy érték csak akkor tekinthető jelennek, ha van bemenet megadva. Ezért az ügyféloldali ellenőrzés a nem null értékű típusokat ugyanúgy kezeli, mint a null értékű típusokat.
  • A sztringmezőben lévő szóközt a jQuery Validation kötelező metódusa érvényes bemenetnek tekinti. A kiszolgálóoldali ellenőrzés érvénytelennek tekint egy kötelező sztringmezőt, ha csak a szóköz van beírva.

Ahogy korábban említettük, a nem null értékű típusok úgy lesznek kezelve, mintha attribútummal [Required(AllowEmptyStrings = true)] rendelkeznének. Ez azt jelenti, hogy akkor is megkapja az ügyféloldali ellenőrzést, ha nem alkalmazza az [Required(AllowEmptyStrings = true)] attribútumot. Ha azonban nem használja az attribútumot, egy alapértelmezett hibaüzenet jelenik meg. Egyéni hibaüzenet megadásához használja az attribútumot.

[Távoli] attribútum

A [Távoli] attribútum ügyféloldali ellenőrzést valósít meg, amelyhez egy metódus meghívása szükséges a kiszolgálón annak megállapításához, hogy a mezőbemenet érvényes-e. Előfordulhat például, hogy az alkalmazásnak ellenőriznie kell, hogy egy felhasználónév már használatban van-e.

Távoli érvényesítés megvalósítása:

  1. Hozzon létre egy műveletmetódust a JavaScript hívásához. A jQuery Validation remote metódus JSON-választ vár:

    • true azt jelenti, hogy a bemeneti adatok érvényesek.
    • false, undefinedvagy null azt jelenti, hogy a bemenet érvénytelen. Az alapértelmezett hibaüzenet megjelenítése.
    • Bármely más sztring azt jelenti, hogy a bemenet érvénytelen. A karakterlánc egyéni hibaüzenetként történő megjelenítése.

    Íme egy példa egy egyéni hibaüzenetet visszaadó műveletmetódusra:

    [AcceptVerbs("GET", "POST")]
    public IActionResult VerifyEmail(string email)
    {
        if (!_userService.VerifyEmail(email))
        {
            return Json($"Email {email} is already in use.");
        }
    
        return Json(true);
    }
    
  2. A modellosztályban jegyzetelje a tulajdonságot egy [Remote] olyan attribútummal, amely az érvényesítési művelet metódusára mutat, ahogyan az alábbi példában látható:

    [Remote(action: "VerifyEmail", controller: "Users")]
    public string Email { get; set; } = null!;
    

A kiszolgálóoldali érvényesítést olyan ügyfelek esetében is végre kell hajtani, amelyek letiltották a JavaScript használatát.

További mezők

Az AdditionalFields attribútum tulajdonsága lehetővé teszi a [Remote] mezők kombinációjának ellenőrzését a kiszolgálón lévő adatokkal szemben. Ha például a User modell rendelkezik FirstName és LastName rendelkezik tulajdonságokkal, érdemes lehet ellenőrizni, hogy a meglévő felhasználók nem rendelkeznek-e már ilyen névpárokkal. Az alábbi példa a AdditionalFieldshasználatát mutatja be:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(LastName))]
[Display(Name = "First Name")]
public string FirstName { get; set; } = null!;

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName))]
[Display(Name = "Last Name")]
public string LastName { get; set; } = null!;

AdditionalFields a "FirstName" és a "LastName" sztringek explicit módon beállíthatók, de a nameof operátor használata egyszerűsíti a későbbi refaktorálást. Az érvényesítés műveleti metódusának mind a firstName-t, mind a lastName-t el kell fogadnia.

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyName(string firstName, string lastName)
{
    if (!_userService.VerifyName(firstName, lastName))
    {
        return Json($"A user named {firstName} {lastName} already exists.");
    }

    return Json(true);
}

Amikor a felhasználó vezeték- vagy utónevet ad meg, a JavaScript távoli hívást indít annak megtekintéséhez, hogy a névpár létrejött-e.

Két vagy több további mező érvényesítéséhez adja meg őket vesszővel tagolt listaként. Ha például egy tulajdonságot MiddleName szeretne hozzáadni a modellhez, állítsa be az [Remote] attribútumot az alábbi példában látható módon:

[Remote(action: "VerifyName", controller: "Users",
    AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

AdditionalFields, mint minden attribútumargumentum, állandó kifejezésnek kell lennie. Ezért ne használjon interpolált sztringet vagy hívjon meg Join inicializáláshoz AdditionalFields.

A beépített attribútumok alternatívái

Ha nem a beépített attribútumok által biztosított ellenőrzésre van szüksége, a következőkre van szüksége:

Egyéni attribútumok

Olyan forgatókönyvek esetén, amelyeket a beépített érvényesítési attribútumok nem kezelnek, egyéni érvényesítési attribútumokat hozhat létre. Hozzon létre egy olyan osztályt, amely örököl a ValidationAttribute osztályból, és írja felül a IsValid metódust.

A IsValid metódus elfogad egy érték nevű objektumot, amely az érvényesítendő bemenet. A túlterhelés egy objektumot is elfogad ValidationContext , amely további információkat nyújt, például a modellkötés által létrehozott modellpéldányt.

Az alábbi példa ellenőrzi, hogy a klasszikus műfajban lévő filmek megjelenési dátuma nem későbbi-e, mint egy adott év. Az [ClassicMovie] attribútum:

  • Csak a kiszolgálón fut.
  • Klasszikus filmek esetén ellenőrzi a kiadás dátumának érvényességét:
public class ClassicMovieAttribute : ValidationAttribute
{
    public ClassicMovieAttribute(int year)
        => Year = year;

    public int Year { get; }

    public string GetErrorMessage() =>
        $"Classic movies must have a release year no later than {Year}.";

    protected override ValidationResult? IsValid(
        object? value, ValidationContext validationContext)
    {
        var movie = (Movie)validationContext.ObjectInstance;
        var releaseYear = ((DateTime)value!).Year;

        if (movie.Genre == Genre.Classic && releaseYear > Year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }
}

Az movie előző példában szereplő változó egy Movie objektumot jelöl, amely az űrlapbeküldésből származó adatokat tartalmazza. Ha az ellenőrzés sikertelen, a ValidationResult rendszer hibaüzenetet ad vissza.

IValidatableObject

Az előző példa csak típusokkal Movie működik. Az osztályszintű ellenőrzés másik lehetősége a modellosztályban való implementálás IValidatableObject , ahogyan az alábbi példában látható:

public class ValidatableMovie : IValidatableObject
{
    private const int _classicYear = 1960;

    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; } = null!;

    [DataType(DataType.Date)]
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; } = null!;

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Genre == Genre.Classic && ReleaseDate.Year > _classicYear)
        {
            yield return new ValidationResult(
                $"Classic movies must have a release year no later than {_classicYear}.",
                new[] { nameof(ReleaseDate) });
        }
    }
}

Egyéni érvényesítés

Az alábbi kód bemutatja, hogyan adhat hozzá modellhibát a modell vizsgálata után:

if (Contact.Name == Contact.ShortName)
{
    ModelState.AddModelError("Contact.ShortName", 
                             "Short name can't be the same as Name.");
}

Az alábbi kód implementálja az érvényesítési tesztet egy vezérlőben:

if (contact.Name == contact.ShortName)
{
    ModelState.AddModelError(nameof(contact.ShortName),
                             "Short name can't be the same as Name.");
}

Az alábbi kód ellenőrzi, hogy a telefonszám és az e-mail egyedi-e:

public async Task<IActionResult> OnPostAsync()
{
    // Attach Validation Error Message to the Model on validation failure.          

    if (Contact.Name == Contact.ShortName)
    {
        ModelState.AddModelError("Contact.ShortName", 
                                 "Short name can't be the same as Name.");
    }

    if (_context.Contact.Any(i => i.PhoneNumber == Contact.PhoneNumber))
    {
        ModelState.AddModelError("Contact.PhoneNumber",
                                  "The Phone number is already in use.");
    }
    if (_context.Contact.Any(i => i.Email == Contact.Email))
    {
        ModelState.AddModelError("Contact.Email", "The Email is already in use.");
    }

    if (!ModelState.IsValid || _context.Contact == null || Contact == null)
    {
        // if model is invalid, return the page with the model state errors.
        return Page();
    }
    _context.Contact.Add(Contact);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Az alábbi kód implementálja az érvényesítési tesztet egy vezérlőben:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,ShortName,Email,PhoneNumber")] Contact contact)
{
    // Attach Validation Error Message to the Model on validation failure.
    if (contact.Name == contact.ShortName)
    {
        ModelState.AddModelError(nameof(contact.ShortName),
                                 "Short name can't be the same as Name.");
    }

    if (_context.Contact.Any(i => i.PhoneNumber == contact.PhoneNumber))
    {
        ModelState.AddModelError(nameof(contact.PhoneNumber),
                                  "The Phone number is already in use.");
    }
    if (_context.Contact.Any(i => i.Email == contact.Email))
    {
        ModelState.AddModelError(nameof(contact.Email), "The Email is already in use.");
    }

    if (ModelState.IsValid)
    {
        _context.Add(contact);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(contact);
}

Az egyedi telefonszámok vagy e-mailek ellenőrzése általában távoli ellenőrzéssel is elvégezhető.

ValidationResult

Vegye figyelembe a következő egyéni beállítást:ValidateNameAttribute

public class ValidateNameAttribute : ValidationAttribute
{
    public ValidateNameAttribute()
    {
        const string defaultErrorMessage = "Error with Name";
        ErrorMessage ??= defaultErrorMessage;
    }

    protected override ValidationResult? IsValid(object? value,
                                         ValidationContext validationContext)
    {
        if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
        {
            return new ValidationResult("Name is required.");
        }

        if (value.ToString()!.ToLower().Contains("zz"))
        {

            return new ValidationResult(
                        FormatErrorMessage(validationContext.DisplayName));
        }

        return ValidationResult.Success;
    }
}

Az alábbi kódban az egyéni [ValidateName] attribútum lesz alkalmazva:

public class Contact
{
    public Guid Id { get; set; }

    [ValidateName(ErrorMessage = "Name must not contain `zz`")] 
    public string? Name { get; set; }
    public string? Email { get; set; }
    public string? PhoneNumber { get; set; }
}

Ha a modell tartalmaz zz, a rendszer egy újat ValidationResult ad vissza.

Felső szintű csomópont érvényesítés

A legfelső szintű csomópontok a következők:

  • Műveleti paraméterek
  • Vezérlő tulajdonságai
  • Lapkezelő paraméterei
  • Lapmodell tulajdonságai

A modellhez kötött legfelső szintű csomópontok érvényesítésre kerülnek a modelltulajdonságok érvényesítésén felül. A mintaalkalmazás alábbi példájában a VerifyPhone metódus a RegularExpressionAttribute felhasználásával érvényesíti a phone műveletparamétert.

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyPhone(
    [RegularExpression(@"^\d{3}-\d{3}-\d{4}$")] string phone)
{
    if (!ModelState.IsValid)
    {
        return Json($"Phone {phone} has an invalid format. Format: ###-###-####");
    }

    return Json(true);
}

A legfelső szintű csomópontok érvényesítési attribútumokkal használhatók BindRequiredAttribute . A mintaalkalmazás alábbi példájában a CheckAge metódus azt határozza meg, hogy a age paramétert a lekérdezési sztringhez kell kötni az űrlap elküldésekor:

[HttpPost]
public IActionResult CheckAge([BindRequired, FromQuery] int age)
{

A Kor ellenőrzése lapon (CheckAge.cshtml) két űrlap található. Az első űrlap egy lekérdezési sztringparaméterként az Age értéket küldi el: 99.

Ha a lekérdezési sztringből megfelelően formázott age paramétert küld el, az űrlap érvényesíti.

Az Életkor ellenőrzése lapon található második űrlap elküldi az Age értéket a kérelem törzsében, és az ellenőrzés sikertelen. A kötés meghiúsul, mert a age paraméternek egy lekérdezési sztringből kell származnia.

Hibák maximális száma

Az érvényesítés a hibák maximális számának elérésekor (alapértelmezés szerint 200) leáll. Ezt a számot a következő kóddal konfigurálhatja:Program.cs

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.MaxModelValidationErrors = 50;
        options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
            _ => "The field is required.");
    });

builder.Services.AddSingleton
    <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();

Maximális rekurzió

ValidationVisitor bejárja az érvényesítendő modell objektumgráfját. Azoknál a modelleknél, amelyek mélyek vagy végtelenül rekurzívek, az érvényesítés veremtúlcsorduláshoz vezethet. MvcOptions.MaxValidationDepth lehetővé teszi az ellenőrzés korai leállítását, ha a látogató rekurziója meghaladja a beállított mélységet. Az alapértelmezett érték MvcOptions.MaxValidationDepth 32.

Automatikus rövidzárlat

Az ellenőrzést automatikusan rövidre zárjuk (kihagyjuk), ha a modellgráf nem igényel ellenőrzést. Azok az objektumok, amelyek esetében a futtatókörnyezet kihagyja az ellenőrzést, primitív gyűjteményeket (például byte[], string[], ) Dictionary<string, string>és olyan összetett objektumgráfokat tartalmaznak, amelyek nem rendelkeznek érvényesítőkkel.

Ügyféloldali ellenőrzés

Az ügyféloldali ellenőrzés megakadályozza a beküldést, amíg az űrlap érvényes nem lesz. A Küldés gomb javaScriptet futtat, amely elküldi az űrlapot, vagy hibaüzeneteket jelenít meg.

Az ügyféloldali érvényesítés elkerüli a kiszolgáló szükségtelen oda-vissza utazását, ha bemeneti hibák jelentkeznek egy űrlapon. Az ügyféloldali érvényesítést _Layout.cshtml_ValidationScriptsPartial.cshtml a következő szkripthivatkozások támogatják:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.12/jquery.validate.unobtrusive.js"></script>

A jQuery Unobtrusive Validation szkript egy egyéni Microsoft előtér-kódtár, amely a népszerű jQuery Validation beépülő modulra épül. A jQuery Unobtrusive Validation nélkül ugyanazt az érvényesítési logikát két helyen kell kódolva lennie: egyszer a modelltulajdonságok kiszolgálóoldali érvényesítési attribútumaiban, majd ismét az ügyféloldali szkriptekben. Ehelyett a címkesegítők és a HTML-segítők az érvényesítési attribútumokat használják, és a modelltulajdonságok metaadatainak beírásával renderelik az érvényesítésre szoruló űrlapelemek HTML 5 data- attribútumait. A jQuery Unobtrusive Validation elemzi az data- attribútumokat, és átadja a logikát a jQuery Validationnek, és hatékonyan "másolja" a kiszolgálóoldali érvényesítési logikát az ügyfélre. Az ügyféloldalon érvényesítési hibákat jeleníthet meg az itt látható címkesegítők használatával:

<div class="form-group">
    <label asp-for="Movie.ReleaseDate" class="control-label"></label>
    <input asp-for="Movie.ReleaseDate" class="form-control" />
    <span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>

Az előző címkesegítők a következő HTML-t jelenítik meg:

<div class="form-group">
    <label class="control-label" for="Movie_ReleaseDate">Release Date</label>
    <input class="form-control" type="date" data-val="true"
        data-val-required="The Release Date field is required."
        id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">
    <span class="text-danger field-validation-valid"
        data-valmsg-for="Movie.ReleaseDate" data-valmsg-replace="true"></span>
</div>

Figyelje meg, hogy a data- HTML-kimenet attribútumai megfelelnek a tulajdonság érvényesítési attribútumainak Movie.ReleaseDate . Az data-val-required attribútum egy hibaüzenetet tartalmaz, amely akkor jelenik meg, ha a felhasználó nem tölti ki a kiadási dátum mezőt. A jQuery Unobtrusive Validation ezt az értéket átadja a jQuery Validation required() metódusnak , amely ezután megjeleníti az üzenetet a kísérő <span> elemben.

Az adattípus-ellenőrzés egy tulajdonság .NET-típusán alapul, kivéve, ha egy [DataType] attribútum felülírja. A böngészők saját alapértelmezett hibaüzenetekkel rendelkeznek, de a jQuery Validation Unobtrusive Validation csomag felülírhatja ezeket az üzeneteket. [DataType] attribútumok és alosztályok, például a [EmailAddress] lehetővé teszik a hibaüzenet megadását.

Nem feltűnő ellenőrzés

A nem zavaró ellenőrzéssel kapcsolatos információkért tekintse meg ezt a GitHub-problémát.

Érvényesítés hozzáadása dinamikus űrlapokhoz

JQuery Unobtrusive Validation átadja az érvényesítési logikát és paramétereket a jQuery Validationnek az oldal első betöltésekor. Ezért az ellenőrzés nem működik automatikusan a dinamikusan létrehozott űrlapokon. Az érvényesítés engedélyezéséhez kérje meg a jQuery Nem feltűnő érvényesítés parancsot, hogy közvetlenül a létrehozás után elemezni tudja a dinamikus űrlapot. Az alábbi kód például egy AJAX-en keresztül hozzáadott űrlapon állítja be az ügyféloldali ellenőrzést.

$.get({
    url: "https://url/that/returns/a/form",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add form. " + errorThrown);
    },
    success: function(newFormHTML) {
        var container = document.getElementById("form-container");
        container.insertAdjacentHTML("beforeend", newFormHTML);
        var forms = container.getElementsByTagName("form");
        var newForm = forms[forms.length - 1];
        $.validator.unobtrusive.parse(newForm);
    }
})

A $.validator.unobtrusive.parse() metódus egy jQuery-választót fogad el egyetlen argumentumához. Ez a módszer utasítja a jQuery Unobtrusive Validationt arra, hogy elemezze a data- attribútumokat a választóban lévő űrlapokon. Az attribútumok értékei ezután átadódnak a jQuery Validation beépülő modulnak.

Ellenőrzés hozzáadása dinamikus vezérlőkhöz

A $.validator.unobtrusive.parse() metódus egy teljes űrlapon működik, nem pedig az egyes dinamikusan létrehozott vezérlőkön, mint például <input> és <select/>. Az űrlap újraelemzéséhez távolítsa el az űrlap korábbi elemzésekor hozzáadott érvényesítési adatokat az alábbi példában látható módon:

$.get({
    url: "https://url/that/returns/a/control",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add control. " + errorThrown);
    },
    success: function(newInputHTML) {
        var form = document.getElementById("my-form");
        form.insertAdjacentHTML("beforeend", newInputHTML);
        $(form).removeData("validator")    // Added by jQuery Validation
               .removeData("unobtrusiveValidation");   // Added by jQuery Unobtrusive Validation
        $.validator.unobtrusive.parse(form);
    }
})

Egyéni ügyféloldali ellenőrzés

Az egyéni ügyféloldali érvényesítés egy egyéni jQuery validation adapterrel működő HTML-attribútumok létrehozásával data- történik. A következő mintaadapter-kód a korábban ebben a cikkben bevezetett [ClassicMovie] és [ClassicMovieWithClientValidator] attribútumokhoz készült:

$.validator.addMethod('classicmovie', function (value, element, params) {
    var genre = $(params[0]).val(), year = params[1], date = new Date(value);

    // The Classic genre has a value of '0'.
    if (genre && genre.length > 0 && genre[0] === '0') {
        // The release date for a Classic is valid if it's no greater than the given year.
        return date.getUTCFullYear() <= year;
    }

    return true;
});

$.validator.unobtrusive.adapters.add('classicmovie', ['year'], function (options) {
    var element = $(options.form).find('select#Movie_Genre')[0];

    options.rules['classicmovie'] = [element, parseInt(options.params['year'])];
    options.messages['classicmovie'] = options.message;
});

Az adapterek írásával kapcsolatos információkért tekintse meg a jQuery Validation dokumentációját.

Az adapter használatát egy adott mezőhöz a következő attribútumok data- váltják ki:

  • A mező megjelölése ellenőrzés tárgyát képezőként (data-val="true").
  • Azonosítsa az érvényesítési szabály nevét és a hibaüzenet szövegét (például data-val-rulename="Error message.").
  • Adjon meg minden további paramétert, amelyekre az érvényesítőnek szüksége van (például data-val-rulename-param1="value").

Az alábbi példa a data-mintaalkalmazás attribútumainak attribútumaitClassicMovie mutatja be:

<input class="form-control" type="date"
    data-val="true"
    data-val-classicmovie="Classic movies must have a release year no later than 1960."
    data-val-classicmovie-year="1960"
    data-val-required="The Release Date field is required."
    id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">

Ahogy korábban említettük, a címkesegítők és a HTML-segítők az érvényesítési attribútumokból származó információkat használják az attribútumok rendereléséhez data- . A kódírásnak két lehetősége van, amelyek egyéni data- HTML-attribútumok létrehozását eredményezik:

  • Hozzon létre egy olyan osztályt, amely származik AttributeAdapterBase<TAttribute> , és egy olyan osztályt, amely megvalósítja IValidationAttributeAdapterProvider, és regisztrálja az attribútumot és annak adapterét a DI-ben. Ez a módszer az egyetlen felelősség elvét követi abban az esetben, ha a kiszolgálóhoz és az ügyfélhez kapcsolódó érvényesítési kód külön osztályokban van. Az adapternek az az előnye is, hogy mivel regisztrálva van a DI-ben, a DI más szolgáltatásai is elérhetők, ha szükséges.
  • Implementálja IClientModelValidator az ValidationAttribute osztályban. Ez a módszer akkor lehet megfelelő, ha az attribútum nem végez kiszolgálóoldali ellenőrzést, és nincs szüksége a diától származó szolgáltatásokra.

Attribútumadapter ügyféloldali ellenőrzéshez

A HTML attribútumok megjelenítésének ezen módszerét a data- attribútum használja a ClassicMovie. Ügyfélérvényesítés hozzáadása ezzel a módszerrel:

  1. Hozzon létre egy attribútumadapter-osztályt az egyéni érvényesítési attribútumhoz. Az osztály származtatása a következőből: AttributeAdapterBase<TAttribute>. Hozzon létre egy metódust AddValidation , amely attribútumokat data- ad hozzá a renderelt kimenethez az alábbi példában látható módon:

    public class ClassicMovieAttributeAdapter : AttributeAdapterBase<ClassicMovieAttribute>
    {
        public ClassicMovieAttributeAdapter(
            ClassicMovieAttribute attribute, IStringLocalizer? stringLocalizer)
            : base(attribute, stringLocalizer)
        {
    
        }
    
        public override void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage(context));
    
            var year = Attribute.Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public override string GetErrorMessage(ModelValidationContextBase validationContext)
            => Attribute.GetErrorMessage();
    }
    
  2. Hozzon létre egy adapter szolgáltató osztályt, amely implementálja a IValidationAttributeAdapterProvider-t. GetAttributeAdapter A metódusban adja át az egyéni attribútumot az adapter konstruktorának, ahogyan az ebben a példában látható:

    public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
    {
        private readonly IValidationAttributeAdapterProvider baseProvider =
            new ValidationAttributeAdapterProvider();
    
        public IAttributeAdapter? GetAttributeAdapter(
            ValidationAttribute attribute, IStringLocalizer? stringLocalizer)
        {
            if (attribute is ClassicMovieAttribute classicMovieAttribute)
            {
                return new ClassicMovieAttributeAdapter(classicMovieAttribute, stringLocalizer);
            }
    
            return baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
        }
    }
    
  3. Regisztrálja a DI-hez tartozó adapterszolgáltatót a következő helyen Program.cs:

    builder.Services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    builder.Services.AddSingleton
        <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
    

IClientModelValidator ügyféloldali ellenőrzéshez

A HTML attribútumok megjelenítésének ezen módszerét a data- attribútum használja a ClassicMovieWithClientValidator. Ügyfélérvényesítés hozzáadása ezzel a módszerrel:

  • Az egyéni érvényesítési attribútumban implementálja az interfészt IClientModelValidator , és hozzon létre egy metódust AddValidation . A metódusban AddValidation adjon hozzá data- attribútumokat az ellenőrzéshez, ahogyan az a következő példában látható:

    public class ClassicMovieWithClientValidatorAttribute :
        ValidationAttribute, IClientModelValidator
    {
        public ClassicMovieWithClientValidatorAttribute(int year)
            => Year = year;
    
        public int Year { get; }
    
        public void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
    
            var year = Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public string GetErrorMessage() =>
            $"Classic movies must have a release year no later than {Year}.";
    
        protected override ValidationResult? IsValid(
            object? value, ValidationContext validationContext)
        {
            var movie = (Movie)validationContext.ObjectInstance;
            var releaseYear = ((DateTime)value!).Year;
    
            if (movie.Genre == Genre.Classic && releaseYear > Year)
            {
                return new ValidationResult(GetErrorMessage());
            }
    
            return ValidationResult.Success;
        }
    
        private static bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
    
            attributes.Add(key, value);
            return true;
        }
    }
    

Ügyféloldali érvényesítés letiltása

Az alábbi kód letiltja az ügyfélérvényesítést a Pagesben Razor :

builder.Services.AddRazorPages()
    .AddViewOptions(options =>
    {
        options.HtmlHelperOptions.ClientValidationEnabled = false;
    });

További lehetőségek az ügyféloldali érvényesítés letiltására:

  • Az összes _ValidationScriptsPartial fájlban kommenteljük ki a .cshtml hivatkozást.
  • Távolítsa el a Pages\Shared_ValidationScriptsPartial.cshtml fájl tartalmát.

Az előző megközelítés nem akadályozza meg a ASP.NET Core IdentityRazor osztálykódtár ügyféloldali ellenőrzését. További információ: Állványzat Identity ASP.NET Core-projektekben.

Probléma részletei

A probléma részletei nem az egyetlen válaszformátum a HTTP API-hibák leírásához, azonban gyakran használják őket a HTTP API-k hibáinak jelentésére.

A probléma részletei szolgáltatás implementálja a felületet, amely támogatja a IProblemDetailsService probléma részleteinek létrehozását a ASP.NET Core-ban. A AddProblemDetails(IServiceCollection) bővítménymetódus a IServiceCollection regisztrálja az alapértelmezett IProblemDetailsService implementációt.

A ASP.NET Core-alkalmazásokban a következő köztes szoftver generálja a probléma részleteit HTTP-válaszok meghívásakorAddProblemDetails, kivéve, ha a Accept kérelem HTTP-fejléce nem tartalmazza a regisztrált IProblemDetailsWriter (alapértelmezett) által támogatott tartalomtípusokat: application/json

  • ExceptionHandlerMiddleware: Probléma részleteit tartalmazó választ hoz létre, ha nincs definiálva egyéni kezelő.
  • StatusCodePagesMiddleware: Alapértelmezés szerint létrehoz egy probléma részleteit tartalmazó választ.
  • DeveloperExceptionPageMiddleware: Probléma részleteit tartalmazó választ hoz létre a fejlesztési környezetben, amikor a kérelem HTTP-fejléce nem tartalmazza a Accept értéket.

További erőforrások

Ez a cikk bemutatja, hogyan érvényesítheti a felhasználói bemenetet egy ASP.NET Core MVC- vagy Razor Pages-alkalmazásban.

Mintakód megtekintése vagy letöltése (hogyan töltsük le).

Modell állapota

A modellállapot két alrendszer hibáit jelöli: a modellkötést és a modellérvényesítést. A modellkötésből származó hibák általában adatkonvertálási hibák. Egy "x" például egy egész számmezőbe van beírva. A modell érvényesítése a modellkötés után történik, és olyan hibákat jelez, amelyekben az adatok nem felelnek meg az üzleti szabályoknak. Például egy 0 értéket ad meg egy olyan mezőben, amely 1 és 5 közötti értékelést vár.

A modellkötés és a modell érvényesítése is egy vezérlőművelet vagy egy Razor Pages-kezelő metódus végrehajtása előtt történik. A webalkalmazások esetében az alkalmazás feladata, hogy megvizsgálja ModelState.IsValid, és megfelelően reagáljon. A webalkalmazások általában hibaüzenettel jelenítik meg a lapot, ahogyan az a következő Razor Pages-példában is látható:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

A vezérlőkkel és nézetekkel rendelkező ASP.NET Core MVC esetében az alábbi példa bemutatja, hogyan ellenőrizheti ModelState.IsValid a vezérlőműveleten belül:

public async Task<IActionResult> Create(Movie movie)
{
    if (!ModelState.IsValid)
    {
        return View(movie);
    }

    _context.Movies.Add(movie);
    await _context.SaveChangesAsync();

    return RedirectToAction(nameof(Index));
}

A webes API-vezérlőknek nem kell ellenőrizniük ModelState.IsValid , hogy rendelkeznek-e az [ApiController] attribútummal. Ebben az esetben a rendszer a hibaadatokat tartalmazó automatikus HTTP 400-választ adja vissza, ha a modell állapota érvénytelen. További információ: Automatikus HTTP 400-válaszok.

Újrafuttatás ellenőrzése

Az érvényesítés automatikus, de előfordulhat, hogy manuálisan szeretné megismételni. Előfordulhat például, hogy egy tulajdonság értékét számítja ki, és újra szeretné futtatni az ellenőrzést, miután a tulajdonságot a kiszámított értékre állítja. Az érvényesítés újrafuttatásához először hívja meg a modellre vonatkozó ellenőrzés törléséhez a ModelStateDictionary.ClearValidationState, majd ezt kövesse a TryValidateModel meghívásával.

public async Task<IActionResult> OnPostTryValidateAsync()
{
    var modifiedReleaseDate = DateTime.Now.Date;
    Movie.ReleaseDate = modifiedReleaseDate;

    ModelState.ClearValidationState(nameof(Movie));
    if (!TryValidateModel(Movie, nameof(Movie)))
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Érvényesítési attribútumok

Az érvényesítési attribútumokkal érvényesítési szabályokat adhat meg a modelltulajdonságokhoz. A mintaalkalmazás alábbi példája egy olyan modellosztályt mutat be, amely érvényesítési attribútumokkal van eljegyzve. Az [ClassicMovie] attribútum egy egyéni érvényesítési attribútum, a többi pedig beépített. Az [ClassicMovieWithClientValidator] nem jelenik meg, amely a testreszabott attribútum megvalósításának egy alternatív módját mutatja be.

public class Movie
{
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; } = null!;

    [ClassicMovie(1960)]
    [DataType(DataType.Date)]
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; } = null!;

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }
}

Beépített attribútumok

Íme néhány beépített érvényesítési attribútum:

  • [ValidateNever]: Azt jelzi, hogy egy tulajdonságot vagy paramétert ki kell zárni az ellenőrzésből.
  • [CreditCard]: Ellenőrzi, hogy a tulajdonság rendelkezik-e hitelkártyaformátummal. További jQuery-érvényesítési módszereket igényel.
  • [Összehasonlítás]: Ellenőrzi, hogy egy modell két tulajdonsága egyezik-e.
  • [EmailAddress]: Ellenőrzi, hogy a tulajdonság e-mail formátumú-e.
  • [Telefon]: Ellenőrzi, hogy a tulajdonság telefonszámformátummal rendelkezik-e.
  • [Tartomány]: Ellenőrzi, hogy a tulajdonság értéke egy megadott tartományba esik-e.
  • [RegularExpression]: Ellenőrzi, hogy a tulajdonság értéke megfelel-e egy megadott reguláris kifejezésnek.
  • [Kötelező]: Ellenőrzi, hogy a mező nem null értékű-e. Az attribútum működésének részleteiért tekintse meg [Required] az attribútumot .
  • [StringLength]: Ellenőrzi, hogy egy sztringtulajdonság értéke nem lépi-e túl a megadott hosszkorlátot.
  • [URL]: Ellenőrzi, hogy a tulajdonság URL-formátummal rendelkezik-e.
  • [Távoli]: Az ügyfél bemenetének ellenőrzése egy műveletmetódus meghívásával a kiszolgálón. Az attribútum működésének részleteiért tekintse meg [Remote] az attribútumot .

Az érvényesítési attribútumok teljes listája megtalálható a System.ComponentModel.DataAnnotations névtérben.

Hibaüzenetek

Az érvényesítési attribútumokkal megadhatja az érvénytelen bemenethez megjelenítendő hibaüzenetet. Például:

[StringLength(8, ErrorMessage = "Name length can't be more than 8.")]

Belsőleg az attribútumok meghívják a String.Format-t, használva a mezőnév helyőrzőjét, és néha további helyőrzőket is. Például:

[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]

Egy tulajdonságra Name alkalmazva az előző kód által létrehozott hibaüzenet a következő: "A névhossznak 6 és 8 között kell lennie".

Annak kiderítéséhez, hogy String.Format egy adott attribútum hibaüzenete mely paramétereknek lesz átadva, tekintse meg a DataAnnotations forráskódját.

Nem null értékű hivatkozástípusok és a [Kötelező] attribútum

Az érvényesítési rendszer úgy kezeli a nem null értékű paramétereket vagy kötött tulajdonságokat, mintha attribútummal [Required(AllowEmptyStrings = true)] rendelkeznének. A környezetek engedélyezésével Nullableaz MVC implicit módon megkezdi a nem null értékű tulajdonságok érvényesítését a nem általános típusokon vagy paramétereken, mintha az [Required(AllowEmptyStrings = true)] attribútummal lettek volna társítva. Vegye figyelembe a következő kódot:

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

Ha az alkalmazás <Nullable>enable</Nullable> segítségével készült, akkor a Name számára hiányzó érték a JSON-fájlban vagy az űrlap-bejegyzésben érvényesítési hibát eredményez. Nullázható hivatkozástípust használva engedélyezheti a Name tulajdonság számára, hogy null vagy hiányzó értékek legyenek megadva.

public class Person
{
    public string? Name { get; set; }
}

Ez a viselkedés letiltható a következő SuppressImplicitRequiredAttributeForNonNullableReferenceTypesbeállítássalProgram.cs:

builder.Services.AddControllers(
    options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);

Nem null értékű tulajdonságok az általános típusokon és a [Kötelező] attribútumon

Az általános típusok nem null értékű tulajdonságainak tartalmazniuk kell az [Required] attribútumot, ha a típus szükséges. A következő kódban TestRequired nem szükséges:

public class WeatherForecast<T>
{
    public string TestRequired { get; set; } = null!;
    public T? Inner { get; set; }
}

A következő kódban TestRequired explicit módon kötelezőként van megjelölve.

using System.ComponentModel.DataAnnotations;

public class WeatherForecast<T>
{
    [Required]
    public string TestRequired { get; set; } = null!;
    public T? Inner { get; set; }
}

[Kötelező] érvényesítés a kiszolgálón

A kiszolgálón a szükséges érték hiányzik, ha a tulajdonság null értékű. A nem null értékű mezők mindig érvényesek, és az [Required] attribútum hibaüzenete soha nem jelenik meg.

A nem null értékű tulajdonság modellkötése azonban meghiúsulhat, ami hibaüzenetet eredményez, például The value '' is invalid: . Ha egyéni hibaüzenetet szeretne megadni a nem null értékű típusok kiszolgálóoldali érvényesítéséhez, a következő lehetőségek közül választhat:

  • Tegye a mezőt nullelláthatóvá (például decimal? helyett decimal). Nullázható<A T> értéktípusokat a rendszer standard null értékű típusokként kezeli.

  • Adja meg a modellkötés által használandó alapértelmezett hibaüzenetet az alábbi példában látható módon:

    builder.Services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    builder.Services.AddSingleton
        <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
    

    További információ a modellkötési hibákról, amelyekhez alapértelmezett üzeneteket állíthat be, lásd: DefaultModelBindingMessageProvider.

[Kötelező] ellenőrzés az ügyfélen

A nem null értékű típusok és sztringek eltérően vannak kezelve az ügyfélen a kiszolgálóhoz képest. Az ügyfél oldalán

  • Egy érték csak akkor tekinthető jelennek, ha van bemenet megadva. Ezért az ügyféloldali ellenőrzés a nem null értékű típusokat ugyanúgy kezeli, mint a null értékű típusokat.
  • A sztringmezőben lévő szóközt a jQuery Validation kötelező metódusa érvényes bemenetnek tekinti. A kiszolgálóoldali ellenőrzés érvénytelennek tekint egy kötelező sztringmezőt, ha csak a szóköz van beírva.

Ahogy korábban említettük, a nem null értékű típusok úgy lesznek kezelve, mintha attribútummal [Required(AllowEmptyStrings = true)] rendelkeznének. Ez azt jelenti, hogy akkor is megkapja az ügyféloldali ellenőrzést, ha nem alkalmazza az [Required(AllowEmptyStrings = true)] attribútumot. Ha azonban nem használja az attribútumot, egy alapértelmezett hibaüzenet jelenik meg. Egyéni hibaüzenet megadásához használja az attribútumot.

[Távoli] attribútum

A [Távoli] attribútum ügyféloldali ellenőrzést valósít meg, amelyhez egy metódus meghívása szükséges a kiszolgálón annak megállapításához, hogy a mezőbemenet érvényes-e. Előfordulhat például, hogy az alkalmazásnak ellenőriznie kell, hogy egy felhasználónév már használatban van-e.

Távoli érvényesítés megvalósítása:

  1. Hozzon létre egy műveletmetódust a JavaScript hívásához. A jQuery Validation remote metódus JSON-választ vár:

    • true azt jelenti, hogy a bemeneti adatok érvényesek.
    • false, undefinedvagy null azt jelenti, hogy a bemenet érvénytelen. Az alapértelmezett hibaüzenet megjelenítése.
    • Bármely más sztring azt jelenti, hogy a bemenet érvénytelen. A karakterlánc egyéni hibaüzenetként történő megjelenítése.

    Íme egy példa egy egyéni hibaüzenetet visszaadó műveletmetódusra:

    [AcceptVerbs("GET", "POST")]
    public IActionResult VerifyEmail(string email)
    {
        if (!_userService.VerifyEmail(email))
        {
            return Json($"Email {email} is already in use.");
        }
    
        return Json(true);
    }
    
  2. A modellosztályban jegyzetelje a tulajdonságot egy [Remote] olyan attribútummal, amely az érvényesítési művelet metódusára mutat, ahogyan az alábbi példában látható:

    [Remote(action: "VerifyEmail", controller: "Users")]
    public string Email { get; set; } = null!;
    

További mezők

Az AdditionalFields attribútum tulajdonsága lehetővé teszi a [Remote] mezők kombinációjának ellenőrzését a kiszolgálón lévő adatokkal szemben. Ha például a User modell rendelkezik FirstName és LastName rendelkezik tulajdonságokkal, érdemes lehet ellenőrizni, hogy a meglévő felhasználók nem rendelkeznek-e már ilyen névpárokkal. Az alábbi példa a AdditionalFieldshasználatát mutatja be:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(LastName))]
[Display(Name = "First Name")]
public string FirstName { get; set; } = null!;

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName))]
[Display(Name = "Last Name")]
public string LastName { get; set; } = null!;

AdditionalFields a "FirstName" és a "LastName" sztringek explicit módon beállíthatók, de a nameof operátor használata egyszerűsíti a későbbi refaktorálást. Az érvényesítés műveleti metódusának mind a firstName-t, mind a lastName-t el kell fogadnia.

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyName(string firstName, string lastName)
{
    if (!_userService.VerifyName(firstName, lastName))
    {
        return Json($"A user named {firstName} {lastName} already exists.");
    }

    return Json(true);
}

Amikor a felhasználó vezeték- vagy utónevet ad meg, a JavaScript távoli hívást indít annak megtekintéséhez, hogy a névpár létrejött-e.

Két vagy több további mező érvényesítéséhez adja meg őket vesszővel tagolt listaként. Ha például egy tulajdonságot MiddleName szeretne hozzáadni a modellhez, állítsa be az [Remote] attribútumot az alábbi példában látható módon:

[Remote(action: "VerifyName", controller: "Users",
    AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

AdditionalFields, mint minden attribútumargumentum, állandó kifejezésnek kell lennie. Ezért ne használjon interpolált sztringet vagy hívjon meg Join inicializáláshoz AdditionalFields.

A beépített attribútumok alternatívái

Ha nem a beépített attribútumok által biztosított ellenőrzésre van szüksége, a következőkre van szüksége:

Egyéni attribútumok

Olyan forgatókönyvek esetén, amelyeket a beépített érvényesítési attribútumok nem kezelnek, egyéni érvényesítési attribútumokat hozhat létre. Hozzon létre egy olyan osztályt, amely örököl a ValidationAttribute osztályból, és írja felül a IsValid metódust.

A IsValid metódus elfogad egy érték nevű objektumot, amely az érvényesítendő bemenet. A túlterhelés egy objektumot is elfogad ValidationContext , amely további információkat nyújt, például a modellkötés által létrehozott modellpéldányt.

Az alábbi példa ellenőrzi, hogy a klasszikus műfajban lévő filmek megjelenési dátuma nem későbbi-e, mint egy adott év. Az [ClassicMovie] attribútum:

  • Csak a kiszolgálón fut.
  • Klasszikus filmek esetén ellenőrzi a kiadás dátumának érvényességét:
public class ClassicMovieAttribute : ValidationAttribute
{
    public ClassicMovieAttribute(int year)
        => Year = year;

    public int Year { get; }

    public string GetErrorMessage() =>
        $"Classic movies must have a release year no later than {Year}.";

    protected override ValidationResult? IsValid(
        object? value, ValidationContext validationContext)
    {
        var movie = (Movie)validationContext.ObjectInstance;
        var releaseYear = ((DateTime)value!).Year;

        if (movie.Genre == Genre.Classic && releaseYear > Year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }
}

Az movie előző példában szereplő változó egy Movie objektumot jelöl, amely az űrlapbeküldésből származó adatokat tartalmazza. Ha az ellenőrzés sikertelen, a ValidationResult rendszer hibaüzenetet ad vissza.

IValidatableObject

Az előző példa csak típusokkal Movie működik. Az osztályszintű ellenőrzés másik lehetősége a modellosztályban való implementálás IValidatableObject , ahogyan az alábbi példában látható:

public class ValidatableMovie : IValidatableObject
{
    private const int _classicYear = 1960;

    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; } = null!;

    [DataType(DataType.Date)]
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; } = null!;

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Genre == Genre.Classic && ReleaseDate.Year > _classicYear)
        {
            yield return new ValidationResult(
                $"Classic movies must have a release year no later than {_classicYear}.",
                new[] { nameof(ReleaseDate) });
        }
    }
}

Felső szintű csomópont érvényesítés

A legfelső szintű csomópontok a következők:

  • Műveleti paraméterek
  • Vezérlő tulajdonságai
  • Lapkezelő paraméterei
  • Lapmodell tulajdonságai

A modellhez kötött legfelső szintű csomópontok érvényesítésre kerülnek a modelltulajdonságok érvényesítésén felül. A mintaalkalmazás alábbi példájában a VerifyPhone metódus a RegularExpressionAttribute felhasználásával érvényesíti a phone műveletparamétert.

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyPhone(
    [RegularExpression(@"^\d{3}-\d{3}-\d{4}$")] string phone)
{
    if (!ModelState.IsValid)
    {
        return Json($"Phone {phone} has an invalid format. Format: ###-###-####");
    }

    return Json(true);
}

A legfelső szintű csomópontok érvényesítési attribútumokkal használhatók BindRequiredAttribute . A mintaalkalmazás alábbi példájában a CheckAge metódus azt határozza meg, hogy a age paramétert a lekérdezési sztringhez kell kötni az űrlap elküldésekor:

[HttpPost]
public IActionResult CheckAge([BindRequired, FromQuery] int age)
{

A Kor ellenőrzése lapon (CheckAge.cshtml) két űrlap található. Az első űrlap egy lekérdezési sztringparaméterként az Age értéket küldi el: 99.

Ha a lekérdezési sztringből megfelelően formázott age paramétert küld el, az űrlap érvényesíti.

Az Életkor ellenőrzése lapon található második űrlap elküldi az Age értéket a kérelem törzsében, és az ellenőrzés sikertelen. A kötés meghiúsul, mert a age paraméternek egy lekérdezési sztringből kell származnia.

Hibák maximális száma

Az érvényesítés a hibák maximális számának elérésekor (alapértelmezés szerint 200) leáll. Ezt a számot a következő kóddal konfigurálhatja:Program.cs

builder.Services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.MaxModelValidationErrors = 50;
        options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
            _ => "The field is required.");
    });

builder.Services.AddSingleton
    <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();

Maximális rekurzió

ValidationVisitor bejárja az érvényesítendő modell objektumgráfját. Azoknál a modelleknél, amelyek mélyek vagy végtelenül rekurzívek, az érvényesítés veremtúlcsorduláshoz vezethet. MvcOptions.MaxValidationDepth lehetővé teszi az ellenőrzés korai leállítását, ha a látogató rekurziója meghaladja a beállított mélységet. Az alapértelmezett érték MvcOptions.MaxValidationDepth 32.

Automatikus rövidzárlat

Az ellenőrzést automatikusan rövidre zárjuk (kihagyjuk), ha a modellgráf nem igényel ellenőrzést. Azok az objektumok, amelyek esetében a futtatókörnyezet kihagyja az ellenőrzést, primitív gyűjteményeket (például byte[], string[], ) Dictionary<string, string>és olyan összetett objektumgráfokat tartalmaznak, amelyek nem rendelkeznek érvényesítőkkel.

Ügyféloldali ellenőrzés

Az ügyféloldali ellenőrzés megakadályozza a beküldést, amíg az űrlap érvényes nem lesz. A Küldés gomb javaScriptet futtat, amely elküldi az űrlapot, vagy hibaüzeneteket jelenít meg.

Az ügyféloldali érvényesítés elkerüli a kiszolgáló szükségtelen oda-vissza utazását, ha bemeneti hibák jelentkeznek egy űrlapon. Az ügyféloldali érvényesítést _Layout.cshtml_ValidationScriptsPartial.cshtml a következő szkripthivatkozások támogatják:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.12/jquery.validate.unobtrusive.js"></script>

A jQuery Unobtrusive Validation szkript egy egyéni Microsoft előtér-kódtár, amely a népszerű jQuery Validation beépülő modulra épül. A jQuery Unobtrusive Validation nélkül ugyanazt az érvényesítési logikát két helyen kell kódolva lennie: egyszer a modelltulajdonságok kiszolgálóoldali érvényesítési attribútumaiban, majd ismét az ügyféloldali szkriptekben. Ehelyett a címkesegítők és a HTML-segítők az érvényesítési attribútumokat használják, és a modelltulajdonságok metaadatainak beírásával renderelik az érvényesítésre szoruló űrlapelemek HTML 5 data- attribútumait. A jQuery Unobtrusive Validation elemzi az data- attribútumokat, és átadja a logikát a jQuery Validationnek, és hatékonyan "másolja" a kiszolgálóoldali érvényesítési logikát az ügyfélre. Az ügyféloldalon érvényesítési hibákat jeleníthet meg az itt látható címkesegítők használatával:

<div class="form-group">
    <label asp-for="Movie.ReleaseDate" class="control-label"></label>
    <input asp-for="Movie.ReleaseDate" class="form-control" />
    <span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>

Az előző címkesegítők a következő HTML-t jelenítik meg:

<div class="form-group">
    <label class="control-label" for="Movie_ReleaseDate">Release Date</label>
    <input class="form-control" type="date" data-val="true"
        data-val-required="The Release Date field is required."
        id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">
    <span class="text-danger field-validation-valid"
        data-valmsg-for="Movie.ReleaseDate" data-valmsg-replace="true"></span>
</div>

Figyelje meg, hogy a data- HTML-kimenet attribútumai megfelelnek a tulajdonság érvényesítési attribútumainak Movie.ReleaseDate . Az data-val-required attribútum egy hibaüzenetet tartalmaz, amely akkor jelenik meg, ha a felhasználó nem tölti ki a kiadási dátum mezőt. A jQuery Unobtrusive Validation ezt az értéket átadja a jQuery Validation required() metódusnak , amely ezután megjeleníti az üzenetet a kísérő <span> elemben.

Az adattípus-ellenőrzés egy tulajdonság .NET-típusán alapul, kivéve, ha egy [DataType] attribútum felülírja. A böngészők saját alapértelmezett hibaüzenetekkel rendelkeznek, de a jQuery Validation Unobtrusive Validation csomag felülírhatja ezeket az üzeneteket. [DataType] attribútumok és alosztályok, például a [EmailAddress] lehetővé teszik a hibaüzenet megadását.

Nem feltűnő ellenőrzés

A nem zavaró ellenőrzéssel kapcsolatos információkért tekintse meg ezt a GitHub-problémát.

Érvényesítés hozzáadása dinamikus űrlapokhoz

JQuery Unobtrusive Validation átadja az érvényesítési logikát és paramétereket a jQuery Validationnek az oldal első betöltésekor. Ezért az ellenőrzés nem működik automatikusan a dinamikusan létrehozott űrlapokon. Az érvényesítés engedélyezéséhez kérje meg a jQuery Nem feltűnő érvényesítés parancsot, hogy közvetlenül a létrehozás után elemezni tudja a dinamikus űrlapot. Az alábbi kód például egy AJAX-en keresztül hozzáadott űrlapon állítja be az ügyféloldali ellenőrzést.

$.get({
    url: "https://url/that/returns/a/form",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add form. " + errorThrown);
    },
    success: function(newFormHTML) {
        var container = document.getElementById("form-container");
        container.insertAdjacentHTML("beforeend", newFormHTML);
        var forms = container.getElementsByTagName("form");
        var newForm = forms[forms.length - 1];
        $.validator.unobtrusive.parse(newForm);
    }
})

A $.validator.unobtrusive.parse() metódus egy jQuery-választót fogad el egyetlen argumentumához. Ez a módszer utasítja a jQuery Unobtrusive Validationt arra, hogy elemezze a data- attribútumokat a választóban lévő űrlapokon. Az attribútumok értékei ezután átadódnak a jQuery Validation beépülő modulnak.

Ellenőrzés hozzáadása dinamikus vezérlőkhöz

A $.validator.unobtrusive.parse() metódus egy teljes űrlapon működik, nem pedig az egyes dinamikusan létrehozott vezérlőkön, mint például <input> és <select/>. Az űrlap újraelemzéséhez távolítsa el az űrlap korábbi elemzésekor hozzáadott érvényesítési adatokat az alábbi példában látható módon:

$.get({
    url: "https://url/that/returns/a/control",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add control. " + errorThrown);
    },
    success: function(newInputHTML) {
        var form = document.getElementById("my-form");
        form.insertAdjacentHTML("beforeend", newInputHTML);
        $(form).removeData("validator")    // Added by jQuery Validation
               .removeData("unobtrusiveValidation");   // Added by jQuery Unobtrusive Validation
        $.validator.unobtrusive.parse(form);
    }
})

Egyéni ügyféloldali ellenőrzés

Az egyéni ügyféloldali érvényesítés egy egyéni jQuery validation adapterrel működő HTML-attribútumok létrehozásával data- történik. A következő mintaadapter-kód a korábban ebben a cikkben bevezetett [ClassicMovie] és [ClassicMovieWithClientValidator] attribútumokhoz készült:

$.validator.addMethod('classicmovie', function (value, element, params) {
    var genre = $(params[0]).val(), year = params[1], date = new Date(value);

    // The Classic genre has a value of '0'.
    if (genre && genre.length > 0 && genre[0] === '0') {
        // The release date for a Classic is valid if it's no greater than the given year.
        return date.getUTCFullYear() <= year;
    }

    return true;
});

$.validator.unobtrusive.adapters.add('classicmovie', ['year'], function (options) {
    var element = $(options.form).find('select#Movie_Genre')[0];

    options.rules['classicmovie'] = [element, parseInt(options.params['year'])];
    options.messages['classicmovie'] = options.message;
});

Az adapterek írásával kapcsolatos információkért tekintse meg a jQuery Validation dokumentációját.

Az adapter használatát egy adott mezőhöz a következő attribútumok data- váltják ki:

  • A mező megjelölése ellenőrzés tárgyát képezőként (data-val="true").
  • Azonosítsa az érvényesítési szabály nevét és a hibaüzenet szövegét (például data-val-rulename="Error message.").
  • Adjon meg minden további paramétert, amelyekre az érvényesítőnek szüksége van (például data-val-rulename-param1="value").

Az alábbi példa a data-mintaalkalmazás attribútumainak attribútumaitClassicMovie mutatja be:

<input class="form-control" type="date"
    data-val="true"
    data-val-classicmovie="Classic movies must have a release year no later than 1960."
    data-val-classicmovie-year="1960"
    data-val-required="The Release Date field is required."
    id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">

Ahogy korábban említettük, a címkesegítők és a HTML-segítők az érvényesítési attribútumokból származó információkat használják az attribútumok rendereléséhez data- . A kódírásnak két lehetősége van, amelyek egyéni data- HTML-attribútumok létrehozását eredményezik:

  • Hozzon létre egy olyan osztályt, amely származik AttributeAdapterBase<TAttribute> , és egy olyan osztályt, amely megvalósítja IValidationAttributeAdapterProvider, és regisztrálja az attribútumot és annak adapterét a DI-ben. Ez a módszer az egyetlen felelősség elvét követi abban az esetben, ha a kiszolgálóhoz és az ügyfélhez kapcsolódó érvényesítési kód külön osztályokban van. Az adapternek az az előnye is, hogy mivel regisztrálva van a DI-ben, a DI más szolgáltatásai is elérhetők, ha szükséges.
  • Implementálja IClientModelValidator az ValidationAttribute osztályban. Ez a módszer akkor lehet megfelelő, ha az attribútum nem végez kiszolgálóoldali ellenőrzést, és nincs szüksége a diától származó szolgáltatásokra.

Attribútumadapter ügyféloldali ellenőrzéshez

A HTML attribútumok megjelenítésének ezen módszerét a data- attribútum használja a ClassicMovie. Ügyfélérvényesítés hozzáadása ezzel a módszerrel:

  1. Hozzon létre egy attribútumadapter-osztályt az egyéni érvényesítési attribútumhoz. Az osztály származtatása a következőből: AttributeAdapterBase<TAttribute>. Hozzon létre egy metódust AddValidation , amely attribútumokat data- ad hozzá a renderelt kimenethez az alábbi példában látható módon:

    public class ClassicMovieAttributeAdapter : AttributeAdapterBase<ClassicMovieAttribute>
    {
        public ClassicMovieAttributeAdapter(
            ClassicMovieAttribute attribute, IStringLocalizer? stringLocalizer)
            : base(attribute, stringLocalizer)
        {
    
        }
    
        public override void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage(context));
    
            var year = Attribute.Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public override string GetErrorMessage(ModelValidationContextBase validationContext)
            => Attribute.GetErrorMessage();
    }
    
  2. Hozzon létre egy adapter szolgáltató osztályt, amely implementálja a IValidationAttributeAdapterProvider-t. GetAttributeAdapter A metódusban adja át az egyéni attribútumot az adapter konstruktorának, ahogyan az ebben a példában látható:

    public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
    {
        private readonly IValidationAttributeAdapterProvider baseProvider =
            new ValidationAttributeAdapterProvider();
    
        public IAttributeAdapter? GetAttributeAdapter(
            ValidationAttribute attribute, IStringLocalizer? stringLocalizer)
        {
            if (attribute is ClassicMovieAttribute classicMovieAttribute)
            {
                return new ClassicMovieAttributeAdapter(classicMovieAttribute, stringLocalizer);
            }
    
            return baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
        }
    }
    
  3. Regisztrálja a DI-hez tartozó adapterszolgáltatót a következő helyen Program.cs:

    builder.Services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    builder.Services.AddSingleton
        <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
    

IClientModelValidator ügyféloldali ellenőrzéshez

A HTML attribútumok megjelenítésének ezen módszerét a data- attribútum használja a ClassicMovieWithClientValidator. Ügyfélérvényesítés hozzáadása ezzel a módszerrel:

  • Az egyéni érvényesítési attribútumban implementálja az interfészt IClientModelValidator , és hozzon létre egy metódust AddValidation . A metódusban AddValidation adjon hozzá data- attribútumokat az ellenőrzéshez, ahogyan az a következő példában látható:

    public class ClassicMovieWithClientValidatorAttribute :
        ValidationAttribute, IClientModelValidator
    {
        public ClassicMovieWithClientValidatorAttribute(int year)
            => Year = year;
    
        public int Year { get; }
    
        public void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
    
            var year = Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public string GetErrorMessage() =>
            $"Classic movies must have a release year no later than {Year}.";
    
        protected override ValidationResult? IsValid(
            object? value, ValidationContext validationContext)
        {
            var movie = (Movie)validationContext.ObjectInstance;
            var releaseYear = ((DateTime)value!).Year;
    
            if (movie.Genre == Genre.Classic && releaseYear > Year)
            {
                return new ValidationResult(GetErrorMessage());
            }
    
            return ValidationResult.Success;
        }
    
        private static bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
    
            attributes.Add(key, value);
            return true;
        }
    }
    

Ügyféloldali érvényesítés letiltása

Az alábbi kód letiltja az ügyfélérvényesítést a Pagesben Razor :

builder.Services.AddRazorPages()
    .AddViewOptions(options =>
    {
        options.HtmlHelperOptions.ClientValidationEnabled = false;
    });

További lehetőségek az ügyféloldali érvényesítés letiltására:

  • Az összes _ValidationScriptsPartial fájlban kommenteljük ki a .cshtml hivatkozást.
  • Távolítsa el a Pages\Shared_ValidationScriptsPartial.cshtml fájl tartalmát.

Az előző megközelítés nem akadályozza meg a ASP.NET Core IdentityRazor osztálykódtár ügyféloldali ellenőrzését. További információ: Állványzat Identity ASP.NET Core-projektekben.

További erőforrások

Ez a cikk bemutatja, hogyan érvényesítheti a felhasználói bemenetet egy ASP.NET Core MVC- vagy Razor Pages-alkalmazásban.

Mintakód megtekintése vagy letöltése (hogyan töltsük le).

Modell állapota

A modellállapot két alrendszer hibáit jelöli: a modellkötést és a modellérvényesítést. A modellkötésből származó hibák általában adatkonvertálási hibák. Egy "x" például egy egész számmezőbe van beírva. A modell érvényesítése a modellkötés után történik, és olyan hibákat jelez, amelyekben az adatok nem felelnek meg az üzleti szabályoknak. Például egy 0 értéket ad meg egy olyan mezőben, amely 1 és 5 közötti értékelést vár.

A modellkötés és a modell érvényesítése is egy vezérlőművelet vagy egy Razor Pages-kezelő metódus végrehajtása előtt történik. A webalkalmazások esetében az alkalmazás feladata, hogy megvizsgálja ModelState.IsValid, és megfelelően reagáljon. A webalkalmazások általában egy hibaüzenettel ismételik meg a lapot:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

A webes API-vezérlőknek nem kell ellenőrizniük ModelState.IsValid , hogy rendelkeznek-e az [ApiController] attribútummal. Ebben az esetben a rendszer a hibaadatokat tartalmazó automatikus HTTP 400-választ adja vissza, ha a modell állapota érvénytelen. További információ: Automatikus HTTP 400-válaszok.

Újrafuttatás ellenőrzése

Az érvényesítés automatikus, de előfordulhat, hogy manuálisan szeretné megismételni. Előfordulhat például, hogy egy tulajdonság értékét számítja ki, és újra szeretné futtatni az ellenőrzést, miután a tulajdonságot a kiszámított értékre állítja. Az érvényesítés újrafuttatásához először hívja meg a modellre vonatkozó ellenőrzés törléséhez a ModelStateDictionary.ClearValidationState, majd ezt kövesse a TryValidateModel meghívásával.

public async Task<IActionResult> OnPostTryValidateAsync()
{
    var modifiedReleaseDate = DateTime.Now.Date;
    Movie.ReleaseDate = modifiedReleaseDate;

    ModelState.ClearValidationState(nameof(Movie));
    if (!TryValidateModel(Movie, nameof(Movie)))
    {
        return Page();
    }

    _context.Movies.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Érvényesítési attribútumok

Az érvényesítési attribútumokkal érvényesítési szabályokat adhat meg a modelltulajdonságokhoz. A mintaalkalmazás alábbi példája egy olyan modellosztályt mutat be, amely érvényesítési attribútumokkal van eljegyzve. Az [ClassicMovie] attribútum egy egyéni érvényesítési attribútum, a többi pedig beépített. Az [ClassicMovieWithClientValidator] nem jelenik meg, amely a testreszabott attribútum megvalósításának egy alternatív módját mutatja be.

public class Movie
{
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

    [ClassicMovie(1960)]
    [DataType(DataType.Date)]
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }
}

Beépített attribútumok

Íme néhány beépített érvényesítési attribútum:

  • [ValidateNever]: Azt jelzi, hogy egy tulajdonságot vagy paramétert ki kell zárni az ellenőrzésből.
  • [CreditCard]: Ellenőrzi, hogy a tulajdonság rendelkezik-e hitelkártyaformátummal. További jQuery-érvényesítési módszereket igényel.
  • [Összehasonlítás]: Ellenőrzi, hogy egy modell két tulajdonsága egyezik-e.
  • [EmailAddress]: Ellenőrzi, hogy a tulajdonság e-mail formátumú-e.
  • [Telefon]: Ellenőrzi, hogy a tulajdonság telefonszámformátummal rendelkezik-e.
  • [Tartomány]: Ellenőrzi, hogy a tulajdonság értéke egy megadott tartományba esik-e.
  • [RegularExpression]: Ellenőrzi, hogy a tulajdonság értéke megfelel-e egy megadott reguláris kifejezésnek.
  • [Kötelező]: Ellenőrzi, hogy a mező nem null értékű-e. Az attribútum működésének részleteiért tekintse meg [Required] az attribútumot .
  • [StringLength]: Ellenőrzi, hogy egy sztringtulajdonság értéke nem lépi-e túl a megadott hosszkorlátot.
  • [URL]: Ellenőrzi, hogy a tulajdonság URL-formátummal rendelkezik-e.
  • [Távoli]: Az ügyfél bemenetének ellenőrzése egy műveletmetódus meghívásával a kiszolgálón. Az attribútum működésének részleteiért tekintse meg [Remote] az attribútumot .

Az érvényesítési attribútumok teljes listája megtalálható a System.ComponentModel.DataAnnotations névtérben.

Hibaüzenetek

Az érvényesítési attribútumokkal megadhatja az érvénytelen bemenethez megjelenítendő hibaüzenetet. Például:

[StringLength(8, ErrorMessage = "Name length can't be more than 8.")]

Belsőleg az attribútumok meghívják a String.Format-t, használva a mezőnév helyőrzőjét, és néha további helyőrzőket is. Például:

[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]

Egy tulajdonságra Name alkalmazva az előző kód által létrehozott hibaüzenet a következő: "A névhossznak 6 és 8 között kell lennie".

Annak kiderítéséhez, hogy String.Format egy adott attribútum hibaüzenete mely paramétereknek lesz átadva, tekintse meg a DataAnnotations forráskódját.

Nem null értékű hivatkozástípusok és [Kötelező] attribútum

Az érvényesítési rendszer úgy kezeli a nem null értékű paramétereket vagy kötött tulajdonságokat, mintha attribútummal [Required(AllowEmptyStrings = true)] rendelkeznének. A Nullable kontextusok engedélyezésével az MVC implicit módon megkezdi a nem-null értékű tulajdonságok vagy paraméterek érvényesítését, mintha rendelkeznének az [Required(AllowEmptyStrings = true)] attribútummal. Vegye figyelembe a következő kódot:

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

Ha az alkalmazás <Nullable>enable</Nullable> segítségével készült, akkor a Name számára hiányzó érték a JSON-fájlban vagy az űrlap-bejegyzésben érvényesítési hibát eredményez. Nullázható hivatkozástípust használva engedélyezheti a Name tulajdonság számára, hogy null vagy hiányzó értékek legyenek megadva.

public class Person
{
    public string? Name { get; set; }
}

Ez a viselkedés letiltható a következő SuppressImplicitRequiredAttributeForNonNullableReferenceTypesbeállítássalStartup.ConfigureServices:

services.AddControllers(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);

[Kötelező] érvényesítés a kiszolgálón

A kiszolgálón a szükséges érték hiányzik, ha a tulajdonság null értékű. A nem null értékű mezők mindig érvényesek, és az [Required] attribútum hibaüzenete soha nem jelenik meg.

A nem null értékű tulajdonság modellkötése azonban meghiúsulhat, ami hibaüzenetet eredményez, például The value '' is invalid: . Ha egyéni hibaüzenetet szeretne megadni a nem null értékű típusok kiszolgálóoldali érvényesítéséhez, a következő lehetőségek közül választhat:

  • Tegye a mezőt nullelláthatóvá (például decimal? helyett decimal). Nullázható<A T> értéktípusokat a rendszer standard null értékű típusokként kezeli.

  • Adja meg a modellkötés által használandó alapértelmezett hibaüzenetet az alábbi példában látható módon:

    services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    services.AddSingleton<IValidationAttributeAdapterProvider,
        CustomValidationAttributeAdapterProvider>();
    

    További információ a modellkötési hibákról, amelyekhez alapértelmezett üzeneteket állíthat be, lásd: DefaultModelBindingMessageProvider.

[Kötelező] ellenőrzés az ügyfélen

A nem null értékű típusok és sztringek eltérően vannak kezelve az ügyfélen a kiszolgálóhoz képest. Az ügyfél oldalán

  • Egy érték csak akkor tekinthető jelennek, ha van bemenet megadva. Ezért az ügyféloldali ellenőrzés a nem null értékű típusokat ugyanúgy kezeli, mint a null értékű típusokat.
  • A sztringmezőben lévő szóközt a jQuery Validation kötelező metódusa érvényes bemenetnek tekinti. A kiszolgálóoldali ellenőrzés érvénytelennek tekint egy kötelező sztringmezőt, ha csak a szóköz van beírva.

Ahogy korábban említettük, a nem null értékű típusok úgy lesznek kezelve, mintha attribútummal [Required(AllowEmptyStrings = true)] rendelkeznének. Ez azt jelenti, hogy akkor is megkapja az ügyféloldali ellenőrzést, ha nem alkalmazza az [Required(AllowEmptyStrings = true)] attribútumot. Ha azonban nem használja az attribútumot, egy alapértelmezett hibaüzenet jelenik meg. Egyéni hibaüzenet megadásához használja az attribútumot.

[Távoli] attribútum

A [Távoli] attribútum ügyféloldali ellenőrzést valósít meg, amelyhez egy metódus meghívása szükséges a kiszolgálón annak megállapításához, hogy a mezőbemenet érvényes-e. Előfordulhat például, hogy az alkalmazásnak ellenőriznie kell, hogy egy felhasználónév már használatban van-e.

Távoli érvényesítés megvalósítása:

  1. Hozzon létre egy műveletmetódust a JavaScript hívásához. A jQuery Validation remote metódus JSON-választ vár:

    • true azt jelenti, hogy a bemeneti adatok érvényesek.
    • false, undefinedvagy null azt jelenti, hogy a bemenet érvénytelen. Az alapértelmezett hibaüzenet megjelenítése.
    • Bármely más sztring azt jelenti, hogy a bemenet érvénytelen. A karakterlánc egyéni hibaüzenetként történő megjelenítése.

    Íme egy példa egy egyéni hibaüzenetet visszaadó műveletmetódusra:

    [AcceptVerbs("GET", "POST")]
    public IActionResult VerifyEmail(string email)
    {
        if (!_userService.VerifyEmail(email))
        {
            return Json($"Email {email} is already in use.");
        }
    
        return Json(true);
    }
    
  2. A modellosztályban jegyzetelje a tulajdonságot egy [Remote] olyan attribútummal, amely az érvényesítési művelet metódusára mutat, ahogyan az alábbi példában látható:

    [Remote(action: "VerifyEmail", controller: "Users")]
    public string Email { get; set; }
    

További mezők

Az AdditionalFields attribútum tulajdonsága lehetővé teszi a [Remote] mezők kombinációjának ellenőrzését a kiszolgálón lévő adatokkal szemben. Ha például a User modell rendelkezik FirstName és LastName rendelkezik tulajdonságokkal, érdemes lehet ellenőrizni, hogy a meglévő felhasználók nem rendelkeznek-e már ilyen névpárokkal. Az alábbi példa a AdditionalFieldshasználatát mutatja be:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(LastName))]
[Display(Name = "First Name")]
public string FirstName { get; set; }

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName))]
[Display(Name = "Last Name")]
public string LastName { get; set; }

AdditionalFields a "FirstName" és a "LastName" sztringek explicit módon beállíthatók, de a nameof operátor használata egyszerűsíti a későbbi refaktorálást. Az érvényesítés műveleti metódusának mind a firstName-t, mind a lastName-t el kell fogadnia.

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyName(string firstName, string lastName)
{
    if (!_userService.VerifyName(firstName, lastName))
    {
        return Json($"A user named {firstName} {lastName} already exists.");
    }

    return Json(true);
}

Amikor a felhasználó vezeték- vagy utónevet ad meg, a JavaScript távoli hívást indít annak megtekintéséhez, hogy a névpár létrejött-e.

Két vagy több további mező érvényesítéséhez adja meg őket vesszővel tagolt listaként. Ha például egy tulajdonságot MiddleName szeretne hozzáadni a modellhez, állítsa be az [Remote] attribútumot az alábbi példában látható módon:

[Remote(action: "VerifyName", controller: "Users", AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

AdditionalFields, mint minden attribútumargumentum, állandó kifejezésnek kell lennie. Ezért ne használjon interpolált sztringet vagy hívjon meg Join inicializáláshoz AdditionalFields.

A beépített attribútumok alternatívái

Ha nem a beépített attribútumok által biztosított ellenőrzésre van szüksége, a következőkre van szüksége:

Egyéni attribútumok

Olyan forgatókönyvek esetén, amelyeket a beépített érvényesítési attribútumok nem kezelnek, egyéni érvényesítési attribútumokat hozhat létre. Hozzon létre egy olyan osztályt, amely örököl a ValidationAttribute osztályból, és írja felül a IsValid metódust.

A IsValid metódus elfogad egy érték nevű objektumot, amely az érvényesítendő bemenet. A túlterhelés egy objektumot is elfogad ValidationContext , amely további információkat nyújt, például a modellkötés által létrehozott modellpéldányt.

Az alábbi példa ellenőrzi, hogy a klasszikus műfajban lévő filmek megjelenési dátuma nem későbbi-e, mint egy adott év. Az [ClassicMovie] attribútum:

  • Csak a kiszolgálón fut.
  • Klasszikus filmek esetén ellenőrzi a kiadás dátumának érvényességét:
public class ClassicMovieAttribute : ValidationAttribute
{
    public ClassicMovieAttribute(int year)
    {
        Year = year;
    }

    public int Year { get; }

    public string GetErrorMessage() =>
        $"Classic movies must have a release year no later than {Year}.";

    protected override ValidationResult IsValid(object value,
        ValidationContext validationContext)
    {
        var movie = (Movie)validationContext.ObjectInstance;
        var releaseYear = ((DateTime)value).Year;

        if (movie.Genre == Genre.Classic && releaseYear > Year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }
}

Az movie előző példában szereplő változó egy Movie objektumot jelöl, amely az űrlapbeküldésből származó adatokat tartalmazza. Ha az ellenőrzés sikertelen, a ValidationResult rendszer hibaüzenetet ad vissza.

IValidatableObject

Az előző példa csak típusokkal Movie működik. Az osztályszintű ellenőrzés másik lehetősége a modellosztályban való implementálás IValidatableObject , ahogyan az alábbi példában látható:

public class ValidatableMovie : IValidatableObject
{
    private const int _classicYear = 1960;

    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Title { get; set; }

    [DataType(DataType.Date)]
    [Display(Name = "Release Date")]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [StringLength(1000)]
    public string Description { get; set; }

    [Range(0, 999.99)]
    public decimal Price { get; set; }

    public Genre Genre { get; set; }

    public bool Preorder { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Genre == Genre.Classic && ReleaseDate.Year > _classicYear)
        {
            yield return new ValidationResult(
                $"Classic movies must have a release year no later than {_classicYear}.",
                new[] { nameof(ReleaseDate) });
        }
    }
}

Felső szintű csomópont érvényesítés

A legfelső szintű csomópontok a következők:

  • Műveleti paraméterek
  • Vezérlő tulajdonságai
  • Lapkezelő paraméterei
  • Lapmodell tulajdonságai

A modellhez kötött legfelső szintű csomópontok érvényesítésre kerülnek a modelltulajdonságok érvényesítésén felül. A mintaalkalmazás alábbi példájában a VerifyPhone metódus a RegularExpressionAttribute felhasználásával érvényesíti a phone műveletparamétert.

[AcceptVerbs("GET", "POST")]
public IActionResult VerifyPhone(
    [RegularExpression(@"^\d{3}-\d{3}-\d{4}$")] string phone)
{
    if (!ModelState.IsValid)
    {
        return Json($"Phone {phone} has an invalid format. Format: ###-###-####");
    }

    return Json(true);
}

A legfelső szintű csomópontok érvényesítési attribútumokkal használhatók BindRequiredAttribute . A mintaalkalmazás alábbi példájában a CheckAge metódus azt határozza meg, hogy a age paramétert a lekérdezési sztringhez kell kötni az űrlap elküldésekor:

[HttpPost]
public IActionResult CheckAge([BindRequired, FromQuery] int age)
{

A Kor ellenőrzése lapon (CheckAge.cshtml) két űrlap található. Az első űrlap egy lekérdezési sztringparaméterként az Age értéket küldi el: 99.

Ha a lekérdezési sztringből megfelelően formázott age paramétert küld el, az űrlap érvényesíti.

Az Életkor ellenőrzése lapon található második űrlap elküldi az Age értéket a kérelem törzsében, és az ellenőrzés sikertelen. A kötés meghiúsul, mert a age paraméternek egy lekérdezési sztringből kell származnia.

Hibák maximális száma

Az érvényesítés a hibák maximális számának elérésekor (alapértelmezés szerint 200) leáll. Ezt a számot a következő kóddal konfigurálhatja:Startup.ConfigureServices

services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        options.MaxModelValidationErrors = 50;
        options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
            _ => "The field is required.");
    });

services.AddSingleton<IValidationAttributeAdapterProvider,
    CustomValidationAttributeAdapterProvider>();

Maximális rekurzió

ValidationVisitor bejárja az érvényesítendő modell objektumgráfját. Azoknál a modelleknél, amelyek mélyek vagy végtelenül rekurzívek, az érvényesítés veremtúlcsorduláshoz vezethet. MvcOptions.MaxValidationDepth lehetővé teszi az ellenőrzés korai leállítását, ha a látogató rekurziója meghaladja a beállított mélységet. Az alapértelmezett érték MvcOptions.MaxValidationDepth 32.

Automatikus rövidzárlat

Az ellenőrzést automatikusan rövidre zárjuk (kihagyjuk), ha a modellgráf nem igényel ellenőrzést. Azok az objektumok, amelyek esetében a futtatókörnyezet kihagyja az ellenőrzést, primitív gyűjteményeket (például byte[], string[], ) Dictionary<string, string>és olyan összetett objektumgráfokat tartalmaznak, amelyek nem rendelkeznek érvényesítőkkel.

Ügyféloldali ellenőrzés

Az ügyféloldali ellenőrzés megakadályozza a beküldést, amíg az űrlap érvényes nem lesz. A Küldés gomb javaScriptet futtat, amely elküldi az űrlapot, vagy hibaüzeneteket jelenít meg.

Az ügyféloldali érvényesítés elkerüli a kiszolgáló szükségtelen oda-vissza utazását, ha bemeneti hibák jelentkeznek egy űrlapon. Az ügyféloldali érvényesítést _Layout.cshtml_ValidationScriptsPartial.cshtml a következő szkripthivatkozások támogatják:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.js"></script>

A jQuery Unobtrusive Validation szkript egy egyéni Microsoft előtér-kódtár, amely a népszerű jQuery Validation beépülő modulra épül. A jQuery Unobtrusive Validation nélkül ugyanazt az érvényesítési logikát két helyen kell kódolva lennie: egyszer a modelltulajdonságok kiszolgálóoldali érvényesítési attribútumaiban, majd ismét az ügyféloldali szkriptekben. Ehelyett a címkesegítők és a HTML-segítők az érvényesítési attribútumokat használják, és a modelltulajdonságok metaadatainak beírásával renderelik az érvényesítésre szoruló űrlapelemek HTML 5 data- attribútumait. A jQuery Unobtrusive Validation elemzi az data- attribútumokat, és átadja a logikát a jQuery Validationnek, és hatékonyan "másolja" a kiszolgálóoldali érvényesítési logikát az ügyfélre. Az ügyféloldalon érvényesítési hibákat jeleníthet meg az itt látható címkesegítők használatával:

<div class="form-group">
    <label asp-for="Movie.ReleaseDate" class="control-label"></label>
    <input asp-for="Movie.ReleaseDate" class="form-control" />
    <span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>

Az előző címkesegítők a következő HTML-t jelenítik meg:

<div class="form-group">
    <label class="control-label" for="Movie_ReleaseDate">Release Date</label>
    <input class="form-control" type="date" data-val="true"
        data-val-required="The Release Date field is required."
        id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">
    <span class="text-danger field-validation-valid"
        data-valmsg-for="Movie.ReleaseDate" data-valmsg-replace="true"></span>
</div>

Figyelje meg, hogy a data- HTML-kimenet attribútumai megfelelnek a tulajdonság érvényesítési attribútumainak Movie.ReleaseDate . Az data-val-required attribútum egy hibaüzenetet tartalmaz, amely akkor jelenik meg, ha a felhasználó nem tölti ki a kiadási dátum mezőt. A jQuery Unobtrusive Validation ezt az értéket átadja a jQuery Validation required() metódusnak , amely ezután megjeleníti az üzenetet a kísérő <span> elemben.

Az adattípus-ellenőrzés egy tulajdonság .NET-típusán alapul, kivéve, ha egy [DataType] attribútum felülírja. A böngészők saját alapértelmezett hibaüzenetekkel rendelkeznek, de a jQuery Validation Unobtrusive Validation csomag felülírhatja ezeket az üzeneteket. [DataType] attribútumok és alosztályok, például a [EmailAddress] lehetővé teszik a hibaüzenet megadását.

Nem feltűnő ellenőrzés

A nem zavaró ellenőrzéssel kapcsolatos információkért tekintse meg ezt a GitHub-problémát.

Érvényesítés hozzáadása dinamikus űrlapokhoz

JQuery Unobtrusive Validation átadja az érvényesítési logikát és paramétereket a jQuery Validationnek az oldal első betöltésekor. Ezért az ellenőrzés nem működik automatikusan a dinamikusan létrehozott űrlapokon. Az érvényesítés engedélyezéséhez kérje meg a jQuery Nem feltűnő érvényesítés parancsot, hogy közvetlenül a létrehozás után elemezni tudja a dinamikus űrlapot. Az alábbi kód például egy AJAX-en keresztül hozzáadott űrlapon állítja be az ügyféloldali ellenőrzést.

$.get({
    url: "https://url/that/returns/a/form",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add form. " + errorThrown);
    },
    success: function(newFormHTML) {
        var container = document.getElementById("form-container");
        container.insertAdjacentHTML("beforeend", newFormHTML);
        var forms = container.getElementsByTagName("form");
        var newForm = forms[forms.length - 1];
        $.validator.unobtrusive.parse(newForm);
    }
})

A $.validator.unobtrusive.parse() metódus egy jQuery-választót fogad el egyetlen argumentumához. Ez a módszer utasítja a jQuery Unobtrusive Validationt arra, hogy elemezze a data- attribútumokat a választóban lévő űrlapokon. Az attribútumok értékei ezután átadódnak a jQuery Validation beépülő modulnak.

Ellenőrzés hozzáadása dinamikus vezérlőkhöz

A $.validator.unobtrusive.parse() metódus egy teljes űrlapon működik, nem pedig az egyes dinamikusan létrehozott vezérlőkön, mint például <input> és <select/>. Az űrlap újraelemzéséhez távolítsa el az űrlap korábbi elemzésekor hozzáadott érvényesítési adatokat az alábbi példában látható módon:

$.get({
    url: "https://url/that/returns/a/control",
    dataType: "html",
    error: function(jqXHR, textStatus, errorThrown) {
        alert(textStatus + ": Couldn't add control. " + errorThrown);
    },
    success: function(newInputHTML) {
        var form = document.getElementById("my-form");
        form.insertAdjacentHTML("beforeend", newInputHTML);
        $(form).removeData("validator")    // Added by jQuery Validation
               .removeData("unobtrusiveValidation");   // Added by jQuery Unobtrusive Validation
        $.validator.unobtrusive.parse(form);
    }
})

Egyéni ügyféloldali ellenőrzés

Az egyéni ügyféloldali érvényesítés egy egyéni jQuery validation adapterrel működő HTML-attribútumok létrehozásával data- történik. A következő mintaadapter-kód a korábban ebben a cikkben bevezetett [ClassicMovie] és [ClassicMovieWithClientValidator] attribútumokhoz készült:

$.validator.addMethod('classicmovie', function (value, element, params) {
    var genre = $(params[0]).val(), year = params[1], date = new Date(value);

    // The Classic genre has a value of '0'.
    if (genre && genre.length > 0 && genre[0] === '0') {
        // The release date for a Classic is valid if it's no greater than the given year.
        return date.getUTCFullYear() <= year;
    }

    return true;
});

$.validator.unobtrusive.adapters.add('classicmovie', ['year'], function (options) {
    var element = $(options.form).find('select#Movie_Genre')[0];

    options.rules['classicmovie'] = [element, parseInt(options.params['year'])];
    options.messages['classicmovie'] = options.message;
});

Az adapterek írásával kapcsolatos információkért tekintse meg a jQuery Validation dokumentációját.

Az adapter használatát egy adott mezőhöz a következő attribútumok data- váltják ki:

  • A mező megjelölése ellenőrzés tárgyát képezőként (data-val="true").
  • Azonosítsa az érvényesítési szabály nevét és a hibaüzenet szövegét (például data-val-rulename="Error message.").
  • Adjon meg minden további paramétert, amelyekre az érvényesítőnek szüksége van (például data-val-rulename-param1="value").

Az alábbi példa a data-mintaalkalmazás attribútumainak attribútumaitClassicMovie mutatja be:

<input class="form-control" type="date"
    data-val="true"
    data-val-classicmovie="Classic movies must have a release year no later than 1960."
    data-val-classicmovie-year="1960"
    data-val-required="The Release Date field is required."
    id="Movie_ReleaseDate" name="Movie.ReleaseDate" value="">

Ahogy korábban említettük, a címkesegítők és a HTML-segítők az érvényesítési attribútumokból származó információkat használják az attribútumok rendereléséhez data- . A kódírásnak két lehetősége van, amelyek egyéni data- HTML-attribútumok létrehozását eredményezik:

  • Hozzon létre egy olyan osztályt, amely származik AttributeAdapterBase<TAttribute> , és egy olyan osztályt, amely megvalósítja IValidationAttributeAdapterProvider, és regisztrálja az attribútumot és annak adapterét a DI-ben. Ez a módszer az egyetlen felelősség elvét követi abban az esetben, ha a kiszolgálóhoz és az ügyfélhez kapcsolódó érvényesítési kód külön osztályokban van. Az adapternek az az előnye is, hogy mivel regisztrálva van a DI-ben, a DI más szolgáltatásai is elérhetők, ha szükséges.
  • Implementálja IClientModelValidator az ValidationAttribute osztályban. Ez a módszer akkor lehet megfelelő, ha az attribútum nem végez kiszolgálóoldali ellenőrzést, és nincs szüksége a diától származó szolgáltatásokra.

Attribútumadapter ügyféloldali ellenőrzéshez

A HTML attribútumok megjelenítésének ezen módszerét a data- attribútum használja a ClassicMovie. Ügyfélérvényesítés hozzáadása ezzel a módszerrel:

  1. Hozzon létre egy attribútumadapter-osztályt az egyéni érvényesítési attribútumhoz. Az osztály származtatása a következőből: AttributeAdapterBase<TAttribute>. Hozzon létre egy metódust AddValidation , amely attribútumokat data- ad hozzá a renderelt kimenethez az alábbi példában látható módon:

    public class ClassicMovieAttributeAdapter : AttributeAdapterBase<ClassicMovieAttribute>
    {
        public ClassicMovieAttributeAdapter(ClassicMovieAttribute attribute,
            IStringLocalizer stringLocalizer)
            : base(attribute, stringLocalizer)
        {
    
        }
    
        public override void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage(context));
    
            var year = Attribute.Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public override string GetErrorMessage(ModelValidationContextBase validationContext) =>
            Attribute.GetErrorMessage();
    }
    
  2. Hozzon létre egy adapter szolgáltató osztályt, amely implementálja a IValidationAttributeAdapterProvider-t. GetAttributeAdapter A metódusban adja át az egyéni attribútumot az adapter konstruktorának, ahogyan az ebben a példában látható:

    public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
    {
        private readonly IValidationAttributeAdapterProvider baseProvider =
            new ValidationAttributeAdapterProvider();
    
        public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute,
            IStringLocalizer stringLocalizer)
        {
            if (attribute is ClassicMovieAttribute classicMovieAttribute)
            {
                return new ClassicMovieAttributeAdapter(classicMovieAttribute, stringLocalizer);
            }
    
            return baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
        }
    }
    
  3. Regisztrálja a DI-hez tartozó adapterszolgáltatót a következő helyen Startup.ConfigureServices:

    services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.MaxModelValidationErrors = 50;
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                _ => "The field is required.");
        });
    
    services.AddSingleton<IValidationAttributeAdapterProvider,
        CustomValidationAttributeAdapterProvider>();
    

IClientModelValidator ügyféloldali ellenőrzéshez

A HTML attribútumok megjelenítésének ezen módszerét a data- attribútum használja a ClassicMovieWithClientValidator. Ügyfélérvényesítés hozzáadása ezzel a módszerrel:

  • Az egyéni érvényesítési attribútumban implementálja az interfészt IClientModelValidator , és hozzon létre egy metódust AddValidation . A metódusban AddValidation adjon hozzá data- attribútumokat az ellenőrzéshez, ahogyan az a következő példában látható:

    public class ClassicMovieWithClientValidatorAttribute :
        ValidationAttribute, IClientModelValidator
    {
        public ClassicMovieWithClientValidatorAttribute(int year)
        {
            Year = year;
        }
    
        public int Year { get; }
    
        public void AddValidation(ClientModelValidationContext context)
        {
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
    
            var year = Year.ToString(CultureInfo.InvariantCulture);
            MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
        }
    
        public string GetErrorMessage() =>
            $"Classic movies must have a release year no later than {Year}.";
    
        protected override ValidationResult IsValid(object value,
            ValidationContext validationContext)
        {
            var movie = (Movie)validationContext.ObjectInstance;
            var releaseYear = ((DateTime)value).Year;
    
            if (movie.Genre == Genre.Classic && releaseYear > Year)
            {
                return new ValidationResult(GetErrorMessage());
            }
    
            return ValidationResult.Success;
        }
    
        private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
    
            attributes.Add(key, value);
            return true;
        }
    }
    

Ügyféloldali érvényesítés letiltása

Az alábbi kód letiltja az ügyfélérvényesítést a Pagesben Razor :

services.AddRazorPages()
    .AddViewOptions(options =>
    {
        options.HtmlHelperOptions.ClientValidationEnabled = false;
    });

További lehetőségek az ügyféloldali érvényesítés letiltására:

  • Az összes _ValidationScriptsPartial fájlban kommenteljük ki a .cshtml hivatkozást.
  • Távolítsa el a Pages\Shared_ValidationScriptsPartial.cshtml fájl tartalmát.

Az előző megközelítés nem akadályozza meg a ASP.NET Core IdentityRazor osztálykódtár ügyféloldali ellenőrzését. További információ: Állványzat Identity ASP.NET Core-projektekben.

További erőforrások