-1

I want to upload files and post json data at the same using asp.net web api, i am not able to figure out how to code for controller to receive json data and file request also not able to figure out how to do setting in postman for testing the same.

public async Task<JObject> Save(Validate val)
{
}
  • 1
    Have you got *any* code to show for your attempts? – Caius Jard Oct 22 '20 at 09:22
  • currently json data is getting posted successfully i want to send file at the same time json data. – Shubham Angne Oct 22 '20 at 09:24
  • Probably easiest for the device sending the json to read the file and send it in the json too. Next easiest is to put a same ID in both and make two requests, and reassociate them on the server side with the ID - we use this to good effect to send messages with attachments; the message shows immediately, and the attachment completes later – Caius Jard Oct 22 '20 at 09:33
  • we are avoiding file to base64 because length will get increased depends on file size – Shubham Angne Oct 22 '20 at 09:38
  • If you want to upload the file along with other data from form to server, you can not use JSON format. You need to use form collection. – Chetan Oct 22 '20 at 09:45
  • @Chetan Ranpariya sir, not from form but from android/ios app buit using flutter, middleware is API – Shubham Angne Oct 22 '20 at 10:04
  • In any case, the app is a client and API is hosted on server, if you want to submit the File from client to server it can not be done via JSON Payload. – Chetan Oct 22 '20 at 10:07
  • @ChetanRanpariya *If you want to upload the file along with other data from form to server, you can not use JSON format* - did you just claim that it's impossible to transmit the contents of a file from client to server using JSON? – Caius Jard Oct 22 '20 at 14:55
  • @CaiusJard I have tried using json but never succeeded. Tried from both angular and regular asp.net mvc client. So based in my experience it can not be done. But I am ready to know and learn how it is possible with Json. – Chetan Oct 23 '20 at 01:05
  • https://stackoverflow.com/questions/45264447/is-it-possible-to-attach-file-in-post-json and https://stackoverflow.com/questions/1443158/binary-data-in-json-string-something-better-than-base64 and https://dotnetcoretutorials.com/2018/07/21/uploading-images-in-a-pure-json-api/ ... – Caius Jard Oct 23 '20 at 04:28
  • Oh... there are more than one approaches to upload file via json. Thanks @CaiusJard for sharing this... – Chetan Oct 23 '20 at 23:58
  • why we avoided converting into json because we have to upload more than 5 image files onclick event of Android/IOS app button, base64 string will be much longer. especially if someone is using high end smartphones. – Shubham Angne Oct 25 '20 at 13:56

1 Answers1

1

Uploading a file from web form to server requires a different approach specially when you want to upload file with other model data.

Files selected on the client can not be submitted as JSON to the server. So we need to submit the form as a Collection to the server. We also can not use application\json as content-type.

Consider following example. The example is demonstrated with ASP.NET MVC application example.

First thing you need to do is add the File object as part of the model class.

public class ClientDocument
{
    public int Id {get;set;}
    public int ClientId {get;set;}
    public string Title {get;set;}
    // Below property is used for getting file from client to the server.
    public IFormFile File {get;set;}
}

Then you need to create a form in the View. Assume that the view has Model type set to the above class.

<form id="someForm" method="post">
    @Html.HiddenFor(m => m.ClientId)
    <table>
        <tr>
            <td>
                @Html.LabelFor(m => m.Title)
            </td>
            <td>
                @Html.TextFor(m => m.Title)
            </td>
       </tr>
       <tr>
           <td>
               @Html.LabelFor(m => m.File)
           </td>
           <td>
               //Following line of code will render file control, where user can select file from the local machine.
               @Html.TextBoxFor(m => m.File, new { Type = "file" })
           </td>
       </tr>
       <tr>
          <td colspan="2">
              <button type="button" onclick="SubmitForm();">Submit</button>
          </td>
       </tr>
    </table>
</form>

Following is the JavaScript code for submitting the form. SubmitForm function in the JavaScript will convert the form to a FormData object.

FormData is a JavaScript object which represents data as a colleciton of Key/value pairs. Once the FormData object is created, we will post it to the server. As I mentioned above we can not use application\json content-type, we need to use multipart/form-data as encodingtype of the payload.

<script>
    function SubmitForm() {
        if ($("#someForm").valid()) {
             var form = $("#someForm")[0];
             var data = new FormData(form);
             
             $.ajax({
                type: "POST",
                enctype: 'multipart/form-data',
                url: "http://www.somedomain.com/api/ClientDocument/Save",
                data: data,
                processData: false,
                contentType: false,
                cache: false,
                beforeSend: function () {
                    // show waiting icon.
                },
                success: function (data) {
                    //Hiding waiting icon;
                    //Display the response in the UI.
                },
                error: function (xhr, status, errorThrown) {
                    console.log('ERROR : ' + xhr.responseText);
                }
            });
        }
    }
</script>

Now at the server end the controller action would look like following.

public IActionResult Save(ClientDocument model)
{
        try
        {
            //Access File Property to save it on server or upload to some storage
            var fileObject = model.File;
            var tartgetLocation = "D:\\ClientDocuments\\" + fileObject.FileName;
            
             using (var stream = new FileStream(tartgetLocation , FileMode.Create))
            {
                fileObject.CopyTo(stream);
            }
            
            // Write code to save information to database.
        }
        catch (Exception ex)
        {
            //Handle Exception
            return Json(new {Status= "Failed"});
        }

        return Json( new {Status= "Success"});
    }

I know that this is not the exact answer you might be looking for. But this should give you an idea about how to approach the problem and apply the same technique if applicable in your use case.

Chetan
  • 6,711
  • 3
  • 22
  • 32