我需要在模型中将byte[]
验证为Required
,但每当我在其上使用Data Annotation
[Required]
时,它都不会做任何事情。即使我选择了一个文件,它也会输出错误信息。
详细说明:
型号:
Public class MyClass
{
[Key]
public int ID {get; set;}
[Required]
public string Name {get; set;}
public byte[] Image {get; set;}
[Required]
public byte[] Template {get; set;}
}
查看:
<div class="editor-label">
<%:Html.LabelFor(model => model.Image) %>
</div>
<div class="editor-field">
<input type="file" id="file1" name="files" />
</div>
<div class="editor-label">
<%:Html.Label("Template") %>
</div>
<div class="editor-field">
<input type="file" id="file2" name="files"/>
</div>
<p>
<input type="submit" value="Create" />
</p>
我查看了帖子,并注意到人们使用自定义验证,但他们使用HttpPostedFileBase
作为文件类型而不是像我这样的byte[]
,出于某些原因,当我尝试使用相同的时候缺少ID的错误...即使模型已经声明了它自己的ID。
编辑:
上下文 - OnModelCreating
Report
个附加内容
modelBuilder.Entity<Report>().Property(p => p.Image).HasColumnType("image");
modelBuilder.Entity<Report>().Property(p => p.Template).HasColumnType("image");
请注意,由于image
错误,我必须将ColumnType
设为Byte array truncation to a length of 4000.
。
控制器:
public ActionResult Create(Report report, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
db.Configuration.ValidateOnSaveEnabled = false;
if (files.ElementAt(0) != null && files.ElementAt(0).ContentLength > 0)
{
using (MemoryStream ms = new MemoryStream())
{
files.ElementAt(0).InputStream.CopyTo(ms);
report.Image = ms.GetBuffer();
}
}
if (files.ElementAt(1) != null && files.ElementAt(1).ContentLength > 0)
{
using (MemoryStream ms1 = new MemoryStream())
{
files.ElementAt(1).InputStream.CopyTo(ms1);
report.Template = ms1.GetBuffer();
}
}
db.Reports.Add(report);
db.SaveChanges();
//Temporary save method
var tempID = 10000000 + report.ReportID;
var fileName = tempID.ToString(); //current by-pass for name
var path = Path.Combine(Server.MapPath("~/Content/Report/"), fileName);
files.ElementAt(1).SaveAs(path);
db.Configuration.ValidateOnSaveEnabled = true;
return RedirectToAction("Index");
}
希望你可能会注意到我错过了什么。
答案 0 :(得分:4)
RequiredAttribute
检查null和空字符串。
public override bool IsValid(object value)
{
if (value == null)
return false;
string str = value as string;
if (str != null && !this.AllowEmptyStrings)
return str.Trim().Length != 0;
else
return true;
}
如果您的字节数组为空,这可以正常工作,但您可能也想检查一个空数组(没有看到如何分配Template
属性的值,我只能猜测这是案子)。您可以定义自己的必需属性,为您进行此项检查。
public class RequiredCollectionAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
bool isValid = base.IsValid(value);
if(isValid)
{
ICollection collection = value as ICollection;
if(collection != null)
{
isValid = collection.Count != 0;
}
}
return isValid;
}
}
现在,只需使用新的Required
属性替换Template
媒体资源上的RequiredCollection
属性。
[RequiredCollection]
public byte[] Template {get; set;}
答案 1 :(得分:0)
我查看了帖子并注意到人们使用自定义验证 但他们使用HttpPostedFileBase作为文件类型而不是 像我这样的字节[] ..
是否要将发布的文件绑定到模型中的byterray字段?如果是,您必须使用自定义模型绑定器。
ASP.NET MVC已经有一个用于字节数组的内置模型绑定器,因此您可以按照post中的建议轻松扩展它。
public class CustomFileModelBinder : ByteArrayModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var file = controllerContext.HttpContext.Request.Files[bindingContext.ModelName];
if (file != null)
{
if (file.ContentLength != 0 && !String.IsNullOrEmpty(file.FileName))
{
var fileBytes = new byte[file.ContentLength];
file.InputStream.Read(fileBytes, 0, fileBytes.Length);
return fileBytes;
}
return null;
}
return base.BindModel(controllerContext, bindingContext);
}
}
protected void Application_Start()
{
...
ModelBinders.Binders.Remove(typeof(byte[]));
ModelBinders.Binders.Add(typeof(byte[]), new CustomFileModelBinder());
}
现在上传的文件将直接作为bytearray存在于属性中。
答案 2 :(得分:0)
我改变了我的Create
方法,这就是我想出来的。似乎工作正常,但......
if (files.ElementAt(1) != null && files.ElementAt(1).ContentLength > 0)
{
using (MemoryStream ms1 = new MemoryStream())
{
files.ElementAt(1).InputStream.CopyTo(ms1);
report.Template = ms1.GetBuffer();
}
}
else // this part of code did the trick, although not sure how good it is in practice
{
return View(report);
}