0

私のクラスでは、次のような添付ファイルのプロパティがあります...

public class Certificate {
    [Required]
    // TODO:  Wow looks like there's a problem with using regex in MVC 4, this does not work!
    [RegularExpression(@"^.*\.(xlsx|xls|XLSX|XLS)$", ErrorMessage = "Only Excel files (*.xls, *.xlsx) files are accepted")]
    public string AttachmentTrace { get; set; }
}

正規表現に問題はありませんが、常に ModelState.IsValid が false になります。これは非常に些細で単純な正規表現のようですが、何か不足していますか? 独自のカスタム検証を作成する必要がありますか?

タイプファイルの通常の入力を介してAttachmentTraceにデータを入力しています:

<div class="editor-label">
    @Html.LabelFor(model => model.AttachmentTrace)
</div>
<div class="editor-field">
    @Html.TextBoxFor(model => model.AttachmentTrace, new { type = "file" })
    @Html.ValidationMessageFor(model => model.AttachmentTrace)
</div>

アクション メソッドは単なる通常のアクションです。

public ActionResult Create(Certificate certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail)
    {
        if (ModelState.IsValid)
        {
            // code ...
        }
        return View(certificate);
    }
4

1 に答える 1

1

わかりました、これが私が見つけた解決策です。私はそこに他の解決策があると確信しています。私のアプリケーションは EF コード ファースト マイグレーションを使用し、モデルでHttpPostedFileBaseプロパティ タイプを指定しているため、マイグレーションを追加するときに次のエラーが発生します。

モデルの生成中に 1 つ以上の検証エラーが検出されました: System.Data.Entity.Edm.EdmEntityType: : EntityType 'HttpPostedFileBase' にはキーが定義されていません。この EntityType のキーを定義します。\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'HttpPostedFileBases' は、キーが定義されていないタイプ 'HttpPostedFileBase' に基づいています。

そのため、AttachmentTrace プロパティに文字列型を使用することに固執する必要がありました。

解決策は、次のような ViewModel クラスを使用することです。

public class CertificateViewModel {
    // .. other properties
    [Required]
    [FileTypes("xls,xlsx")]
    public HttpPostedFileBase AttachmentTrace { get; set; }
}

次に、そのように FileTypesAttribute を作成します。このコードは、この優れた投稿から借用しました。

public class FileTypesAttribute : ValidationAttribute {
    private readonly List<string> _types;

    public FileTypesAttribute(string types) {
        _types = types.Split(',').ToList();
    }

    public override bool IsValid(object value) {
        if (value == null) return true;
        var postedFile = value as HttpPostedFileBase;
        var fileExt = System.IO.Path.GetExtension(postedFile.FileName).Substring(1);
        return _types.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    public override string FormatErrorMessage(string name) {
        return string.Format("Invalid file type. Only {0} are supported.", String.Join(", ", _types));
    }
}

コントローラー アクションでは、代わりに ViewModel を使用するように変更し、AutoMapper を使用してそれをエンティティにマップし直す必要がありました (ちなみにこれは優れています)。

public ActionResult Create(CertificateViewModel certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail) {
        if (ModelState.IsValid) {
            // Let's use AutoMapper to map the ViewModel back to our Certificate Entity
            // We also need to create a converter for type HttpPostedFileBase -> string
            Mapper.CreateMap<HttpPostedFileBase, string>().ConvertUsing(new HttpPostedFileBaseTypeConverter());
            Mapper.CreateMap<CreateCertificateViewModel, Certificate>();
            Certificate myCert = Mapper.Map<CreateCertificateViewModel, Certificate>(certificate);
            // other code ...
        }
        return View(myCert);
    }

AutoMapper については、次のように HttpPostedFileBase 用に独自の TypeConverter を作成しました。

public class HttpPostedFileBaseTypeConverter : ITypeConverter<HttpPostedFileBase, string> {

    public string Convert(ResolutionContext context) {
        var fileBase = context.SourceValue as HttpPostedFileBase;
        if (fileBase != null) {
            return fileBase.FileName;
        }
        return null;
    }
}

それでおしまい。これが、同じ問題を抱えている可能性のある他の人に役立つことを願っています.

于 2013-03-13T05:48:55.870 に答える