hey*_*uss 5 asp.net-mvc asp.net-web-api
测试用于文件上载的Web API,有一个像这样的简单视图模型:
public class TestModel {
public string UserId {get;set;}
public HttpPostedFileBase ImageFile {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
用于方法:
[HttpPost]
public void Create(TestModel model)
Run Code Online (Sandbox Code Playgroud)
当我尝试将多部分/表单数据编码的表单发布到操作时,我收到此异常:
System.InvalidOperationException: No MediaTypeFormatter is available to read an object of type 'TestModel' from content with media type 'multipart/form-data'.
at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)
Run Code Online (Sandbox Code Playgroud)
这适用于默认的MVC模型绑定器,但显然不适用于Web API.发现有人提到在上传文件时不能使用视图模型,只是将数据分成两个调用.这对我不起作用,因为我需要发布其他字段才能真正对上传的文件做些什么.有没有办法实现这个目标?
您可以编写自定义MediaTypeFormatter以方便您的方案,也可以使用MultipartFormDataStreamProvider.FormData.AllKeys集合手动将数据从请求中提取出来.这样,您可以在一个请求中发布文件和其他字段.
Mike Wasson的一个很好的教程可以在这里找到:http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2
查看我原来的答案 /sf/answers/882267991/
基本上结合我的博客文章中的方法和 TryValidateProperty() 建议来维护模型验证注释。
编辑:我继续对博客文章中的代码进行了代码增强。我将很快发布这个更新的代码。这是一个简单的示例,它验证每个属性并允许您访问结果数组。只是一种方法的示例
public class FileUpload<T>
{
private readonly string _RawValue;
public T Value { get; set; }
public string FileName { get; set; }
public string MediaType { get; set; }
public byte[] Buffer { get; set; }
public List<ValidationResult> ValidationResults = new List<ValidationResult>();
public FileUpload(byte[] buffer, string mediaType, string fileName, string value)
{
Buffer = buffer;
MediaType = mediaType;
FileName = fileName.Replace("\"","");
_RawValue = value;
Value = JsonConvert.DeserializeObject<T>(_RawValue);
foreach (PropertyInfo Property in Value.GetType().GetProperties())
{
var Results = new List<ValidationResult>();
Validator.TryValidateProperty(Property.GetValue(Value),
new ValidationContext(Value) {MemberName = Property.Name}, Results);
ValidationResults.AddRange(Results);
}
}
public void Save(string path, int userId)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
var SafeFileName = Md5Hash.GetSaltedFileName(userId,FileName);
var NewPath = Path.Combine(path, SafeFileName);
if (File.Exists(NewPath))
{
File.Delete(NewPath);
}
File.WriteAllBytes(NewPath, Buffer);
var Property = Value.GetType().GetProperty("FileName");
Property.SetValue(Value, SafeFileName, null);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12994 次 |
| 最近记录: |