Элемент управления 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);
});
}
Это не красиво, но оно должно работать и обеспечивать результаты, которые вам нужны.