mvc 一般绑定 byte[] 属性
mvc genericly binding byte[] properties
我试过使用自定义模型活页夹,但我的 request.files 没有填充。在表单集合中,byte[] 属性 的类型文件输入仅由文件名填充。
<input id="collection[@index].@p.Name" name="collection[@index].@p.Name" type="file" />
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace male.services.mvc.Binders
{
public class CustomModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.GetProperties().Any(o => o.PropertyType == typeof(byte[])))
{
HttpRequestBase request = controllerContext.HttpContext.Request;
foreach (var pi in bindingContext.ModelType.GetProperties().Where(o => o.PropertyType == typeof(byte[])))
{
// can't access any property in the parameters that gives me my file input or my stream
}
return base.BindModel(controllerContext, bindingContext);
}
else
{
return base.BindModel(controllerContext, bindingContext);
}
}
}
}
我找到了答案。这将允许我直接从 html 文件输入到 EF 模型,而无需为每个模型类型和需要它的 属性 类型手工制作文件参数。 (Aint nobody got time for that)
为了将表格 post 文件,它必须具有 enctype 属性:
<form enctype="multipart/form-data" ... />
完成后,可以通过 controllerContext.HttpContext.Request.Files
访问文件
更新 - 工作示例
注意:如果您不尝试绑定集合,则不需要 Regex
内容。你也不需要 EndsWith
,你可以只使用 ==
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
namespace male.services.mvc.Binders
{
public class CustomModelBinder : DefaultModelBinder
{
HttpRequestBase request;
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
request = controllerContext.HttpContext.Request;
return base.BindModel(controllerContext, bindingContext);
}
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.PropertyType == typeof(byte[]))
{
var key = request.Files.AllKeys.SingleOrDefault(o => o.EndsWith($"].{propertyDescriptor.Name}"));
var fileIndex = Regex.Match(key, @"\[(.*)\]").Groups[1].Value;
var modelIndex = Regex.Match(bindingContext.ModelName, @"\[(.*)\]").Groups[1].Value;
if(fileIndex == modelIndex)
{
HttpPostedFileWrapper httpPostedFile = (HttpPostedFileWrapper)request.Files[request.Files.AllKeys.SingleOrDefault(o => o.EndsWith(propertyDescriptor.Name))];
using (MemoryStream ms = new MemoryStream())
{
httpPostedFile.InputStream.CopyTo(ms);
propertyDescriptor.SetValue(bindingContext.Model, ms.ToArray());
}
}
}
else
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
}
我试过使用自定义模型活页夹,但我的 request.files 没有填充。在表单集合中,byte[] 属性 的类型文件输入仅由文件名填充。
<input id="collection[@index].@p.Name" name="collection[@index].@p.Name" type="file" />
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace male.services.mvc.Binders
{
public class CustomModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.GetProperties().Any(o => o.PropertyType == typeof(byte[])))
{
HttpRequestBase request = controllerContext.HttpContext.Request;
foreach (var pi in bindingContext.ModelType.GetProperties().Where(o => o.PropertyType == typeof(byte[])))
{
// can't access any property in the parameters that gives me my file input or my stream
}
return base.BindModel(controllerContext, bindingContext);
}
else
{
return base.BindModel(controllerContext, bindingContext);
}
}
}
}
我找到了答案。这将允许我直接从 html 文件输入到 EF 模型,而无需为每个模型类型和需要它的 属性 类型手工制作文件参数。 (Aint nobody got time for that)
为了将表格 post 文件,它必须具有 enctype 属性:
<form enctype="multipart/form-data" ... />
完成后,可以通过 controllerContext.HttpContext.Request.Files
更新 - 工作示例
注意:如果您不尝试绑定集合,则不需要 Regex
内容。你也不需要 EndsWith
,你可以只使用 ==
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
namespace male.services.mvc.Binders
{
public class CustomModelBinder : DefaultModelBinder
{
HttpRequestBase request;
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
request = controllerContext.HttpContext.Request;
return base.BindModel(controllerContext, bindingContext);
}
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.PropertyType == typeof(byte[]))
{
var key = request.Files.AllKeys.SingleOrDefault(o => o.EndsWith($"].{propertyDescriptor.Name}"));
var fileIndex = Regex.Match(key, @"\[(.*)\]").Groups[1].Value;
var modelIndex = Regex.Match(bindingContext.ModelName, @"\[(.*)\]").Groups[1].Value;
if(fileIndex == modelIndex)
{
HttpPostedFileWrapper httpPostedFile = (HttpPostedFileWrapper)request.Files[request.Files.AllKeys.SingleOrDefault(o => o.EndsWith(propertyDescriptor.Name))];
using (MemoryStream ms = new MemoryStream())
{
httpPostedFile.InputStream.CopyTo(ms);
propertyDescriptor.SetValue(bindingContext.Model, ms.ToArray());
}
}
}
else
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
}