在MVC中删除“删除”post方法中的内容(EF 4.1)

时间:2012-02-28 15:51:04

标签: asp.net-mvc asp.net-mvc-3 entity-framework entity-framework-4

遵循此示例.. http://msdn.microsoft.com/en-us/data/gg685489

我遇到了删除功能的问题。

[HttpPost]
public ActionResult Delete(int id, Blog blog)
{
    try
    {
        using (var db = new BlogDataEntities())
        {
            //Having issue here.. as soon as the next line is run in debug
            //mode .. it goes to catch.. and returns a view with null values.

            db.Entry(blog).State = System.Data.EntityState.Deleted;
            db.SaveChanges();
        }
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

在我检查的参数'blog'中没有得到需要删除的实际博客模型。所有其他方法都可以正常工作(编辑,删除(获取)..等等.. 但删除帖子失败。我错过了什么吗?提前感谢您的帮助。

编辑:

查看代码

@model DBFirstMVC.Models.Blog

@{
 ViewBag.Title = "Delete";
 }

  <h2>Delete</h2>

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

<div class="display-label">Title</div>
<div class="display-field">@Model.Title</div>

<div class="display-label">BloggerName</div>
<div class="display-field">@Model.BloggerName</div>
 </fieldset>
@using (Html.BeginForm()) {
  <p>
    <input type="submit" value="Delete" /> |
    @Html.ActionLink("Back to List", "Index")
  </p>
 }

编辑2: 非剃刀代码:

<% using (Html.BeginForm()) { %>
<p>
    <input type="submit" value="Delete" /> |
    <%: Html.ActionLink("Back to List", "Index") %>
</p>
<% } %>

编辑3 :(我在aspx中尝试过)

<% using (Html.BeginForm()) { %>
<p>

    <%=Html.DisplayForModel();%> //Tried Html.EditorForModel also..
    <input type="submit" value="Delete" /> |
    <%: Html.ActionLink("Back to List", "Index") %>
</p>
<% } %>

最终编辑(更正解决方案)

@model DBFirstMVC.Models.Blog

@{
 ViewBag.Title = "Delete";
}

<h2>Delete</h2>

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

@using (Html.BeginForm()) {
 <p>
<fieldset>
<legend>Blog</legend>

<div class="display-label">Title</div>
<div class="display-field">@Model.Title</div>

<div class="display-label">BloggerName</div>
<div class="display-field">@Model.BloggerName</div>

  <input type="submit" value="Delete" /> |
@Html.ActionLink("Back to List", "Index")
</fieldset>
</p>
}

4 个答案:

答案 0 :(得分:6)

上下文可能没有您博客的条目,因为它没有附加到上下文。

您可能需要首先检索博客,然后使用Entry方法将其标记为已删除:

[HttpPost]
public ActionResult Delete(int id, Blog blog)
{
    try
    {
        using (var db = new BlogDataEntities())
        {
            // retrieve the blog from the database
            var realBlog = db.Blogs.Find(blog.Id);

           // nothing to do here, just redirect
           if( realBlog == null )
                return RedirectToAction("Index");

          // since you have the entity just do this instead:
          db.Blogs.Remove(realBlog);
          db.SaveChanges();
        } 

        return RedirectToAction("Index");
    }
    catch( Exception )
    {
        return View();
    }
}

我不同意将您的实体用作模型的想法。您应该使用View Models。

修改

由于您现在说博客没有通过,请尝试以下方法:

@model Blog

@using ( Html.BeginForm() )
{
    @Html.EditorForModel()

    <input type="submit" value="Delete" />
}

您实际上并没有给模型绑定器提供构建模型所需的任何细节。

答案 1 :(得分:1)

是否可以尝试以下方法:

[HttpPost]
public ActionResult Delete(Blog deletedBlog)
{
    try
    {
        using (var db = new BlogDataEntities())
        {
            // get blog entry from db context!!
            Blog blog = db.Blogs.Find(deletedBlog.Id);
            //Having issue here.. as soon as the next line is run in debug
            //mode .. it goes to catch.. and returns a view with null values.

            db.Entry(blog).State = System.Data.EntityState.Deleted;
            db.SaveChanges();
        }
        return RedirectToAction("Index");
    }
    catch(Exception e)
    {
        // should catch more specific exception
        // but catching 'e' should be a start
        return View();
    }
}

[更新] - 从视图中传入您的Blog模型,因为Dismissile说,您应该真正使用视图模型,而不是实体模型。

此外,您应该捕获内部异常消息并检查以获取更多线索。

答案 2 :(得分:1)

blog操作中的Delete参数最有可能为空,因为您只发布博客的ID,而不是整个博客对象。我要么修改删除操作以仅接受id(根据Dismissile的答案),要么修改删除视图以发布整个博客对象并从Action中删除id(因为它属于博客对象):

[HttpPost]
public ActionResult Delete(Blog blog)
{
    try
    {
        using (var db = new BlogDataEntities())
        {
            db.Entry(blog).State = System.Data.EntityState.Deleted;
            db.SaveChanges();
        }
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

答案 3 :(得分:1)

我在一些评论中发布了这个帖子,但我认为这对于“替代方案”应该是一个单独的答案。

您的控制器应该很苗条,并尽可能地遵守single responsibility principle

<强> BlogController

public class BlogController : Controller
{
    private BlogService blogService;

    public BlogService()
    {
        blogService = new BlogService();
    }

    [HttpPost]
    public ActionResult Delete(int id)
    {

        // make sure the user has permission to delete before actually deleting

        // now that we know the user has permission
        if (blogService.Delete(id))
        {
            return RedirectToAction("Index");
        }
        else
        {
            return View();
        }
    }
}

现在,您将拥有一个符合single responsibility principle

的可重复使用服务图层

<强> BlogService

public class BlogService
{

    private BlogDataEntities dc;

    public BlogService()
    {
        dc = new BlogDataEntities();
    }

    public bool Delete(int Id)
    {
        try
        {
            var blog= (from b in dc.Blogs where Blog.ID == Id select b).First();

           // blog doesn't exist, exit and return false.
           if( blog == null )
                return false;

          // blog exists, remove it
          dc.Blogs.Remove(blog);

          // push the delete to the database
          SaveChanges();

          // it worked, return true.
          return true;
        }
        catch(System.Exception ex)
        {
            // an error happened, handle it and return false.
            return false;
        }
    }

    // I like to keep my `SubmitChanges()` Separate in case I need to 
    // stack up a few processes before hitting the database.
    public void SaveChanges()
    {
        dc.SaveChanges();
    }  
}