在.aspx文件中设置一个a href 下载文件链接到一个cshtml网页,显示无法找到资源

登录以解锁更多InfoQ新功能
获取更新并接收通知
给您喜爱的内容点赞
关注您喜爱的编辑与同行
966,690 四月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
使用shieldUI Chart控件在ASP.NET和MVC应用程序中创建一个销售仪表板
使用shieldUI Chart控件在ASP.NET和MVC应用程序中创建一个销售仪表板
David Johnson
0&他的粉丝
3&他的粉丝
日. 估计阅读时间:
,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。
亲爱的读者:我们最近添加了一些个人消息定制功能,您只需选择感兴趣的技术主题,即可获取重要资讯的。
相关厂商内容
相关赞助商
本示例将使用ASP.NET与MVC两种方式讲解。
ASP.NET版本
我首先建立一个Visual Studio的web项目,这个web应用包含一个单独的.aspx文件,其中包含了相关的控件。第二步则是将图表组件所在的.dll文件加入当前项目:
将组件所在的.dll文件加入项目之后,我们还需要在项目中引用它。可以直接在.aspx页面中完成,请见下面的示例:
&%@ Register Assembly=&Shield.Web.UI&
Namespace=&Shield.Web.UI& TagPrefix=&shield& %&
因为这个控件其实是对一个客户端JavaScript组件的服务端封装,我们还需要引用基础的JavaScript图表文件,同样也在.aspx文件中完成:
&link rel=&stylesheet& type=&text/css&
href=&shield-chart.1.2.2-Trial/shield-chart.1.2.2-Trial/css/shield-chart.min.css&/&
&script src=&shield-chart.1.2.2-Trial/shield-chart.1.2.2-Trial/js/jquery-1.9.1.min.js&
type=&text/javascript&&&/script&
&script src=&shield-chart.1.2.2-Trial/shield-chart.1.2.2-Trial/js/shield-chart.all.min.js&
type=&text/javascript&&&/script&
接下来就是要将需求转化为代码了,需求中表示我们需要两个或者更多的图表。在这个示例中,我们将使用一个图表显示所有的季度,另外用一个图表显示每个季度的相关数据,最后还有一个图表与第二个图表相关联。这样,我们就可以按照季度和产品线进行分类,这对于销售仪表板来说是一种常见的数据可视化场景。按照以上所概括的步骤,让我们首先将第一个图表加入.aspx文件中。它的声明部分如下所示:
&asp:UpdatePanel ID=&UpdatePanel2& runat=&server& UpdateMode=&Conditional&
ChildrenAsTriggers=&false&&
&ContentTemplate&
&shield:ShieldChart ID=&ShieldChart1& runat=&server& AutoPostBack=&true&
OnSelectionChanged=&ShieldChart1_SelectionChanged& Width=&320px& Height=&330px&
OnTakeDataSource=&ShieldChart1_TakeDataSource&&
&PrimaryHeader Text=&Quarterly Sales&&
&/PrimaryHeader&
&ExportOptions AllowExportToImage=&false& AllowPrint=&false& /&
&TooltipSettings CustomPointText=&Sales Volume: &b&{point.y}&/b&&&
&/TooltipSettings&
&shield:ChartAxisX CategoricalValuesField=&Quarter&&
&/shield:ChartAxisX&
&shield:ChartAxisY&
&Title Text=&Quarter verview&&&/Title&
&/shield:ChartAxisY&
&DataSeries&
&shield:ChartBarSeries DataFieldY=&Sales&&
&Settings EnablePointSelection=&true& EnableAnimation=&true&&
&DataPointText BorderWidth=&&&
&/DataPointText&
&/Settings&
&/shield:ChartBarSeries&
&/DataSeries&
&Legend Align=&Center& BorderWidth=&&&&/Legend&
&/shield:ShieldChart&
&/ContentTemplate&
&/asp:UpdatePanel&
这里用一个update panel将控件包装起来,以提供更平滑的视觉上的更新。
为了将数据加载到图表控件中,我们利用了TakeDataSource这个事件处理器,以下是.aspx文件的code behind中的部分代码:
protected void ShieldChart1_TakeDataSource(object sender,Shield.Web.UI.
ChartTakeDataSourceEventArgs e)
ShieldChart1.DataSource = new object[]
new {Quarter = &Q1&, Sales = 312 },
new {Quarter = &Q2&, Sales = 212 },
new {Quarter = &Q3&, Sales = 322 },
new {Quarter = &Q4&, Sales = 128 }
控件的DataSource属性告诉了图表需要传递给它以实现可视化的数据是什么。我们传入了一个简单的对象数组,它包含了每个季度的销售数据,这样图表就可以表现出每个季度的数据了。接下来将第二个相关的图表也加入.aspx文件中,看起来是这样的:
&div id=&container2& style=&width: 490 height: 340 margin: top: 5
left: 5 position:&&
&asp:UpdatePanel ID=&UpdatePanel1& runat=&server& pdateMode=&Conditional&
ChildrenAsTriggers=&false&&
&ContentTemplate&
&shield:ShieldChart ID=&ShieldChart2& nTakeDataSource=&ShieldChart2_
TakeDataSource& AutoPostBack=&true&
OnSelectionChanged=&ShieldChart2_SelectionChanged& runat=&server&
Width=&463px& Height=&331px&&
&ExportOptions AllowExportToImage=&false& AllowPrint=&false& /&
&PrimaryHeader Text=&Select a Quarter to show products sales&&
&/PrimaryHeader&
&shield:ChartAxisY&
&Title Text=&Break-Down for selected quarter&&&/Title&
&/shield:ChartAxisY&
&DataSeries&
&shield:ChartDonutSeries EnableValueXSorting=&false& ollectionAlias=&Q
Data& DataFieldY=&Data& DataFieldX=&Product&&
&Settings EnablePointSelection=&true& EnableAnimation=&true&
AddToLegend=&true&&
&DataPointText BorderWidth=&&&
&/DataPointText&
&/Settings&
&/shield:ChartDonutSeries&
&/DataSeries&
&Legend Align=&Center& BorderWidth=&&&&/Legend&
&/shield:ShieldChart&
&/ContentTemplate&
&Triggers&
&asp:AsyncPostBackTrigger ControlID=&ShieldChart1& EventName=&SelectionChanged& /&
&/Triggers&
&/asp:UpdatePanel&
第一和第二个图表控件都应用了一个被选择的事件处理器,以允许对相关控件进行重建,因为他们各自带有一个子图表。这个项目允许最终用户在&SheidChart1&控件以可视化方式显示的4个季度选择一个季度。接下来,对所选中的季度,&ShieldChart&控件会以饼图的方式显示所有可用的数据。用户接下来可以从饼图中选择一个特定的分类,这又载入了第三个图表的数据。它的定义如下所示:
&div id=&container3_box& style=&width: 925 height: 300 border: 2px solid #40B3DF;
margin: top: 420 left: 25 position:&&
&div id=&container3& style=&width: 890 height: 290 margin: top: 5
left: 5 position:&&
&asp:UpdatePanel ID=&UpdatePanel3& runat=&server& UpdateMode=&Conditional&&
&ContentTemplate&
&shield:ShieldChart ID=&ShieldChart3& runat=&server& nTakeDataSource=
&ShieldChart3_TakeDataSource&
Width=&905px& Height=&280px&&
&DataSeries&
&shield:ChartLineSeries DataFieldY=&QuarterSales&&
&Settings AddToLegend=&false&&
&DataPointText BorderWidth=&&&
&/DataPointText&
&/Settings&
&/shield:ChartLineSeries&
&/DataSeries&
&PrimaryHeader Text=&Select a product to show sales details...&&
&/PrimaryHeader&
&ExportOptions AllowExportToImage=&false& AllowPrint=&false& /&
&Legend Align=&Center& BorderWidth=&&&&/Legend&
&/shield:ShieldChart&
&/ContentTemplate&
&Triggers&
&asp:AsyncPostBackTrigger ControlID=&ShieldChart2& EventName=&SelectionChanged& /&
&/Triggers&
&/asp:UpdatePanel&
为了允许对子图表进行重建,还需要加入一个额外的步骤。这一步是当图表被选择的事件触发后在服务端完成的,这样就可以避免编写客户端代码了。具体的服务端代码如下所示:
protected void ShieldChart1_SelectionChanged(object sender,
ChartSelectionChangedEventArgs e)
if (e.Selected)
SelectedQuarter = e.N
DataPerformance = GetPerformanceData().Where(d =& d.Quarter == electedQuarter).
DataPerformance =
ShieldChart2.DataBind();
protected void ShieldChart2_SelectionChanged(object sender,
ChartSelectionChangedEventArgs e)
if (e.Selected)
SalesData = GetSalesDataProducts().Where(s =& s.Quarter == SelectedQuarter &&
s.Product == e.Item.ValueX.ToString()).ToList();
SalesData =
ShieldChart3.DataBind();
以上就完成了ASP.NET的版本,销售仪表板已经可以使用了。请随意该示例代码并作为今后的参考。
MVC应用程序
这个示例也可以很方便地搭建在MVC上。首先建立一个新的Visual Studio 2012 MV应用程序,使用.NET Framework 4.0。为了使用图表控件的功能,我在项目中添加了对Shield.Mvc.UI这个dll文件的引用:
以下是该应用程序的文件夹结构:
接下来我会逐一地讲解每个文件夹中令人感兴趣的部分,并讲述一些代码之外的信息,以及每段代码的重要性。首先从Views文件夹开始,它包含了四个不同的视图,三个用来显示图表,另一个则包含主体页面结构。第一个视图是&Layout.cshtml&,它决定了页面的主体结构,并且加入了图表组件与它的封装所需的各种css文件与js文件的引用。
&meta name=&viewport& content=&width=device-width& /&
&title&Sales Dashboard - Shield Chart for ASP.NET MVC&/title&
&link rel=&stylesheet& type=&text/css& href=&content/shield-chart.1.2.3-
Trial/css/shield-chart.min.css& /&
&script src=&content/shield-chart.1.2.3-Trial/js/jquery-1.9.1.min.js&
type=&text/javascript&&&/script&
&script src=&content/shield-chart.1.2.3-Trial/js/shield-chart.all.min.js&
type=&text/javascript&&&/script&
&link rel=&stylesheet& type=&text/css& href=&content/css/site.css& /&
&script src=&content/js/scripts.js& type=&text/javascript&&&/script&
&div class=&page&&
&div class=&header&&
&div class=&main&&
@RenderBody()
&div class=&clear&&
&div class=&footer&&
该视图中还包含了一个对&scripts.js&的引用,这个文件包含了客户端事件的处理器,但本文的末尾部分讨论了该文件的更多细节。
下一个视图&Index.cshtml&包含了&季度&图表的定义,这是唯一一个会在初始化页面时就显示的图片,选择这张图表上的某个季度就会加载相应的饼图。这个视图的声明部分包括了设置控件的各种必需属性,例如它的X轴与Y轴,还有DataSeries属性以及实际的数据。其中有趣的一点是&Events&属性,它定义了从条状图中选择某个点之后的事件处理器,这一点对于关联图表与子图表非常关键,当用户从第一张图表中选择了某个季度后,子图表就会显示相应的数据。该页面的代码如下所示:
ViewBag.Title = &Sales Dashboard with Shield Chart for ASP.NET MVC&;
Layout = &~/Views/Shared/Layout.cshtml&;
@model IEnumerable&SalesDashboardMVC.Models.QuarterlySales&
&div class=&dashboard&&
&div class=&header&&
Sales DashBoard using &span class=&highlight&&Shield
UI MVC Chart&/span&
&div class=&topleft&&
@(Html.ShieldChart(Model)
.Name(&quarterlySales&)
.HtmlAttribute(&class&, &chart&)
.PrimaryHeader(header =& header.Text(&Quarterly Sales&))
.Export(false)
.Tooltip(tooltip =& tooltip.CustomPointText(&Sales Volume: &b&{point.y}&/b&&))
.AxisX(axisX =& axisX.CategoricalValues(model =& model.Quarter))
.AxisY(axisY =& axisY.Title(title =& title.Text(&Quarterly Overview&)))
.DataSeries(dataSeries =& dataSeries
.Data(model =& model.Sales)
.EnablePointSelection(true))
.ChartLegend(chartLegend =& chartLegend
.Align(Shield.Mvc.UI.Chart.Align.Center))
.Events(events =& events.PointSelect(&app.quarterSelected&)))
&div class=&topright&&
&div class=&bottom&&
当用户从页面初始化时就显示的条状图中选择了某个季度后,第一个子图表就会加载相应的数据,并显示为一个饼图。它的定义包含在&_PerformanceChart.cshtml&视图中,代码如下所示:
@model IEnumerable&SalesDashboardMVC.Models.PerformanceData&
@(Html.ShieldChart(Model)
.Name(&productsByQuarter&)
.HtmlAttribute(&class&, &chart&)
.Export(false)
.PrimaryHeader(header =& header.Text(&Select a Quarter to show products sales&))
.AxisY(axisY =& axisY.Title(title =& title.Text(&Break-Down for selected quarter&)))
.DataSeries(dataSeries =& dataSeries
.Name(&Q Data&)
.Data(model =& new
collectionAlias = model.Product,
x = model.Product,
y = model.Data,
.EnablePointSelection(true)
.AddToLegend(true))
.ChartLegend(chartLegend =& chartLegend.Align(Shield.Mvc.UI.Chart.Align.Center))
.Events(events =& events.PointSelect(&app.productSelected&)))
当用户选择了饼图里的某一项之后,就会加载数据并显示最后一张图表。它的代码包含在&_SalesDetailsChart.cshtml&文件中,具体定义如下:
@model IEnumerable&SalesDashboardMVC.Models.SalesByProduct&
@(Html.ShieldChart(Model)
.Name(&salesDetails&)
.HtmlAttribute(&class&, &chart&)
.PrimaryHeader(header =& header.Text(&Select a product to show sales details&))
.Export(false)
.DataSeries(dataSeries =& dataSeries
.Data(model =& model.QuarterSales)
.AddToLegend(false)))
&Models&文件夹包含了数据的模型,它将用以加载三个不同的图表。举例来说,首个图表将对应类型&QuarterlySales&中的数据,它的代码如下:
namespace SalesDashboardMVC.Models
public class QuarterlySales
public string Quarter { }
public decimal Sales { }
public static IEnumerable&QuarterlySales& GetData()
yield return new QuarterlySales() { Quarter = &Q1&, Sales = 312 };
yield return new QuarterlySales() { Quarter = &Q2&, Sales = 212 };
yield return new QuarterlySales() { Quarter = &Q3&, Sales = 322 };
yield return new QuarterlySales() { Quarter = &Q4&, Sales = 128 };
其它图表也将对应类似的数据类,我在这里就略过不提了。&Controllers&文件夹包含了一个单独的控制器,它将响应图表的选择所对应的各种行为。代码如下:
public class HomeController: Controller
// GET: /Home/
public ActionResult Index()
return View(QuarterlySales.GetData());
public ActionResult Performance(string quarter)
return View(&_PerformanceChart&,
PerformanceData.GetDataByQuarter(quarter));
public ActionResult Details(string product, string quarter)
return View(&_SalesDetailsChart&, alesByProduct.
GetDataByProductAndQuarter(product, quarter));
有一段重要的代码需要引起注意,那就是&Content&文件夹下的&scripts.js&文件。从以上的代码声明可以看出,第一与第二个图表包括了选择事件的处理器。这些处理器将处理客户端的事件,这是由用户在条状图或饼图中选择了一段数据所触发的,而&scripts.js&文件则包含了这些事件的客户端处理器,它的代码如下:
(function (jQuery) {
this.app = {
quarter: &&,
quarterSelected: function (e) {
var quarter = app.quarter = e.point.
$(&.topright&).load(&/performance/& + quarter);
$(&.bottom&).empty();
productSelected: function (e) {
var product = e.point.x,
quarter = app.
$(&.bottom&).load(&/details/& + product + &/& + quarter);
}).call(this, jQuery);
实质上,这段代码会发起一个Ajax请求,它将处理被选择的数据,而这是由方法的参数中传递的。该请求将触发&Performance&或者&Details&的行为处理器,它们都由&HomeController&中的控制器所定义。
我们的代码中最主要的部分到这里差不多就介绍完了,完整的代码和一个可运行的项目都可以在下载。
David Johnson来自于英国伦敦,他已经是一位37岁的&老&程序员了。过去的15年来他主要工作于web技术的领域,而过去10年中他主要专注于ASP.NET和MVC平台。David作为一名外包开发者参与了许多项目,最近的职位是在ShieldUI担任首席开发者。
查看英文原文:
Author Contacted
语言 & 开发
403 他的粉丝
ASP.NET MVC
0 他的粉丝
0 他的粉丝
0 他的粉丝
11 他的粉丝
691 他的粉丝
ASP.NET WebForms
0 他的粉丝
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
InfoQ每周精要
订阅InfoQ每周精要,加入拥有25万多名资深开发者的庞大技术社区。
架构 & 设计
文化 & 方法
InfoQ.com及所有内容,版权所有 ©
C4Media Inc. InfoQ.com 服务器由 提供, 我们最信赖的ISP伙伴。
极客邦控股(北京)有限公司
找回密码....
InfoQ账号使用的E-mail
关注你最喜爱的话题和作者
快速浏览网站内你所感兴趣话题的精选内容。
内容自由定制
选择想要阅读的主题和喜爱的作者定制自己的新闻源。
设置通知机制以获取内容更新对您而言是否重要
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
我们发现您在使用ad blocker。
我们理解您使用ad blocker的初衷,但为了保证InfoQ能够继续以免费方式为您服务,我们需要您的支持。InfoQ绝不会在未经您许可的情况下将您的数据提供给第三方。我们仅将其用于向读者发送相关广告内容。请您将InfoQ添加至白名单,感谢您的理解与支持。如何将HTML网站与aspx相连 效果是点击HTML的按钮跳到aspx页面 怎么实现???急求_百度知道
如何将HTML网站与aspx相连 效果是点击HTML的按钮跳到aspx页面 怎么实现???急求
我有更好的答案
直接a链接不就可以了???&a href=&test.aspx&&&input type=&button& id=&button& value=&跳转& /&&/a&
为您推荐:
其他类似问题
aspx的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。正如ASP.NET MVC名字所揭示的一样,是以模型-视图-控制设计模式构建在ASP.NET基础之上的WEB应用程序,我们需要创建相应的程序类来协调处理,完成从客户端请求到结果相应的整个过程:
VS2012中一个典型的MVC工程结构是这样的:
Controllers文件夹下存放控制类,Models文件下是业务数据模型类,Views文件下则是类似于aspx的视图文件。在传统ASP.NET form的应用程序中,客户端的请求最后都映射到磁盘上对应路径的一个aspx的页面文件,而MVC程序中所有的网络请求映射到控制类的某一个方法,我们就从控制类说起,而在讲控制类前,必须要讲的是URL路由。
注册URL路由
我们在浏览器中请求链接&http://mysite.com/Home/Index,MVC认为是这样的URL模式(默认路径映射):
{controller}/{action}
也就是说上面的请求会被映射到Home控制类的Index方法,MVC命名规则中控制类必须以Controller结尾,所以Home控制类应该是HomeController:&
public class HomeController : Controller
public ActionResult Index()
return View();
&MVC是根据什么将上面的请求映射到控制类的相应方法的呢?答案就是路由表,Global.asax在应用程序启动时会调用路由配置类来注册路径映射:
public class MvcApplication : System.Web.HttpApplication
protected void Application_Start()
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
路径映射的配置类则在App_Start目录下:
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 }
routes.MapRoute()添加了一个URL路由到路由表中,URL的映射模式是"{controller}/{action}/{id}",controller和action我们已经清楚,id则是请求中额外的参数,比如我们的请求可以是&http://mysite.com/Home/Index/3,对应的action方法可以是:
public ActionResult Index(int id=1)
  return View();
在传递到Index方法时参数id会被赋值3(保存在RouteData.Values["id"]),MVC足够智能来解析参数并转化为需要的类型,MVC称之为模型绑定(后续具体来看)。上面注册路由时使用了默认参数:defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },如果我们在请求URL没有指定某些参数,defaults参数会被用作默认值,比如:
mydomain.com = mydomain.com/home/index
mydomain.com/home = mydomain/home/index
mydomain.com/customer = mydomain/customer/index
id为可选参数,可以不包括在URL请求中,所以上面注册的路径可以映射的URL有:
mydomain.com
mydomain.com/home
mydomain.com/home/list
mydomain.com/customer/list/4
除此之外不能映射的请求都会得到404错误,比如mydomain.com/customer/list/4/5,这里参数过多不能被映射。
RouteCollection.MapRoute()等同于:
Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
routes.Add("MyRoute", myRoute);
这里直接向Routes表添加一个Route对象。
其他一些URL映射的例子:
routes.MapRoute("", "Public/{controller}/{action}",new { controller = "Home", action = "Index" }); //URL可以包含静态的部分,这里的public
routes.MapRoute("", "X{controller}/{action}"); //所有以X开头的控制器路径,比如mydomain.com/xhome/index映射到home控制器
routes.MapRoute("ShopSchema", "Shop/{action}",new { controller = "Home" }); //URL可以不包含控制器部分,使用这里的默认Home控制器
routes.MapRoute("ShopSchema2", "Shop/OldAction",new { controller = "Home", action = "Index" }); //URL可以是全静态的,这里mydomain.com/shop/oldaction传递到home控制器的index方法
一个比较特殊的例子:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
这可以映射任意多的URL分段,id后的所有内容都被赋值到cathall参数,比如/Customer/List/All/Delete/Perm,catchall = Delete/Perm。
需要注意的是路径表的注册是有先后顺序的,按照注册路径的先后顺序在搜索到匹配的映射后搜索将停止。
命名空间优先级
MVC根据{controller}在应用程序集中搜索同名控制类,如果在不同命名空间下有同名的控制类,MVC会给出多个同名控制类的异常,我们可以在注册路由的时候指定搜索的命令空间:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional ,
new[] { "URLsAndRoutes.AdditionalControllers" });
这里表示我们将在"URLsAndRoutes.AdditionalControllers"命名空间搜索控制类,可以添加多个命名空间,比如:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.AdditionalControllers", "UrlsAndRoutes.Controllers"});
"URLsAndRoutes.AdditionalControllers", "UrlsAndRoutes.Controllers"两个命名空间是等同处理没有优先级的区分,如果这两个空间里有重名的控制类一样导致错误,这种情况可以分开注册多条映射:
routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.AdditionalControllers" });
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "URLsAndRoutes.Controllers" });
除了在注册路由映射时可以指定控制器搜索命名空间,还可以使用正则表达式限制路由的应用范围,比如:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^H.*", action = "^Index$|^About$", httpMethod = new HttpMethodConstraint("GET")},
new[] { "URLsAndRoutes.Controllers" });
这里限制MyRoute路由仅用于映射所有H开头的控制类、且action为Index或者About、且HTTP请求方法为GET的客户端请求。
如果标准的路由限制不能满足要求,可以从IRouteConstraint接口扩展自己的路由限制类:
public class UserAgentConstraint : IRouteConstraint {
private string requiredUserA
public UserAgentConstraint(string agentParam) {
requiredUserAgent = agentP
public bool Match(HttpContextBase httpContext, Route route, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection) {
return httpContext.Request.UserAgent != null &&httpContext.Request.UserAgent.Contains(requiredUserAgent);
在注册路由时这样使用:
routes.MapRoute("ChromeRoute", "{*catchall}",
new { controller = "Home", action = "Index" },
new { customConstraint = new UserAgentConstraint("Chrome")},
new[] { "UrlsAndRoutes.AdditionalControllers" });
这表示我们限制路由仅为浏览器Agent为Chrome的请求时使用。
路由到磁盘文件
除了控制器方法,我们也需要返回一些静态内容比如HTML、图片、脚本到客户端,默认情况下路由系统优先检查是否有和请求路径一致的磁盘文件存在,如果有则不再从路由表中匹配路径。我们可以通过配置颠倒这个顺序:
public static void RegisterRoutes(RouteCollection routes) {
routes.RouteExistingFiles = true;
还需要修改web配置文件:
&add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition=""/&
这里设置preCondition为空。如果我们再请求一些静态内容比如~/Content/StaticContent.html时会优先从路径表中匹配。
而如果我们又需要忽略某些路径的路由匹配,可以:
public static void RegisterRoutes(RouteCollection routes) {
routes.RouteExistingFiles = true;
routes.IgnoreRoute("Content/{filename}.html"); ...
它会在RouteCollection中添加一个route handler为StopRoutingHandler的路由对象,在匹配到content路径下的后缀为html的文件时停止继续搜索路径表,转而匹配磁盘文件。
生成对外路径
路径表注册不仅影响到来自于客户端的URL映射,也影响到我们在视图中使用HTML帮助函数生成对外路径,比如我们注册了这样的映射
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes) {
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
在视图中调用Html.ActionLink生成一个对外路径:
@Html.ActionLink("This is an outgoing URL", "CustomVariable")
根据我们当前的请求链接,http://localhost:5081/home,生成的outgoing链接为:&
&a href="/Home/CustomVariable"&This is an outgoing URL&/a&
而如果我们调整路径表为:
public static void RegisterRoutes(RouteCollection routes) {
routes.MapRoute("NewRoute", "App/Do{action}", new { controller = "Home" });
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
&@Html.ActionLink("This is an outgoing URL", "CustomVariable")&&得到的结果是:
&a href="/App/DoCustomVariable"&This is an outgoing URL&/a&
它将使用在路径表中找到的第一条匹配的记录来生成相应的链接路径。
Html.ActionLink()有多个重载,可以多中方式生成URL链接:
@Html.ActionLink("This targets another controller", "Index", "Admin") //生成到Admin控制器Index方法的链接
@Html.ActionLink("This is an outgoing URL",
"CustomVariable", new { id = "Hello" }) //生成额外参数的链接,比如上面的路径配置下结果为&href="/App/DoCustomVariable?id=Hello"&;如果路径映射为 "{controller}/{action}/{id}",结果为href="/Home/CustomVariable/Hello"
@Html.ActionLink("This is an outgoing URL", "Index", "Home", null, new {id = "myAnchorID", @class = "myCSSClass"}) //设定生成A标签的属性,结果类似&&a class="myCSSClass"href="/" id="myAnchorID"&This is an outgoing URL&/a& &
参数最多的调用方式是:
@Html.ActionLink("This is an outgoing URL", "Index", "Home",
"https", "myserver.mydomain.com", " myFragmentName",
new { id = "MyId"},
new { id = "myAnchorID", @class = "myCSSClass"})
得到的结果是:
&a class="myCSSClass" href="https://myserver.mydomain.com/Home/Index/MyId#myFragmentName" id="myAnchorID"&This is an outgoing URL&/a&
&Html.ActionLink方法生成的结果中带有HTML的&a&标签,而如果只是需要URL,可以使用Html.Action(),比如:
@Url.Action("Index", "Home", new { id = "MyId" }) //结果为单纯的/home/index/myid
如果需要在生成URL指定所用的路径记录,可以:
@Html.RouteLink("Click me", "MyOtherRoute","Index", "Customer") //指定使用路径注册表中的MyOtherRoute记录
上面讲的都是在Razor引擎视图中生成对外URL,如果是在控制器类中我们可以:
string myActionUrl = Url.Action("Index", new { id = "MyID" });
string myRouteUrl = Url.RouteUrl(new { controller = "Home", action = "Index" });
更多的情况是在控制类方法中需要转到其他的Action,我们可以:
public RedirectToRouteResultMyActionMethod() {
  return RedirectToAction("Index");
public RedirectToRouteResult MyActionMethod() {
  return RedirectToRoute(new { controller = "Home", action = "Index", id = "MyID" });
创建自定义ROUTE类
除了使用MVC自带的Route类,我们可以从RouteBase扩展自己的Route类来实现自定义的路径映射:
public class LegacyRoute : RouteBase
private string[]
public LegacyRoute(params string[] targetUrls)
urls = targetU
public override RouteData GetRouteData(HttpContextBase httpContext)
RouteData result = null;
string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFileP
if (urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase))
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action", "GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);
public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values)
VirtualPathData result = null;
if (values.ContainsKey("legacyURL") &&
urls.Contains((string)values["legacyURL"], StringComparer.OrdinalIgnoreCase))
result = new VirtualPathData(this,
new UrlHelper(requestContext)
.Content((string)values["legacyURL"]).Substring(1));
GetRouteData()函数用于处理URL请求映射,我们可以这样注册路径映射:
routes.Add(new LegacyRoute(
"~/articles/Windows_3.1_Overview.html",
"~/old/.NET_1.0_Class_Library"));
上面的例子中如果我们请求"~/articles/Windows_3.1_Overview.html"将被映射到Legacy控制器的GetLegacyURL方法。
GetVirtualPath()方法则是用于生成对外链接,在视图中使用:
@Html.ActionLink("Click me", "GetLegacyURL", new { legacyURL = "~/articles/Windows_3.1_Overview.html" })
生成对外链接时得到的结果是:
&a href="/articles/Windows_3.1_Overview.html"&Click me&/a&
创建自定义ROUTE Handler
除了可以创建自定义的Route类,还可以创建自定义的Route handler类:
public class CustomRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
return new CustomHttpHandler();
public class CustomHttpHandler : IHttpHandler {
public bool IsReusable {
get { return false; }
public void ProcessRequest(HttpContext context) {
context.Response.Write("Hello");
注册路径时使用自定义的Route handler:
routes.Add(new Route("SayHello", new CustomRouteHandler()));
其效果就是针对链接 /SayHello的访问得到的结果就是&Hello&。
大型的Web应用可能分为不同的子系统(比如销售、采购、管理等)以方便管理,可以在MVC中创建不同的Area来划分这些子系统,在VS中右键点击Solution exploer-&Add-&Area可以添加我们想要的区域,在Solution exploer会生成Areas/&区域名称&的文件夹,其下包含Models、Views、Controllers三个目录,同时生成一个AreaRegistration的子类,比如我们创建一个名为Admin的区域,会自动生成名为AdminAreaRegistration的类:
namespace UrlsAndRoutes.Areas.Admin {
public class AdminAreaRegistration : AreaRegistration {
public override string AreaName {
return "Admin";
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
它的主要作用是注册一个到Admin/{controller}/{action}/{id}路径映射,在global.asax中会通过AreaRegistration.RegisterAllAreas()来调用到这里的RegisterArea()来注册区域自己的路径映射。
在Area下创建Controller、视图同整个工程下创建是相同的,需要注意的是可能遇到控制器重名的问题,具体解决参见命名空间优先级一节。
如果在视图中我们需要生成到特定Area的链接,可以在参数中指定Area:
@Html.ActionLink("Click me to go to another area", "Index", new { area = "Support" })
如果需要得到顶级控制器的链接area=""留空即可。
以上为对《Apress Pro ASP.NET MVC 4》第四版相关内容的总结,不详之处参见原版 。&&
阅读(...) 评论()

我要回帖

更多关于 ie a标签href下载文件 的文章

 

随机推荐