gpt4 book ai didi

asp.net-core - ASP.NET Core 1.1 中多部分/表单数据(文件 + JSON)帖子的模型绑定(bind)

转载 作者:行者123 更新时间:2023-12-04 14:55:11 25 4
gpt4 key购买 nike

我正在尝试构建一个 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。

理想情况下,我希望我的 Controller 方法看起来像:

[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; }
}

但是,唉,这不只是工作{TM}。当我像这样拥有它时, IFormFile 确实会被填充,但 json 字符串不会反序列化为其他属性。

我还尝试向 Text 添加一个 UploadPayload 属性,该属性具有除 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; }
}

我有一个解决方法是避免模型绑定(bind)并使用 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,然后以某种方式让它进入我可以调用 await TryUpdateModelAsync(payloadModel, ...) 但无法弄清楚如何到达那里的状态 - 那没有看起来也很干净。

是否有可能像我的第一次尝试一样达到我想要的“透明”模型绑定(bind)状态?如果是这样,人们将如何做到这一点?

最佳答案

这里的第一个问题是数据需要以稍微不同的格式从客户端发送。您的 UploadPayload 中的每个属性类需要以自己的形式发送:

const formData = new FormData();
formData.append(`file`, file);
formData.append('md5', JSON.stringify(md5));
formData.append('sessionIds', JSON.stringify(sessionIds));

完成此操作后,您可以添加 [FromForm] MD5 的属性属性来绑定(bind)它,因为它是一个简单的字符串值。这不适用于 SessionIds属性,因为它是一个复杂的对象。

可以使用自定义模型绑定(bind)器从表单数据中绑定(bind)复杂的 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;
}
}

然后您可以使用 ModelBinder您的 DTO 类中的属性以指示应该使用此绑定(bind)器来绑定(bind) MyJson属性(property):

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 文档中阅读有关自定义模型绑定(bind)的更多信息: https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding

关于asp.net-core - ASP.NET Core 1.1 中多部分/表单数据(文件 + JSON)帖子的模型绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44979737/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com