【问题标题】:Specifying single method as target for multiple controller URL's将单个方法指定为多个控制器 URL 的目标
【发布时间】:2016-03-18 12:22:28
【问题描述】:

有很多问题反过来询问这个逻辑,但是,我找不到我的问题的答案。我是 MVC 新手,所以可能没有正确指定术语。

我有一个包含表单的视图,用户可以在其中请求产品。无论产品如何,都使用相同的视图,但特定字段显示在与该特定产品相关的表单中,例如

public class RequestController : Controller
{
    // This bit works fine and displays the appropriate form in the view
    public ActionResult MyProduct(string id)
    {
        if (string.IsNullOrWhiteSpace(id))
        {
            return new HttpNotFoundResult();
        }
        ProductRequest qd = new ProductRequest();
        switch (id)
        {
            case "Beer":
                qd.RequestType = Models.RequestType.Beer;
                break;
            case "Coffee":
                qd.RequestType = Models.RequestType.Coffee;
                break;
            case "Soda":
                qd.RequestType = Models.RequestType.Soda;
                break;
        }
        return View("Index", qd);
    }

    // Need to get all forms rendered by the above to post here...
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult MyProduct(ProductRequest qd)
    {
        if (!ModelState.IsValid)
        {
            return View(qd);
        }
        else
        {
            // To do ...
        }
    }
}

当表单在视图中呈现时,使用...

@using (Html.BeginForm())

...呈现的 HTML 为每种产品类型显示不同的表单目标 URL,例如:

<form action="/Request/MyProduct/Beer" method="post">

无论产品类型如何,我都可以让form action 属性使用相同的控制器/方法吗?例如

<form action="/Request/MyProduct" method="post">

鉴于 MVC 似乎提供的灵活性,我认为有不同的方法可以实现这一点,但我正在寻找最佳实践作为学习经验。

【问题讨论】:

    标签: c# .net asp.net-mvc asp.net-mvc-5


    【解决方案1】:

    Html.BeginForm() 调用接受各种参数,这些参数可以声明您希望表单使用的控制器/方法。

    @using (Html.BeginForm("MyProduct", "Request", FormMethod.Post, new { enctype = "multipart/form-data"}))
    

    应该产生:

    <form action="/Request/MyProduct" enctype="multipart/form-data" method="post">
    

    【讨论】:

      【解决方案2】:

      除了阻止您轻松控制操作 url 之外,Html.BeginForm 帮助器对您自己编写 html 有什么附加价值?

      就个人而言,我已经禁止了大多数 Html 助手的使用,这只是妨碍我而不是帮助我。

      自己编写 html 代码,这通常比使用 html 助手更简洁(如answer 所示)。

      <form action"@Url.Action("MyProduct", "Request")" method="post">
          @* Add [ValidateAntiForgeryToken, HttpPost] attributes to target action *@
          @Html.AntiForgeryToken()
          ...
      </form>
      

      (更好的是,使用UrlHeper extensions 来定义和集中您的URI,而不是在您的视图或控制器中调用Url.Action。)

      为了完整起见,我应该提一下,大多数输入字段 html 辅助扩展(以For 为后缀的)具有利用视图模型的数据注释的附加值。但我认为这些注释是不好的做法,因为它们处理在严格的 MVC 模式中不是视图模型责任的主题。 (显示标签?应该由视图控制。验证规则?应该由控制器控制。动作参数和/或参数模型?没有理由绑定到视图模型名称。)

      【讨论】:

      • 谢谢。 BeginForm 可能没有任何价值(我只是在学习)。我希望我能找到如何在超链接和.Url.Action 等项目中强类型化控制器和方法,因为使用字符串 (IMO) 并不比自己编写原始 HTML 更好。
      • 关于Url.Action 中的字符串,确切地说。这就是我推荐使用 UrlHelper 扩展的原因。
      • 您自己编写的扩展,还是现有的?只是想知道“外面”有什么?
      • 点击我放的链接。扩展您自己的写作以指定您的网址。本质上,您定义了包含对 url 帮助程序的实际调用的扩展方法,从而允许您将所有魔术字符串集中在一个扩展类中,而不是在您的代码周围传播/复制它们。
      • 由于您需要一些指导,我添加了反 CSRF 保护。它应该以任何形式存在,从而导致服务器端发生一些数据更改。有关安全威胁的更多信息,请参阅Owasp 及其Top 10 project
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-15
      • 2017-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多