asp.net-core – ASP.NET Core 1.1中的multipart / form-data(Fi
我正在尝试构建一个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)); 执行此操作后,可以将[F??romForm]属性添加到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-mvc – Kendo Grid导出到Excel – 所有页面都不起作
- asp.net-mvc – 如何在MVC3中的数据库中提交数据后清除模型
- asp.net – 在ASP MVC3中,如何使用uri执行控制器和动作?
- asp.net-core – 如何在ApplicationStarted事件中优雅地中止
- asp.net – 授权和验证对静态内容的访问(pdf)
- asp.net-core-mvc – 将复杂对象存储在MVC 6中的TempData中
- Asp.net基本对象
- asp.net – 为MVC视图订购实体框架项和子项
- asp.net – 英国邮政编码查找流程的好例子
- asp.net – 引用不稳定的DLL
- asp.net – 公共访问本地IIS服务器
- asp.net-mvc – 使用ASP.New MVC 4 Web Api进行授
- 经典ASP亚马逊s3休闲授权
- asp.net-mvc – MiniProfiler与EF“模型第一”ed
- asp.net – 无法加载类型’site._Default'[已
- asp.net-mvc – 如何强制Razor使Editorfor输入fl
- 启用禁用按钮asp .net – 使用javascript
- 事件(Event),绝大多数内存泄漏(Memory Leak)的
- asp.net – 从VS2008发布的等效msbuild命令
- asp.net – 更改单个URL查询字符串值