2016-09-03 10 views
0

Я пытаюсь создать простую CMS, которая позволяет автору загружать файлы (в частности, изображения, но тип файла на данный момент не очень важен).Передача имени файла на вид

Загрузка файла работает нормально. Однако я хочу предоставить возможность перечислить и впоследствии удалить файл (возможно, позже несколько файлов, но на данный момент один файл одновременно).

Я осмотрел сеть. Я вижу множество примеров, использующих EF для хранения местоположения файла в БД, потому что у них есть разрешения и роли и т. Д. В то время как это то, что мне может понадобиться в будущем, это не уровень сложности, который я готов добавить правильно Теперь.

Все, что я хочу, это просто нажать ссылку удаления (как будто вы удаляете запись в БД). Чтобы вызвать действие, которое вызывает просмотр подтверждения удаления. Затем на этом представлении нажмите кнопку удаления, чтобы фактически удалить файл и вернуть пользователя в список. Ниже мой код до сих пор:

Это было бы представление, в котором перечислены файлы:

@model IEnumerable<FileInfo> 

@{ 
    ViewBag.Title = "File List"; 
} 

<h2>Index</h2> 

<p> 
    @Html.ActionLink("Upload", "Upload") 
</p> 
<table class="table"> 
    <tr> 
     <th>File Name</th> 
     <th>Actions</th> 
    </tr> 

    @foreach (FileInfo file in Model) 
    { 
     <tr> 
      <td>@file.Name</td> 
      <td>@Html.ActionLink("Delete", "Delete", new { fileName = @file.Name })</td> 
     </tr> 
    } 
</table> 

я не буду показывать контроллер для этой точки зрения, как это относительно просто и не там, где я имею проблему (я думать). Я только показал это, чтобы вы могли видеть ссылку на удаление и сказать мне, что что-то не так.

Ниже удаления вид подтверждения:

@model FileInfo 

@{ 
    ViewBag.Title = "Delete"; 
} 

<h2>Delete</h2> 

<h3>Are you sure you want to delete this?</h3> 

<dl class="dl-horizontal"> 
    <dt> 
     @Html.DisplayNameFor(model => model.FullName) 
    </dt> 

    <dd> 
     @Html.DisplayFor(model => model.FullName) 
    </dd> 
</dl> 
@using (Html.BeginForm("Delete", "FileManagement", FormMethod.Post, new { enctype = "multipart/form-data" })) 
{ 
    @Html.AntiForgeryToken() 

    <div class="form-actions no-color"> 
     @Html.ActionLink("Back to list of views", "Index", null, new { @class = "btn btn-success" }) 
     &nbsp;|&nbsp; 
     @*@Html.ActionLink("Delete", "Delete", null, new { @class = "btn btn-danger" })*@ 
     <input type="submit" value="Delete file" formaction="Delete" formmethod="delete" class="btn btn-danger" /> 
    </div> 
} 

Ниже приведены два Удалять действия (GET и POST/DELETE)

// GET: FileManagement/Delete/filename 
    public ActionResult Delete() 
    { 
     return View(); 
    } 

    // POST: FileManagement/Delete/filename 
    [HttpDelete] 
    [ValidateAntiForgeryToken] 
    public ActionResult Delete(string fileName) 
    { 
     var path = Path.Combine(Server.MapPath("~/UserFiles"), fileName); 

     if (System.IO.File.Exists(path)) 
      System.IO.File.Delete(path); 
     else 
      return HttpNotFound(); 

     return RedirectToAction("Index"); 
    } 

Я не вид модели, как я не подключен к базе данных (пока). Файлы просто загружаются в папку ~/UserFiles/someFileName.ext, и полный путь получается путем добавления этого к server.mappath обычным способом.

Проблема, с которой я столкнулась, заключается в том, чтобы получить имя файла в окне подтверждения удаления, а также кнопку удаления, которая передала бы ее удалению для выполнения задания.

Спасибо за любую помощь.

+0

Ваша форма не размещать какие-либо значения - вы не имеете вход или значение маршрута для 'filename' поэтому значение из Параметр 'string fileName' всегда будет' null' (обратите внимание, что вам не нужно 'new {enctype =" multipart/form-data "}' - это необходимо только для загрузки файла на сервер) –

+0

Ваш метод GET не есть параметр для получения 'fileName' из' ActionLink() 'либо. И тогда он не передает модель в представление, поэтому его «null» (и вам действительно нужно отобразить подтверждение в основном представлении). –

+0

. Форма подтверждения удаления не показывает имя файла по какой-либо причине. Я учил, что получаю это из первоначального представления (списка), когда я нажал кнопку удаления там, но по какой-то причине он не перешел к форме подтверждения удаления. Будет ли перемещение формы в окне удаления выше имени поля и значения? Возможно, я должен поместить скрытый элемент управления в форму списка с именем файла и прочитать это каким-то образом в контроллере удаления? Или использовать viewbag/data? –

ответ

1

В вашем основном представлении (я предполагаю, что Index.cshtml) вы правильно генерируете строковое значение запроса для fileName, но метод GET не имеет параметра для его принятия. Он должен был бы быть

// GET: FileManagement/Delete/filename 
public ActionResult Delete(string fileName) 

и в этом случае вам необходимо будет инициализировать новый FileInfo класс, основанный на fileName и передать эту модель с точки зрения.

Следующая проблема заключается в том, что ваша форма на странице подтверждения не передает имя файла обратно методу POST, но это вызывает еще одну проблему, поскольку у вас не может быть метода GET и POST с тем же signatute, так что вы необходимо изменить название одного из методов, например

[HttpGet] 
public ActionResult ConfirmDelete(string fileName) 

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Delete(string fileName) 

и подтверждения удаления страницы, изменить форму

@using (Html.BeginForm("Delete", "FileManagement", new { fileName = Model.Name })) // enctype not required 
{ 
    @Html.AntiForgeryToken() 
    <input type="submit" value="Delete file" class="btn btn-danger" /> 
} 

Однако, вы можете значительно повысить производительность за счет создания формы в Index вид и вытеснение не инь диалога подтверждения (метод GET больше не требуется)

@foreach (FileInfo file in Model) 
{ 
    .... 
    @using(Html.BeginForm("Delete", "FileManagement", new { fileName = file.Name })) 
    { 
     @Html.AntiForgeryToken() 
     <input type="submit" value="delete" /> 
    } 
} 

и добавление сценария для отображения диалогового окна

$('form').submit(function() { 
    return conform("Are your sure .... "); 
}); 

, который будет отображать браузеры диалоговых Javascript подтверждения. Вы можете улучшить интерфейс с помощью JQuery плагин для диалога подтверждения (или реализовать свой собственный, как описаны в this article)


Вы должны также рассмотреть возможность использования Ajax для отправки формы (и в обратном вызове, удалите кнопку и связанную с ней строку таблицы). Типичная реализация может выглядеть

@foreach (FileInfo file in Model) 
{ 
    <tr> 
     <td>@file.Name</td> 
     <td> 
      <form class="deleteform"> 
       @Html.AntiForgeryToken() 
       <input type="hidden" name="fileName" value="@file.Name" /> 
       <input type="submit" value="delete" /> 
      </form> 
     </td> 
    </tr> 
} 

var url = '@Url.Action("Delete", "FileManagement")'; 
$('.deleteform').submit(function() { 
    var formData = $(this).serialize(); 
    var row = $(this).closest('tr'); 
    $.post(url, formData, function(response) { 
     if (response) { 
      row.remove(); 
     } else { 
      // Oops - display message? 
     } 
    }).fail(function (response) { 
     // Oops 
    }); 
    return false; // cancel the default submit 
}); 

и метод контроллера

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Delete(string fileName) 
{ 
    .... // delete the file 
    return Json(true); // indicate success 
    // or return Json(null); to indicate failure 
} 
+0

Еще раз спасибо Стивен за вашу помощь и ресурсы. –

+0

Я сделал большую часть того, что вы сказали, и это работает. Однако иногда я получаю исключение IOException, и я пытаюсь обработать его, установив ModelState.AddModelError в блок catch и добавив на страницу сводку проверки/.validationmessage. Но когда страница обновляется, сообщения не отображаются.Любые идеи, или это лучше задается как еще один вопрос? –

+0

Вам нужно будет задать новый вопрос, чтобы мы могли видеть весь используемый вами код (но если вы используете ajax для публикации, то вы можете сделать это легко в соответствии с разрешением на ответ) –

Смежные вопросы