Creating a Delete link with MVC using POST to avoid security issues

It is fairly common to have a list of records with a hyperlink to delete a record.  The problem here is that with MVC the hyperlink will use a GET request to delete a record.  This is a fairly big security issue as anybody can browse to the URL and delete a record from your system.  In this post I’ll explain how you can use the Ajax helpers to create a hyperlink that will call your delete method without using GET.

Stephen Walther has a great post here where he explains the issue and gives a couple of different solutions; one using hand written Ajax and the other without using Ajax.  There is no point in reiterating what he has to say so it’s definately worth a read.  Here I am going to use the Ajax helpers to perform the same functionality, which minimises the code required.

I have a view that renders a table that looks like this:

Here is the Delete method in my controller:

[HttpDelete]
public ActionResult Delete(int id)
{
    Student student = context.Student.FirstOrDefault(s => s.ID.Equals(id));
    if (student != null)
    {
        context.DeleteObject(student);
        context.SaveChanges();
    }

    return RedirectToAction("Index");
}

In this method I am using the Entity Framework to delete a record from my database.  The problem with this method using the GET verb would be that anybody could navigate to http://www.mydomain.com/Student/Delete/1 and it would delete the record from my database. We definately don’t want this. There would also be a chance that a search engine bot could access the method, again deleting data.

You can see that I’ve decorated the method with the HttpDelete attribute. As Stephen states in his post, HTML only supports GET and POST, but as we’re using Ajax, which uses the XmlHttpRequest object we can use any of the available verbs, so delete is available.

To render my delete link on the form I am using the Ajax.ActionLink helper method:

<%= Ajax.ActionLink("Delete", "Delete", new { id = student.ID },
    new AjaxOptions()
    {
        HttpMethod="Delete",
        Confirm="Are you sure you want to delete this student?",
        OnComplete = "function() { $(this).parent().parent().remove() }"
    }) %>

The helper method is very similar to the Html.ActionLink method, except it will use Ajax to perform the request. The first three parameters are straight forward; the link text, the action name and the route values. The fourth parameter is an instance of AjaxOptions.

I have set three of the properties, the first being the HttpMethod which is set to delete.  This allows the request to be made to my Delete method which is decorated with the HttpDelete attribute.  I have also set the Confirm property which displays a JavaScript confirm dialog before making the request.  Lastly I’ve set the OnComplete property which is some client script that will be run once tha Ajax request has completed.  In this instance I am using jQuery to remove the row from the table.

Using this approach is a fairly simple way to use hyperlinks to delete data without using a GET request therefore improving your site’s security. Of course you may not want your site to be dependant on JavaScript in which case you can use the second approach detailed in Stephen’s post.

Posted on by Joe in Ajax, jQuery, MVC

6 Responses to Creating a Delete link with MVC using POST to avoid security issues

  1. TheCloudlessSky

    Did you even test the javascript OnComplete? It doesn’t work at all for me with the closure…

  2. Indulis

    I changed the OnComplete like this:
    OnComplete = “$(‘#item_” + @student.Id + “‘).remove();”

    And add id value to table row:

  3. Indulis

    id=’@(“item_” + item.Id)’

  4. Joe

    Yeah I tested it, it worked fine. Is you delete link in a table cell like the screenshot?

  5. Sean

    Is it possible to use your delete method above and have it work with the validateantiforgerytoken? If not, is there a way to do so without adding more jQuery? I’m just trying to minimize the amount of jQuery I have to add. Thanks.

  6. mark baer

    what about handling an error from the delete method in the controller? I like the ajax way of calling this delete, but is there an “onFailure” method or something where I can handle an error from the server??? Thanks.

Add a Comment