Редактировать
Я обнаружил, что проблема в том, что компоненты представления не могут иметь @section ( см. ViewComponent и @Section # 2910 ), поэтому добавление пользовательской проверки на стороне клиента с использованием ненавязчивой библиотеки кажется невозможным (или очень сложный). Более того, невозможность включения необходимого javascript в компонент View заставляет меня сожалеть о том, что я следую этому подходу для модульности моего приложения, в первую очередь ...
Я учусь создавать собственные атрибуты проверки с поддержкой на стороне клиента. Мне удалось реализовать пользовательский валидатор для свойства строки, и он работает довольно хорошо, но когда я попытался сделать таковой для входного файла, он не работает (т.е. когда я выбираю файл на моем компьютере, приложение не отображается сообщения проверки. Проверка на стороне сервера работает. Вот некоторый код, который показывает мою реализацию.
Класс модели
public class UploadPanelModel
{
public int? ID { get; set; }
public string Title { get; set; }
public string Description { get; set; } //Raw HTML with the panel description
[FileType(type: "application/pdf")]
[FileSize(maxSize: 5000000)]
public IFormFile File { get; set; }
public byte[] FileBytes { get; set; }
public ModalModel Modal { get; set; } //Only used if the Upload panel uses a modal.
Валидатор
public class FileSizeAttribute : ValidationAttribute, IClientModelValidator
{
private long _MaxSize { get; set; }
public FileSizeAttribute (long maxSize)
{
_MaxSize = maxSize;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
UploadPanelModel panel = (UploadPanelModel)validationContext.ObjectInstance;
return (panel.File==null || panel.File.Length <= _MaxSize) ? ValidationResult.Success : new ValidationResult(GetFileSizeErrorMessage(_MaxSize));
}
private string GetFileSizeErrorMessage(long maxSize)
{
double megabytes = maxSize / 1000000.0;
return $"El archivo debe pesar menos de {megabytes}MB";
}
public void AddValidation(ClientModelValidationContext context)
{
if(context == null)
{
throw new ArgumentNullException(nameof(context));
}
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-filesize", GetFileSizeErrorMessage(_MaxSize));
var maxSize = _MaxSize.ToString();
MergeAttribute(context.Attributes, "data-val-filesize-maxsize", maxSize);
}
private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
}
JavaScript в Razor View
@section Scripts{
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script type="text/javascript">
$.validator.addMethod('filesize',
function (value, element, params) {
var size = $((params[0]).val()).size(),
maxSize = params[1];
if (size < maxSize) {
return false;
}
else {
return false;
}
}
);
$.validator.unobtrusive.adapters.add('filesize',
['maxSize'],
function (options) {
var element = $(options.form).find('input#File')[0];
options.rules['filesize'] = [element, options.params['maxSize']];
options.messages['filesize'] = options.message;
}
);
</script>
Я всегда возвращаю false в методе javascript, чтобы приложение показывало ошибку проверки независимо от выбранного файла, но оно все равно не работает.