MVCApplication---Application_Statr--RegisterRoutes--给RouteCollection添加规则,请求进到网站---X----请求地址被路由按照顺序匹配,遇到一个温和的就结束,就到对应的控制器和action。

在程序中使用log4net,首先nuget引入程序集

Logger代码

public class Logger
{
static Logger()
{
XmlConfigurator.Configure(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CfgFiles\\log4net.config")));
ILog Log = LogManager.GetLogger(typeof(Logger));
Log.Info("系统初始化Logger模块");
} private ILog loger = null;
public Logger(Type type)
{
loger = LogManager.GetLogger(type);
} /// <summary>
/// Log4日志
/// </summary>
/// <param name="msg"></param>
/// <param name="ex"></param>
public void Error(string msg = "出现异常", Exception ex = null)
{
Console.WriteLine(msg);
loger.Error(msg, ex);
} /// <summary>
/// Log4日志
/// </summary>
/// <param name="msg"></param>
public void Warn(string msg)
{
Console.WriteLine(msg);
loger.Warn(msg);
} /// <summary>
/// Log4日志
/// </summary>
/// <param name="msg"></param>
public void Info(string msg)
{
Console.WriteLine(msg);
loger.Info(msg);
} /// <summary>
/// Log4日志
/// </summary>
/// <param name="msg"></param>
public void Debug(string msg)
{
Console.WriteLine(msg);
loger.Debug(msg);
} }

配置文件log4net.config

<?xml version="1.0" encoding="utf-8"?>
<log4net>
<!-- Define some output appenders -->
<appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
<file value="log\log.txt" /> <!--追加日志内容-->
<appendToFile value="true" /> <!--防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--可以为:Once|Size|Date|Composite-->
<!--Composite为Size和Date的组合-->
<rollingStyle value="Composite" /> <!--当备份文件时,为文件名加的后缀-->
<datePattern value="yyyyMMdd.TXT" /> <!--日志最大个数,都是最新的-->
<!--rollingStyle节点为Size时,只能有value个日志-->
<!--rollingStyle节点为Composite时,每天有value个日志-->
<maxSizeRollBackups value="20" /> <!--可用的单位:KB|MB|GB-->
<maximumFileSize value="3MB" /> <!--置为true,当前最新日志文件名永远为file节中的名字-->
<staticLogFileName value="true" /> <!--输出级别在INFO和ERROR之间的日志-->
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="FATAL" />
</filter> <layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender> <!-- levels: OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL -->
<root>
<priority value="ALL"/>
<level value="ALL"/>
<appender-ref ref="rollingAppender" />
</root>
</log4net>
public class MvcApplication : System.Web.HttpApplication
{
private Logger logger = new Logger(typeof(MvcApplication));
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();//注册区域
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//注册全局的Filter
RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由
BundleConfig.RegisterBundles(BundleTable.Bundles);//合并压缩 ,打包工具 Combres this.logger.Info("网站启动了。。。");
} }

Area

Area请参考博客:

http://www.cnblogs.com/zgqys1980/archive/2012/08/22/2650774.html

有时候因为一个Web项目可以非常大非常复杂,多人合作开发,命名就成问题了。Area可以把项目拆分开,方便团队合作,演变到后面就可以做成插件式开发了:

MvcApplication--Application_Start--AreaRegistration.RegisterAllAreas()---其实就是把SystemAreaRegistration给注册下---添加URL地址规则--请求来了就匹配(area在普通的之前)

众所周知,MVC请求的最后是反射调用Controller+Action,信息来自于url+roy=ute,路由匹配时,只能找到Action和Controller,其实还有个步骤,扫描+存储,在bin里面找Controller的子类,然后把命名空间---类名称+方法全部存起来。

控制器类可以出现在MVC项目之外,唯一的规则就是继承自Controller,Area也可以独立开,规则是必须有个继承AreaRegistration。

 public class SystemAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "System";
}
} public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "System_default",
url: "System/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
}
}

Razor语法:cshtml本质是一个类文件,混编了html+cs代码
写后台代码:行内--单行--多行--关键字
后台代码写html:@: 闭合的html标签 <text></text>

Html扩展控件:封装个方法,自动生成html
后端一次性完成全部内容,而且html标签闭合
我们还可以自行封装这种扩展方法
但是这个已经不流行了,就是UI改动需要重新发布
更多应该是前后分离,写前端的人是不会懂后端的写法

Layout
Masterpage--layout 默认是_layout 可以自行指定
@Styles.Render("~/Content/css") 使用样式包
@Scripts.Render("~/bundles/modernizr") 使用js包
@RenderBody() 就是页面的结合点
@RenderSection("scripts", required: false)

partialPage局部页---ascx控件,是没有自己的ACTION
@{ Html.RenderPartial("PartialPage", "这里是Html.RenderPartial"); }
@Html.Partial("PartialPage", "这里是Html.Partial")

子请求
@Html.Action("ChildAction", "Second", new { name = "Html.Action" })
@{Html.RenderAction("ChildAction", "Second", new { name = "Html.RenderAction" });}
有action,也可以传参数
[ChildActionOnly]//只能被子请求访问 不能独立访问

Asp.net MVC中Html.Partial, RenderPartial, Action,RenderAction 区别和用法请参考https://www.cnblogs.com/gesenkof99/archive/2013/06/03/3115052.html

Route

其实,路由这个东西,如果没必要的话,还是不要随便乱改了

下面是路由的一些改动:

public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//忽略路由 正则表达式 {resource}表示变量 a.axd/xxxx resource=a pathInfo=xxxx
//.axd是历史原因,最开始都是webform,请求都是.aspx后缀,IIS根据后缀转发请求;MVC出现了,没有后缀,IIS6以及更早版本,打了个补丁,把mvc的请求加上个.axd的后缀,然后这种都转发到网站----新版本的IIS已经不需要了,遇到了就直接忽略,还是走原始流程
routes.IgnoreRoute("CustomService/{*pathInfo}");//以CustomService开头,都不走路由 routes.MapRoute(
name: "About",
url: "About",
defaults: new { controller = "Home", action = "About", id = UrlParameter.Optional }
);//固定路由,/Home/About----About routes.MapRoute(
name: "Test",
url: "Test/{action}/{id}",
defaults: new { controller = "Second", action = "Index", id = UrlParameter.Optional }
);//修改控制器, routes.MapRoute(
name: "Regex",
url: "{controller}/{action}_{year}_{month}_{day}",
defaults: new { controller = "Second", action = "Index", id = UrlParameter.Optional },
constraints: new { year = @"\d{4}", month = @"\d{2}", day = @"\d{2}" }
);
//http://localhost:2017/second/Time_2019_06_13 Regex
//http://localhost:2017/second/Time_2019_6_13 失败
//http://localhost:2017/second/Time?year=2019&month=6&day=13 Default
//http://localhost:2017/test/Time?year=2019&month=6&day=13 Test
//http://localhost:2017/test/Time_2019_06_13 失败的,只会被一个路由匹配 //常规路由,一般来说,我们不怎么扩展这个路由
routes.MapRoute(
name: "Default",//路由名称,RouteCollection是key-value,key 避免重复
url: "{controller}/{action}/{id}",//正则规则:两个斜线 3个变量
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
//默认值 没有id变量 就是UrlParameter.Optional 没有action就是index 没有controller是home
); }
}

有关路由,请参考https://www.tuicool.com/articles/ne2Qfe

 IOC和MVC的结合,工厂的创建和Bussiness初始化

MVC请求进来,漏油匹配,找到控制器和Action,控制器是个普通的类,Action是个普通的实例方法,是不是有一个过程,叫实例化控制器?但是现在希望通过容器来实例化这个控制器。

路由匹配后得到控制器名称--MVCHandler---ControllerBuilder.GetControllerFactory()---然后创建控制器的实例。

public class DIFactory
{
public static IUnityContainer GetContainer()
{
IUnityContainer container = null;
//container.RegisterType
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
container = new UnityContainer();
section.Configure(container, "Bingle"); return container;
}
}

不要每次都创建一个,判断是否为null

 /// <summary>
/// 依赖注入工厂
/// </summary>
public class DIFactory
{
private static object _SyncHelper = new object();
private static Dictionary<string, IUnityContainer> _UnityContainerDictionary = new Dictionary<string, IUnityContainer>(); /// <summary>
/// 根据containerName获取指定的container
/// </summary>
/// <param name="containerName">配置的containerName,默认为defaultContainer</param>
/// <returns></returns>
public static IUnityContainer GetContainer(string containerName)
{
if (!_UnityContainerDictionary.ContainsKey(containerName))
{
lock (_SyncHelper)
{
if (!_UnityContainerDictionary.ContainsKey(containerName))
{
//配置UnityContainer
IUnityContainer container = new UnityContainer();
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
configSection.Configure(container, containerName);
_UnityContainerDictionary.Add(containerName, container);
}
}
}
return _UnityContainerDictionary[containerName];
}
}

ControllerBuilder有个SetControllerFactory。

 public class BingleControllerFactory : DefaultControllerFactory
{
private Logger logger = new Logger(typeof(BingleControllerFactory)); protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
this.logger.Warn($"{controllerType.Name}被构造..."); IUnityContainer container = DIFactory.GetContainer();
//return base.GetControllerInstance(requestContext, controllerType);
return (IController)container.Resolve(controllerType);
}
}
/// <summary>
/// 自定义的控制器实例化工厂
/// </summary>
public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer UnityContainer
{
get
{
return DIFactory.GetContainer();
}
} /// <summary>
/// 创建控制器对象
/// </summary>
/// <param name="requestContext"></param>
/// <param name="controllerType"></param>
/// <returns></returns>
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (null == controllerType)
{
return null;
}
IController controller = (IController)this.UnityContainer.Resolve(controllerType);
return controller;
}
/// <summary>
/// 释放
/// </summary>
/// <param name="controller"></param>
public override void ReleaseController(IController controller)
{
//释放对象
//this.UnityContainer.Teardown(controller);//释放对象 Unity容器释放对象只有单例那些,瞬时的是不存在释放管理的,直接.net框架自身会即时完成对象释放
/*
I wrote an article about using object lifetimes managers in Unity and their impact on disposing.
If you use default TransientLifetimeManager or PerResolveLifetimeManager the Unity will even don't track existence of your objects so it can't call Dispose.
The only lifetime managers which calls Dispose on resolved instances are ContainerControlledLifetimeManager (aka singleton) and HierarchicalLifetimeManager.
The Dispose is called when the lifetime manager is disposed.
*/
base.ReleaseController(controller);//
}
}

步骤:

  1、自己定义一个类,继承DefaultControllerFactory

  2、SetFactory,实例化控制器会进到这里

  3、引入第三方容器,将控制器的实例化换成容器操作

  这样就完成了MVC+IOC的结合。

.NET MVC5简介(二)的更多相关文章

  1. {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)

    Django基础七之Ajax 本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 一 Ajax简介 ...

  2. Windbg 脚本命令简介 二, Windbg command

    Windbg  脚本命令简介 二, Windbg  script command $<, $><, $$<, $$><, $$>a< (Run Scri ...

  3. {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)

    {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)   Django基础七之 ...

  4. WPF Binding值转换器ValueConverter使用简介(二)-IMultiValueConverter

    注: 需要继承IMultiValueConverter接口,接口使用和IValueConverter逻辑相同. 一.MultiBinding+Converter 多值绑定及多值转换实例 当纵向流量大于 ...

  5. ASP.NET MVC5(二):控制器、视图与模型

    前言 本篇博文主要介绍ASP.NET MVC中的三个核心元素:控制器.视图与模型,以下思维导图描述了本文的主要内容. 控制器 控制器简介 在介绍控制器之前,简单的介绍一下MVC工作原理:URL告知路由 ...

  6. Hibernate框架简介(二)基本使用增、删、改、查

    一.Hibernate框架简介 Hibernate是一个优秀的Java持久化层解决方案,是当今主流的对象-关系映射(ORM,ObjectRelationalMapping)工具 1.1.理解持久化 瞬 ...

  7. c# MVC5(二) MVC与IOC结合

    今天主要来讲解使用Unity来自动注入.Unity前面我们已经详细的介绍过了,如有需要请自行前往去看,今天我们的重点是说MVC与IOC的结合. IOC:控制反转,控制反转的工具是DI(依赖注入:构造函 ...

  8. Selenium简介(二)--基于CORE/IDE的简单应用

    参考  http://blog.csdn.net/iamqa/article/details/4398240 Selenium简介(一)--总体介绍  http://blog.csdn.net/iam ...

  9. 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>

    上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...

随机推荐

  1. SVM算法核函数的选择

    SVM支持向量机,一般用于二分类模型,支持线性可分和非线性划分.SVM中用到的核函数有线性核'linear'.多项式核函数pkf以及高斯核函数rbf. 当训练数据线性可分时,一般用线性核函数,直接实现 ...

  2. 使用策略模式重构switch case 代码

    目录 1.背景 2.案例 3.switch…case…方式实现 4.switch…case…带来的问题 5.使用策略模式重构switch…case…代码 6.总结 1.背景 之前在看<重构    ...

  3. JQuery Ztree 树插件配置与应用小结

    JQuery Ztree 树插件配置与应用小结 by:授客 QQ:1033553122 测试环境 Win7 jquery-3.2.1.min.js 下载地址: https://gitee.com/is ...

  4. [b0044] numpy_快速上手

    1 概念理清 2 创建数组 2.1 f1= np.array( [ [1,2,3,4], [2,3,4,5], [3,4,5,6] ]) 其他代码 a= np.array([ [ [3.4,5,6,8 ...

  5. docker实用命令

    退出容器又不关闭容器:Ctrl + P + Q 比如这种情况: 直接输入exit 会退出且关闭容器,工程就stop了 或者Ctrl + C,会报错KeyboardInterrupt,工程就也stop了 ...

  6. 你不知道的 flex-shrink 计算规则

    对于 flex-shrink 我们都知道它在 flex 布局中控制 flex 盒子空间不足时子元素改如何收缩,平常开发中更多的是使用默认值 1 或者设置 0.那设置其他值的时候会有什么效果呢,不少文章 ...

  7. npm简单实用

    npm包管理工具 npm可以理解为前端的maven,一个包的管理工具 1. 查看npm和node版本 node -v npm -v 2. 初始化项目 npm init 默认配置初始化项目 npm in ...

  8. python执行cmd命令

    os.system os.system用来执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功 注意:os.system是简单粗暴的执行cmd指令,如果想获取在cmd输出的内 ...

  9. seq参数 RANDOM 参数 openssl参数 cut参数

    #seq命令用于以指定增量从首数开始打印数字到尾数 语法: [2] seq [选项] 首数 尾数 [3] seq [选项] 首数 增量 尾数选项: seq 实例 一 存入数据库 然后 输出数据库的代码 ...

  10. 在Windows系统中安装matplotlib,需要注意的问题

    matplotlib的下载地址:https://pypi.org/project/matplotlib/#files 以python3.6为例,适合的版本matplotlib-3.1.1-cp36-c ...