How can I extend and add to the IFormFile Interface in .NET Core. Need to append data to the serialised array when submitting an ajax request

Abhilash Gopalakrishna

I need to upload a file using .net core.

I am using a multipart form and AJAX.

However I have a unique requirement. I need to be able to add data to the serialized array and then bind it to the controller through an ajax POST request and Model Binding.

I need to add an id, which i pass to the controller. Based on the id I decide to which row in a table I save the uploaded file details.

My Controller to which I am Posting:

 [HttpPost]
        public async Task<IActionResult> File(List<IFormFile> files)
        {
            long size = files.Sum(f => f.Length);


            var filePath = Path.GetTempFileName();


            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await formFile.CopyToAsync(stream);
                    }
                }
            }

            string fpath = filePath;

            var query = from d in db.TableA
                        where d.File == null && d.id == id // This is where I need to compare the ID
                        select d;


            foreach (TableA details in query)
            {
                details.File = filePath;
            }
            try
            {
                await db.SaveChangesAsync(); // await needed to hold execution
            }
            catch (Exception e)
            {
                Console.WriteLine(e);

            }


            return RedirectToAction("View");
        }

where d.File == null && d.id == id // This is where I need to compare the ID

Multi Part Form:

<form method="post" id="typea" enctype="multipart/form-data" asp-controller="Main" asp-action="File">
<label class="btn btn-info"> Upload your document <input type="file" name="files" onchange="this.form.submit()" hidden />
</label>
</form>

My Ajax call:

 $(document).ready(function () {
        $('#typea').click(function () {


            event.preventDefault();


            var $form = $(this);
            var serializedData = $form.serializeArray();
            serializedData.push({ name: "ID", value: "typea" });
            $.ajax({
                url: "Main/File",
                type: "POST",
                data: serializedData

            });

        });

My problem is this:

If i push the array I cannot count on IFormFile Interface for model binding.

Can I somehow extend the IFormFIle interface?

Or is there a way I can do it without using the IFormFile. I tried to write my own model referencing from the IFormFIle interface but could not.

public interface IFormFile
{
    string ContentType { get; }
    string ContentDisposition { get; }
    IHeaderDictionary Headers { get; }
    long Length { get; }
    string Name { get; }
    string FileName { get; }
    Stream OpenReadStream();
    void CopyTo(Stream target);
    Task CopyToAsync(Stream target, CancellationToken cancellationToken = null);
}

I could not use the methods of the interface, which is obvious. Pointers please :).

itminus
  1. You don't need to implements (extends) the IFormFile interface, a wrapper by composition is preferred over inheritance. Simply create a dummy POCO to hold the information :

    public class IFormFilesWrapper{
    
        public string Id {get;set;}  // you might change the type to Guid / int /e.t.c
    
        public IList<IFormFile> Files {get;set;}
    }
    

    and the action method will be :

    [HttpPost]
    public async Task<IActionResult> File(IFormFilesWrapper filesWrapper)
    {
        var id = filesWrapper.Id;  // here's the Id posted by client
    
        long size = filesWrapper.Files.Sum(f => f.Length);
    
        var filePath = Path.GetTempFileName();
    
        foreach (var formFile in filesWrapper.Files)
        {
            if (formFile.Length > 0)
            {
                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await formFile.CopyToAsync(stream);
                }
            }
        }
    
        // ...
    }
    
  2. As a side note, if I remember correctly, the $form.serializeArray() doesn't work well for multipart/form-data. So I use a plain FormData to generate the payload :

    $(document).ready(function () {
        $('#typea>button').click(function () {
    
            event.preventDefault();
    
            var form = document.querySelector("#typea");
            var formData = new FormData(form);
            formData.append("ID","typea");
    
            var xhr = new XMLHttpRequest();
            xhr.open("POST","Main/File");
            xhr.send(formData);
        });
    });
    

A screenshot :

enter image description here

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to add data to a form when submitting via a POST AJAX request?

IFormFile property in .NET Core ViewModel causing stalled AJAX Request

How can i extend downloading of personal data in ASP.NET Core Mvc?

How to display an array consisting of serialised data?

How can I convert String (which is actually Bitmap) to IFormFile in asp.net core 1.0 c#

Can I trust the .Length property on IFormFile in ASP.NET Core?

Json Serialisers vs .net serialised classes for JQuery AJAX result data

How can I extend this interface with Typescript

I need to add data into an Array

When using Stripe's PaymentRequestButton how can I change the label and total before submitting the token request?

How can I link two Java serialised objects back together?

How can I add a callback when a new thread is being created in ASP.NET Core?

How can I add different multiple row data in ASP.NET Core MVC?

how can i clear the text in the text box when the form is submitting through load() ajax function

How to convert array of objects to serialised?

How can I extend an existing interface when the definitions require an import statement?

With TypeScript, how can I extend an interface that can be one of multiple types?

How can I extend the Array class in Babel?

How Can I Extend ASP.NET Core 2.0's Roles to Handle Different Permissions at Different Locations?

Do I need an array with Core Data?

How can I add raw data body to an axios request?

Add serialised data to wp database from form of radio buttons via AJAX

How can I add a query in Ajax code with the parameter data passed?

How to use IFormFile as property when uploading file to a server using Asp.NET Core 3.1 framework?

How can I add a picked image into core data

How can I trigger beforeunload warning when refreshing but not when submitting

How can I extend a non generic interface into a generic one?

How can I extend an interface and override a property's type?

How can I extend a TypeScript interface and infer the arguments?