MVC请求处理程序

时间:2017-03-22 07:10:03

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

ASP.NET根据文件扩展名将HTTP请求映射到HTTP处理程序。我只是想知道它在MVC中是如何工作的,因为在MVC中我们只是指向控制器内部的action方法。我们没有指定任何扩展。

然后我尝试从 this link

了解处理程序在MVC应用程序执行过程中的工作原理

但我还是不明白。任何人都可以解释处理程序在MVC中的工作方式以及它与普通ASP.NET处理程序的不同之处。

3 个答案:

答案 0 :(得分:2)

可能你对这些术语感到困惑。

MVC使用路由表来查找到特定View的路由。

就像你有www.YourSite.com/index.aspx一样,你有www.YourSite.com/Home/Index

区别在于,in ASP.Net, you will be directly loading the .aspx file和网址in MVC, you will go to the Home controller and look for an Index action. The Index action will then render it's view一样。

此处,每个视图或部分视图都将在控制器中包含其ActionMethod。

如果没有关联的控制器和操作,则无法呈现视图!

您可以查看this link以获取进一步的参考。

你将在Global.asax文件中有一个默认路由来完成这项工作。

如果您有任何复杂的(有多个参数),您需要手动将它们添加到路由表中。关于这一点的更多信息在链接中。

希望这会有所作为。

答案 1 :(得分:2)

事实上,这里的全面解释真的超出范围,你应该阅读它以深入学习它,如果你接受建议,如果你能找到一个,一本书通常是一个更好的资源博客帖子等(根据我的经验,博客文章可能由任何可能没有线索的人撰写)。只要确保你阅读评论,以确定一本书是否好,这样你就不会被误导。

无论如何,我会尝试概述基础知识,而不会在细节上添加太多噪音,因为这会导致太多。

正如其他人在他们的回答中已经提到的,在MVC生态系统中,有一个称为路由和路由表的概念。基本上,它们是模式的集合。请求到达时,请求标头包含请求的URL,例如:

  • http://localhost:12345/
  • http://localhost:12345/home/index
  • http://localhost:12345/products/catalog
  • http://localhost:12345/products/details/1
  • http://localhost:12345/promotion

有一个原因我写了不止一种,格式不同。让我们一个一个地检查它们。

http://localhost:12345/示例

第一个,http://localhost:12345/是最简单的,它通常被称为默认路由。通常,这指向Index中的无参数HomeController操作方法,默认区域(即"无区域")。请注意,动作和控制器以及区域(以及几乎任何细节)都是可配置的。您可以通过添加默认路由来完成此工作,但这通常由项目模板为您完成。您可以在App_Start / RouteConfig文件中找到它,它的name参数为"Default"

routes.MapRoute(
  name: "Default",
  url: "{controller}/{action}/{id}",
  defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

因此,每当有一个请求(其中我以原始方式说这个)的附加部分存在时,它们就会被Index内的HomeController动作处理。正如您在上面的代码中看到的那样,IndexHomeControllerdefaults:参数中配置,您必须转到此处才能更改默认值。如果您改为使用名为Welcome的操作,则需要将其传递给上述方法:

defaults: new { controller = "Home", action = "Welcome", id = UrlParameter.Optional }

另请注意,尽管我已经写过"其中没有其他部分存在",通过其他部分我只是指路段 - 例如,查询字符串?param1=value1 不会阻止选择此路线。

http://localhost:12345/home/index示例

这与上面完全相同。我只包含了这个,所以你可以看到即使这个特定路由是默认路由,也没有什么能阻止你实际指定控制器和动作。

http://localhost:12345/products/catalog示例

这个的基本工作方式与上面两个相同,只是这不是默认路由,因此您需要明确指定控制器和操作,以便将请求路由到适当的控制器并且行动。再看一下上面的配置代码。您可以看到已定义"{controller}/{action}/{id}"网址格式。您不需要来创建新路由,因为此模式可用于此示例。比较它们,你可以看到原因:

http://localhost:12345/products   /catalog
                      {controller}/{action}/{id}

从位移可以看出,products被识别为控制器名称,catalog被识别为操作名称,并且id被赋予默认值{{ 1}},可以省略它的值,路由仍然对请求有效。因此,只要默认区域中存在UrlParameter.Optional且其中包含ProductsController操作,其具有Catalog参数,或者根本没有参数,或者任何现有参数一个默认值(或可以为空,在这种情况下它将被传递为null),路由系统将使用此路由作为请求。

id示例

与上述相同,但此处http://localhost:12345/products/details/1已映射到1段。只要默认区域中有id,并且其中存在ProductsController操作,该操作根本没有参数(因为Details是可选的,它可能是忽略),或者有一个名为id的参数,并且如果可能存在的每个其他参数都有一个默认值(或者可以默认为null - 这意味着它是一个引用类型),那么这个路由可以用于请求。

id示例

这是我为特定目的而包含的特殊内容。我们假设您拥有http://localhost:12345/promotion。您仍然可以定义路由模式

PromotionController

正如您所看到的,我们假设您有一个routes.MapRoute( name: "Promo", url: "promotion", defaults: new { controller = "Products", action = "Promotion" } ); ,其中包含ProductsController个动作。而您可以直接请求网址Promotion(并且它实际上会有效)指定"专用"路线也可以。我之所以添加此示例,原因如下:

  • 这样你可以看到这样的事情是可能的
  • 因为可能会出现需要的情况,例如:
    • 现在可以更改找到特定功能的路径,但由于您的用户可能已使用旧网址为该网页添加了书签,因此您不希望他们看到404。在这种情况下,这条路线用于"重新路由" (不是HTTP重定向,只是找不到更好的词)旧的URL到新的。
    • 在某些情况下,您不希望公开控制器/操作层次结构。在这个例子中,只需输入" promotion"可能比打字"产品/促销"对用户更有说服力。您可以在此示例中与此争论,但仍然可能有更好的示例,在这种情况下这是可行的。此外,您可以使用它来提供更短的网址。

最后,让我们谈谈整个路由系统的一些事情。

  1. 可能存在将 映射到多个路由的情况。在这种情况下,定义模式的顺序是决定因素。匹配网址的第一个被选中,这意味着您应该从最具体的(也就是更少或根本没有变化的部分)开始指定您的路线模式。没有变化部分的模式的示例是我写的最后一个网址,它具有http://localhost:12345/products/promotion的硬编码模式。您可以通过模式中没有promotion来识别这些。最不具体的(换句话说,更一般的)应该在方法的底部。如果仍然存在重叠,则应重新考虑如何定义路线。

  2. 还有其他因素会影响是否可以选择某个操作来提供请求。例如,动作方法上{}的存在将告诉动作调用者(以及不是路由引擎)此方法只能用于请求是POST请求(除非还应用了[HttpPostAttribute])。请注意,路由系统和所谓的动作调用程序是两个不同的东西 - 您可以发现自己处于这样的情况:路由系统将找到路由的模式匹配但操作调用程序找不到合适的操作 - 例如,如上所述,匹配的模式没有GET处理程序,但请求实际上是HTTP GET。这超出了您的问题范围,但希望将其作为提示包含在内,以便您了解需要查找它。上面提到的[HttpGetAttribute]HttpPost属性是特殊属性,为了通过实现您自己的属性来实现此类功能,您的属性必须来自HttpGet类。

    < / LI>
  3. 正如您在问题中所说,请求不会映射到文件,而是映射到控制器和操作。因此,假设找到了匹配的路由模式,并且要使用的控制器恰好为ActionMethodSelectorAttribute,并且操作为Home(Controller)。系统做了什么(这不是路由系统从此处负责)它扫描正在运行的应用程序的程序集(使用反射)并枚举其中的所有类。它寻找符合某些标准的课程(我不确定以下内容是否100%准确和/或全面):

    • 直接或间接从Index
    • 派生
    • 不抽象
    • 公开(不确定这个)
    • 有一个公共构造函数(对此也不确定)
    • 这个名称是ControllerHome(不确定只是HomeController是否有效,实际上这是一个约定用名称后缀#34; Controller&#34; )
  4. 如果未找到,则根据匹配的路由无法满足请求。如果找到多个,则无法确定要使用的那个并且会引发错误。

    如果找到一个匹配的类(Controller),则系统将进一步调查它。它现在将寻找以下方法:

    • 是动作方法,即它们的返回类型是Home还是派生类(这不是AJAX请求所必需的)
    • 公开
    • 其参数满足前面讨论的路线定义的约束
    • 应用于特定方法的任何ActionResult派生属性不会阻止根据请求属性执行操作。

    如果找不到或多个匹配的操作方法,则无法满足请求并引发错误。

    如果只有一个匹配项,则会调用它来完成请求。

答案 2 :(得分:0)

不要太混淆

所有控制器都是类

所有行动都是方法

你只是从地址栏调用方法(函数),这些都是......

mvc处理程序检查在类(Controller)中是否存在方法(ActionRsult) 具有相同的名称和匹配的所有

的参数