Asp.net mvc “中缺少某些内容”;删除“;MVC中的post方法(EF 4.1)

Asp.net mvc “中缺少某些内容”;删除“;MVC中的post方法(EF 4.1),asp.net-mvc,asp.net-mvc-3,entity-framework,entity-framework-4,Asp.net Mvc,Asp.net Mvc 3,Entity Framework,Entity Framework 4,下面是这个例子 我在删除功能方面遇到问题 [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 .. i

下面是这个例子

我在删除功能方面遇到问题

[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”没有得到需要删除的实际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>
 }
@model DBFirstMVC.Models.Blog
@{
ViewBag.Title=“删除”;
}
删除
是否确实要删除此项?
博客
标题
@模型名称
博客名
@Model.blogger名称
@使用(Html.BeginForm()){

|
@ActionLink(“返回列表”、“索引”)

}
编辑2: 视图中的非Razor代码:

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


|

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



//也尝试了Html.EditorForModel。。
|

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

@model DBFirstMVC.Models.Blog
@{
ViewBag.Title=“删除”;
}
删除
是否确实要删除此项?
@使用(Html.BeginForm()){

博客
标题
@模型名称
博客名
@Model.blogger名称
|
@ActionLink(“返回列表”、“索引”)

}
是否可以尝试以下操作:

[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();
    }
}
[更新]-从视图中传入您的博客模型,但正如Dismissile所说,您应该真正使用视图模型,而不是实体模型


此外,您应该捕获内部异常消息,并检查它以获得进一步的线索。

上下文可能没有日志条目,因为它没有附加到上下文

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

[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();
    }
}
不过,我不太同意使用实体作为模型的想法。你应该使用视图模型

编辑

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

@model Blog

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

    <input type="submit" value="Delete" />
}
@model博客
@使用(Html.BeginForm())
{
@Html.EditorForModel()
}

实际上,您没有向模型绑定器提供构建模型所需的任何详细信息。

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


我在几条评论中发表了这篇文章,但我觉得它值得一个单独的“替代”答案

你的控制器应该是纤细的,并且尽可能地贴在地板上

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();
        }
    }
}
现在,您将拥有一个可重用的服务层,该服务层依附于

博客服务

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();
    }  
}


捕获异常并查看异常是什么problem@ZVenue我已使用您的新详细信息更新了我的答案。您传递的数据不足,无法构建您的模型。有关非razor语法,请参阅OP中的EDIT2。如何在非razor中编写EditorForModel?仍然不工作,请参阅OP中我的新编辑。谢谢。我发布了有关s的答案将代码中的关注点留给后代,但@Dismissile的观点是正确的答案。唯一的问题是我已经有了一个类似于“获取”Delete的方法。public ActionResult Delete(int id){using(var db=new BlogDataEntities()){return View(db.Blogs.Find(id));}啊,当然。我想得太慢了。你当然需要一个viewmodel传回HttpPost操作。我会稍微修改我的答案…这里也一样..请查看我的评论以获得另一个解决方案..我没有正确地传递博客..我缺少了什么?在这种情况下,deletedBlog在传递到方法时是空的。。为什么模型不能通过点击删除按钮?你的razor视图代码在delete.cshtml中是什么样子的。在你的问题中弹出它,因为我认为这是我的帮助。请参阅OP Edit。是的,博客模型确实没有通过。但是编辑视图代码和操作代码的工作方式相同,编辑操作也很好。它得到了e blog model passed..删除代码与示例中的代码非常相似..但是blog仍然没有被传递..有没有办法强制视图将模型传递给控制器..我尝试了你的解决方案..我认为错误在某个地方..我缺少一些非常简单的东西..blog根本没有被传递..公共活动nResult Delete(int id,Blog Blog)Blog在这里为空..Delete GET方法正确地显示了完整的Blog记录..但是当我单击Delete按钮时,调用了POST方法..在这里我看到Blog没有被传递..它传递了Blog的空值..@ZVenue更新了答案。尝试输入@Html.EditorForModel()在表单标签中的您的视图中,+1对于得出解决方案不屑一顾。我知道删除视图中一定有问题(因此我的评论要求这样做)…你是如何用非剃须刀语法编写的..或者似乎不起作用的..虽然它起作用,但它会给你的应用程序增加不必要的开销。当删除只需要博客帖子的
id
时,为什么要传递整个
Blog
对象?这似乎像是向讨厌的蚊子发射了一枚导弹。你唯一需要传递整个
Blog
对象的时候de>Blog对象位于
C
reate,
R
ead,
U
pdate上。代码没有明确说明其发布Id或Blog。它只是一个删除按钮。请参见OP中的Edit。Edit具有类似的代码,并且它成功地传递了Blog。@ZVenue-编辑操作接收非空Blog模型的原因是视图发布一个表单,其中包含构造博客对象所需的所有参数。在delete的情况下,传递的唯一参数是id(来自querystring)。
[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();
    }
}
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();
        }
    }
}
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();
    }  
}