`

5.5URL和Action匹配的秘密

阅读更多
Routes是如何把URL映射为Action

-请求路由管道

请求管道概述

1.UrlRotingModule视图使用RouteTable里的注册路由当前请求
2.如果匹配成功,则从路由对象生成IRouteHandler对象
3.Routing模块调用IRouteHandler中的GetHandler方法,这一方法返回一个IHttpHandler
4.ProcessRequest对象调用Http handler对象响应
5.在MVC架构中IRouteHandler对象默认是一个MvcRouteHandler对象,它返回的对象是一个MvcHandler对象

路由匹配法则
-routedata
{foo}/{bar}/{baz}
Public Interface IRouteConstraint{
BoolMatch(HttpContextBasehttpContext,
Route route,
string parameterName,
RouteValuedictionaryvalues,
RouteDirectionrouteDirection);
}
routes.MapRoute(“name”,”{controller}”,null,new{httpMethod=new HttpMethonConstraint(“GET”)});

Route扩展

routes.MapResources(“Products”);

描述信息   
/Products 显示所有products   
/Products/new 生成一个表格用于添加新纪录   
/Products/1 显示ID是1的记录   
/Products/1/edit 编辑ID是1的记录


public class RestRoute:RouteBase{
public override RouteDataGetRouteData
(HttpContextBasehttpcontext){}
public override VirtualPathDataGetVirtualPath
(RequestContextrequestcontext,
RouteValueDictionaryvalues){}
}



List<Route> _internalRoutes= new List<Route>();
public string Resource { get; private set; }
public RestRoute(string resource)
{
this.Resource= resource;
MapRoute(resource, “index”, “GET”, null);
MapRoute(resource, “create”, “POST”, null);
MapRoute(resource + “/new”, “newitem”, “GET”, null);
MapRoute(resource + “/{id}”, “show”, “GET”, new { id = @”\d+” });
MapRoute(resource + “/{id}”, “update”, “PUT”, new { id = @”\d+” });
MapRoute(resource + “/{id}”, “delete”, “DELETE”, new { id = @”\d+” });
MapRoute(resource + “/{id}/edit”, “edit”, “GET”, new { id = @”\d+” });
}
public void MapRoute(string url, string actionName, string httpMethod,
object constraints)
{
RouteValueDictionaryconstraintsDictionary;if (constraints != null)
{
constraintsDictionary= new RouteValueDictionary(constraints);
}
else
{
constraintsDictionary= new RouteValueDictionary();
}
constraintsDictionary.Add(“httpMethod”, new HttpMethodConstraint(httpMethod));
_internalRoutes.Add(new Route(url, new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new
{ controller = Resource, action = actionName}),
Constraints = constraintsDictionary
});
}

public override RouteDataGetRouteData(HttpContextBasehttpContext)
{
foreach(varroute in this._internalRoutes)
{
varrvd= route.GetRouteData(httpContext);
if (rvd!= null) return rvd;
}
return null;
}
public override VirtualPathDataGetVirtualPath(RequestContextrequestContext,
RouteValueDictionaryvalues)
{
foreach(varroute in this._internalRoutes)
{
VirtualPathDatavpd= route.GetVirtualPath(requestContext, values);
if (vpd!= null) return vpd;
}
return null;
}

Routes.Add(new RestRoute("Products"));

编辑Routes

Protected void Application_start(){
AreaRegistration.RegisterAllAreas();
RouteTable.Routes.registerRoutes(“~/Config/routes.cs”);
}
using System.Web.Mvc;
using System.Web.Routing;
using EditableRoutesWeb;
// Use this one for Full Trust
public class Routes : IRouteRegistrar
{public void RegisterRoutes(RouteCollectionroutes){
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.MapRoute(“Default”,“{controller}/{action}/{id}”,new {
controller = “Home”,
action = “Index”,
id = ““ });}}

使用Cache监控代码

using System;
using System.Web.Compilation;
using System.Web.Routing;
namespace EditableRoutesWeb{
public static class RouteRegistrationExtensions{
public static void RegisterRoutes(
this RouteCollectionroutes,stringvirtualPath){
ConfigFileChangeNotifier.Listen(
virtualPath, vp=> routes.ReloadRoutes(vp));
}
static void ReloadRoutes(this RouteCollectionroutes, string virtualPath)
{
varassembly = BuildManager.GetCompiledAssembly(virtualPath);
var registrar = assembly.CreateInstance(“Routes”) as IRouteRegistrar;
using(routes.GetWriteLock())
{
routes.Clear();
registrar.RegisterRoutes(routes);
}}}}

怎么知道有改变?

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
namespace EditableRoutesWeb{
public class ConfigFileChangeNotifier{
private ConfigFileChangeNotifier(Action<string> changeCallback)
: this(HostingEnvironment.VirtualPathProvider, changeCallback){}
private ConfigFileChangeNotifier(VirtualPathProvidervpp,
Action<string> changeCallback) {
_vpp= vpp;
_changeCallback= changeCallback;
}
VirtualPathProvider_vpp;
Action<string> _changeCallback;
// When the file at the given path changes, we’ll call the supplied action.
public static void Listen(string virtualPath, Action<string> action) {
varnotifier= new ConfigFileChangeNotifier(action);
notifier.ListenForChanges(virtualPath);
}
void ListenForChanges(string virtualPath) {
// Get a CacheDependencyfrom the BuildProvider, so that we know
// anytime something changes
varvirtualPathDependencies= new List<string>();
virtualPathDependencies.Add(virtualPath);
CacheDependencycacheDependency= _vpp.GetCacheDependency(
virtualPath, virtualPathDependencies, DateTime.UtcNow);
HttpRuntime.Cache.Insert(virtualPath/*key*/,
virtualPath/*value*/,
cacheDependency,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(OnConfigFileChanged));
}
void OnConfigFileChanged(string key, object value,
ChItRdR) {...

2011-4-17 14:50 danny
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics