SVS 没有尽头

SVS is SQL & Visual Studio
随笔 - 9, 评论 - 8, 引用 - 0

导航

工具

关于

做技术的路没有尽头,你只能看到前方几公里,但是更远的地方总是看不太清,当远处的景色渐渐清晰,回首看,有我们深深的足迹。兄弟们,上路吧,前方还有更多的难关,也有更美的景色。

每月存档

广告



访客

 
好久没有写文章了,有时候想写点东西但是又不知该写点什么。总觉得微软的技术不错,但是就是更新的太快,也许我们也老了。很多人还在用VS2003写东西,因为他们觉得够用了,而且升级到VS2008上,大家也都不能确定会有多少Code需要重构,所以还沿用至今。
最近一直在关注ASP.NET MVC的东西,感觉微软有后发制人的想法,虽然明年才能发布(也不知道会不会跳票,估计是等VS一起发布)但是现在但是可以用这个东西做点事情了,毕竟ASP.NET MVC中很多思想和模式都已经渐渐成熟了,个人觉得这是个好东东,但是需要更多的指导手册。在ASP.net站点上有一套screencast不错,将一个完整的MVC应用的设计开发过程都展示出来,而且有Code可以下载学习。
很多初学者会发现Route是一个不好搞定的东东,默认情况下新建的ASP.NET MVC项目会建立Controller/Views/Models目录,但是大多数情况下,我们的应用结构肯定不是这个样子的例如
WebApp/
WebApp/Areas/
WebApp/Areas/HR
WebApp/Areas/HR/Controller
WebApp/Areas/HR/Views
WebApp/Areas/HR/Models
WebApp/Controller
WebApp/Views
WebApp/Models
这样规划开起来更清晰,但是需要我们对于Route做一些特殊的处理,我们需要对于Controller和View做相应的扩展,因为我们的View中页面和空间的位置以及Controller的名称空间都发生了变化。我们需要做一个自定义的WebFormViewEngine并扩展RouteCollection对于Controller映射方法

在WebFormViewEngine中我们需要重载FindPartialView和FindView方法,以便于MVC在Render的时候可以找到相应的.ascx和aspx。在扩展RouteCollection是主要是需要重新映射Controller的名称空间。
接下来只需要在Global.asax.cs中使用MapAreas和MapRootAreas注册你的Route,并ViewEngines.Engines中添加我们的的WebFormViewEngine 就可以了。

下面是相应的代码片段
    public class AreaViewEngine : WebFormViewEngine {
        public AreaViewEngine() : base() {
            ViewLocationFormats = new[] {
                "~/{0}.aspx",
                "~/{0}.ascx",
                "~/Views/{1}/{0}.aspx",
                "~/Views/{1}/{0}.ascx",
                "~/Views/Shared/{0}.aspx",
                "~/Views/Shared/{0}.ascx",
            };

            MasterLocationFormats = new[] {
                "~/{0}.master",
                "~/Shared/{0}.master",
                "~/Views/{1}/{0}.master",
                "~/Views/Shared/{0}.master",
            };

            PartialViewLocationFormats = ViewLocationFormats;
        }

        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName) {
           
            ViewEngineResult areaResult = null;
           
            if (controllerContext.RouteData.Values.ContainsKey("area")) {
                string areaPartialName = FormatViewName(controllerContext, partialViewName);
                areaResult = base.FindPartialView(controllerContext, areaPartialName);
                if (areaResult != null && areaResult.View != null) {
                    return areaResult;
                }
                string sharedAreaPartialName = FormatSharedViewName(controllerContext, partialViewName);
                areaResult = base.FindPartialView(controllerContext, sharedAreaPartialName);
                if (areaResult != null && areaResult.View != null) {
                    return areaResult;
                }
            }
           
            return base.FindPartialView(controllerContext, partialViewName);
        }

        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName) {

            ViewEngineResult areaResult = null;

            if (controllerContext.RouteData.Values.ContainsKey("area")) {
                string areaViewName = FormatViewName(controllerContext, viewName);
                areaResult = base.FindView(controllerContext, areaViewName, masterName);
                if (areaResult != null && areaResult.View != null) {
                    return areaResult;
                }
                string sharedAreaViewName = FormatSharedViewName(controllerContext, viewName);
                areaResult = base.FindView(controllerContext, sharedAreaViewName, masterName);
                if (areaResult != null && areaResult.View != null) {
                    return areaResult;
                }
            }
           
            return base.FindView(controllerContext, viewName, masterName);
        }

        private static string FormatViewName(ControllerContext controllerContext, string viewName) {
            string controllerName = controllerContext.RouteData.GetRequiredString("controller");

            string area = controllerContext.RouteData.Values["area"].ToString();
            return "Areas/" + area + "/Views/" + controllerName + "/" + viewName;
        }

        private static string FormatSharedViewName(ControllerContext controllerContext, string viewName) {
            string area = controllerContext.RouteData.Values["area"].ToString();
            return "Areas/" + area + "/Views/Shared/" + viewName;
        }
    }

public static class AreaRouteHelper {
        public static void MapAreas(this RouteCollection routes, string url, string rootNamespace, string[] areas) {
            Array.ForEach(areas, area => {
                Route route = new Route("{area}/" + url, new MvcRouteHandler());
                route.Constraints = new RouteValueDictionary(new { area });
                string areaNamespace = rootNamespace + ".Areas." + area + ".Controllers";
                route.DataTokens = new RouteValueDictionary(new { namespaces = new string[] { areaNamespace } });
                route.Defaults = new RouteValueDictionary(new { action = "Index", controller = "Home", id = "" });
                routes.Add(route);
            });
        }

        public static void MapRootArea(this RouteCollection routes, string url, string rootNamespace, object defaults) {
            Route route = new Route(url, new MvcRouteHandler());
            route.DataTokens = new RouteValueDictionary(new { namespaces = new string[] { rootNamespace + ".Controllers" } });
            route.Defaults = new RouteValueDictionary(new { area="root", action = "Index", controller = "Home", id = "" });
            routes.Add(route);
        }
    }
具体的可以参考 http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx

相关文章

打印 | 张贴于 2008-11-11 14:24:52 | Tag:暂无标签

留言反馈

暂时没有留言纪录
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode MVC Blogger System