You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET中Change事件下从View向Controller传递IFormFile模型值的问题及相关技术咨询

Let's break down your problems one by one and fix them step by step:

1. Fixing the null ViewModel issue in Controller

The main reason your DailySelectedProductViewModel is coming through as null is twofold: you're not correctly retrieving the ProductId from the UI, and you're sending a plain JavaScript object instead of properly structured FormData (required for file uploads in ASP.NET). Here's how to resolve this:

Step 1: Correctly fetch ProductId from the DOM

Your current code var product_Id = (this.ProductId); doesn't actually grab the ProductId value. Instead, pull it from the hidden input in the same list item as the file uploader:

// Get the parent list item containing the current upload component
var listItem = $(this).closest("li");
// Retrieve ProductId from the hidden input field
var product_Id = listItem.find("input[type='hidden'][name*='ProductId']").val();

Step 2: Properly construct and send FormData

File uploads require using FormData to package data correctly, and you need to match the keys in FormData to the property names in your ViewModel. Update your AJAX code like this:

$(".uploadFile").on('change', function () {
    console.log('new file uploaded');
    var listItem = $(this).closest("li");
    var file_data = $(this).find(".productImage").prop("files")[0];
    var files = event.target.files;
    
    // Update preview image
    $(this).find(".imageViewer").attr("src", window.URL.createObjectURL(files[0]));
    
    // Initialize FormData and append values matching ViewModel properties
    var form_data = new FormData();
    form_data.append("ProductId", product_Id);
    form_data.append("ProductImage", file_data);
    
    $.ajax({
        url: "/DailyMenuPlanner/AddPhoto",
        cache: false,
        contentType: false,
        processData: false,
        data: form_data, // Send FormData instead of a plain object
        type: 'post',
        success: function (result) {
            alert(result.success ? "success!" : "fail!");
        },
        error: function(xhr) {
            console.log("Error details:", xhr.responseText); // Add debug logging for issues
        }
    });
});

Step 3: Verify your ViewModel structure

Ensure your DailySelectedProductViewModel has public getters and setters (required for ASP.NET model binding):

public class DailySelectedProductViewModel
{
    public int ProductId { get; set; }
    public IFormFile ProductImage { get; set; }
    // Add other properties as needed
}

Note: You can remove the redundant asp-for-ProductId attribute from your file input in the HTML—asp-for="@Model.Products[i].ProductImage" already generates the correct name attribute for binding.

2. Converting IFormFile to a byte array

Your existing conversion code is valid, but we can refine it to add error handling and ensure proper resource disposal:

[HttpPost]
public async Task<JsonResult> AddPhoto(DailySelectedProductViewModel dataModel)
{
    // Validate input first
    if (dataModel.ProductImage == null || dataModel.ProductImage.Length == 0)
    {
        return Json(new { success = false, message = "No file was uploaded" });
    }

    byte[] imageAsArray;
    // Use using statements to ensure streams are disposed properly
    using (var memoryStream = new MemoryStream())
    {
        await dataModel.ProductImage.CopyToAsync(memoryStream);
        imageAsArray = memoryStream.ToArray();
    }

    // Use imageAsArray for storage or further processing here
    return Json(new { success = true, fileName = dataModel.ProductImage.FileName });
}

An alternative, more direct approach:

using (var fileStream = dataModel.ProductImage.OpenReadStream())
using (var memoryStream = new MemoryStream())
{
    await fileStream.CopyToAsync(memoryStream);
    imageAsArray = memoryStream.ToArray();
}

3. Storing file data in SQL Server

  • About the image type: While SQL Server's image type can technically store byte array data, it's deprecated (since SQL Server 2005). Microsoft strongly recommends using VARBINARY(MAX) instead—it's designed specifically for large binary data like images, documents, etc., and supports modern features.
  • Storing the byte array: You can directly save the byte array to a VARBINARY(MAX) column in your table. If using Entity Framework, your entity class would have a property like public byte[] ProductImageData { get; set; }, which automatically maps to the VARBINARY(MAX) column.

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 13:42:28