3

I have an ASP.Net MVC site that allows the user to subtmit a form along with uploading files.

This part works. But in my MVC Post method, I need to call an ASP.Net Web API method and pass it the model.

This is the part I don't know how to do.

Here is my model in my MVC App:

public class MyModel
{
    public DateTime SubmittedDate { get; set; }
    public string Comments { get; set; }   
    public IEnumerable<HttpPostedFileBase> Files { get; set; }
}

In my MVC site I have the following method:

[HttpPost]
public async Task<ActionResult> Details(MyModel model)
{
    if (!ModelState.IsValid)
    // the rest of the method
}

In this method the files and model are correctly populated. When I put a breakpoint and navigate over the Files property I can see the correct number of files with the correct names and file types.

In my Details method, I want to call a method on another site which is a Web API site.

Here is the method on the Web API site:

[HttpPost]
public HttpResponseMessage Foo(MyModel myModel)
{
    // do stuff
}

Normally in my MVC method I would call the Web API using the HttpClient class using the PostAsJsonAsync method.

But when I do:

HttpResponseMessage response = await httpClient.PostAsJsonAsync(urlServiceCall, myModel);

I receive this error:

Newtonsoft.Json.JsonSerializationException

Additional information: Error getting value from 'ReadTimeout' on 'System.Web.HttpInputStream'.

Gilles
  • 5,269
  • 4
  • 34
  • 66
  • 1
    That is because it is trying to serialize the input stream of the files. I would suggest creating a new model for the web api that have the stream as byte arrays. the serializer would do better with the arrays than the stream. – Nkosi Oct 27 '16 at 13:30

2 Answers2

1

I ended up suing Nkosi's suggestion.

I created a new model for the Web Api:

public class OtherModel
{
    public string Comments { get; set; }
    public List<byte[]> FileData { get; set; }
}

In my MVC method I used the following the Read the HttpPostFiles:

foreach (var file in model.Files)
{
    byte[] fileData = new byte[file.ContentLength];                
    await file.InputStream.ReadAsync(fileData, 0, file.ContentLength);
    testModel.FileData.Add(fileData);
}

Now I can use the HttpClient using PostAsJsonAsync and everything works correctly.

Gilles
  • 5,269
  • 4
  • 34
  • 66
1

That is because it is trying to serialize the input stream of the files. I would suggest creating a new model for the web api that have the stream as byte arrays.

public class PostedFile {
    public int ContentLength { get; set; }
    public string ContentType { get; set; }
    public string FileName { get; set; }
    public byte[] Data { get; set; }
}

public class WebApiModel {
    public DateTime SubmittedDate { get; set; }
    public string Comments { get; set; }
    public List<PostedFile> Files { get; set; }
}

the serializer would do better with the arrays than the stream.

Nkosi
  • 235,767
  • 35
  • 427
  • 472