一、前言

       上一篇讲述的是将BIM平台后台架构CoreService.sln,该解决方案主要作用是对管控平台的核心业务进行封装,然后让前端的ApiController去调用该解决方案中的对应的dll方法。说到MVC前端架构,可能很多人都有一个误区,觉得都是按照微软的例子去写即可。其实在中大型的项目中按照微软MVC的demo样例去实施会对今后的维护工作带来一定难度。我在BIM平台部门的时候经历过多次MVC架构的修改,在熟悉了整个Web开发一个月之后,我与另一位Tech Leader准备再次进行改造,奠定了以后项目的基调,这大概算是我留给老东家最后的礼物吧。该架构功能清晰,方便复制开发,模块化相对于之前有了质的飞越。

二、架构简图

       整个MVC的架构很简单,就三个csproj:

  1. PlatForm.WebApp.Infrastructure —— BIM平台的基础,用于定义基类、定义基本Config等等。该dll应该是以后很少改动的。
  2. PlatForm.WebApp.ApiBusiness  —— BIM平台中的ApiController中的Action引用该dll中的方法,该dll再引用之前CoreService.sln中相关的方法。
  3. PlatForm.WebApp —— BIM平台的前端(ASP.NET MVC)

图示:

三、详解

       依照上图中的调用关系,我们首先来看Infrastructure它有哪些内容:

a. Application文件夹:

该文件夹包含Config文件夹与MvcApplication.cs。

Config文件夹主要包含:BundleConfig(css、js的路由控制)、FilterConfig(过滤器控制)、RouteConfig(controller路由控制)、WebApiConfig(apicontroller路由控制)

MvcApplication:

 public abstract class BaseMvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RegisterAreas(); if (!ApplicationService.Instance.IsInitialized)
ApplicationService.Instance.Initialize(); IUnityContainer container = ServiceLocator.Instance.GetContainer(); // WebApi
GlobalConfiguration.Configuration.DependencyResolver = new Microsoft.Practices.Unity.WebApi.UnityDependencyResolver(container); // MVC
DependencyResolver.SetResolver(new Microsoft.Practices.Unity.Mvc.UnityDependencyResolver(container)); InitializeMvcFactory(); RegisterApiConfig();
RegisterGlobalFilter();
RegisterRoutes();
RegisterBundles();
} protected virtual void RegisterAreas()
{
AreaRegistration.RegisterAllAreas();
} protected virtual void RegisterBundles()
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
} protected virtual void RegisterRoutes()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
} protected virtual void RegisterGlobalFilter()
{
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
} protected virtual void RegisterApiConfig()
{
WebApiConfig.Register(GlobalConfiguration.Configuration);
} protected virtual void InitializeMvcFactory()
{
// Customize MVC controller
BIMPlatformControllerFactory controllerFactory = GetControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory); BIMPlatformHttpControllerSelector httpControllerSelector = GetHttpControllerSelector();
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), httpControllerSelector);
} protected virtual BIMPlatformHttpControllerSelector GetHttpControllerSelector()
{
// Customize API Controller
return new BIMPlatformHttpControllerSelector(GlobalConfiguration.Configuration);
} protected virtual BIMPlatformControllerFactory GetControllerFactory()
{
return new BIMPlatformControllerFactory();
} public override void Init()
{
this.PostAuthenticateRequest += (sender, e) => HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required); base.Init();
} /// <summary>
/// Get the EF DB Context when begin the Http Request so that the application could use one context per request
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Application_BeginRequest(object sender, EventArgs e)
{
//Avoid Error("Response for preflight has invalid HTTP status code 405") from H5 App
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.End();
}
} /// <summary>
/// Dispose the EF DB Context when begin the Http Request
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Application_EndRequest(object sender, EventArgs e)
{
try
{
// Singleton
IEnumerable<IRepositoryContext> lcolContexts = ServiceLocator.Instance.GetServices<IRepositoryContext>();
if (lcolContexts != null)
{
foreach (IRepositoryContext lobjContext in lcolContexts)
{
ServerLogger.Info("Start to dispose DB context");
lobjContext.Dispose();
ServerLogger.Info("Disposed DB context");
}
}
}
catch (Exception ex)
{
// Log error
ServerLogger.Error("Failed to dispose DB Context", ex);
}
}
}

b. Controller文件夹:主要放置BaseController类,该类继承Controller类并根据项目进行自定义改写

c. Filters文件夹:该文件夹主要放置一些自定义的Attribute类

d. Integration文件夹:该文件夹中的类主要是继承DefaultControllerFactory、继承DefaultHttpControllerSelector、继承Attribute并根据项目进行自定义改写


       ApiBusiness 这个csproj不用多说,它就是纯写Apicontroller/Action,没啥花招,相应的api服务引用CoreService中相应的dll就可以了。


      WebApp 这个csproj是整个Web前端平台的关键,其使用Areas将各个功能进行模块化区分:

a. AppStart文件夹:主要重写BundleConfig与RouteConfig,供Global.asax进行覆盖使用。

public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
#region layout
bundles.Add(new ScriptBundle("~/Content/layout/js").Include(
"~/Content/Common/plug-in/JQuery/jquery-2.1.0.js",
"~/Content/Common/plug-in/BootStrap/bootstrap.js",
"~/Content/Common/plug-in/SweetAlert/sweet-alert.js",
));
bundles.Add(new StyleBundle("~/Content/layout/css").Include(
"~/Content/Common/plug-in/BootStrap/bootstrap.css",
"~/Content/Common/fonts/fontawesome/font-awesome.css",
"~/Content/Common/plug-in/SweetAlert/sweet-alert.css",
"~/Content/Layout/css/layout.css"
));
#endregion
... ...
} }
 public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); string defaultsAppSettings = ConfigurationManager.AppSettings["DefaultPage"];
string[] defaultArray = defaultsAppSettings.Split('/'); routes.MapRoute(
name: "login_default",
url: "{controller}/{action}/{id}",
defaults: new { controller = defaultArray[], action = defaultArray[], id = UrlParameter.Optional },
namespaces: new string[] { "Platform.WebApp.Controllers" }
);
}
}
public class MvcApplication : BaseMvcApplication
{
protected override void RegisterBundles()
{
base.RegisterBundles();
BundleConfig.RegisterBundles(BundleTable.Bundles);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}

b. Content文件夹,这个不用多说,一张图就懂了,主要放置全局性的前端文件:

c. Controllers与Views文件夹:只放关于Home与Account相关的东西,注意Controller中的命名空间必须为:Platform.WebApp.Controllers

d. Areas文件夹:放置各个模块。假设有一个模块是BIMModel,其架构如下:

其关键在于AreaRegistration类:

public class BIMModleAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "BIMModel"; }
} public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"bimmodel_default",
"bimmodel/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new string[] { "Platform.WebApp.Areas.BIMModel.Controllers" }
);
}
}

注意其controller路由为"bimmodel/{controller}/{action}/{id}",其Controller的命名空间为"Platform.WebApp.Areas.BIMModel.Controllers"

四、总结

       经过一番折腾,BIM平台就这样可以搭建起来了,当然要搞的好还是需要很多功夫的。

五、后记

       这个月7号就要去新公司报到了。在找下家的时候,按照惯例HR总会问你为什么要换工作?我的答案大概和很多人一样:可爱的领导与同事都走了,钱也没给够。我原来的公司大领导和各小组领导都是非常可爱的人,他们从一个公司出来一起创业,把自己知道的所有技能都毫无保留的教授给新人,整个公司欣欣向荣,团结一致。

但是被完全收购之后却是另一番景象,集团空降领导,外行指挥内行,军心涣散,原来的大领导也被架空出走。空降大领导画大饼可厉害了,开会的时候喊出:“三年之后咱分公司独立上市”,真是想起了无间道里的 “说好了三年,三年之后又三年,三年之后又三年,都快十年了,老大!”。空降大领导想搞大事还不肯加大薪资投入,各组核心都纷纷离开公司,连刚进几个月的实习都想着离开,各小组领导们也很伤心。

领导们都是很可爱的人,和我吃中饭的时候他们对我说到,看到咱公司培养出的怪物们都去了非常棒的企业,他们也很欣慰,圈子很小,以后合作机会还多,记得回来看看!

祝福老东家,希望领导们与同事们都能一切顺利!

进入新公司后自己一个人负责一个产品,重新架构一个BIM软件,也祝福自己,希望努力工作,带给家人幸福!

【.Net架构】BIM软件架构03:Web管控平台MVC架构的更多相关文章

  1. IT咨询顾问:一次吐血的项目救火 java或判断优化小技巧 asp.net core Session的测试使用心得 【.NET架构】BIM软件架构02:Web管控平台后台架构 NetCore入门篇:(十一)NetCore项目读取配置文件appsettings.json 使用LINQ生成Where的SQL语句 js_jquery_创建cookie有效期问题_时区问题

    IT咨询顾问:一次吐血的项目救火   年后的一个合作公司上线了一个子业务系统,对接公司内部的单点系统.我收到该公司的技术咨询:项目启动后没有规律的突然无法登录了,重新启动后,登录一断时间后又无法重新登 ...

  2. 【.NET架构】BIM软件架构02:Web管控平台后台架构

    一.前言        之前一篇叙述的是Revit插件(桌面软件)的软件架构,本篇将开始叙述Web项目的架构方案.今年一月在老东家加入BIM平台部门,为一些大型国家项目搭建BIM管控平台,业主使用管控 ...

  3. SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

    熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...

  4. 【.NET架构】BIM软件架构01:Revit插件产品架构梳理

    一.前言        BIM:Building Information Modeling 建筑信息模型,就是将建筑的相关信息附着于模型中,以管理该建筑在设计.算量.施工.运维全生命周期的情况.创建模 ...

  5. KingbaseFlySync V1R6 管控平台Linux命令行安装

    关键字: KingbaseFlySync.KingbaseES.Linux.x86_64.mips64el.aarch64.Java 管控平台: Web管控平台(Manager.Console.Com ...

  6. Intellij IDEA采用Maven+Spring MVC+Hibernate的架构搭建一个java web项目

    原文:Java web 项目搭建 Java web 项目搭建 简介 在上一节java web环境搭建中,我们配置了开发java web项目最基本的环境,现在我们将采用Spring MVC+Spring ...

  7. 从服务端架构设计角度,深入理解大型APP架构升级

    随着智能设备普及和移动互联网发展,移动端应用逐渐成为用户新入口,重要性越来越突出.但企业一般是先有PC端应用,再推APP,APP 1.0版的功能大多从现有PC应用平移过来,没有针对移动自身特点考虑AP ...

  8. PHP学习(MVC架构与面向对象)

    想好好的学一下php中的一些面向对象的知识,以前只是为了打CTF随意的学了一下,但是为了以后的代码审计(准备PHP这边把thinkphp这个框架好好的学一下). PHP面向对象的基本知识 类与对象 类 ...

  9. Web应用的组件化(二)——管控平台 #7

    Web应用的组件化(二) 管控平台 在上一篇中我们提到了组件化的大致思路,这一篇主要讲述在这么做之后,我们需要哪些外围手段去管控整个开发过程.从各种角度看,面对较大规模前端开发团队,都有必要建立这么一 ...

随机推荐

  1. ffplay.c函数结构简单分析(画图)

    最近重温了一下FFplay的源代码.FFplay是FFmpeg项目提供的播放器示例.尽管FFplay只是一个简单的播放器示例,它的源代码的量也是不少的.之前看代码,主要是集中于某一个"点&q ...

  2. 《C语言点滴》书评

    说起C语言方面的书,你最先想到的是哪一本?不论图书本身是好是坏,反正我想到的是谭浩强的<C程序设计>--它已然是一部"圣经"了.那么,为什么赵岩老师还要写一本<C ...

  3. java开源项目之IQQ学习记录之项目环境搭建与启动

    本文链接地址:http://blog.csdn.net/sushengmiyan/article/details/18779727 作者:sushengmiyan 现在就码字说说今天晚上搞定的一个项目 ...

  4. Spark-SQL连接MySql关系型数据库

    本文主要分析Spark SQL官方文档中有关于JDBC To Other Databases部分,以MySQL数据库为例,结合数据读写操作的实例代码进行详细的分析.本文中的代码需要使用到Mysql J ...

  5. android官方技术文档翻译——Android Lint

    本文译自androd官方技术文档<Android Lint>,原文地址:http://tools.android.com/tips/lint. 本文地址:http://blog.csdn. ...

  6. Adapterview和adapter的联系

    在J2EE中提供过一种非常好的框架--MVC框架,实现原理:数据模型M(Model)存放数据,利用控制器C(Controller)将数据显示在视图V(View)上.在Android中有这样一种高级控件 ...

  7. AngularJS进阶(三十二)书海拾贝之特殊的ng-src和ng-href

    书海拾贝之特殊的ng-src和ng-href 在说明这两个指令的特殊之前,需要先了解一下ng的启动及执行过程,如下: 1) 浏览器加载静态HTML文件并解析为DOM: 2) 浏览器加载angular. ...

  8. Leetcode_24_Swap Nodes in Pairs

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/43302355 Given a linked list, s ...

  9. 实用Android 屏幕适配方案分享

    转载地址:http://blog.csdn.net/gao_chun/article/details/45645051 真正可用,并且简单易行,可以在多个屏幕大小和屏幕密度上有良好表现的Android ...

  10. git remote

    在git里,服务器上的仓库在本地称之为remote. 直接clone一个仓库: $: git clone git@search.ued.taobao.net:projects/search.git 另 ...