简体   繁体   中英

Partial View not updating on ajax post success function

I am currently trying to create a system that will display uploaded images(s) from a file input to a div in my view. (and have plans to add support for documents later)

The problem is that the partial view does not seem to be updating when I use an onchange function for the file input to pass the image(s) to my partial view that should be re-loaded into a div in my view and display the images.

I know that the partial view loads the first time, because of the onload function that alerts me when the div is loaded is doing nothing after the initial page load.

I know the request is being sent because when I try to perform a console.log or other actions inside the success function of the ajax call, they all work properly.

My view:

<div>
<h3>Attach File(s) (optional):</h3>
<form enctype="multipart/form-data">
    <input id="fileInput" onchange="addFile()" type="file" accept="image/png, image/gif, image/jpeg, .pdf, .doc" /> 
</form>
    <br />
    <br />
    <img width="750" style="display:none" id="UploadedImage" src="#" />
    <div id="fileDiv">
        <partial name="~/Views/Shared/_FilePreviewPartial.cshtml" />
    </div>
</div>

My javascript function:

function addFile() {

    var input = document.getElementById("fileInput");
    var files = input.files;
    var formData = new FormData();

    for (var i = 0; i != files.length; i++) {
        formData.append("files", files[i]);
    }

    $.ajax(
        {
            url: "/RODispositions/UpdateFilePreview/",
            data: formData,
            processData: false,
            contentType: false,
            type: "POST",
            success: function (data) {
                $("#fileDiv").html(data);
                console.log("posted");
            }
        }
    );
}

My partial view:

<body onload="console.log('refreshed file div')">
<div>
@foreach(var image in @Model.RODImages)
{
    <img width="750" id="UploadedImage" src="#" />
    <br />
    <a href="#">Remove</a>
}

@foreach(var document in @Model.RODDocuments)
{
    <a href="">Download file</a>
    <br />
    <a href="#">Remove</a>
}
</div>
</body>

My controller method:

    [HttpPost]
    public PartialViewResult UpdateFilePreviewAsync(ICollection<IFormFile> files)
    {
        var vm = new ViewModel()
        {
            RODImages = new List<byte[]>(),
            RODDocuments = new List<byte[]>()
        };

        foreach (var file in files)
        {
            if (file.Length > 0)
            {
                using (var ms = new MemoryStream())
                {
                    file.CopyTo(ms);
                    var fileBytes = ms.ToArray();
                    vm.RODImages.Append(fileBytes);
                }
            }
        }

        return PartialView("_FilePreviewPartial", vm);
    }

The partial is being loaded the first time that I load the page, but is not being loaded again after the ajax call. I have made similar functions that have loaded a PartialViewResult into a div with no issues before, but have no idea why this is not working. Bear in mind that I am still new to .NET programming, so any help and/or explanation would be appreciated.

Change the Action name UpdateFilePreviewAsync to UpdateFilePreview;

    [HttpPost]
    public IActionResult UpdateFilePreview(ICollection<IFormFile> files)
    {
        var vm = new ViewModel()
        {
            RODImages = new List<byte[]>(),
            RODDocuments = new List<byte[]>()
        };

        foreach (var file in files)
        {
            if (file.Length > 0)
            {
                using (var ms = new MemoryStream())
                {
                    file.CopyTo(ms);
                    var fileBytes = ms.ToArray();
                    vm.RODImages.Add(fileBytes);
                }
            }
        }

        return PartialView("_FilePreviewPartial", vm);

    }

After doing what LajosArpad suggested and attempting to update the div to display a string in the ajax success function instead of the partial view I was trying to load, the file div did update. Meaning that the issue was with the ActionResult being passed back to the ajax success function. After going back though my controller code I found the issue to be that I had been trying to add each image to the list with the List.Append function instead of the List.Add function and that was somehow messing with the data that was returned, and changing the List.Append to List.Add allowed the partial view to be loaded properly.

The partial is being loaded the first time that I load the page, but is not being loaded again after the ajax call.

Firstly, it should be vm.RODImages.Add(fileBytes); instead of .Append() .

Then, your partial view even does not set the image src by the byte array .

Besides, it seems you want to post multiple files, be sure add multiple attribute in your input like below:

<input id="fileInput" multiple  onchange="addFile()" type="file" accept="image/png, image/gif, image/jpeg, .pdf, .doc"/> 

Here is a simple demo:

[HttpPost]
public PartialViewResult UpdateFilePreviewAsync(ICollection<IFormFile> files)
{
    var vm = new ViewModel()
    {
        RODImages = new List<byte[]>(),
        RODDocuments = new List<byte[]>()
    };

    foreach (var file in files)
    {
        if (file.Length > 0)
        {
            using (var ms = new MemoryStream())
            {
                file.CopyTo(ms);
                var fileBytes = ms.ToArray();
                vm.RODImages.Add(fileBytes);
            }
        }
    }

    return PartialView("_FilePreviewPartial", vm);
}

Partial View:

@model ViewModel
<body onload="console.log('refreshed file div')">
<div>
@foreach(var image in @Model.RODImages)
{
                                           //modify here...
    <img width="750" id="UploadedImage" src="data:image/png;base64, @Convert.ToBase64String(image)" />           
    <br />
    <a href="#">Remove</a>
}

@foreach(var document in @Model.RODDocuments)
{
    <a href="">Download file</a>
    <br />
    <a href="#">Remove</a>
}
</div>
</body>

Note:

If your image format are all different , I think you need modify your ViewModel like below:

Model:

public class ViewModel
{
    public List<RODImages> RODImages { get; set; }
    public List<RODDocuments> RODDocuments { get; set; }
}
public class RODImages
{
    public byte[] RODImage { get; set; }
    public string Format { get; set; }
}
public class RODDocuments
{
    public byte[] RODDocument { get; set; }
    public string Format { get; set; }
}

Controller:

[HttpPost]
public PartialViewResult UpdateFilePreviewAsync(ICollection<IFormFile> files)
{
    var vm = new ViewModel()
    {
        RODImages = new List<RODImages>(),
        RODDocuments = new List<RODDocuments>()
    };

    foreach (var file in files)
    {
        if (file.Length > 0)
        {
            using (var ms = new MemoryStream())
            {
                file.CopyTo(ms);
                var fileBytes = ms.ToArray();
                vm.RODImages.Add(new RODImages() { RODImage= fileBytes ,Format=file.ContentType});
            }
        }
    }

    return PartialView("_FilePreviewPartial", vm);
}

Partial View:

@model ViewModel
<body onload="console.log('refreshed file div')">
<div>
@foreach(var image in @Model.RODImages)
{
                                             //modify here........
    <img width="750" id="UploadedImage" src="data:@image.Format;base64, @Convert.ToBase64String(image.RODImage)" />
    <br />
    <a href="#">Remove</a>
}

@foreach(var document in @Model.RODDocuments)
{
    <a href="">Download file</a>
    <br />
    <a href="#">Remove</a>
}
</div>
</body>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM