views:

86

answers:

2

I have a table with records that has delete links. Basically I followed the NerdDinner tutorial for that part in MVC. But I don't want to have the confirm view, I'd rather have a confirm dialog, and then if confirmed let the HttPost action method delete the record directly.

I have something working, but being new to both MVC and jQuery, I'm not sure if I'm doing it right.

Here's the jQuery:

    $(function () {
        $('.delete').click(function () {
            var answer = confirm('Do you want to delete this record?');
            if (answer) {
                $.post(this.href, function () {
                    window.location.reload(); //Callback
                });
                return false;
            }
            return false;
        });
    });

And the delete actionlink:

<%: Html.ActionLink("Delete", "Delete", new { id = user.UserID }, new { @class = "delete" })%>

And finally, the delete action method:

    [HttpPost]
    public ActionResult Delete(int id)
    {
        _db = new UsersEntities();
        try
        {
            //First delete the dependency relationship:
            DeleteUserVisits(id);
            //Then delete the user object itself:
            DeleteUser(id);
        }
        catch (Exception)
        {
            return View("NotFound");
        }

        return RedirectToAction("Index");
    }

Now, I have a few questions about this:

  1. I found the function for making the link POST instead of GET on the internet: `$.post(this.href); return false; And I'm not sure what the "return false" part does. I tried to modify it for my needs with a callback and so on, and kept the return part without knowing what it's for.

  2. Secondly, the action method has the HttpPost attribute, but I have also read somewhere that you can use a delete verb. Should you? And what about the RedirectToAction? The purpose of that was originally to refresh the page, but that didn't work, so I added the window.location.reload instead in a callback in the jQuery. Any thoughts?

  3. The Delete action method calls a couple of helper methods because it seems with the Entity Framework that I use for data, I can't just delete an record if it has relationship dependencies. I had to first delete the relationships and then the "User" record itself. That works fine, but I would have thought it would be possible to just delete a record and all the relationships would be automatically deleted...?

  4. I know you're not supposed to just delete with links directly because crawlers etc could accidentally be deleting records. But with the jQuery, are there any security issues with this? Crawlers couldn't do that when there is a jQuery check in between, right?

Any clarifications would be greatly appreciated!

+1  A: 

There you go, with full code :

http://haacked.com/archive/2009/01/30/delete-link-with-downlevel-support.aspx

Or just the html helper :

public static string DeleteLink(this HtmlHelper html, string linkText, string routeName, object routeValues) {
    var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
    string url = urlHelper.RouteUrl(routeName, routeValues);

    string format = @"<form method=""post"" action=""{0}"" class=""delete-link"">
    <input type=""submit"" value=""{1}"" />
    {2}
    </form>";

    string form = string.Format(format, html.AttributeEncode(url), html.AttributeEncode(linkText), html.AntiForgeryToken());

    return form + html.RouteLink(linkText, routeName, routeValues, new { @class = "delete-link", style = "display:none;" });
}

For your questions :

  1. When you do a return false at the end of a javascript click handler on a link, the browser executes the javascript but doesn't follow the link, because of the return false.

  2. For (maximum) cross browser compatibility, you shouldn't use the DELETE verb.

  3. I don't know EF well enough, but doesn't it provide mapping configuration for cascading delete ?

  4. HTTP GET should only be used to get information, for example, provide parameters for a search. Crawlers usually don't care about javascript, so they will blindly follow you links. If it is http://mysite/delete/everything, then, bad for you, if you hadn't the [HttpPost] on you controller action

mathieu
+1  A: 
  1. The return false statement serves the same purpose as e.preventDefault() in this case. By returning false JavaScript is preventing the browser from executing the link's default click handler.

  2. The DELETE verb is for RESTful web services, it is most likely not what you want in this situation because not all browsers fully implement it. Read more about them here: Creating a RESTful Web Service Using ASP.Net MVC

  3. The deletion rules for child entities depend on the entity OnDelete/OnUpdate rules in the context definition and also on foreign key constraints in the database. You can learn more about foreign key constraints here.

  4. A crawler will not be able to activate your delete link in this fashion because you have specified the delete action be issued via a POST. If the delete were a GET then it would be a concern. Still, it's not wise to keep links that directly modify your content on front-facing pages that do not require authentication as a human could most certainly exploit the process.

Nathan Taylor
Thanks! But regarding the deletion rules: how do I set them? Googling on it I understand I should "set cascade delete" in the database too. But I can't find anything about how to do that. All I know is "Enforce foreign key constraints" is set to yes in the relationships.
Anders Svensson
It will depend on your database engine, but here's some examples of how to define Foreign Key constraints: http://www.1keydata.com/sql/sql-foreign-key.html
Nathan Taylor