開始する基本的な質問:モデル内のオブジェクトのリストの上に、目立たないカスタムバリデーターをどのように配置できますか?たとえば、私のモデルでは複数のファイルのアップロードが許可されているため、ファイルのリストがあり、それらの各ファイルでバリデーターを実行したいとしますか?
次に、具体的な例を示します。ファイル拡張子が禁止されている拡張子のリストに含まれていないかどうかを確認する、目立たないカスタムバリデーターがあります。
public class FileExtensionValidatorAttribute : ValidationAttribute, IClientValidatable {
protected static string[] PROHIBITED_EXTENSIONS = {
// ... List of extensions I don't allow.
};
public override bool IsValid(object value) {
if (value is IEnumerable<HttpPostedFileBase>) {
foreach (var file in (IEnumerable<HttpPostedFileBase>)value) {
var fileName = file.FileName;
if (PROHIBITED_EXTENSIONS.Any(x => fileName.EndsWith(x))) return false;
}
} else {
var file = (HttpPostedFileBase)value;
var fileName = file.FileName;
if (PROHIBITED_EXTENSIONS.Any(x => fileName.EndsWith(x))) return false;
}
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
var modelClientVlidationRule = new ModelClientValidationRule {
ErrorMessage = this.ErrorMessageString,
ValidationType = "fileextension",
};
modelClientVlidationRule.ValidationParameters.Add("prohibitedextensions", string.Join("|", PROHIBITED_EXTENSIONS));
yield return modelClientVlidationRule;
}
}
IsValidで、単一のファイルまたはファイルのリストを受け入れるようにこれを作成したことに注意してください。
私のモデルクラスでは、これを単一のHttpPostedFileBaseで利用できます。
[FileExtensionValidator(ErrorMessage = "Invalid Extension")]
public HttpPostedFileBase Upload { get; set; }
次に、私のビューでjqueryのバリデーターにアタッチします。
jQuery.validator.addMethod("fileExtension", function (value, element, param) {
var extension = "";
var dotIndex = value.lastIndexOf('.');
if (dotIndex != -1) extension = value.substring(dotIndex + 1).toLowerCase();
return $.inArray(extension, param.prohibitedExtensions) === -1;
});
jQuery.validator.unobtrusive.adapters.add('fileextension', ['prohibitedextensions'], function (options) {
options.rules['fileExtension'] = {
prohibitedExtensions: options.params.prohibitedextensions.split('|')
};
options.messages['fileExtension'] = options.message;
});
これはすべて、クライアント側とサーバー側でうまく機能します...ただし、単一のHttpPostedFileBaseでのみ機能します。問題は、ユーザーに1つ以上のファイルをアップロードする機能を提供する必要があることです。モデルをこれに変更した場合:
[FileExtensionValidator(ErrorMessage = "Invalid Extension")]
public List<HttpPostedFileBase> Uploads { get; set; }
...クライアント側の検証は実行されなくなりました。サーバー側のみが機能します。これは、ビューソースを実行するときに明らかです。生成される<input>タグには、実行する必要のあるすべてのdata-val属性がありません。デバッグを行う際に、GetClientValidationRulesが呼び出されることはありません。
私は何が欠けていますか?
これは私がそれをどのようにレンダリングしたかによるのでしょうか?HttpPostedFileBaseにEditorTemplateを使用しているだけです。
@model System.Web.HttpPostedFileBase
@Html.TextBoxFor(m => m, new { type = "file", size = 60 })
...そして私の見解はそれを次のようにレンダリングします:
<p>@Html.EditorFor(m => m.Uploads)</p>
アドバイスをいただければ幸いです。