由于外包公司结束合作,所以考虑把其APP服务替换过来,因原后台是用php写的,在不影响员客户端使用的情况下在MVC下重写路由配置实现处理原php链接地址的请求,但实现时发现怎么也匹配不到自己写的路由,度娘上找到一博文,解决了当时问题,应该是台湾wili保哥写的吧,记得以前看过保哥大神写的《ASP.NET MVC 4开发指南》,不知道是不是同一个,转帖如下:

ASP.NET MVC 4 在 .NET 4.0 與 .NET 4.5 的專案範本差異

昨天在【ASP.NET MVC 4 開發實戰】課程中,學員們發現了一個問題,就是在實作與測試 ASP.NET MVC 的 Routing (路由) 機制的過程中,發現有個功能有些人做得出來,有些人卻做不出來,當我前去查看時也沒立即發現問題癥結,中午休息的空檔終於找到的這個細微的差異之處,所以還是寫篇文章提醒正準備開始使用 .NET Framework 4.5 的 ASP.NET MVC 開發人員。

在此我們先建立一個以 .NET Framework 4.0 為主的 ASP.NET MVC 4 專案:

專案範本則以「網際網路應用程式」為主要範本:

接著我們開啟專案下 App_Start\RouteConfig.cs 檔案,試圖修改預設路由的 url 參數定義:

我們試著將 {action} 修改成 {action}.aspx

這時,我們可以測試該專案,連接以下網址

http://localhost:26618/Home/Index.aspx

你會看到網頁是可以正常顯示的,如下圖示:

接著,我們試著將 {action} 修改成 {action}.{ext},把 .aspx 修改成一個路由變數

我們定義了 .{ext} 這個路由變數,代表我們可以在 {action} 後面加上任意 "副檔名”,然而事實上這不是個 “副檔名”,而是一個路由值而已!

這時,我們可以測試該專案,連接以下網址

http://localhost:26618/Home/Index.php

( 備註:這是為了示範路由與網址的對應而設計的一個範例,你就算把 .php 改成 .jsp 都能執行 )

你會看到網頁是可以正常顯示的,如下圖示:

接下來,我們建立一個以 .NET Framework 4.5 為主的 ASP.NET MVC 4 專案:

然後完全使用上述的範例執行一次,但練習到最後,你卻會發現,使用以下網址可行:

http://localhost:26636/Home/Index.aspx

但使用以下網址卻會引發 HTTP 錯誤 404.0 – Not Found 的錯誤 ( 而且該錯誤是從 IIS 傳來的 )

http://localhost:26636/Home/Index.php

但是如果我在 .php 後面加上一條斜線 ( / ),問題竟然可以解決,例如:

http://localhost:26636/Home/Index.php/

後來我用 WinMerge 工具比對兩個 ASP.NET MVC 專案資料夾的差異,這才發現,雖然兩個都是 ASP.NET MVC 4 專案,但是 web.config 的預設內容卻改變了,是在 <system.webServer> 區段下的 <modules> 區段,原本在 .NET 4.0 專案範本中有下圖這段runAllManagedModulesForAllRequests 設定,但是在 .NET 4.5 卻被移除,進而導致此差異:

然而,這段設定最主要是針對 IIS7+ ( 含 IIS 7.5, IIS 8.0 ) 的 整合 (Integrated) 模式下進行設定,如果你不加上 <modules runAllManagedModulesForAllRequests="true" /> 的話,在預設的情況下,透過 .NET 撰寫的 HttpModules 只能針對 Managed 要求進行處裡 (也就是那些透過 .NET 執行的程式),那些透過原生模組 (native modules) 處裡的檔案,例如 JPEG, CSS, JavaScript 等靜態檔案,就不會流經這些 HttpModules 進行處裡,在這種情況下,如果你沒有明確註冊 HttpHandler 在 IIS 裡面的話,將會導致 IIS 無法判定明確的 MIME Type 而導致找不到網頁的情況,也就是我們這次遇到的問題。

當然,最簡單的應變措施就是直接把這段設定加回去,不過,加回去之前請三思,這條設定被拿掉是有原因的,而原因就出在:效能衝擊 ( Performance Impact )!

在 IIS6 以前,IIS 在處理 HTTP 要求的過程中,只能透過 原生模組 (native modules) 處裡所有要求,並且預設透過副檔名來決定如何對應不同的原生模組,以 ASP.NET 為例,就會有一個 .aspx 對應到 c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll 的設定,相關設定畫面可參考如下圖示,你可以發現,所有 HTTP 要求都必須透過「對應」的方式,才能得知正確的 Handler,接下來才能將 HTTP 要求委派給對應的 Handler 進行處理:

以下是從聖哥的【Windows Server 2008 應用程式新平台 - IIS 7.0】簡報中擷取的一段圖示,你可以從這裡看出 IIS 6.0 在處理要求的流程。

這裡你將會發現到,如果我們要透過「身分驗證」模組處裡本次要求,他是 IIS 內建的一個原生模組,雖然我們也可以在 ASP.NET 撰寫 HttpHandler 或 HttpModules 做到相同的事情,但是這些由 ASP.NET 撰寫的程式預設只能處理所有與 ASP.NET 相關的要求而已,也就是那些副檔名註冊在 IIS 裡面,並且設定到 aspnet_isapi.dll 的那些副檔名,才真正能執行到這段程式碼。反之,如果今天從用戶端傳來的 HTTP 要求是 *.htm 副檔名,他所對應到的只要不是 aspnet_isapi.dll 的話,就執行不到這段由 ASP.NET 開發框架下撰寫的 HttpHandler 或 HttpModules。我在 2007 年曾經寫過的一篇文章,就是試圖解決這個問題,參見:如何讓 ASP.NET 的表單驗證功能保護 .htm 的檔案

從 IIS7 開始,這個所謂的 IIS Request Pipeline (要求管線) 做了一次重大個改進,一個名為「整合」模式的新式要求管線,把整個模組執行的過程做出了改善,他允許你用 .NET 撰寫 Managed Modules,並且可以套用在任何 HTTP 要求上面,徹底打破架構上的限制,以下是 IIS7+ 新式要求管線示意圖: 
:若想深入研究的人,建議可閱讀 Introduction to IIS Architectures 文章。)

回到本文提出的問題,當我們沒有 <modules runAllManagedModulesForAllRequests="true" /> 這項預設設定的話 ( 預設為 false ),代表的是,我們在 ASP.NET 定義的模組 (modules),只想處理 Managed 要求 (就是那些註冊為 .NET 相關的要求) 而已,而非 所有 HTTP 要求 (AllRequests),所以當你試圖要求 *.php 等尚未註冊的 handler 時,自然就會引發 HTTP 錯誤 404.0 – Not Found的錯誤!

不過,可能會有人想問,為什麼我在 .php 後面加上一條斜線 ( / ),問題竟然可以解決呢?

因為從 ASP.NET 4.0 開始,新增了一個 ExtensionlessUrlHandler 要求處理器 (handler),這是一個專門用來處理那些「沒有副檔名的 HTTP 要求」。因為我們在撰寫 ASP.NET MVC 的時候,通常不會在網址加上所謂的「副檔名」,對於這些要求,IIS 會不知道應該將要求如何派送給那個 handler 處理,所以才衍生出這樣的需求,可以說是為了 ASP.NET MVC 量身打造的!

像是 ExtensionlessUrlHandler 這樣的處理器,如果要在 IIS6 實現,必須要註冊所謂的萬用字元應用程式對應才有可能 (設定了這個會影響 IIS6 的執行效能),最主要還是 IIS 架構上的差異使然。

你可以從下圖看到 ASP.NET MVC 專案範本中,預設就會載入所謂的 ExtensionlessUrlHandler 處理器!

文字版本如下:

<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       modules="IsapiModule"
       scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
       preCondition="classicMode,runtimeVersionv4.0,bitness32"
       responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       modules="IsapiModule"
       scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
       preCondition="classicMode,runtimeVersionv4.0,bitness64"
       responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       type="System.Web.Handlers.TransferRequestHandler"
       preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

如果你想註冊 *.php 並且讓 ASP.NET MVC 路由可以辨識的話,可以參考以下設定:

<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       modules="IsapiModule"
       scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
       preCondition="classicMode,runtimeVersionv4.0,bitness32"
       responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       modules="IsapiModule"
       scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
       preCondition="classicMode,runtimeVersionv4.0,bitness64"
       responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       type="System.Web.Handlers.TransferRequestHandler"
       preCondition="integratedMode,runtimeVersionv4.0" />
  <add name="(PHP) ExtensionlessUrlHandler-ISAPI-4.0_32bit"
       path="*.php"
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       modules="IsapiModule"
       scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
       preCondition="classicMode,runtimeVersionv4.0,bitness32"
       responseBufferLimit="0" />
  <add name="(PHP) ExtensionlessUrlHandler-ISAPI-4.0_64bit"
       path="*.php"
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       modules="IsapiModule"
       scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
       preCondition="classicMode,runtimeVersionv4.0,bitness64"
       responseBufferLimit="0" />
  <add name="(PHP) ExtensionlessUrlHandler-Integrated-4.0"
       path="*.php"
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       type="System.Web.Handlers.TransferRequestHandler"
       preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

最後想要補充說明的是,如果你自行開發 HTTP 模組 ( HttpModules ) 的話,就算你手動加上<modules runAllManagedModulesForAllRequests="false" /> 設定,可能會認為「任何原生模組相關的 HTTP 要求」( 例如: *.htm, *.css 之類的 ) 都不會再流經你自行開發的 HTTP 模組,然而,這是個錯誤觀念!

使用這個 runAllManagedModulesForAllRequests 設定,最主要的差異在於:

  • 當設定為 true 的時候,所有 HTTP 要求,包含已註冊的未註冊的附檔名對應,都會流經你自己撰寫的 HTTP 模組。
  • 當設定為 false 的時候,所有 HTTP 要求,所有已註冊的附檔名對應,還是會流經你自己撰寫的 HTTP 模組。

這個小細節對於寫 HTTP 模組的開發人員來說非常重要!

ASP.NET MVC5写.php路由匹配时的问题 ASP.NET MVC 4 在 .NET 4.0 与.NET 4.5 的專案範本差異的更多相关文章

  1. ASP.NET MVC5 :Attribute路由使用详解

    1.什么是Attribute路由?怎么样启用Attribute路由? 微软在 ASP.NET MVC5 中引入了一种新型路由:Attribute路由,顾名思义,Attribute路由是通过Attrib ...

  2. 通过阅读ASP.NET MVC5 框架解密 路由的一点心得

    路由: 1.在ASP.NET中路由不专属与ASP.NET MVC,因为路由(Route)是在system.web 命名空间下的,所以传统的WebForm也可以使用路由. 2.什么叫做路由 采用某种机制 ...

  3. 在ASP.NET MVC5中使用特性路由

    首先在RegisterRoutes时开启特性路由功能: routes.MapMvcAttributeRoutes(); 然后,就可以使用了. [Route("{productId:int}/ ...

  4. ASP.NET MVC5(一)—— URL路由

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  5. ASP.NET MVC5使用Area区域

    转载:http://www.lanhusoft.com/Article/217.html 在大型的ASP.NET mvc5项目中一般都有许多个功能模块,这些功能模块可以用Area(中文翻译为区域)把它 ...

  6. Asp.net MVC]Asp.net MVC5系列——Routing特性

    目录 概述 路由特性 使用路由 可选参数和参数的默认值 路由前缀 默认路由 路由约束 自定义路由约束 路由名 区域(Area) 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列— ...

  7. 《ASP.NET MVC 5 破境之道》:第一境 ASP.Net MVC5项目初探 — 第三节:View层简单改造

    第一境 ASP.Net MVC5项目初探 — 第三节:View层简单改造 MVC默认模板的视觉设计从MVC1到MVC3都没有改变,比较陈旧了:在MVC4中做了升级,好看些,在不同的分辨率下,也能工作得 ...

  8. ASP.NET MVC3中的路由系统 Routes

    MVC中,用户访问的地址并不映射到服务器中对应的文件,而是映射到对应Control里对应的ActionMethod,由ActionMethod来决定返回用户什么样的信息.而把用户访问的地址对应到对应的 ...

  9. ASP.NET MVC3中的路由系统(Routes) .

    MVC中,用户访问的地址并不映射到服务器中对应的文件,而是映射到对应Control里对应的ActionMethod,由ActionMethod来决定返回用户什么样的信息.而把用户访问的地址对应到对应的 ...

随机推荐

  1. canvas一周一练 -- canvas基础学习

    从上个星期开始,耳朵就一直在生病,里面长了个疙瘩,肿的一碰就疼,不能吃饭不能嗨 (┳_┳)……在此提醒各位小伙伴,最近天气炎热,一定要注意防暑上火,病来如山倒呀~ 接下来我正在喝着5块一颗的药学习ca ...

  2. POJ 2251 三维BFS(基础题)

    Dungeon Master Description You are trapped in a 3D dungeon and need to find the quickest way out! Th ...

  3. 关于github 0.6.2版本的使用方法

    貌似做为一名前端开发人员,没听过使用过github,node,vue就像落伍一样,本人也是在前端自摸自爬的路上越走越远了,经常在群里听大神们讨论vue,github,node,好生羡慕,没人教,没人带 ...

  4. Argparse4j

    argparse4j 是 Python argparse 命令行解析器的 Java 语言移植版.这个要比spring AspectJ 更简单,更方便实现. <dependency> < ...

  5. sping 框架学习之——初始篇

    sping框架学习: 1,什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以 ...

  6. CentOS 6 下无法wget https链接的解决方法

    CentOS6下最高版本的wget是1.11,但非常遗憾的是这个版本有bug,是没办法用来下载https链接的东西的,所以有些人为了避免这种情况会帮脚本加上不检查ssl的参数--no-check-ce ...

  7. C++ STL map详解

    一.解释: p { margin-bottom: 0.25cm; direction: ltr; color: #00000a; line-height: 120%; text-align: just ...

  8. Classy(排序)

    Description In his memoir So, Anyway. . ., comedian John Cleese writes of the class di erence betwee ...

  9. C语言左值,运算符的优先级以及结合性探讨

    刚刚开始看一本书.<C陷阱与缺陷>,相信学习C语言的大家都对这本书有耳闻.今天看到了里面的贪心法则.也即在读到一个字符后,尽可能多的读入更多的字符,直到读入的字符组成的字符串已经不可能再组 ...

  10. mybatis中的mapper接口文件以及example类的实例函数以及详解

    ##Example example = new ##Example(); example.setOrderByClause("字段名 ASC"); //升序排列,desc为降序排列 ...