Added additional validation to model

This commit is contained in:
Jim Paine 2020-04-14 13:22:18 +01:00
Родитель c9bdda99fa
Коммит 9341078255
8 изменённых файлов: 126 добавлений и 4 удалений

Просмотреть файл

@ -181,6 +181,11 @@ namespace Project.Zap.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> AddShift(SearchShiftViewModel viewModel) public async Task<IActionResult> AddShift(SearchShiftViewModel viewModel)
{ {
if(!ModelState.IsValid)
{
return View("Add", viewModel);
}
List<Shift> shifts = viewModel.NewShift.Map().ToList(); List<Shift> shifts = viewModel.NewShift.Map().ToList();
shifts.ForEach(async x => await this.shiftRepository.Add(x)); shifts.ForEach(async x => await this.shiftRepository.Add(x));

Просмотреть файл

@ -0,0 +1,40 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
namespace Project.Zap.Filters
{
public class DateLessThanAttribute : ValidationAttribute
{
public string PropertyName { get; private set; }
public string GetErrorMessageKey() => "StartLessThanEnd";
public DateLessThanAttribute(string propertyName)
{
this.PropertyName = propertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ErrorMessage = ErrorMessageString;
DateTime currentValue = (DateTime)value;
PropertyInfo property = validationContext.ObjectType.GetProperty(this.PropertyName);
if (property == null)
{
throw new ArgumentException("Property with this name not found");
}
DateTime comparisonValue = (DateTime)property.GetValue(validationContext.ObjectInstance);
if (currentValue > comparisonValue)
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Localization;
namespace Project.Zap.Filters
{
public class DateLessThanAttributeAdapter : AttributeAdapterBase<DateLessThanAttribute>
{
private readonly IStringLocalizer stringLocalizer;
public DateLessThanAttributeAdapter(DateLessThanAttribute attribute, IStringLocalizer stringLocalizer) : base(attribute, stringLocalizer)
{
this.stringLocalizer = stringLocalizer;
}
public override void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-datelessthan", GetErrorMessage(context));
string propertyName = Attribute.PropertyName;
MergeAttribute(context.Attributes, "data-val-datelessthan-property", propertyName);
}
public override string GetErrorMessage(ModelValidationContextBase validationContext) => this.stringLocalizer[Attribute.GetErrorMessageKey()];
}
}

Просмотреть файл

@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.Extensions.Localization;
using System.ComponentModel.DataAnnotations;
namespace Project.Zap.Filters
{
public class DateLessThanAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
private readonly IValidationAttributeAdapterProvider baseProvider = new ValidationAttributeAdapterProvider();
public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
if (attribute is DateLessThanAttribute dateLessThanAttribute)
{
return new DateLessThanAttributeAdapter(dateLessThanAttribute, stringLocalizer);
}
return baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
}
}
}

Просмотреть файл

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Project.Zap.Filters;
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@ -15,6 +16,7 @@ namespace Project.Zap.Models
[BindProperty] [BindProperty]
[Required] [Required]
[Display(Name = "Start")] [Display(Name = "Start")]
[DateLessThan("End")]
[DisplayFormat(DataFormatString = "{yyyy-MM-ddTHH:mm}")] [DisplayFormat(DataFormatString = "{yyyy-MM-ddTHH:mm}")]
public DateTime Start { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0); public DateTime Start { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
@ -31,11 +33,13 @@ namespace Project.Zap.Models
[BindProperty] [BindProperty]
[Required] [Required]
[Range(1, 200)]
[Display(Name = "Quantity")] [Display(Name = "Quantity")]
public int Quantity { get; set; } public int Quantity { get; set; }
[BindProperty] [BindProperty]
[Required] [Required]
[Range(0, 200)]
[Display(Name = "Available")] [Display(Name = "Available")]
public int Available { get; set; } public int Available { get; set; }

Просмотреть файл

@ -129,6 +129,9 @@
<data name="Start" xml:space="preserve"> <data name="Start" xml:space="preserve">
<value>Start</value> <value>Start</value>
</data> </data>
<data name="StartLessThanEnd" xml:space="preserve">
<value>Start Date and Time needs to be before End</value>
</data>
<data name="StoreName" xml:space="preserve"> <data name="StoreName" xml:space="preserve">
<value>Store Name</value> <value>Store Name</value>
</data> </data>

Просмотреть файл

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Cosmos.Fluent;
@ -14,6 +15,7 @@ using Microsoft.Extensions.Localization;
using Microsoft.Graph; using Microsoft.Graph;
using Microsoft.Graph.Auth; using Microsoft.Graph.Auth;
using Microsoft.Identity.Client; using Microsoft.Identity.Client;
using Project.Zap.Filters;
using Project.Zap.Library.Models; using Project.Zap.Library.Models;
using Project.Zap.Library.Services; using Project.Zap.Library.Services;
using Project.Zap.Middleware; using Project.Zap.Middleware;
@ -65,7 +67,9 @@ namespace Project.Zap
services.AddLocalization(options => options.ResourcesPath = "Resources"); services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddControllers().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) services.AddControllers().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(); .AddDataAnnotationsLocalization();
services.AddRazorPages(); services.AddRazorPages();
services.AddSingleton<IValidationAttributeAdapterProvider, DateLessThanAttributeAdapterProvider>();
services.AddTransient<Database>(x => this.GetCosmosDatabase().Result); services.AddTransient<Database>(x => this.GetCosmosDatabase().Result);

Просмотреть файл

@ -1,7 +1,7 @@
@{ @{
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer @inject IViewLocalizer Localizer
} }
@model Project.Zap.Models.SearchShiftViewModel @model Project.Zap.Models.SearchShiftViewModel
@ -38,4 +38,23 @@
</div> </div>
<input type="hidden" asp-for="@Model.NewShift.Available" /> <input type="hidden" asp-for="@Model.NewShift.Available" />
<button type="submit" class="btn btn-primary mb-2">@Localizer["AddButton"]</button> <button type="submit" class="btn btn-primary mb-2">@Localizer["AddButton"]</button>
</form> </form>
@section Scripts
{
<script>
$.validator.addMethod('datelessthan', function (value, element, params) {
var compareDateId = "#NewShift_" + params[0].dataset.valDatelessthanProperty;
var compareValue = $(compareDateId).val()
return value < compareValue;
return true;
});
$.validator.unobtrusive.adapters.add('datelessthan', ['property'], function (options) {
options.rules['datelessthan'] = [options.element, parseInt(options.params['property'])];
options.messages['datelessthan'] = options.message;
});
</script>
}