2

Versions: ASP.NET and Web Tools - 17.10.341.11210 C# Tools - 4.10.0-3.24312.19+ JQuery - 3.3.1.js JS - 2.8.3.js

I'm trying to pass an IFormFile and a string from a JSON file select and a string input.

The File Selection and string input both work (I've used alerts to confirm that both collect the right information)

When I send them together to my C# method, they both arrive null (even though they aren't from previous testing). My JavaScript and HTML code:

HTML:

<div class="text-center">
    <h1 class="display-4">Validation</h1>
    <p>
        <label for="string" style="margin: 5px">String Validation?</label>
        <br />
        <input type="email" id="string" name="string" value="[email protected]" style="margin:5px;">
        <br />
    </p>
</div>


<div class="text-center">
    <label for="fileSelection" style="margin: 5px">Please select which file you would like to validate.</label>
    <br />
    <span id="csvOnly" class="uploadErrorMsg">Only CSV files are able to be uploaded</span>
    <br />
    <input type="file" id="fileSelection" name="fileSelection" accept=".csv, text/csv" />
    <br />
    <button id="btnValidate" onclick="btnValidate()">Validate</button> <!--onclick="btnUpload_Click()" name="btnUpload" -->
    <br />
    <label id="lblError"></label>

</div>

Javascript:

function btnValidate() {
    input = document.getElementById('fileSelection');
    file = input.files[0];
    fileName = file.name;
    fileName = fileName.toUpperCase();
    
    //alert("file = " + file.name); //good

    var stringSelection = document.getElementById('string').value;
    //alert("string is = " + stringSelection); //good

    if (fileName.includes('CSV')) {
        //alert("string is = " + stringSelection); //good

        var data = new FormData();
        file = input.files[0];
        data.append("File", file);
        console.log(data);
        //alert("file = " + data.values);

        //var parameters = { file: data, inputString: stringSelection };
        //alert("parameters = " + parameters.inputString" " + parameters.file); //bad
        //alert("parameters = " + parameters.file.value); //good

        $.ajax({
            type: "POST",
            url: "@Url.Content("~/Validation/UploadFile")",
            dataType: 'json',
            contentType: false,
            processData: false,
            data: { file:data, inputString: stringSelection},
    //other things I've tried
    //JSON.stringify({ file: data, inputString: 'stringSelection' }),
    //'{ "file":' + data + ', "inputString": "stringSelection" }', 
    //JSON.stringify({ parameters }),
    //{parameters},
            
            success: function(data){
                return result;
            },
            error: function (xhr, status, error) {
                alert("error message " + error + " " + status);
            }
        });
    }
}

C# Code

public JsonResult UploadPayrollFile(IFormFile file, string stringSelection)
{
    //do stuff
    //I setup a breakpoint here to check to see what information is coming in, both parameters are coming in null. 
    //When I adjust the method to check for a singular parameter, they work (separately)
}

I walked through this question here and those options did not work for me.

The program actually runs. It doesn't throw errors.

16
  • 1
    Have you looked at your Network tab to see what's being sent? What steps have you take to debug this?
    – mykaf
    Commented Jul 17, 2024 at 16:51
  • What asp.net / asp.net core version are you using? And can you please edit you question to share a sample raw request?
    – dbc
    Commented Jul 17, 2024 at 17:03
  • @mykaf - i have and it's doing the same thing as above. singularly, it's passing the information. but when i try to pass the two parameters, it's null. Commented Jul 17, 2024 at 17:35
  • 1
    Please add the relevant html also. When/how is the JS function called?
    – mykaf
    Commented Jul 17, 2024 at 17:46
  • 1
    Okay, the answer is ready. Let me know if it's helping you. Commented Jul 24, 2024 at 19:06

3 Answers 3

4
+25

METHOD 1 - Sending file without using JSON:

If the C# method "UploadPayrollFile" is in the "Validation" controller, to solve the problem, without changing the C# code, it is enough to make the following changes in the JavaScript code (Without using JSON - In the continuation of the answer, I will also explain how to transfer data using JSON):

1- Inside the Ajax call, modify the "url:" line as follows:

url: "@Url.Content("~/Validation/UploadPayrollFile")",

2- Inside the Ajax call, modify the "data:" line as follows:

data: data,

3- After "data.append("File", file);" Add the following line:

data.append("stringSelection", stringSelection);

That is, the JavaScript code should be as follows:

function btnValidate() {
    input = document.getElementById('fileSelection');
    file = input.files[0];
    fileName = file.name.toUpperCase();

    var stringSelection = document.getElementById('string').value;

    if (fileName.endsWith('.CSV')) {
        var data = new FormData();
        file = input.files[0];
        data.append("File", file);
        data.append("stringSelection", stringSelection);
        console.log(data);

        $.ajax({
            type: "POST",
            url: "@Url.Content("~/Validation/UploadPayrollFile")",
            //dataType: 'json',
            contentType: false,
            processData: false,
            data: data,
        
            success: function(data){
                return result;
            },
            error: function (xhr, status, error) {
                alert("error message " + error + " " + status);
            }
        });
    }
}

Tip 1:

In order to execute the code, the presence of "dataType: 'json'" does not cause problems in the Ajax call, but it is extra and it is better to remove it.

Tip 2:

It is better to use the following code instead of "if (fileName.includes('CSV'))". Because if, for example, the file type is not CSV, but CSV is used in its name, it may accept the file incorrectly.

if (fileName.endsWith('.CSV'))

METHOD 2 - Sending file using JSON:

If I want to give an exact answer to the question "Passing two parameters (IFormFile and a string) with JSON to C#", I should say:

Short answer:

It is not easy to send the uploaded file in JSON format to the .NET Core C# project. Please see the following links:

Is it possible to send a list of files and a whole json object in a FormData object to a ASP.NET CORE MVC Controller

Is it impossible to mix fileupload and raw json in asp core web api?

Full answer:

If we want to do with JSON, we need to send the file name, file size and file content in separate fields.

Service settings for .NET Core project for using JSON:

1- Install the "Microsoft.AspNetCore.Mvc.NewtonsoftJson" NuGet package with the appropriate version:

For example, if you are using .NET 6, version 6 of the package will work.

2- In the "Program.cs" file, add the following line:

builder.Services.AddControllersWithViews().AddNewtonsoftJson();

In the "Model" folder on the server side, add the following code:

public class FormInfo
{
    public string InputString { get; set; } = "";
    public string FileName { get; set; } = "";
    public int FileSize { get; set; } = 0;
    public byte[]? FileContent { get; set; } = null;
}

In the "Validation" controller on the server side, the method will be, for example, as follows:

[HttpPost]
public JsonResult UploadPayrollFile([FromBody] FormInfo data)
{
    //do stuff

    return new JsonResult(new { ErrorMessage = ""});
}

The JavaScript code will be something like the following code:

function btnValidate() {
    input = document.getElementById('fileSelection');
    file = input.files[0];
    fileName = file.name.toUpperCase();
   
    var stringSelection = document.getElementById('string').value;
    if (fileName.includes('CSV')) {
        file = input.files[0];
        // We need to read the content of the uploaded file as a stream and convert it to a byte array. For example, suppose the content is something like the following:
        var FileContent = [5, 54, 87];
        var data = { "InputString": stringSelection, "FileName":  file.name, "FileSize": file.size, "FileContent": FileContent };

        $.ajax({
            type: "POST",
            url: "@Url.Content("~/Validation/UploadPayrollFile")",
            contentType: "application/json",
            dataType: 'json',
            data:  JSON.stringify(data),
        
            success: function(data){
                // Ajax call is OK, but processing the file on the server side may face problems
                if (!data.errorMessage)
                    alert("Is done!");
                else
                    alert("Server-side error: " + data.errorMessage);
            },
            error: function (xhr, status, error) {
                alert("error message " + error + " " + status);
            }
        });
    }
}
0
1

As per your code, you are pass body as JSON but you have to pass as FormData in AJAX call.

Change your Javascript code & Try this:

var data = new FormData();
data.append("file", input.files[0]);

$.ajax({
    type: "POST",
    mimeType: "multipart/form-data",
    url: "@Url.Content("~/Validation/UploadFile")" + "?stringSelection=" + document.getElementById('string').value,
    contentType: false,
    processData: false,
    data: data,     
    success: function(data){
        return result;
    },
    error: function (xhr, status, error) {
        alert("error message " + error + " " + status);
    }
});

Still not work, Then Add FromForm Attribute to you C# code :

public JsonResult UploadPayrollFile([FromForm] IFormFile file, string stringSelection)
{
    //do stuff
}
3
  • Your AJAX Url will be looks like "Validation/UploadFile?stringSelection=some_text" Commented Jul 26, 2024 at 9:58
  • You can also append stringSelection to the FormData instead of using querystring.
    – Poul Bak
    Commented Jul 26, 2024 at 10:41
  • @PoulBak, Thanks for your suggestion, I will try this & verify it. Commented Jul 26, 2024 at 10:47
0

Ensure name parameter for the file input in the UI layer matches, C# variable name for the IFormFile in controller. Currently, it is called as "fileSelection" in UI layer and "file" in controller.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.