asp.net-core – ASP.NET Core 1.1中的multipart / form-data(File
|
我正在尝试构建一个ASP.NET Core 1.1 Controller方法来处理如下所示的HTTP请求: POST https://localhost/api/data/upload HTTP/1.1
Content-Type: multipart/form-data; boundary=--------------------------625450203542273177701444
Host: localhost
Content-Length: 474
----------------------------625450203542273177701444
Content-Disposition: form-data; name="file"; filename="myfile.txt"
Content-Type: text/plain
<< Contents of my file >>
----------------------------625450203542273177701444
Content-Disposition: form-data; name="text"
Content-Type: application/json
{"md5":"595f44fec1e92a71d3e9e77456ba80d0","sessionIds":["123","abc"]}
----------------------------625450203542273177701444--
它是一个multipart / form-data请求,其中一部分是(小)文件,另一部分是基于提供的规范的json blob. 理想情况下,我喜欢我的控制器方法看起来像: [HttpPost]
public async Task Post(UploadPayload payload)
{
// TODO
}
public class UploadPayload
{
public IFormFile File { get; set; }
[Required]
[StringLength(32)]
public string Md5 { get; set; }
public List<string> SessionIds { get; set; }
}
但唉,这不是Just Work {TM}.当我这样时,IFormFile会填充,但json字符串不会反序列化到其他属性. 我还尝试向UploadPayload添加一个Text属性,该属性具有除IFormFile以外的所有属性,并且也不接收数据.例如. public class UploadPayload
{
public IFormFile File { get; set; }
public UploadPayloadMetadata Text { get; set; }
}
public class UploadPayloadMetadata
{
[Required]
[StringLength(32)]
public string Md5 { get; set; }
public List<string> SessionIds { get; set; }
}
我的解决方法是避免模型绑定并使用MultipartReader: [HttpPost]
public async Task Post()
{
...
var reader = new MultipartReader(Request.GetMultipartBoundary(),HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
var filePart = section.AsFileSection();
// Do stuff & things with the file
section = await reader.ReadNextSectionAsync();
var jsonPart = section.AsFormDataSection();
var jsonString = await jsonPart.GetValueAsync();
// Use $JsonLibrary to manually deserailize into the model
// Do stuff & things with the metadata
...
}
做上面的操作绕过了模型验证功能等.另外,我想也许我可以把那个jsonString然后以某种方式让它进入一个状态,然后我可以调用等待TryUpdateModelAsync(payloadModel,…)但是无法弄清楚如何到那儿 – 这似乎也没那么干净. 是否有可能像我的第一次尝试一样达到我想要的“透明”模型绑定状态?如果是这样,那怎么会这样呢? 解决方法这里的第一个问题是数据需要以稍微不同的格式从客户端发送. UploadPayload类中的每个属性都需要以自己的形式发送:const formData = new FormData();
formData.append(`file`,file);
formData.append('md5',JSON.stringify(md5));
formData.append('sessionIds',JSON.stringify(sessionIds));
执行此操作后,可以将[FromForm]属性添加到MD5属性以将其绑定,因为它是一个简单的字符串值.这不适用于SessionIds属性,因为它是一个复杂的对象. 可以使用自定义模型绑定器来完成从表单数据绑定复杂JSON: public class FormDataJsonBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if(bindingContext == null) throw new ArgumentNullException(nameof(bindingContext));
// Fetch the value of the argument by name and set it to the model state
string fieldName = bindingContext.FieldName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(fieldName);
if(valueProviderResult == ValueProviderResult.None) return Task.CompletedTask;
else bindingContext.ModelState.SetModelValue(fieldName,valueProviderResult);
// Do nothing if the value is null or empty
string value = valueProviderResult.FirstValue;
if(string.IsNullOrEmpty(value)) return Task.CompletedTask;
try
{
// Deserialize the provided value and set the binding result
object result = JsonConvert.DeserializeObject(value,bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(result);
}
catch(JsonException)
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
然后,您可以在DTO类中使用ModelBinder属性来指示此绑定器应该用于绑定MyJson属性: public class UploadPayload
{
public IFormFile File { get; set; }
[Required]
[StringLength(32)]
[FromForm]
public string Md5 { get; set; }
[ModelBinder(BinderType = typeof(FormDataJsonBinder))]
public List<string> SessionIds { get; set; }
}
您可以在ASP.NET Core文档中阅读有关自定义模型绑定的更多信息:https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 如何将一个对象序列化为查询字符串格式?
- ASP.NET web.config中数据库连接字符串connectionStrings节
- asp.net-core – 如何将ASP.NET 5从Beta6升级到Beta7
- asp.net – IIS URL重写 – 具有多个域
- asp.net-mvc-3 – 可用会员入门套件/成员资料用于ASP.NET M
- 认证 – asp.net mvc 3:Page.User.IsInRole(“xy”)返回nu
- 实体框架 – 如何添加外部参考ASP.Net MVC 5身份?
- ASP.NET(MVC)服务图像
- asp.net – 不能得到内容的内容,因为内容不是文字
- asp.net – asp文本框限制字符数?
- 如何从ASP.NET MVC中的自定义帮助程序中访问当前
- asp.net-core – .Net 5中的调试设置
- asp.net – web.config文件中的特殊字符
- 如何为ASP.NET WebAPI 2中使用路由属性的特定控制
- 在ASP.NET 4 ReportViewer中使用对象数据源
- asp.net – OutOfMemoryException当发送大文件50
- asp.net – 将JSON对象反序列化为列表不能使用as
- asp.net-mvc – ASP.NET MVC QueryString默认覆盖
- 如何强制编译ASP.NET MVC视图?
- asp.net-mvc-3 – 在Razor View模型中添加一个类
