GVKun编程网logo

ASP.NET MVC 优化笔记 -SEO(asp.net mvc视频教程)

1

在本文中,我们将给您介绍关于ASP.NETMVC优化笔记-SEO的详细内容,并且为您解答asp.netmvc视频教程的相关问题,此外,我们还将为您提供关于AndroidstudioInspection

在本文中,我们将给您介绍关于ASP.NET MVC 优化笔记 -SEO的详细内容,并且为您解答asp.net mvc视频教程的相关问题,此外,我们还将为您提供关于Android studio Inspection 优化笔记、ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门、ASP.NET Core 或 ASP.NET Core MVC 解决方案无法运行,IIS Express 抛出 HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动、ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?的知识。

本文目录一览:

ASP.NET MVC 优化笔记 -SEO(asp.net mvc视频教程)

ASP.NET MVC 优化笔记 -SEO(asp.net mvc视频教程)

1.站点地图构建:

    

/// <summary>
   ///  实现XML格式 站点地图输出
   ///  By:rhythmk.cnblogs.com
   /// </summary>
    public class SitemapResult : ActionResult
    {
        public SitemapResult(Sitemap sitemap)
        {
            this.Sitemap = sitemap;
        }

        public Sitemap Sitemap { get; private set; }

        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.ContentType = "text/xml";
            XmlSerializer serializer = new XmlSerializer(typeof(Sitemap));
            serializer.Serialize(context.HttpContext.Response.Output,
                                 this.Sitemap);
        }
    }

    /// <summary>
    /// 站点地图实体
    ///  By:rhythmk.cnblogs.com
    /// </summary>
    [XmlRoot(ElementName = "urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
    [Serializable]
    public class Sitemap : List<SitemapUrl>
    {


        [XmlInclude(typeof(SitemapUrl))]
        public void Serialize(TextWriter writer)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Sitemap));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(writer);
            serializer.Serialize(xmlTextWriter,
                                 this);
        }


    }

    [XmlRoot(ElementName = "url")]
    [XmlType(TypeName = "url")]
    [Serializable]
    public class SitemapUrl
    {
        private DateTime lastModified;



        [XmlElement(ElementName = "loc")]
        public string Location { get; set; }

        [XmlElement(ElementName = "lastmod")]
        public string LastModified
        {
            get
            {
                if (DateTime.MinValue.Equals(this.lastModified))
                {
                    this.lastModified = DateTime.Now;
                }

                return this.lastModified.ToString("yyyy-MM-dd");
            }
            set { this.lastModified = DateTime.Parse(value); }
        }

        [XmlElement(ElementName = "changefreq")]
        public ChangeFrequency ChangeFrequency { get; set; }

        [XmlElement(ElementName = "priority")]
        public double Priority { get; set; }


    }


    public enum ChangeFrequency
    {
        always,
        hourly,
        daily,
        weekly,
        monthly,
        yearly,
        never
    }

 使用:

/// <summary>
        ///   站点地图
        /// </summary>
        /// <param name="pageIndex"> 页面索引</param>
        /// <param name="subjectID"> 科目 </param>
        /// <returns></returns>

        public ActionResult Index(int subjectID = 0, int pageIndex = 1)
        {
            int total = 0;
            int pageSize=2000;
            var list = GetExamList(subjectID, pageIndex, pageSize,ref total);
            Sitemap site = new Sitemap();
            var time= DateTime.Now.ToLongDateString() ;
            
            foreach (var p in list)
            {
                site.Add(new SitemapUrl()
                {
                    ChangeFrequency = ChangeFrequency.weekly,
                    LastModified = time,
                    Location = string.Format("http://rhythmk/home/view/{0}?t={1}", p.ExaminationID , p.ExaminationTitle),
                    Priority = 0.7
                });
            }

            return new SitemapResult(site);

        }

2.判断是否为搜索引擎:

 

/// <summary>
        /// 判断是否为搜索引擎访问
        /// </summary>
        /// <param name="useragent"></param>
        /// <returns></returns>
        public static bool IsSearchEngine(string useragent)
        {
            bool engine = false;
            if (!string.IsNullOrEmpty(useragent))
            {
                var SpiderKey = System.Configuration.ConfigurationManager.AppSettings["SpiderKey"].ToString();
                // spiderkey=@"Googlebot|Feedfetcher-Google|Baiduspider|Yahoo\s*\!\s*Slurp|YodaoBot|Sosoimagespider|Sosospider|Sogou\s*Web\s*Sprider"
                System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(SpiderKey, RegexOptions.IgnoreCase | RegexOptions.Compiled);
                engine = rx.IsMatch(useragent);
            }
            return engine;
        }

           public  ActionResult View()
           {
           
           bool engine = IsSearchEngine( this.HttpContext.Request.ServerVariables["Http_User_Agent"]);
            
             // 判断是否为搜索引擎 然后使用不同的试图呈现数据 
            if (engine)
            {
               
                return View("SearchView", entity);
            }
            else
            {
                return View(entity);
            }
            }

3. 检验是否成功:

   修改浏览器   Http_User_Agent   值,以达到模拟搜索引擎爬虫浏览效果。

  以火狐为例:

   3.1地址栏键入:about:config 回车

   3.2 设置:general.useragent.override–>"Baiduspider" 。可以达到模拟百度爬虫效果。

     火符默认:Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.4.154.29 Safari/525.19

   设置完成后可以通过浏览http://www.docin.com/p-259119935.html 此网址 于其他未设置的浏览器比较 浏览页面效果。

Android studio Inspection 优化笔记

Android studio Inspection 优化笔记

以下内容皆为基于百度后一些内容整合,这个笔记只是为了自己日后方便查看所做,若有不对之处,请大家多多指教。

  • Android > Lint > Performance 

1、HashMap can be replaced with SparseArray

      一般Key为int型时可以使用SparseArray替代HashMap使用,SparseArray是Android所独有的,其目的是为了更加节省内存资源

      好处2点:1、装载速度更快 2、消耗内存更小  

      缺点:如果是倒序插入值的时候 不建议使用SparseArray替代,因为会比正序插入转载时间多了大约10倍

2、Handler reference leaks

      在应用程序线程的MessageQueue中排队的Message对象 还保留他们的目标Handler。如果Handler是一个内部类(注:无论是匿名还是非匿名,匿名是比较常见用法),它的外部类将被保留(至于为什么, 请参考Java嵌套类相关说明)。为了避免泄漏外部类,声明一个Handler子类为静态内部类(注:这样就避免了Handler对象对外部类实例的自动引用),其内部持有一个对外部类对象的WeakReference。

总结:1、在 onDestroy中使用 mHandler.removeCallbacksAndMessages( null ); 清除该 Handler为target的所有Message(包括Callback)
   2、Handler的实现类采用静态内部类的方式,避免对外部类的强引用,在其内部声明一个WeakReference引用到外部类的实例。
static class MyHandler extends Handler {
        // WeakReference to the outer class''s instance.
        private WeakReference<myactivity> mOuter;
 
        public MyHandler(MyActivity activity) {
            mOuter = new WeakReference<myactivity>(activity);
        }
 
        @Override
        public void handleMessage(Message msg) {
            MyActivity outer = mOuter.get();
            if (outer != null) {
                // Do something with outer as your wish.
            }
        }
    }
更多说明可以看下边的链接~

Android Handler leak 分析及解决办法


3、Inefficient layout weight

当在一个LinearLayout布局中仅包含一个定义weight属性的view控件时,直接指定0dp到其width或height属性更高效,因为在初始化时不再需要测量这个view控件的尺寸,反正到最后它都会霸占所有剩余空间的了。

4、Memory allocations within drawing code

在实际开发中Android中自带的控件有时无法满足我们的需求,这时就需要我们重写控件来实现我们想要的功能。

还有个关于UI体验的问题,就是在onDraw()函数中最好不要去创建对象,否则就提示下面的警告信息:因为onDraw()调用频繁,不断进行创建和垃圾回收会影响UI显示的性能

5、Missing baselineAligned attribute

当LinerLayout的子View都是ViewGroup(自定义控件除外)时,Lint认为它的子View已经不需要基准线对齐了,为了不让LinerLayout去做无用的计算对齐的操作,提出了如上警告,修改掉之后就可以提高性能。当LinerLayout的子View都是ViewGroup(自定义控件除外)时,Lint认为它的子View已经不需要基准线对齐了,为了不让LinerLayout去做无用的计算对齐的操作,提出了如上警告,修改掉之后就可以提高性能。

6、Nested weights are bad for performance

原因分析:在布局进行嵌套使用时,父布局与子布局都使用了android:layout_weight,但不是必须使用时,便会出现如题所示的警告信息。

  解决方法:根据实际情况,去除子布局中非必须使用的android:layout_weight。

7、Do not place Android context classes in static fields

 不去使用静态的context 也不要在Application中设置静态的context来使用,使用context的时候根据使用的场景 判断一下应该使用什么样的context
Android Context 上下文 你必须知道的一切       使用ApplicationContext作为全局变量引用的缺陷   




由于参考内容过多,本文改为译文咯~~

ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门

ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门

默认的身份认证好授权系统



UserManager用来操作用户的类,

Singi用来身份认证的

添加AccountController

先声明SignInManager和UserManager这两个服务

快捷键Ctrl+.

两个都需要分别进行Ctrl+.快速的生成

创建登陆的Action Login

建立View

创建LoginViewModel

主要是用户名和密码两个字段



登陆的逻辑

注册的逻辑



退出的逻辑

创建regiser的视图页面

在_Lauout里面添加了注册和登陆的链接


点击注册发现报错了。没有注册服务

注册服务

这里按照官方文档来就可以了

这里么有ApplicationDbContext


这里修改为IdentityContext

先进行数据迁移

报错,项目里面多余一个DbContext。一个是自己的DbConext 一个是Identity的DbContext

所以需要指定具体的DbContect


注册服务的时候,指明迁移的类库名称

再次尝试成功





上面只是配置了DbConext,还需要注册IdentityUser的服务


前面多加了一个叹号

密码严格要求了

参考官方文档:把这块复制过去进行修改



判断用户登陆成功后就不再显示,注册和登陆的按钮,在View页面注册ItentityUser





运行页面并不好用,没有使用中间件

登陆成功后

授权

添加一个学生,要求只有登陆的用户才可以进去添加
授权使用Authorize这个属性,这样就只有登陆的用户才可以访问这个Create页面

这个标签可以作用于Controller也可以作用于action,这里我们先作用于Create的两个Action就可以了

Authorize属性也可以加一些参数。。。、这里展示先不加
测试页面。

需要一个LoginPartial页面,一旦没有权限就会跳转到这个页面。这里我们先不做,

 

ASP.NET Core 或 ASP.NET Core MVC 解决方案无法运行,IIS Express 抛出 HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动

ASP.NET Core 或 ASP.NET Core MVC 解决方案无法运行,IIS Express 抛出 HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动

如何解决ASP.NET Core 或 ASP.NET Core MVC 解决方案无法运行,IIS Express 抛出 HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动

即使在 Visual Studio 中最简单的“Hello world”ASP.NET Core Web 应用程序上,我也遇到过此错误。 (Win 10 Pro、IIS Express、VS 2019 CE。)重现步骤:

  1. 在 Visual Studio 2019 中创建新的 ASP.NET Core 或 ASP.NET Core MVC 解决方案。选择选项以生成基本“hello world”应用程序的脚手架代码。无论您的目标是 .NET Core 2.1、.NET Core 3.1 还是 .NET 5.0,在我尝试的场景中结果都是一样的。

  2. 项目和解决方案已加载,源代码可见且看起来正确。按F5运行它。应用编译但不运行。

预期行为:“hello world”应用加载。

实际行为:在网络浏览器中显示此错误消息:

“HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动”(以及一些 故障排除步骤,然后)“有关更多信息,请访问: https://go.microsoft.com/fwlink/?LinkID=2028265”。

  1. 继续并点击该链接,然后使用这些资源仔细检查您是否拥有所有需要的包并且您的 IIS 配置正确。我的机器在我的机器上看起来很好,但我仍然收到这个错误。我什至尝试重新安装 VS、托管包、IIS 等,但无济于事。

注意:此问题与“500.32 ANCM Failed To 加载 DLL”或“500.36 ANCM 进程外处理程序加载失败” 错误,但我在故障排除过程中也遇到了这些错误,所以我 在这里提及它们,以防对其他人有帮助。

另请注意:您不一定有损坏的 ASP.NET Core 模块为 this documentation 会让您相信。

  1. 检查事件日志,您会发现其中存在一些错误,但在这种情况下,这些错误对诊断问题没有特别帮助。就我而言,它只是说

"应用程序 ''/LM/W3SVC/2/ROOT'' 具有物理根目录 ''H:\\Repo (R;)\\sandBox\\AspNetCoreWebApp001\\AspNetCoreWebApp001''加载失败 核心资源异常消息:CLR 工作线程提前退出"

"应用程序已从 Program.Main 退出,退出代码 = ''-2147450743''。请检查 stderr 日志以获取更多信息。"

他们将 IIS Express AspNetCore 模块显示为源。供应商文档在这种情况下并没有太大帮助。

  1. 仔细检查以确保 IIS 配置正确,并且安装了正确的包,包括 .NET Core 托管包。如果您不这样做,或者您正在尝试不同的配置,就像我在故障排除期间一样,那么您可能会看到上面提到的 ANCM 错误。如果您遇到这些错误,这里有 two links 可以提供帮助。我阅读了这些链接并多次仔细检查了我的机器。就我而言,这一切都是正确和完整的,但我仍然有错误。

  2. 再和电脑打几下,叫它一些坏名字,第三次重新安装Visual Studio,第八次验证IIS设置,向你的朋友寻求帮助,再次检查SO和Google。简单的 hello world 应用程序仍然无法运行,同样的错误。它在另一台机器上运行,所以代码本身没有任何问题。

解决方法

这是最终在我的机器上修复它的解决方案:我将解决方案移到了不同​​的文件夹。 HUH???如何我问,这能不能解决这个问题。经过一番折腾,我终于找到了根本原因:路径中有一个分号。是的。就我而言,我一直将解决方案存储在名为“H:\\Repo (R;)”的目录中。事实证明,即使 Windows 操作系统允许使用 ; 字符,.NET CLR 根本不喜欢它,也不知道如何处理它。因此它会生成无用的错误消息。

试试看。重命名“这应该可以工作”解决方案的文件夹以删除分号,关闭并重新打开 VS 中的解决方案,按 F5 并观察它运行。或者转到工作解决方案并将文件夹重命名为包含分号,然后观察它是否会破坏 CLR。​​

我很好奇文件夹名称中的任何其他特殊字符是否会导致问题,所以我检查了所有这些字符(在文件夹上,而不是文件名上,但我希望文件名也有类似的结果)。这是我的详尽测试:

Windows 不允许在文件夹名称中使用这些:

\\/:*?"<>|

当路径包含以下任何特殊字符时,解决方案将加载并运行:

`~-_+='',.()[]{}!@#$%&

但是,在 Windows 允许的路径中包含这些字符中的任何一个都会导致 CLR 或 Visual Studio 中的问题:

; 导致“HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动”

^ VS 无法加载解决方案并显示如下错误消息:

"在命令行中指定了以下文件:<.sln> 找不到这些文件,也不会加载这些文件。” 而是加载了一个完全空的 VS 实例。

我还尝试在 VS 中在名称中包含分号的文件夹下创建一个新的“hello world”控制台应用程序,你猜怎么着?这也无法运行。虽然在这种情况下,显然 IIS 没有 HTTP 错误。相反,它说

“未能创建 CoreCLR,HRESULT:0x80070057”

并抛出进程退出代码。再一次,这是路径中有分号的结果,因为从路径中删除该分号并在 VS 中重新加载解决方案可以使其正确运行。所以分号问题似乎源于CLR,因此与IIS无关。

以下是一些有关根本原因的相关帖子,这对于在 IIS Express 上运行的 Web 应用程序并不明显:

Failed to create CoreCLR,HRESULT: 0x80070057

https://github.com/dotnet/sdk/issues/13954

因此,感谢那些对 RCA 非常有帮助的帖子的作者。

有人会认为操作系统允许的特殊字符也可以用于 Visual Studio 代码的路径中。那好吧。吸取的教训。

ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?

ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?

 

ASP.NET MVC 的路由实际上是建立在 ASP.NET 的路由系统之上的.

MVC 路由注册通常是这样的:

RouteTable 是一个全局路由表, 它的 Routes 静态属性是一个 RouteCollection 类型的实例,而 RouteCollection 是一个继承自 Collection<RouteBase> 的子类, RouteBase 是 ASP.NET 路由系统定义的基类

.

RouteBase 有一个唯一的实现类:

当我们通过如下方法注册一个路由时:

 

实际是向全局路由表中添加了一个 Route 类型的实例,部分源码如下: 

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
    {
      ......
      Route route = new Route(url, (IRouteHandler) new MvcRouteHandler())
      {
    ......
      };
    ......
      routes.Add(name, (RouteBase) route);
      return route; }

从源码中我们可以看到,添加 Route 对象的时候,直接传入了一个 MvcRouteHandler 类型的实例.

我们知道, ASP.NET 的路由系统对路由的解析是通过一个注册的 HttpModule 对象实现对请求的拦截,然后为当前 Http 上下文动态映射一个 HttpHandler 对象, 而这个  HttpHandler 对象会接管对当前请求的处理并最终对请求予以响应.

这个注册的 HttpModule 对象的类型叫做 UrlRoutingModule .

我们可以在ASP.NET 的全局系统配置文件中找到它:

     <httpModules>
        ......
            <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule"/>
           ......
        </httpModules>

该类型在 PostResolveRequestCache 事件实现对请求的拦截:

 在拦截时,它做了这么几件事(部分源码省略):

public virtual void PostResolveRequestCache(HttpContextBase context)
    {
      RouteData routeData = this.RouteCollection.GetRouteData(context);     
      IRouteHandler routeHandler = routeData.RouteHandler; IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);  context.RemapHandler(httpHandler); }

1.遍历所有注册的路由,也就是所有添加到全局路由表中的 Route 类型的实例,通过调用它们的 GetRouteData 方法,拿到第一个匹配的 RouteData (路由数据);

2.拿到路由数据中的 RouteHandler 对象, 其实就是 MvcRouteHandler 类型的实例;

3.调用 MvcRouteHandler 的 GetHttpHandler 方法,拿到 HttpHandler.

MvcRouteHandler 的 GetHttpHandler 方法源码如下:

protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
      requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));
      return (IHttpHandler) new MvcHandler(requestContext);
    }

可以看到,直接 new 了一个 MvcHandler 类型的实例,

最终,请求转交给这个 MvcHandler 类型的实例处理.

 

ASP.NET Web API 是怎么与 ASP.NET 路由系统接轨的呢?

我们知道, ASP.NET 的路由系统对路由的解析是通过一个注册的 HttpModule 对象实现对请求的拦截,然后为当前 Http 上下文动态映射一个 HttpHandler 对象, 而这个  HttpHandler 对象会接管对当前请求的处理并最终对请求予以响应.

这一条不仅对 MVC 适用, 对 Web API 同样适用,因为他俩都是借助于 ASP.NET 的路由系统.

区别在于 HttpHandler 的类型不一样而已.

ASP.NET Web API 注册路由的代码通常是这样的:

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new
                {
                    id = RouteParameter.Optional } );

config.Routes 是一个 HttpRouteCollection 类型的实例,并且是只读的.

只读的,就意味着只能在该实例所属的类的构造函数中初始化.

我们知道,这个 config 是 HttpConfiguration 类型,它在 GlobalConfiguration 类中初始化.

在它的初始化代码中,我们可以看到:

private static Lazy<HttpConfiguration> CreateConfiguration()
        {
            return new Lazy<HttpConfiguration>(() =>
            {
                HttpConfiguration config = new HttpConfiguration(new HostedHttpRouteCollection(RouteTable.Routes));
          ......return config;
            });
        }

 

HttpConfiguration 实际是对 HostedHttpRouteCollection 的封装,而后者是对 RouteTable.Route 的封装. 即 ASP.NET 全局路由表的封装.

所以说, HttpConfiguration 类型封装了 ASP.NET 的全局路由表. 它的 Routes 属性的实际类型是  HostedHttpRouteCollection

我们再回头看 config.Routes.MapHttpRoute 方法 , 也就是 HostedHttpRouteCollection 类型的 MapHttpRoute 方法:

public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler)
        {
            ......
            IHttpRoute route = routes.CreateRoute(routeTemplate, defaultsDictionary, constraintsDictionary, dataTokens: null, handler: handler);
            routes.Add(name, route);
            return route;
        }

很简单,创建了一个路由,然后添加它.

我们继续查看 HostedHttpRouteCollection 类型的 CreateRoute 方法:

public override IHttpRoute CreateRoute(string uriTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, HttpMessageHandler handler)
    {
    ......
    return (IHttpRoute) new HostedHttpRoute(uriTemplate, defaults, constraints, dataTokens, handler); }

返回了一个 HostedHttpRoute 类型的实例.

我们可以把这个方法 和 上面 MVC 的 MapRoute 方法做比较:

MVC:

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
    {
      ......
      Route route = new Route(url, (IRouteHandler) new MvcRouteHandler())
      {
    ......
      };
    ......
      routes.Add(name, (RouteBase) route);
      return route;
    }

 

是不是非常像!不同的只是 MVC  new 的路由对象是 Route 类型,而 Web API new 的路由对象是 HostedHttpRoute 类型.

讲到这里,其实 ASP.NET Web API 的路由系统还没有和 ASP.NET 的路由系统衔接起来,它们二者的关系仅仅体现在下面这句话:

HttpConfiguration 实际是对 HostedHttpRouteCollection 的封装,而后者是对 RouteTable.Route 的封装. 即 ASP.NET 全局路由表的封装.

但是,当 HostedHttpRoute 创建后,调用 HostedHttpRouteCollection 的 Add 方法添加时,衔接就真正开始了:

public override void Add(string name, IHttpRoute route)
        {
            _routeCollection.Add(name, route.ToRoute());
        }
 

 _routeCollection 是 RouteCollection 类型,没看错,就是 ASP.NET 路由系统的 RouteCollection .

所以,这句代码实际是向 ASP.NET 路由系统的路由集合中添加路由,目的就是为了让 UrlRoutingModule 能够拦截到匹配了 Web API 注册的路由的请求.

但是,问题来了,从上面 MVC 的讲解中我们知道, ASP.NET 路由系统的 RouteCollection 是一个继承自 Collection<RouteBase> 的子类, RouteBase 是 ASP.NET 路由的基类,

而 HostedHttpRoute 是实现了 IHttpRoute 接口的实例, 

IHttpRoute  和 RouteBase 风马牛不相接啊!

所以,添加时,Web API 通过 HostedHttpRoute  的 ToRoute 方法,将自己转成了 RouteBase 类型!!

这个转化非常简单:

public static Route ToRoute(this IHttpRoute httpRoute)
        {
       ...... HostedHttpRoute hostedHttpRoute = httpRoute as HostedHttpRoute; if (hostedHttpRoute != null) { return hostedHttpRoute.OriginalRoute; }
       ...... }

问题又来了, HostedHttpRoute 类型的 OriginalRoute 是个什么鬼?当然,肯定是个 Route  类型,也就是说,它是一个 ASP.NET 路由系统定义的 Route 类型.那它是怎么来的呢?

我们知道,在 Web API 注册路由时, MapHttpRoute 内部创建了一个 HostedHttpRoute 类型的实例,并且是直接 new 的.

那么我们去看看 HostedHttpRoute 的构造函数:

public HostedHttpRoute(string uriTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, HttpMessageHandler handler)
        {
            ......
            OriginalRoute = new HttpWebRoute(uriTemplate, routeDefaults, routeConstraints, routeDataTokens, HttpControllerRouteHandler.Instance, this);
            ......
        }

OriginalRoute 原来是一个 HttpWebRoute 类型,而 HttpWebRoute 则是 ASP.NET 路由系统定义的 Route 类型的子类.

并且,创建 HttpWebRoute 类型的实例时,传入了一个 ASP.NET 路由系统定义的 IRouteHandler 类型的实例 : HttpControllerRouteHandler.Instance

而 HttpControllerRouteHandler 的 GetHttpHandler 方法如下:

/// <summary>
        /// Provides the object that processes the request.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the request.</param>
        /// <returns>
        /// An object that processes the request.
        /// </returns>
        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new HttpControllerHandler(requestContext.RouteData);
        }

返回了一个 HttpControllerHandler 类型的实例.

HttpControllerHandler 类型的XML注释则非常清晰的解释了它的作用:

  /// 用于将 ASP.NET 请求传递给管道并写回结果。</summary>

这里说的管道,自然就是 Web API 的消息处理管道了.

 

总结:

ASP.NET MVC 和 ASP.NET Web API 都是通过 UrlRoutingModule ,在 PostResolveRequestCache 事件实现对请求的拦截.

拦截后,通过对HTTP上下文,路由等一系列处理后,

MVC 创建了 MvcHandler 进行具体的请求处理及响应;

Web API 创建了 HttpControllerHandler 进行具体的请求处理及响应.

原文出处:https://www.cnblogs.com/refuge/p/10505565.html

今天的关于ASP.NET MVC 优化笔记 -SEOasp.net mvc视频教程的分享已经结束,谢谢您的关注,如果想了解更多关于Android studio Inspection 优化笔记、ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门、ASP.NET Core 或 ASP.NET Core MVC 解决方案无法运行,IIS Express 抛出 HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动、ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?的相关知识,请在本站进行查询。

本文标签: