Rest 如何将文件作为ViewModel对象的一部分发送到Web API

Rest 如何将文件作为ViewModel对象的一部分发送到Web API,rest,api,.net-core,asp.net-core-2.0,Rest,Api,.net Core,Asp.net Core 2.0,我有带有以下控制器的.NET核心Web应用程序: [HttpPost] public async Task<IActionResult> Update(StudentDetailsViewModel vm) { var tokenNo = HttpContext.Session.GetString("Token"); vm.ID = Convert.ToInt32(HttpContext.Session.G

我有带有以下控制器的.NET核心Web应用程序:

    [HttpPost]
    public async Task<IActionResult> Update(StudentDetailsViewModel vm)
    {           
        var tokenNo = HttpContext.Session.GetString("Token");
        vm.ID = Convert.ToInt32(HttpContext.Session.GetString("StudentId"));

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenNo);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var putStudentUrl = _appSettings.Value.Apis.GSRTCApi.Url + _appSettings.Value.Apis.GSRTCApi.StudentsEndpoint + vm.ID;

        var settings = new JsonSerializerSettings();

        var stringData = JsonConvert.SerializeObject(vm); 

        var contentData = new StringContent(stringData, Encoding.UTF8, "application/json");

        var response = await client.PutAsync(putStudentUrl, contentData); // contentData);


        return RedirectToAction("Index", "Home");
    }
[HttpPost]
公共异步任务更新(StudentDetailsViewModel vm)
{           
var tokenNo=HttpContext.Session.GetString(“令牌”);
vm.ID=Convert.ToInt32(HttpContext.Session.GetString(“StudentId”);
HttpClient=新的HttpClient();
client.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载者”,令牌号);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
var putStudentUrl=_-appSettings.Value.api.GSRTCApi.Url+_-appSettings.Value.api.GSRTCApi.StudentsEndpoint+vm.ID;
var settings=new JsonSerializerSettings();
var stringData=JsonConvert.SerializeObject(vm);
var contentData=newstringcontent(stringData,Encoding.UTF8,“application/json”);
var response=await client.PutAsync(putStudentUrl,contentData);//contentData);
返回重定向到操作(“索引”、“主页”);
}
控制器调用我的Web API,一切正常,直到我通过html表单上传文件。发生这种情况时,将在客户端StudentDetailsViewModel的IFormFile属性中拾取该文件,但在进行API调用时,整个对象为null。API控制器是:

[HttpPut("{id}")]
public async Task<IActionResult> Put(int? id, [FromBody]StudentViewModel student)
{
    // API operations here
} 
[HttpPut(“{id}”)]
公共异步任务Put(int?id,[FromBody]StudentViewModel student)
{
//这里的API操作
} 

我怀疑我没有正确序列化StudentDetailsViewModel对象,因为我有一个属性IFormFile,它是一个接口。但是,我不确定如何定制Json.Newsoft对象

要发送
ifformfile
,您需要使用
FromForm
,这是从body和
MultipartFormDataContent
中删除
时的默认值

以下是完整的步骤:

  • Web应用程序模型
  • public class StudentDetailsViewModel
    {
    公共int Id{get;set;}
    公共字符串名称{get;set;}
    公共文件{get;set;}
    }
    
  • Web应用程序控制器
  • public异步任务更新(StudentDetailsViewModel-vm)
    {
    HttpClient=新的HttpClient();
    var putStudentUrl=@“url”;
    字节[]数据;
    使用(var br=new二进制读取器(vm.File.OpenReadStream())
    {
    data=br.ReadBytes((int)vm.File.OpenReadStream().Length);
    }
    ByteArrayContent字节=新的ByteArrayContent(数据);
    MultipartFormDataContent multiContent=新的MultipartFormDataContent();
    添加(字节,“文件”,vm.file.FileName);
    Add(新的StringContent(vm.Id.ToString()),“Id”);
    添加(新的StringContent(vm.Name),“Name”);
    var response=await client.PutAsync(putStudentUrl,多内容);
    返回重定向到操作(“索引”、“主页”);
    }
    
  • webapi模型
  • 公共类学生视图模型
    {
    公共int Id{get;set;}
    公共字符串名称{get;set;}
    公共文件{get;set;}
    }
    
  • Web API控制器
  • [HttpPut(“{id}”)]
    公共异步任务Put(int?id,StudentViewModel student)
    {
    使用(var stream=newfilestream(@“文件路径”,FileMode.Create))
    {
    等待student.File.CopyToAsync(流);
    }
    返回Ok();
    }
    

    注意
    multiContent.Add(字节,“文件”,vm.file.FileName),第二个参数是
    ifformfile
    字段的名称。

    包括模型和调用JS。我没有JS代码只是一个带有asp标记的表单。我有一个虚拟对象属性作为模型的一部分,当我使用[FromForm]而不是[FromBody]时,我无法将其发送到API。此外,它对我来说似乎不是一个非常优雅的解决方案,因为我需要将每一个属性添加到多内容中。对我来说不起作用。我在API控制器上得到415种不受支持的媒体类型。
    multiContent.Add(字节,“file”,vm.file.FileName)-对我来说很有用,它是一个
    ByteArrayContent
    而不是
    StreamContent
    。尽管不确定
    StreamContent
    是否也能正常工作。