ASP.Net

Datavalidering

Backend Dag 6 Agila Projekt, Datavalidering & CORS.pdf
2.3 MB


bild.png

Det räcker att ni har koll på:

Required
Email Adress
Range
StringLength

Validation attributes

Validation attributes let you specify validation rules for model properties. The following example from the shows a model class that is annotated with validation attributes. The [ClassicMovie] attribute is a custom validation attribute and the others are built in. Not shown is [ClassicMovieWithClientValidator], which shows an alternative way to implement a custom attribute.
C#Copy
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; }
}

Built-in attributes

Here are some of the built-in validation attributes:
: Indicates that a property or parameter should be excluded from validation.
: Validates that the property has a credit card format. Requires.
: Validates that two properties in a model match.
: Validates that the property has an email format.
: Validates that the property has a telephone number format.
: Validates that the property value falls within a specified range.
: Validates that the property value matches a specified regular expression.
: Validates that the field isn't null. Seefor details about this attribute's behavior.
: Validates that a string property value doesn't exceed a specified length limit.
: Validates that the property has a URL format.
: Validates input on the client by calling an action method on the server. Seefor details about this attribute's behavior.
A complete list of validation attributes can be found in the namespace.

Error messages

Validation attributes let you specify the error message to be displayed for invalid input. For example:
C#Copy
[StringLength(8, ErrorMessage = "Name length can't be more than 8.")]

Internally, the attributes call with a placeholder for the field name and sometimes additional placeholders. For example:
C#Copy
[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]

When applied to a Name property, the error message created by the preceding code would be "Name length must be between 6 and 8.".
To find out which parameters are passed to String.Format for a particular attribute's error message, see the .

Non-nullable reference types and the [Required] attribute

The validation system treats non-nullable parameters or bound properties as if they had a [Required(AllowEmptyStrings = true)] attribute. By , MVC implicitly starts validating non-nullable properties or parameters as if they had been attributed with the [Required(AllowEmptyStrings = true)] attribute. Consider the following code:
C#Copy
public class Person
{
public string Name { get; set; }
}

If the app was built with <Nullable>enable</Nullable>, a missing value for Name in a JSON or form post results in a validation error. Use a nullable reference type to allow null or missing values to be specified for the Name property:
C#Copy
public class Person
{
public string? Name { get; set; }
}

This behavior can be disabled by configuring in Program.cs:
C#Copy
builder.Services.AddControllers(
options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);

Non-nullable properties on generic types and [Required] attribute

Non-nullable properties on generic types must include the [Required] attribute when the type is required. In the following code, TestRequired is not required:
C#Copy
public class WeatherForecast<T>
{
public string TestRequired { get; set; } = null!;
public T? Inner { get; set; }
}

In the following code, TestRequired is explicitly marked as required:
C#Copy
using System.ComponentModel.DataAnnotations;

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


[Required] validation on the server

On the server, a required value is considered missing if the property is null. A non-nullable field is always valid, and the [Required] attribute's error message is never displayed.
However, model binding for a non-nullable property may fail, resulting in an error message such as The value '' is invalid. To specify a custom error message for server-side validation of non-nullable types, you have the following options:
Make the field nullable (for example,decimal?instead ofdecimal).value types are treated like standard nullable types.
Specify the default error message to be used by model binding, as shown in the following example:
C#Copy
builder.Services.AddRazorPages() .AddMvcOptions(options => { options.MaxModelValidationErrors = 50; options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor( _ => "The field is required."); }); builder.Services.AddSingleton <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
For more information about model binding errors that you can set default messages for, see.

[Required] validation on the client

Non-nullable types and strings are handled differently on the client compared to the server. On the client:
A value is considered present only if input is entered for it. Therefore, client-side validation handles non-nullable types the same as nullable types.
Whitespace in a string field is considered valid input by the jQuery Validationmethod. Server-side validation considers a required string field invalid if only whitespace is entered.
As noted earlier, non-nullable types are treated as though they had a [Required(AllowEmptyStrings = true)] attribute. That means you get client-side validation even if you don't apply the [Required(AllowEmptyStrings = true)] attribute. But if you don't use the attribute, you get a default error message. To specify a custom error message, use the attribute.

[Remote] attribute

The attribute implements client-side validation that requires calling a method on the server to determine whether field input is valid. For example, the app may need to verify whether a user name is already in use.

To implement remote validation:
Create an action method for JavaScript to call. The jQuery Validationmethod expects a JSON response:
truemeans the input data is valid.
false,undefined, ornullmeans the input is invalid. Display the default error message.
Any other string means the input is invalid. Display the string as a custom error message.
Here's an example of an action method that returns a custom error message:
C#Copy
[AcceptVerbs("GET", "POST")] public IActionResult VerifyEmail(string email) { if (!_userService.VerifyEmail(email)) { return Json($"Email {email} is already in use."); } return Json(true); }
In the model class, annotate the property with a[Remote]attribute that points to the validation action method, as shown in the following example:
C#Copy
[Remote(action: "VerifyEmail", controller: "Users")] publicstring Email { get; set; } = null!;

Additional fields

The property of the [Remote] attribute lets you validate combinations of fields against data on the server. For example, if the User model had FirstName and LastName properties, you might want to verify that no existing users already have that pair of names. The following example shows how to use AdditionalFields:
C#Copy
[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 could be set explicitly to the strings "FirstName" and "LastName", but using the operator simplifies later refactoring. The action method for this validation must accept both firstName and lastName arguments:
C#Copy
[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);
}

When the user enters a first or last name, JavaScript makes a remote call to see if that pair of names has been taken.
To validate two or more additional fields, provide them as a comma-delimited list. For example, to add a MiddleName property to the model, set the [Remote] attribute as shown in the following example:
C#Copy
[Remote(action: "VerifyName", controller: "Users",
AdditionalFields = nameof(FirstName) + "," + nameof(LastName))]
public string MiddleName { get; set; }

AdditionalFields, like all attribute arguments, must be a constant expression. Therefore, don't use an or call
to initialize AdditionalFields.

Alternatives to built-in attributes

If you need validation not provided by built-in attributes, you can:

Custom attributes

For scenarios that the built-in validation attributes don't handle, you can create custom validation attributes. Create a class that inherits from , and override the method.
The IsValid method accepts an object named value, which is the input to be validated. An overload also accepts a object, which provides additional information, such as the model instance created by model binding.
The following example validates that the release date for a movie in the Classic genre isn't later than a specified year. The [ClassicMovie] attribute:
Is only run on the server.
For Classic movies, validates the release date:
C#Copy
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;
}
}

The movie variable in the preceding example represents a Movie object that contains the data from the form submission. When validation fails, a with an error message is returned.

IValidatableObject

The preceding example works only with Movie types. Another option for class-level validation is to implement in the model class, as shown in the following example:
C#Copy
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) }); } }
}

T

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.