Here is my approach for deleting stuff with ASP.NET MVC 2.

As mentioned here, the default Delete view isn't quite correct. What I wanted is a deletion solution that:

  • is powered with Ajax for a better user experience
    • we will make a HTTP DELETE on /Items/Delete/12 to delete item #12
  • is accessible for non-JS enabled browsers (we need a confirmation form)
    • when confirmed, the deletion occurs with HTTP POST on /Items/Delete/12 to delete item #12

With those specifications, we can write the following (wrong) controller code:

  1. public class ItemsController : Controller
  2. {
  3. [HttpGet]
  4. public ActionResult Delete(int id) {
  5.  
  6. ViewData.Model = new ConfirmFormModel {
  7. Id = id.ToString(),
  8. BackAction = "Index"
  9. };
  10.  
  11. return View();
  12. }
  13.  
  14. [HttpDelete]
  15. [HttpPost]
  16. public ActionResult Delete(ConfirmFormModel model) {
  17. ViewData.Model = model;
  18.  
  19. // business action here
  20.  
  21. // if we use Ajax, backaction will be null and have
  22. // to prevent a secondary GET request
  23. return model.BackAction == null ? null : RedirectToAction(model.BackAction);
  24. }
  25.  
  26. }
  1. /// <summary>
  2. /// Simple model class to store the Id for a confirmation form.
  3. /// </summary>
  4. public class ConfirmFormModel {
  5.  
  6. /// <summary>
  7. /// Item's ID
  8. /// </summary>
  9. public string Id { get; set; }
  10.  
  11. /// <summary>
  12. /// Confirmation message.
  13. /// </summary>
  14. public string Message { get; set; }
  15.  
  16. /// <summary>
  17. /// The controller action to redirect to if the user wants to cancel.
  18. /// </summary>
  19. public string BackAction { get; set; }
  20.  
  21. }

A created a little model class to store the confirmation message and the item ID; this way I can use it all over my project. You can notice the [HttpDelete] and [HttpPost] on the second Delete() method. Obviously this won't work as asked here. You have to create your own attribute.

So I created the related views with (not-included) javascript. Here is the index:

  1. <!-- Index page -->
  2.  
  3. <ul>
  4. <% for (int i = 0; i < 10; i++) { %>
  5. <li><%= Html.ActionLink("Delete #" + i, "Delete", new { id = i }, new { @class = "deleteLink" })%></li>
  6. <% } %>
  7. </ul>

The delete page where I include a generic partial-view:

  1. <!-- Delete page -->
  2.  
  3. <h3>Confirmation</h3>
  4.  
  5. <% Html.RenderPartial("ConfirmForm", Model); %>

Finally, the partial view:

  1. <!-- Delete form in a partial view -->
  2.  
  3. <% Html.BeginForm(); %>
  4. <fieldset>
  5. <legend>Confirmation</legend>
  6.  
  7. <p><%= Html.Encode(Model.Message ?? "Are you sure you want to delete this?")%></p>
  8.  
  9. <p>
  10. <%= Html.HiddenFor(m => m.Id) %>
  11. <%= Html.HiddenFor(m => m.BackAction) %>
  12. <%= Html.ActionLink("Cancel", Model.BackAction ?? "Index") %>
  13. <input type="submit" name="Continue" value="Continue" />
  14. </p>
  15. </fieldset>
  16. <% Html.EndForm(); %>

Now we have a working solution to confirm some action on a website. Sources attached...