Orchard學習 0二、orchard 路由

    Orchard對mvc路由從新作了包裝,重寫了asp.net的路由模塊shell

1、路由模塊類圖
一、路由 Descriptor
RouteDescriptor是對常規mvc路由的包裝類,它的Route屬性就是在mvc註冊路由中使用的RouteBase類型。在Orchard中註冊路由,應該用這種方式
  1. newRouteDescriptor{
        Route=newRoute(
            "Admin/Blogs/Create",
            newRouteValueDictionary{
                {"area","Orchard.Blogs"},
                {"controller","BlogAdmin"},
                {"action","Create"}
            },
            newRouteValueDictionary(),
            newRouteValueDictionary{
                {"area","Orchard.Blogs"}
            },
            newMvcRouteHandler())
    }
    View Code

     

     

 
二、路由實現
    Orchard的路由實現有2個類組成:HubRoute和ShellRoute類。它們都繼承了System.Web.Routing.RouteBase類,要從新實現GetRouteData和GetVirtualPath方法
2.一、 HubRoute類中的 GetRouteData方法
  1. publicoverrideRouteDataGetRouteData(HttpContextBase httpContext)
    {
        var settings = _runningShellTable.Match(httpContext);
    
        if(settings ==null)
        returnnull;
         //這裏獲取1個ShellRoute的集合
        IList<RouteBase> routes;
        if(!_routesByShell.TryGetValue(settings.Name,out routes))
        {
            returnnull;
        }
    
        foreach(var route in routes)
        {
            RouteData routeData = route.GetRouteData(httpContext);//這裏的route是ShellRoute類型
            if(routeData !=null)
        {
            return routeData;
        }
        }
    
        returnnull;
    }
    View Code

     

HubRoute類只是1個route的分配器,它的 GetRouteData方法只是從1個 ShellRoute集合中獲取匹配的  ShellRoute,而真正的獲取 RouteData 實例的是 ShellRoute 類中的  GetRouteData方法
 
2.二、 ShellRoute 中的 GetRouteData方法
  1. publicoverrideRouteDataGetRouteData(HttpContextBase httpContext)
    {
        // locate appropriate shell settings for request
        var settings = _runningShellTable.Match(httpContext);
    
        // only proceed if there was a match, and it was for this client
        if(settings ==null|| settings.Name!= _shellSettings.Name)
            returnnull;
    
        var effectiveHttpContext = httpContext;
        if(_urlPrefix !=null)
            effectiveHttpContext =newUrlPrefixAdjustedHttpContext(httpContext, _urlPrefix);
    
        var routeData = _route.GetRouteData(effectiveHttpContext);//這裏獲取的是真正的mvc RouteData
        if(routeData ==null)
            returnnull;
    
        // otherwise wrap handler and return it
         routeData.RouteHandler=newRouteHandler(_workContextAccessor, routeData.RouteHandler,SessionState);
         routeData.DataTokens["IWorkContextAccessor"]= _workContextAccessor;
    
        if(IsHttpRoute)
        {
            routeData.Values["IWorkContextAccessor"]= _workContextAccessor;// for WebApi
        }
    
        return routeData;
    }
    View Code

     

三、路由註冊
    Orchard的路由註冊功能由2個接口定義:IRouteProvider、IRoutePublisher。Orchard提供默認的實現:DefaultRouteProvider和RoutePublisher類
3.一、 DefaultRouteProvider類:
  1. publicclassDefaultRouteProvider:IRouteProvider
    {
         //GetRoutes方法中定義了你要使用的全部的路由信息.
        publicIEnumerable<RouteDescriptor>GetRoutes()
        {
            returnnew[]{
            newRouteDescriptor{
                Priority=-20,
                Route=newRoute(
                    "{controller}/{action}/{id}",
                    newRouteValueDictionary{
                    {"controller","home"},
                    {"action","index"},
                    {"id",""},
                },
            newRouteValueDictionary{
                {"controller",newHomeOrAccount()}
                },
                newMvcRouteHandler())
                }
            };
        }
    
        publicvoidGetRoutes(ICollection<RouteDescriptor> routes)
        {
            foreach(var routeDescriptor inGetRoutes())
                routes.Add(routeDescriptor);
        }
    
    }
    View Code

     

3.二、 RoutePublisher類:
  1.  public void Publish(IEnumerable<RouteDescriptor> routes)
            {
                var routesArray = routes
                    .OrderByDescending(r => r.Priority)
                    .ToArray();
    
                // this is not called often, but is intended to surface problems before
                // the actual collection is modified
                var preloading = new RouteCollection();
                foreach (var routeDescriptor in routesArray)
                {
    
                    // extract the WebApi route implementation
                    var httpRouteDescriptor = routeDescriptor as HttpRouteDescriptor;
                    if (httpRouteDescriptor != null)
                    {
                        var httpRouteCollection = new RouteCollection();
                        httpRouteCollection.MapHttpRoute(httpRouteDescriptor.Name, httpRouteDescriptor.RouteTemplate, httpRouteDescriptor.Defaults, httpRouteDescriptor.Constraints);
                        routeDescriptor.Route = httpRouteCollection.First();
                    }
    
                    preloading.Add(routeDescriptor.Name, routeDescriptor.Route);
                }
    
    
                using (_routeCollection.GetWriteLock())
                {
                    // existing routes are removed while the collection is briefly inaccessable
                    _routeCollection
                        .OfType<HubRoute>()
                        .ForEach(x => x.ReleaseShell(_shellSettings));
    
                    // new routes are added
                    foreach (var routeDescriptor in routesArray)
                    {
                        // Loading session state information. 
                        var defaultSessionState = SessionStateBehavior.Default;
    
                        ExtensionDescriptor extensionDescriptor = null;
                        if (routeDescriptor.Route is Route)
                        {
                            object extensionId;
                            var route = routeDescriptor.Route as Route;
                            if (route.DataTokens != null && route.DataTokens.TryGetValue("area", out extensionId) ||
                               route.Defaults != null && route.Defaults.TryGetValue("area", out extensionId))
                            {
                                extensionDescriptor = _extensionManager.GetExtension(extensionId.ToString());
                            }
                        }
                        else if (routeDescriptor.Route is IRouteWithArea)
                        {
                            var route = routeDescriptor.Route as IRouteWithArea;
                            extensionDescriptor = _extensionManager.GetExtension(route.Area);
                        }
    
                        if (extensionDescriptor != null)
                        {
                            // if session state is not define explicitly, use the one define for the extension
                            if (routeDescriptor.SessionState == SessionStateBehavior.Default)
                            {
                                Enum.TryParse(extensionDescriptor.SessionState, true /*ignoreCase*/, out defaultSessionState);
                            }
                        }
    
                        // Route-level setting overrides module-level setting (from manifest).
                        var sessionStateBehavior = routeDescriptor.SessionState == SessionStateBehavior.Default ? defaultSessionState : routeDescriptor.SessionState;
    
                        var shellRoute = new ShellRoute(routeDescriptor.Route, _shellSettings, _workContextAccessor, _runningShellTable)
                        {
                            IsHttpRoute = routeDescriptor is HttpRouteDescriptor,
                            SessionState = sessionStateBehavior
                        };
    
                        var area = extensionDescriptor == null ? "" : extensionDescriptor.Id;
    
                        var matchedHubRoute = _routeCollection.FirstOrDefault(x =>
                        {
                            var hubRoute = x as HubRoute;
                            if (hubRoute == null)
                            {
                                return false;
                            }
    
                            return routeDescriptor.Priority == hubRoute.Priority && hubRoute.Area.Equals(area, StringComparison.OrdinalIgnoreCase) && hubRoute.Name == routeDescriptor.Name;
                        }) as HubRoute;
    
                        if (matchedHubRoute == null)
                        {
                            matchedHubRoute = new HubRoute(routeDescriptor.Name, area, routeDescriptor.Priority, _runningShellTable);
    
                            int index;
                            for (index = 0; index < _routeCollection.Count; index++)
                            {
                                var hubRoute = _routeCollection[index] as HubRoute;
                                if (hubRoute == null)
                                {
                                    continue;
                                }
                                if (hubRoute.Priority < matchedHubRoute.Priority)
                                {
                                    break;
                                }
                            }
    
                            _routeCollection.Insert(index, matchedHubRoute);
                        }
    
                        matchedHubRoute.Add(shellRoute, _shellSettings);
                    }
                }
            }
    View Code

     

Publish方法將路由註冊到asp.net mvc 的路由系統中。
 
2、如何在Module開發中使用路由系統
    Orchard的功能都是經過Module實現的。那麼在Module開發中如何使用 路由呢?咱們以Orcahrd本身的 Orchard.Blogs  Module爲例,在Orchard中實現本身的路由其實很簡單,只須要在本身的 Module中建立1個實現IRouteProvider接口的類型便可。
  1.  public class Routes : IRouteProvider
        {
            private readonly IArchiveConstraint _archiveConstraint;
            private readonly IRsdConstraint _rsdConstraint;
    
            public Routes(
                IArchiveConstraint archiveConstraint,
                IRsdConstraint rsdConstraint)
            {
                _archiveConstraint = archiveConstraint;
                _rsdConstraint = rsdConstraint;
            }
    
            public void GetRoutes(ICollection<RouteDescriptor> routes)
            {
                foreach (var routeDescriptor in GetRoutes())
                    routes.Add(routeDescriptor);
            }
    
            public IEnumerable<RouteDescriptor> GetRoutes()
            {
                return new[] {
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/Create",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogAdmin"},
                                                                                          {"action", "Create"}
                                                                                      },
                                                             new RouteValueDictionary(),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Edit",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogAdmin"},
                                                                                          {"action", "Edit"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Remove",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogAdmin"},
                                                                                          {"action", "Remove"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogAdmin"},
                                                                                          {"action", "Item"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Posts/Create",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogPostAdmin"},
                                                                                          {"action", "Create"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Posts/{postId}/Edit",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogPostAdmin"},
                                                                                          {"action", "Edit"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Posts/{postId}/Delete",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogPostAdmin"},
                                                                                          {"action", "Delete"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Posts/{postId}/Publish",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogPostAdmin"},
                                                                                          {"action", "Publish"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs/{blogId}/Posts/{postId}/Unpublish",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogPostAdmin"},
                                                                                          {"action", "Unpublish"}
                                                                                      },
                                                             new RouteValueDictionary (),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Admin/Blogs",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogAdmin"},
                                                                                          {"action", "List"}
                                                                                      },
                                                             new RouteValueDictionary(),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "Blogs",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "Blog"},
                                                                                          {"action", "List"}
                                                                                      },
                                                             new RouteValueDictionary(),
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Route = new Route(
                                                             "{*path}",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "BlogPost"},
                                                                                          {"action", "ListByArchive"}
                                                                                      },
                                                             new RouteValueDictionary {
                                                                                          {"path", _archiveConstraint},
                                                                                      },
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     },
                                 new RouteDescriptor {
                                                         Priority = 11,
                                                         Route = new Route(
                                                             "{*path}",
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"},
                                                                                          {"controller", "RemoteBlogPublishing"},
                                                                                          {"action", "Rsd"}
                                                                                      },
                                                             new RouteValueDictionary {
                                                                                          {"path", _rsdConstraint}
                                                                                      },
                                                             new RouteValueDictionary {
                                                                                          {"area", "Orchard.Blogs"}
                                                                                      },
                                                             new MvcRouteHandler())
                                                     }
                             };
            }
        }
    View Code

     

3、Orchard路由系統如何工做的。
一、將自定義路由註冊到asp.net mvc路由系統中
         這個工做是在建立和激活shell的時候,調用  DefaultOrchardShell類的Activate方法時進行的
  1. publicvoidActivate()
    {
        var allRoutes =newList<RouteDescriptor>();
         allRoutes.AddRange(_routeProviders.SelectMany(provider => provider.GetRoutes()));
         allRoutes.AddRange(_httpRouteProviders.SelectMany(provider => provider.GetRoutes()));
    
         _routePublisher.Publish(allRoutes);//這裏就是註冊路由
        _modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders()));
    
         using (var events = _eventsFactory())
        {
            events.Value.Activated();
        }
    
         _sweepGenerator.Activate();
    }
    View Code

     

二、路由的使用:像mvc路由同樣使用自定義路由。
 



相關文章
相關標籤/搜索