【问题标题】:Delete Action From View Page从视图页面删除操作
【发布时间】:2009-07-30 19:27:43
【问题描述】:

您好。

为了尝试了解 MVC,我刚刚实现了一个简单的添加/删除页面,该页面也可以查看记录。这使用户可以更轻松地从一个页面完成大多数事情,而不必离开去完成简单的任务。该页面允许您添加一条运行良好的记录(具有 ID 和名称的企业)。但是,当我删除一条记录时,我已执行以下操作以允许删除:

<%= Html.ActionLink("delete", "DeleteBusiness", new { businessToDelete = B.BusinessID }) %>

这可以很好地删除记录。这是我的控制器操作的样子:

public ActionResult DeleteBusiness(string businessToDelete)
{
     try
     {
       if (!ModelState.IsValid)
         return View("Businesses", _contractsControlRepository.ListBusinesses());

         _contractsControlRepository.DeleteBusiness(businessToDelete);

         return View("Businesses", _contractsControlRepository.ListBusinesses());
     }
     catch
     {
       return View("Businesses", _contractsControlRepository.ListBusinesses());
     }
}

因此,在“业务”页面中,我有一个 ActionLink,它只是将我引导至控制器中的此操作,该操作完成工作,然后返回我之前所在的视图。那么问题是 一旦我删除了记录,我的实际 URL 最终会像这样:

http://localhost:3340/Accounts/ContractsControl/DeleteBusiness?businessToDelete=TEST

这不好,因为当我再去添加新记录时,它不会让我。让我添加记录的控制器操作如下所示:

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Businesses(Business business)
  {
    try
    {
      if (!ModelState.IsValid)
        return View(_contractsControlRepository.ListBusinesses());

      _contractsControlRepository.CreateBusiness(business);
      return View(_contractsControlRepository.ListBusinesses());
    }
    catch
    {
      return View(_contractsControlRepository.ListBusinesses());
    }
  }

任何post 请求都被视为创建新记录。这个对吗?这是我的观点,最重要的是:

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

  <fieldset class="inline-fieldset">
    <legend>Add Business</legend>

    <p>
    <label for="ID">ID</label>

    <%= Html.TextBox("BusinessID", null, new { style = "width:50px;", @class = "uppercase", maxlength = "4" })%>
    <%= Html.ValidationMessage("BusinessID", "*")%>

    <label for="Business">Business</label>

    <%= Html.TextBox("BusinessCol")%>
    <%= Html.ValidationMessage("BusinessCol", "*")%>

    <input type="submit" value="Add" />
  </p>

  <%= Html.ValidationSummary("Uh-oh!") %>

  </fieldset>

<% } %>

<table>
<tr>
<th>ID</th>
<th>Business</th>
<th></th>
<th></th>
</tr>
  <% foreach (Business B in ViewData.Model)
  { %>
    <tr>
      <td><%= B.BusinessID %></td>
      <td><%= B.BusinessCol %></td>
      <td class="edit"><%= Html.ActionLink("edit", "EditBusiness", new { id = B.BusinessID }) %></td>
      <td class="delete"><%= Html.ActionLink("delete", "DeleteBusiness", new { businessToDelete = B.BusinessID }) %></td>
    </tr>
  <% } %>
</table>

正如您在最底部看到的那样,我有操作链接(忽略编辑链接)。因此,如果我删除一条记录,然后立即尝试添加一条记录,它将无法正常工作,因为(我假设)URL 错误。我在这里做错了什么?

已修复

  public RedirectToRouteResult DeleteBusiness(string businessToDelete)
  {
    try
    {
      if (!ModelState.IsValid)
        return RedirectToAction("Businesses");

      _contractsControlRepository.DeleteBusiness(businessToDelete);

      return RedirectToAction("Businesses");
    }
    catch
    {
      return RedirectToAction("Businesses");
    }
  }

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    如果删除成功,为什么不将用户重定向回“列出企业”页面?

    【讨论】:

      【解决方案2】:

      我第二个 maciejkow 的回答,如果用户尝试刷新页面,重定向消除了用户重新发布数据的机会。

      另一件事,我不会将删除操作放在链接中(即 GET),这类操作应该始终是 POST(出于缓存原因,自动化工具有时会跟随页面上的链接),所以我会包装一个迷你表单中的按钮来执行您的删除操作,您的 businessToDelete 变量位于隐藏字段中。

      【讨论】:

      • 这有点乱,不是吗?但是,我完全理解您陈述中的逻辑。只是在这个例子中,在每个条目旁边添加一个带有删除按钮的数据表很方便。其实这确实是系统的要求。
      • 在 NerdDinner 教程中,不允许在 HTTP GET 上删除的具体原因是“我们要小心防范网络爬虫......当他们跟随链接时无意中导致数据被删除...”
      • 确实是一个很好的理由。但是,如果我想要每个人都有一个删除按钮怎么办?我真的必须为每个人提供一个表单和一个按钮吗?我需要它们作为超链接而不是表单。
      • 是的,您可能需要在每个删除按钮周围使用一个小表单(最简单的方法)。如果您担心混乱,您可以编写一个 HtmlHelper 扩展方法来生成必要的标记。
      • 一个描述gridview中删除链接的链接 - stephenwalther.com/blog/archive/2009/01/21/…
      【解决方案3】:

      我刚刚完成了 NerdDinner 教程。

      删除的控制器在里面

      // GET: /Dinners/Delete/1
      public ActionResult Delete(int id)
      {
          Dinner dinner = dinnerRepository.GetDinner(id);
          if (dinner == null)
          {
              return View("NotFound");
          }
          else
          {
              return View(dinner);
          }
      }
      
      
          // POST: /Dinners/Delete/1
          [AcceptVerbs(HttpVerbs.Post)]
          public ActionResult Delete(int id, string confirmButton)
          {
              Dinner dinner = dinnerRepository.GetDinner(id);
      
              if (dinner == null)
              {
                  return View("NotFound");
              }
      
              dinnerRepository.Delete(dinner);
              dinnerRepository.Save();
      
              return View("Deleted");
          }
      

      Get 的控制器是。

      // GET: /Dinners/Edit/2
      [Authorize]
      public ActionResult Edit(int id)
      {
      
          Dinner dinner = dinnerRepository.GetDinner(id);
      
          if (!dinner.IsHostedBy(User.Identity.Name))
          {
              return View("InvalidOwner");
          }
      
          return View(new DinnerFormViewModel(dinner));
      }
      
      //
      // POST: /Dinners/Edit/2
      [AcceptVerbs(HttpVerbs.Post),Authorize]
      public ActionResult Edit(int id, FormCollection formValues)
      {
          Dinner dinner = dinnerRepository.GetDinner(id);
          if (!dinner.IsHostedBy(User.Identity.Name))
          {
              return View("InvalidOwner");
          }
          try
          {
      
              UpdateModel(dinner);
              dinnerRepository.Save();
      
              return RedirectToAction("Details", new { id = dinner.DinnerID });
          }
          catch (Exception ex)
          {
              foreach (var issue in dinner.GetRuleViolations())
              {
                  ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
              }
              return View(new DinnerFormViewModel(dinner));
          }           
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-25
        • 1970-01-01
        • 1970-01-01
        • 2019-07-21
        相关资源
        最近更新 更多