Хорошо, вот решение, которое я нашел. Я уверен, что есть другие решения. Сначала немного фона, потому что мое приложение использует EF код-первой миграцию, указав в HttpPostedFileBase типа свойства в моей модели, производит эту ошибку при добавлении миграции:
Один или несколько ошибок проверки были обнаружены в процессе генерации модели: 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 как так, я заимствовал этот код из this excellent post.
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, я создал свой собственный TypeConverter для HttpPostedFileBase следующим образом:
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;
}
}
Вот и все. Надеюсь, это поможет другим, у кого может быть такая же проблема.
как вы заселяетесь AttachmentTrace? –
Forty-Two, я заполняю его через обычный ввод файла типа (просто добавленный код выше). Благодарю. – sammydc
Ну, как вы это делаете, я бы предположил, что значение AttachmentTrace не то, что вы ожидаете (имя файла), а скорее нечто вроде «System.Web.HttpPostedFileWrapper». –