了解 MVC 中的 [HttpPost]、[HttpGet] 和 Complex Actionmethod 参数

Understanding [HttpPost], [HttpGet] and Complex Actionmethod parameters in MVC

我对 MVC 设计模式和框架非常陌生。我也不太精通 ASP.NET 表单的基础知识。但是,我确实了解 Web 开发和 HTTP Post 和 GET 的基础知识。

现在,我学习了一些 MVC 教程,虽然我已经很好地掌握了 MVC 模式的工作原理以及 "Routing Engine" 的工作原理。然后突然我遇到了一个看起来像下面的代码:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return Content("Thanks", "text/html");
    }
}

看着它我有几个问题:

public ActionResult Index(MyViewModel model)?"

由于 NyViewModel 是一个复杂类型,您不能将其作为 URL 的一部分传递。你怎么称呼它?

我想我在这个谜题中遗漏了一个大问题,这两个问题是相互关联的。但是,需要一些帮助来理解这种关系

最佳实践 - 请求处理

最佳做法是在您的控制器中仅使用 public 方法,这些方法将通过视图或 json 提供服务。对于控制器中的所有 public 方法,最佳做法是用 [HttpGet][HttpPost] 标记它们,或者我不会介绍的其他类型之一,因为它们更具优势案例场景。

这些 Http 属性将方法限制为仅服务于那些特定类型的请求。虽然默认值为 [HttpGet],但我发现在所有情况下不标记 [HttpGet] 有时会在存在命名冲突时导致意外行为。

最佳实践 - PRG

Post-Redirect-Get 是一种设计模式,它基本上规定任何时候您要发送来自 POST 请求的响应,您应该重定向到 get 以便发送回复。这可以防止出现多种情况,包括如果使用后退按钮则不再发布

重定向通常以 [HttpPost] ActionResult 的形式出现,使用 return RedirectToAction("MyHttpGetAction");

发布复杂模型

您可以通过多种方式发送复杂模型。主要区别在于,如果您使用 GET 请求,它在 url 中,如果您使用 POST 请求,它在请求 headers 中。如果您使用 ajax 那么差异就会变得模糊,因为您几乎总是将它发送到 body.

[HttpPost] 属性告诉路由引擎将任何 POST 请求发送到该操作方法到一个方法而不是另一个方法。这是一种重载。

Why is this second method adorned with [HttpPost] when the first method does not require any attributes?

方法的默认值是 [HttpGet]。因此,不需要属性。

Are there any guidelines on when to use [Http] attributes and when not?

理想情况下,属性应该在每个方法上,以避免混淆。随着您对事情的运作方式越来越熟悉,您通常会走捷径(就像其他任何事情一样),并在您知道它们没有必要时省略它们。

Since MyViewModel is a complex type, you can not pass it as part of URL. How can you call it?

数据将从请求正文中的数据转换为模型。这可以作为 JSON 对象或表单数据出现。 (有一些技巧可以从 URL 初始化对象,但它们可能有点复杂和高级。)

通常,复杂的 objects 在 HTTP body 中通过支持它的动词(例如 POST 和 PUT)传递。 body 内容必须通过模型绑定验证。这基本上意味着如果它是 Content-Type 的 POST 请求:application/json,它必须从 JSON 反序列化到 MyViewModel。如果内容为XML,则必须反序列化为XML.

一般惯例是先获取 URL 路径、查询和 headers 中可以找到的所有基本类型,然后是 POST 中的一个复杂类型(或PUT) body 之后。我相信可以将复杂类型放在其他地方,但是如果您是初学者,您可能会接触到类型转换器和自定义属性。

Why is this second method adorned with [HttpPost] when the first method does not require any attributes? Are there any guidelines on when to use [Http] attributes and when not?

"[HttpPost]" 告诉路由引擎此方法重载 通过 HTTP POST 可用。在这种情况下,尝试使用 body PUT /home/index 将失败,并返回 404 Not Found。 Index() 的 parameter-free 版本不需要它,因为它可以与任何 HTTP 动词一起使用,包括 GET、POST 和 PUT。