GVKun编程网logo

asp.net – 使用“async”(即使它应该完成)作为MVC路由的一部分使路由死锁;怎么可以避免呢?

7

如果您想了解asp.net–使用“async”(即使它应该完成)作为MVC路由的一部分使路由死锁;怎么可以避免呢?的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于ASP.NetMVCC#中

如果您想了解asp.net – 使用“async”(即使它应该完成)作为MVC路由的一部分使路由死锁;怎么可以避免呢?的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于ASP .Net MVCC# 中默认路由的三个部分是什么?、ASP.NET Core中使用默认MVC路由的配置、ASP.NET MVC路由扩展:路由映射、ASP.NET MVC路由的无限URL参数的有价值的信息。

本文目录一览:

asp.net – 使用“async”(即使它应该完成)作为MVC路由的一部分使路由死锁;怎么可以避免呢?

asp.net – 使用“async”(即使它应该完成)作为MVC路由的一部分使路由死锁;怎么可以避免呢?

考虑以下(基于默认的MVC模板),这是在后台发生的一些“东西”的简化版本 – 它完好无损,并显示预期的结果20:
public ActionResult Index()
{
    var task = SlowDouble(10);
    string result;
    if (task.Wait(2000))
    {
        result = task.Result.ToString();
    }
    else
    {
        result = "timeout";
    }

    ViewBag.Message = result;
    return View();
}
internal static Task<long> SlowDouble(long val)
{
    taskcompletionsource<long> result = new taskcompletionsource<long>();
    ThreadPool.QueueUserWorkItem(delegate
    {
        Thread.Sleep(50);
        result.SetResult(val * 2);
    });
    return result.Task;
}

然而,现在如果我们在混合中添加一些异步:

public static async Task<long> IndirectSlowDouble(long val)
{
    long result = await SlowDouble(val);

    return result;
}

并将路由中的第一行更改为:

var task = IndirectSlowDouble(10);

那么它不行;它代替了。如果我们添加断点,返回结果;在异步方法中只有在路由已经完成之后才会发生,基本上看起来系统不愿意使用任何线程恢复异步操作,直到请求完成。更糟:如果我们使用了.Wait()(或访问.Result),那么它将完全死锁。

那是什么呢?明显的解决方法是“不要异步”,但是在使用库时并不容易。最后,SlowDouble和IndirectSlowDouble之间没有任何功能上的区别(尽管有明显的结构差异)。

注意:在控制台/ winform / etc中完全相同的东西可以正常工作。

解决方法

这与ASP.NET(Pre .NET 4.5)中实现同步上下文的方式有关。关于这个行为有很多问题:

Task.WaitAll hanging with multiple awaitable tasks in ASP.NET

Asp.net SynchronizationContext locks HttpApplication for async continuations?

在ASP.NET 4.5中,本文介绍了同步上下文的一个新实现。

http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx

ASP .Net MVCC# 中默认路由的三个部分是什么?

ASP .Net MVCC# 中默认路由的三个部分是什么?

ASP.Net MVC 路由模块负责映射传入的浏览器 对特定 MVC 控制器操作的请求。当 ASP.NET MVC 应用程序 启动,然后应用程序向框架注册一个或多个模式 路由表告诉路由引擎如何处理与这些匹配的任何请求 模式。当路由引擎在运行时收到请求时,它会匹配该请求 请求的 URL 与注册的 URL 模式相对应并给出响应 根据模式匹配。

ASP.NET 引入了路由来消除将每个 URL 映射到一个 物理文件。路由使我们能够定义映射到请求的 URL 模式 处理程序。 System.Web.Routing 由 MVC 框架使用,但也被 ASP.NET 动态数据。 MVC 框架利用路由来引导请求 到控制器。 Global.asax 文件是我们应用程序的一部分,我们将在其中 定义我们的应用程序的路由。

下面是 mvc 应用程序的路由配置 -

public class RouteConfig{
   public static void RegisterRoutes(RouteCollection routes){
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      routes.MapRoute(
            name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
      );
   }
}
登录后复制

路由名称

路由是映射到处理程序的 URL 模式。处理程序可以是控制器 处理请求的 MVC 应用程序。路线名称可以用作 对给定路由的具体引用。

约束

针对 URL 模式应用的一组约束,以更狭义地定义 它匹配的 URL。

URL 模式

URL 模式可以包含文字值和变量占位符。文字和 占位符位于 URL 中由斜杠 (/) 分隔的部分中 字符。

当发出请求时,URL 被解析为段和占位符,并且 变量值被提供给请求处理程序。这个过程类似于 查询字符串中的数据被解析并传递给请求处理程序。在这两种情况下 变量信息包含在 URL 中并以以下形式传递给处理程序 键值对。对于查询字符串,键和值都在 URL 中。为了 路由,键是 URL 模式中定义的占位符名称,并且只有 值位于 URL 中。

默认值

当我们定义路由时,可以为参数分配默认值。默认值是 包含默认路由值的对象。默认路由的三段 包含控制器、操作和 ID。

ASP .Net MVCC# 中默认路由的三个部分是什么?

在上面的URL中,将匹配相应的控制器和操作。如果我们是 不发送 URL 中的控制器和操作方法并基于默认值 路由相应的控制器操作方法将被调用。

ASP .Net MVCC# 中默认路由的三个部分是什么?

以上就是ASP .Net MVCC# 中默认路由的三个部分是什么?的详细内容,更多请关注php中文网其它相关文章!

ASP.NET Core中使用默认MVC路由的配置

ASP.NET Core中使用默认MVC路由的配置

ASP.NET Core里Route这块的改动不大,只是一些用法上有了调整,提供了一些更加简洁的语法。

而对于自定义路由的支持当然也是没有问题的,这个功能应该是从MVC1.0版本就已经有这个功能。

先看看ASP.NET Core里面实现默认MVC路由的配置方式

通常情况下,在使用MVC项目的时候,默认的路由就足够了,就是常见的通过Controller和Action获取具体的方法的方式。

从一个最基本的项目开始,执行以下步骤,就可以使得项目支持MVC路由

1.创建一个空白的ASP.NET Core(Empty) Web项目

2.打开project.json,在”dependencies”节点下增加如下依赖项目

"Microsoft.AspNetCore.Mvc": "1.0.0"

保存之后,项目会自动restore packages到本地

3.加入默认MVC路由配置

打开Startup.cs文件

在ConfigureServices方法,加入如下代码

services.AddMvc();

这个扩展方法把Mvc的一些服务都注入到容器中

在Configure方法,注释最后兜底的那个“hello world”语句,这个语句的作用是不管什么请求都它来负责。 

然后在Configure方法加入如下代码

app.UseMvcWithDefaultRoute();

这个扩展方法实际上使用了一个Middleware,默认的Url template跟之前MVC版本的一致,上述代码等同于以下效果

app.UseMvc(routes =>
   {
    routes.MapRoute(
     name: "Default",
     template: "{controller}/{action}/{id?}",
     defaults: new {controller = "Home", action = "Index"}
    );
   });

最终的Startup.cs代码如下

public class Startup
 {
  public void ConfigureServices(IServiceCollection services)
  {
   services.AddMvc();
  }

  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
  {
   loggerFactory.AddConsole();

   if (env.IsDevelopment())
   {
    app.UseDeveloperExceptionPage();
   }

   //app.Run(async (context) =>
   //{
   // await context.Response.WriteAsync("Hello World!");
   //});
   app.UseMvcWithDefaultRoute();
  }
 }

4.到此配置已经完成,但是运行站点直接显示404,没显示Hello world说明已经生效了,只是Empty的项目没有Controller,那么定义一个Controller吧。

手动在项目根目录创建Controllers目录,然后新建一个Controller,名字为HomeController,然后直接运行网站(应该刷新一下就可以了)。

站点继续提示错误,但不是404了,是提示找不到Index这个View。

继续在项目根目录创建Views目录,然后在Views目录下新建一个Home目录,在Home目录新建一个Index.cshtml,填写一些内容,再次刷新就可以了。

当然这是最基本的配置,比如要进一步支持在cshtml里面实现智能感知,支持静态文件路由等还得加入更多的依赖和配置。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:
  • ASP.NET Core中MVC模式实现路由二
  • ASP.NET Core中MVC模式实现路由一
  • ASP.NET Core MVC学习教程之路由(Routing)
  • 详解ASP.NET Core MVC 源码学习:Routing 路由
  • ASP.NET Core MVC 配置全局路由前缀
  • ASP.NET Core MVC路由(Routing)的用法

ASP.NET MVC路由扩展:路由映射

ASP.NET MVC路由扩展:路由映射

上周我写了三篇文章(一、二、三)详细地介绍了ASP.NET的路由系统。ASP.NET的路由系统旨在通过注册URL模板与物理文件之间的映射进而实现请求地址与文件路径之间的分离,但是对于ASP.NET MVC应用来说,请求的目标不再是一个具体的物理文件,而是定义在某个Controller类型中的Action方法。出于自身路由特点的需要,ASP.NET对ASP.NET的路由系统进行了相应的扩展。

目录
一、基本路由映射
二、实例演示:注册路由映射与查看路由信息
三、基于Area的路由映射
    1、AreaRegistration与AreaRegistrationContext 
    2、AreaRegistration的缓存
    3、实例演示:查看基于Area路由信息

一、基本路由映射

通过前面的介绍我们知道基于某个物理文件的路由映射通过调用代表全局路由表的RouteTable的静态属性Routes(一个RouteCollection对象)的MapPageRoute方法来完成,为了实现针对目标Controller和Action的路由,ASP.NET MVC针对RouteCollection类型定义了一系列的扩展方法以实现文件路径无关的路由映射,这些扩展方法定义在RouteCollectionExtensions类型中。如下面的代码片断所示,RouteCollectionExtensions定义了两组方法,方法IgnoreRoute用于注册不需要进行路由的URL模板,对应于RouteCollectionExtensions的Ignore方法;仿佛MapRoute用于进行基于URL模板的路由注册,对应于RouteCollectionExtensions的MapPageRoute方法。

   1: public static class RouteCollectionExtensions
   2: {
   3:     //其他成员   
   4:     public static void IgnoreRoute(this RouteCollection routes, string url);    
   5:     public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);   
   6:  
   7:     public static Route MapRoute(this RouteCollection routes, string name, string url);    
   8:     public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);    
   9:     public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);    
  10:     public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);    
  11:     public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);    
  12:     public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);
  13: }

由于ASP.NET MVC的路由注册与具体的物理文件无关,所以MapRoute方法中并没有一个表示文件路径的physicalFile参数。与直接定义在RouteCollectionExtensions中的Ignore和MapPageRoute方法不同的是,表示默认变量的参数defaults和基于正则表达式的变量约束的参数constraints都不再是一个RouteValueDictionary对象,而是一个普通的object。这主要是为了编程上的便利,使得我们可以通过匿名类型的方式来指定这两个参数值。该方法在内部会通过反射的方式得到指定对象所有属性值,并转换为RouteValueDictionary对象,其属性名和属性值作为字典元素的Key和Value。

对于ASP.NET MVC来说,最终需要通过在请求地址中指定的Controller名称来创建具体的Controller实例。由于Controller名称 仅仅对应着类型的名称,Controller的成功实例化的前提是我们能够正确地解析出它的具体类型,所以我们需要使用了命名空间。在调用MapRoute方法的时候我们可以通过字符串数组类型的参数namespaces来指定一个命名空间的列表。对于注册的命名空间,可以指定一个代表完整命名空间的字符串,也可以使用“*”作为通配符。

添加的命名控件列表最终是被存储于Route对象的DataTokens属性中,对应的Key为“Namespaces”。MapRoute方法没有为初始化Route对象的DataTokens属性提供相应的参数,如果没有指定命名空间列表,所有通过该方法添加的Route对象的DataTokens属性总是一个空的RouteValueDictionary对象。

对于针对定义在某个Controller中的某个Action的请求,如果注册的路由表与之匹配,具体匹配的某个路由对象的GetRouteData被调用并返回一个具体的RouteData对象。根据对请求地址进行解析得到的目标Controller和Action的名称必须包含在该RouteData的Values属性对应的RouteValueDictionary对象中,其对应的Key分别为controlleraction

二、 实例演示:注册路由映射与查看路由信息

ASP.NET MVC通过定义在RouteCollectionExtensions中的扩展方法MapRoute进行路由映射,为了让读者对此有一个深刻的认识,我们来进行一个简单的实例演示。我们依然沿用之前关于获取天气信息的场景,看看通过这种方式进行注册的Route对象针对匹配的HTTP请求返回怎样的RouteData对象。[源代码从这里下载]

我们在创建的ASP.NET Web应用(不是ASP.NET MVC应用)添加一个Web页面(Default.aspx),并按照之前的方式以内联代码的方式直接将RouteData的相关属性显示出来,页面主体部分的HTML如下所示。需要注意的是我们显示的RouteData是从定义的方法GetRouteData方法获取的,而不是对应于当前页面的RouteData属性。

   1: <body>
   2:     <form id="form1" runat="server">
   3:     <div>
   4:         <table>
   5:             <tr>
   6:                 <td>Route:</td>
   7:                 <td><%=GetRouteData().Route != null? GetRouteData().Route.GetType().FullName:"" %></td>
   8:             </tr>
   9:             <tr>
  10:                 <td>RouteHandler:</td>
  11:                 <td><%=GetRouteData().RouteHandler != null? GetRouteData().RouteHandler.GetType().FullName:"" %></td>
  12:             </tr>
  13:             <tr>
  14:                 <td>Values:</td>
  15:                 <td>
  16:                     <ul>
  17:                         <%foreach (var variable in GetRouteData().Values)
  18:                           {%>
  19:                         <li><%=variable.Key%>=<%=variable.Value%></li>
  20:                         <% }%>
  21:                     </ul>
  22:                 </td>
  23:             </tr>
  24:             <tr>
  25:                 <td>DataTokens:</td>
  26:                 <td>
  27:                     <ul>
  28:                         <%foreach (var variable in GetRouteData().DataTokens)
  29:                           {%>
  30:                         <li><%=variable.Key%>=<%=variable.Value%></li>
  31:                         <% }%>
  32:                     </ul>
  33:                 </td>
  34:             </tr>
  35:         </table>
  36:     </div>
  37:     </form>
  38: </body>

我们将GetRouteData方法定义在当前页面的后台代码中。如下面的代码片断所示,我们手工创建了一个HttpRequest和HttpResponse对象,HttpRequest的请求的地址为“http://localhost:3721/0512/3”(3721是本Web应用对应的端口号)。根据这两个对象创建了HttpContext对象,并以此创建一个HttpContextWrapper对象。最终我们将其作为参数调用RouteTable的Routes属性的GetRouteData方法并返回。这个方法实际上就是模拟注册的路由表针对相对地址为“/0512/3”的HTTP请求的路由处理。

   1: public partial class Default : System.Web.UI.Page
   2: {
   3:     private RouteData routeData;
   4:     public RouteData GetRouteData()
   5:     {
   6:         if (null != routeData)
   7:         {
   8:             return routeData;
   9:         }
  10:         HttpRequest request = new HttpRequest("default.aspx", "http://localhost:3721/0512/3", null);
  11:         HttpResponse response = new HttpResponse(new StringWriter());
  12:         HttpContext context = new HttpContext(request, response);
  13:         HttpContextBase contextWrapper = new HttpContextWrapper(context);
  14:         return routeData = RouteTable.Routes.GetRouteData(contextWrapper);
  15:     }
  16: }

具体的路由映射依然定义在添加的Global.asax文件中。如下面的代码片断所示,我们通过调用RouteTable的Routes属性的MapRoute方法注册了一个采用“{areacode}/{days}”作为URL模板的路由对象,并指定了默认变量、约束和命名空间列表。

   1: public class Global : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start(object sender, EventArgs e)
   4:     {
   5:         object defaults = new { areacode = "010", days = 2, defaultCity="BeiJing", defaultDays=2};
   6:         object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}"};
   7:         string[] namespaces = new string[] { "Artech.Web.Mvc", "Artech.Web.Mvc.Html" };
   8:         RouteTable.Routes.MapRoute("default", "{areacode}/{days}", defaults, constraints, namespaces);
   9:     }               
  10: }

如果我们现在在浏览器中访问Default.aspx页面,会得到下图所示的结果,从中我们可以得到一些有用的信息:

三、基于Area的路由映射

对于一个较大规模的Web应用,我们可以从功能上通过Area将其划分为较小的单元。每个Area相当于一个独立的子系统,具有一套包含Models、Views和Controller在内的目录结构和配置文件。一般来说,每个Area具有各自的路由规则(URL模版上一般会体现Area的名称),而基于Area的路由映射通过AreaRegistration进行注册。

AreaRegistration与AreaRegistrationContext

基于Area的路由映射通过AreaRegistration进行注册。如下面的代码片断所示,AreaRegistration是一个抽象类,抽象只读属性AreaName返回当前Area的名称,而抽象方法RegisterArea用于实现基于当前Area的路由注册。

   1: public abstract class AreaRegistration
   2: {    
   3:     public static void RegisterAllAreas();
   4:     public static void RegisterAllAreas(object state);
   5:  
   6:     public abstract void RegisterArea(AreaRegistrationContext context);
   7:     public abstract string AreaName { get; }
   8: }

AreaRegistration定义了两个抽象的静态RegisterAllAreas方法重载,参数state用于传递给具体AreaRegistration的数据。当RegisterAllArea方法执行的时候,它先遍历通过BuildManager的静态方法GetReferencedAssemblies方法得到的编译Web应用所使用的程序集,通过反射得到所有实现了接口IController的类型,并通过反射创建相应的AreaRegistration对象。对于每个AreaRegistration对象,一个AreaRegistrationContext对象被创建出来并作为参数调用它们的RegisterArea方法。

如下面的代码片断所示,AreaRegistrationContext的只读属性AreaName表示Area的名称,属性Routes是一个代表路由表的RouteCollection对象,而State是一个用户自定义对象,它们均通过构造函数进行初始化。具体来说,对于最初通过调用AreaRegistration的静态方法RegisterAllAreas创建的AreaRegistrationContext对象,AreaName来源于当前AreaRegistration对象的同名属性,Routes则对应着RouteTable的静态属性Routes表示的全局路由表,而在调用RegisterAllAreas方法指定的参数(state)作为AreaRegistrationContext对象的State参数。

   1: public class AreaRegistrationContext
   2: {    
   3:     public AreaRegistrationContext(string areaName, RouteCollection routes);
   4:     public AreaRegistrationContext(string areaName, RouteCollection routes, object state);
   5:  
   6:     public Route MapRoute(string name, string url);
   7:     public Route MapRoute(string name, string url, object defaults);
   8:     public Route MapRoute(string name, string url, string[] namespaces);
   9:     public Route MapRoute(string name, string url, object defaults, object constraints);
  10:     public Route MapRoute(string name, string url, object defaults, string[] namespaces);
  11:     public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces);
  12:  
  13:     public string AreaName { get; }
  14:     public RouteCollection Routes { get; }
  15:     public object State { get; }
  16:     public ICollection<string> Namespaces { get; }
  17: }

AreaRegistrationContext的只读属性Namespaces表示一组优先匹配的命名空间(当多个同名的Controller类型定义在不同的命名空间中)。当针对某个具体AreaRegistration的AreaRegistrationContext被创建的时候,如果AreaRegistration类型具有命名空间,那么会在这个命名空间基础上添加“.*”后缀并添加到Namespaces集合中。换言之,对于多个定义在不同命名空间中的同名Controller类型,会优先选择包含在当前AreaRegistration命名空间下的Controller

AreaRegistrationContext定义了一系列的MapRoute用于进行路由映射注册,方法的使用以及参数的含义与定义在RouteCollectionExtensions类型中的同名扩展方法一致。在这里需要特别指出的是,如果MapRoute方法没有指定命名空间,则通过属性Namespaces表示的命名空间列表会被使用;反之,该属性中包含的命名空间被直接忽略

当我们通过Visual Studio的ASP.NET MVC项目模版创建一个Web应用的时候,在的Global.asax文件中会生成如下的代码通过调用AreaRegistration的静态方法RegisterAllAreas实现对所有Area的注册,也就是说针对所有Area的注册发生在应用启动的时候。

   1: public class MvcApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         AreaRegistration.RegisterAllAreas();
   6:     }
   7: }

AreaRegistration的缓存

Area的注册(主要是基于Area的路由映射注册)通过具体的AreaRegistration来实现。在应用启动的时候,为了实现对所有Area的注册,需要遍历通过调用BuildManager的静态方法GetReferencedAssemblies方法得到的程序集列表,并通过从中找到所有AreaRegistration类型。如果一个应用涉及到太多的程序集,这个过程可能会耗费很多时间,为了提供性能,基于AreaRegistration类型列表的缓存被采用。

注:BuildManager的静态方法GetReferencedAssemblies返回所有页编译都必须引用的程序集引用的列表,这包括包含 Web.config 文件的<system.web>/<compilation>/<assemblies>配置节中指定的用于编译Web应用所使用的程序集和从 App_Code 目录中的自定义代码生成的程序集以及其他顶级文件夹中的程序集。

ASP.NET MVC对AreaRegistration类型列表的缓存是基于文件的。具体来说,当通过程序集加载和反射得到了所有的AreaRegistration类型列表后,会将其进行序列化并被保存为一个XML物理文件,这个名为MVC-AreaRegistrationTypeCache.xml的XML文件被存放在ASP.NET的临时目录下,具体的路径如下。其中第一个针对寄宿于IIS中的Web应用,后者针对直接通过Visual Studio Developer Server作为宿主的应用。

下面的XML片断体现了这个作为所有AreaRegistration类型缓存的XML文件的结构,从中我们可以看到所有的AreaRegistration类型名称,连同它所在的托管模块和程序集名称都被保存了下来。当调用AreaRegistration的静态方法RegisterAllAreas被调用之后,系统会试图加载该文件,如果该文件存在并且具有期望的结构,那么将不在通过程序集加载和反射来解析AreaRegistration的类型,而是直接对文件内容进行反序列化从而得到所有AreaRegistration类型的列表。

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <!--This file is automatically generated. Please do not modify the contents of this file.-->
   3: <typeCache lastModified="3/22/2012 2:58:47 PM" mvcVersionId="80365b23-7a1d-42b2-9e7d-cc6f5694c6d1">
   4:   <assembly name="Artech.Admin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
   5:     <module versionId="07be22a1-781d-4ade-bd22-34b0850445ef">
   6:       <type>Artech.Admin.AdminAreaRegistration</type>
   7:     </module>
   8:   </assembly>
   9:   <assembly name="Artech.Portal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
  10:     <module versionId="7b0490d4-427e-43cb-8cb5-ac1292bd4976">
  11:       <type>Artech.Portal.PortalAreaRegistration</type>
  12:     </module>
  13:   </assembly>
  14: </typeCache>

实例演示:查看基于Area路由信息

通过AreaRegistration实现的针对Area的路由注册具有一些特殊的细节差异,我们通过实例演示的方式来说明。我们直接使用前面创建的演示实例,并在项目中创建一个自定义的WeatherAreaRegistration。如下面的代码片断所示,WeatherAreaRegistration继承自抽象基类AreaRegistration,表示Area名称的AreaName属性返回“Weahter”。在实现路由注册的RegisterArea方法中我们调用AreaRegistrationContext对象的MapRoute方法注册了一个URL模版为“weather/{areacode}/{days}"的路由对象。默认变量值、约束也被相应地提供。[源代码从这里下载]

   1: public class WeatherAreaRegistration : AreaRegistration
   2: {
   3:     public override string AreaName
   4:     {
   5:         get { return "Weather"; }
   6:     }
   7:     public override void RegisterArea(AreaRegistrationContext context)
   8:     {
   9:         object defaults = new { areacode = "010", days = 2, defaultCity = "BeiJing", defaultDays = 2 };
  10:         object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}" };
  11:         context.MapRoute("weatherDefault", "weather/{areacode}/{days}", defaults, constraints);
  12:     }
  13: }

我们在Global.asax的Application_Start方法中按照如下的方式调用AreaRegistration的静态方法RegisterAllAreas实现对所有Area的注册。按照我们在上面介绍的Area注册原理,对于第一次RegisterAllAreas方法的调用,会自动加载所有引用的程序集来获取所有的AreaRegistration(当然就包括我们上面定义的WeatherAreaRegistration),最后通过反射创建相应的对象并调用RegisterArea方法。

   1: public class Global : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start(object sender, EventArgs e)
   4:     {
   5:         AreaRegistration.RegisterAllAreas();
   6:     }
   7: }

对于定义在Default.aspx页面后台代码中用于进行路由匹配和获取路由信息的GetRouteData方法中,我们对创建的HttpRequest对象略加修改,使请求地址符合通过WeatherAreaRegistration注册的路由规则(/weather/0512/3)。

   1: public partial class Default : System.Web.UI.Page
   2: {
   3:     private RouteData routeData;
   4:     public RouteData GetRouteData()
   5:     {
   6:         if (null != routeData)
   7:         {
   8:             return routeData;
   9:         }
  10:         HttpRequest request = new HttpRequest("default.aspx", "http://localhost:3721/weather/0512/3", null);
  11:         HttpResponse response = new HttpResponse(new StringWriter());
  12:         HttpContext context = new HttpContext(request, response);
  13:         HttpContextBase contextWrapper = new HttpContextWrapper(context);
  14:         return routeData = RouteTable.Routes.GetRouteData(contextWrapper);
  15:     }
  16: }

在浏览器中访问Default.aspx页面,我们会得到如图2-10所示的结果。通过AreaRegistration注册的路由对象得到的RouteData的不同之处主要反映在其DataTokens属性上。如下图所示,除了表示命名空间列表的元素,DataTokens属性表示的RouteValueDictionary还具有两个额外的元素,其中一个Key为“area”的元素代表Area的名称,另一个Key为“UseNamespaceFallback”的元素具有一个布尔类型的值表示是否需要使用后备的命名空间来解析Controller的类型。

如果调用AreaRegistrationContext的MapRoute方法是显式指定了命名空间,或者说对应的AreaRegistration定义在某个命名空间下,这个名称为“UseNamespaceFallback”的DataToken元素的值为False;反之为True。进一步来说,如果在调用MapRoute方法时指定了命名空间列表,那么AreaRegistration类型所示在命名空间会被忽略。也就是说,后者是前者的一个后备,前者具有更高的优先级。

AreaRegistration类型所示在命名空间也不说直接作为最终RouteData的DataTokens中的命名空间,而是在此基础上加上“.*”后缀。如果对本实例得到得到包含RouteData的DataTokens集合中的命名空间,你会发现其值为“WebApp.*”(WebApp是定义WeatherAreaRegistration的命名空间)。

ASP.NET MVC路由展:路由映射
ASP.NET MVC路由扩展:链接和URL的生成


原文链接: http://www.cnblogs.com/artech/archive/2012/03/26/mvc-routing-01.html

ASP.NET MVC路由的无限URL参数

ASP.NET MVC路由的无限URL参数

我需要一个实现,我可以在我的ASP.NET控制器上获得无限的参数。如果我给你一个例子会更好:

让我们假设我将有以下网址:

example.com/tag/poo/bar/poobar
example.com/tag/poo/bar/poobar/poo2/poo4
example.com/tag/poo/bar/poobar/poo89

正如你所看到的,它将在example.com/tag/之后得到无限数量的标签,并且斜杠在这里将是一个分隔符。

在控制器上我想这样做:

foreach(string item in paramaters) { 

    //this is one of the url paramaters
    string poo = item;

}

有没有什么已知的方法来实现这一点?如何获得控制器的值?使用字典< string,string>或List< string&gt ;?

NOTE :

The question is not well explained IMO but I tried my best to fit it.
in. Feel free to tweak it

解决方法

喜欢这个:
routes.MapRoute("Name","tag/{*tags}",new { controller = ...,action = ... });

ActionResult MyAction(string tags) {
    foreach(string tag in tags.Split("/")) {
        ...
    }
}

今天关于asp.net – 使用“async”(即使它应该完成)作为MVC路由的一部分使路由死锁;怎么可以避免呢?的分享就到这里,希望大家有所收获,若想了解更多关于ASP .Net MVCC# 中默认路由的三个部分是什么?、ASP.NET Core中使用默认MVC路由的配置、ASP.NET MVC路由扩展:路由映射、ASP.NET MVC路由的无限URL参数等相关知识,可以在本站进行查询。

本文标签:

上一篇asp.net – 处理单数和多个控制器/路由

下一篇asp.net-mvc – 基于MVC角色的路由(asp.net mvc路由机制)