Элемент управления Kendo Upload удалить событие не имеет ответа

У меня есть контроль загрузки кендо, как это:

@(Html.Kendo().Upload()
    .Name("attachments")
    .Async(a => a
        .Save("UploadAsync", "Intel")
        .Remove("RemoveAsync", "Intel")
        .AutoUpload(true)
    )
    .Events(e => e
        .Success("onSuccessfulUpload")
        .Remove("onRemoveFile")
    )
    .Validation(v => v.AllowedExtensions(exts))
)

В контроллере его метод Save выглядит следующим образом:

public ActionResult UploadAsync(IEnumerable<HttpPostedFileBase> attachments)
{
    string filename;
    // ... do things ...
    return Json(new { ImageName = filename }, "text/plain");
}

где переменная filename присваивается значение.

Его метод Remove в контроллере выглядит очень похоже:

public ActionResult RemoveAsync(string[] fileNames)
{
    string filename;
    // ... do things ...
    return Json(new { ImageName = filename }, "text/plain");
}

Я проверил, что оба метода контроллера вызваны правильно и переменная filename назначается в обоих случаях.

Загрузка работает, как ожидалось, и событие Success также работает, как и ожидалось. (Предупреждение просто для тестирования.)

function onSuccessfulUpload(e) {
    alert(e.response.ImageName);
}

Вопрос приходит при удалении файла.

Когда я доберусь до события Удалить, e не имеет .response, Она имеет e.files а также e.sender, но нет ответа.

function onRemoveFile(e) {
    alert(e.response);                    // undefined!
    alert(JSON.stringify(e.files));       // works, but does not have what I need
}

Как я могу получить доступ к тому, что RemoveAsync метод возвращает?

2 ответа

Решение

Через некоторое время ковыряясь, я нашел ответ.

Ключ лежал в порядке событий. Моим первым предположением было то, что событие Success было вызвано после успешной загрузки, а событие Remove было вызвано после успешного (?) Удаления.

Фактический порядок событий:

js onUpload> Controller.UploadAsync ()> js onSuccess

js onRemoveFile> Controller.RemoveAsync> js onSuccess

Я создал два параллельных массива в javascript для представления файлов, загруженных в клиентские файлы e.files, которые содержат идентификаторы uid для каждого файла и имена файлов, созданные методом контроллера на стороне сервера (который переименовывает файлы).

var fileUids = [];
var fileSaveNames = [];

Я изменил onSuccessfulUpload Функция этого, когда я обнаружил, что есть операция e.operation, которая определяет, какая операция была успешной:

function onSuccess(e) {
    if (e.operation == "upload") {
        var filename = e.response.ImageName;
        var uid = e.files[0].uid;

        fileUids.push(uid);
        fileSaveNames.push(filename)
        // ...
    }
    else if (e.operation == "remove") {
        var uid = e.files[0].uid;
        var saveIdx = fileUids.indexOf(uid);

        fileSaveNames.splice(saveIdx, 1);
        fileUids.splice(saveIdx, 1);
        // ...
    }
}

Затем я обновил removeFile Функция, которую я теперь знал, была вызвана до метода в контроллере.

function removeFile(e) {

    var uid = e.files[0].uid;
    var idx = fileUids.indexOf(uid);
    e.data = { fileToRemove: fileSaveNames[idx] };
}

Назначение e.data было из-за этого потока, который имеет следующую информацию:

Решение: Все, что нужно, это определить функцию для события загрузки и изменить полезную нагрузку "данные".

Добавьте функцию загрузки JS, чтобы добавить параметр "codeID" в моем случае.

$("#files").kendoUpload({
    [...]
    upload: function (e) {
        e.data = { codeID: $("#id").val() };
    }
});

Теперь на контроллере добавьте параметр и все.

[HttpPost]
public ActionResult Save(IEnumerable<HttpPostedFileBase> files, Guid codeID) { }

Вместо того, чтобы быть в событии Upload, мое находится в событии Remove.

Я выбрал имя параметра fileToRemove и новый RemoveAsync Метод в контроллере таков:

public ActionResult RemoveAsync(string[] fileNames, string fileToRemove)
{
    string returnName = "";

    if (!string.IsNullOrWhiteSpace(fileToRemove))
    {
        // ... do things ...
    }

    return Json(new { ImageName = returnName }, "text/plain");
}

Похоже, что событие удаления не предоставляет такого рода данные, поэтому я вижу только обходной путь для решения этой проблемы.

Вы можете попытаться поместить имя результата в заголовки, и вы сможете прочитать результат:

// Controller
Response.AddHeader("ImageName", imageName); // before Json(...)

// View/JS
alert(e.headers['ImageName']);

Я не проверял это, и я вижу риск того, что remove событие не читает асинхронный ответ, это объясняет, почему response объект недоступен

В этом случае вы можете попытаться использовать следующий обходной путь: не вызывайте какой-либо URL-адрес при удалении (или не используйте какое-либо действие без какого-либо тела, просто результат) и внутри обратного вызова события выполните RemoveAsync сам.

// View/JS
function onRemoveFile(e) {
    $.post('@Html.Url("RemoveAsync", "Intel")', e.files, function(response) {
        alert(response);
    });
}

Это не красиво, но оно должно работать и обеспечивать результаты, которые вам нужны.

Другие вопросы по тегам