.NET MVC5简介(二)
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简介(二)的更多相关文章
- {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)
Django基础七之Ajax 本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 一 Ajax简介 ...
- Windbg 脚本命令简介 二, Windbg command
Windbg 脚本命令简介 二, Windbg script command $<, $><, $$<, $$><, $$>a< (Run Scri ...
- {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)
{Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) Django基础七之 ...
- WPF Binding值转换器ValueConverter使用简介(二)-IMultiValueConverter
注: 需要继承IMultiValueConverter接口,接口使用和IValueConverter逻辑相同. 一.MultiBinding+Converter 多值绑定及多值转换实例 当纵向流量大于 ...
- ASP.NET MVC5(二):控制器、视图与模型
前言 本篇博文主要介绍ASP.NET MVC中的三个核心元素:控制器.视图与模型,以下思维导图描述了本文的主要内容. 控制器 控制器简介 在介绍控制器之前,简单的介绍一下MVC工作原理:URL告知路由 ...
- Hibernate框架简介(二)基本使用增、删、改、查
一.Hibernate框架简介 Hibernate是一个优秀的Java持久化层解决方案,是当今主流的对象-关系映射(ORM,ObjectRelationalMapping)工具 1.1.理解持久化 瞬 ...
- c# MVC5(二) MVC与IOC结合
今天主要来讲解使用Unity来自动注入.Unity前面我们已经详细的介绍过了,如有需要请自行前往去看,今天我们的重点是说MVC与IOC的结合. IOC:控制反转,控制反转的工具是DI(依赖注入:构造函 ...
- Selenium简介(二)--基于CORE/IDE的简单应用
参考 http://blog.csdn.net/iamqa/article/details/4398240 Selenium简介(一)--总体介绍 http://blog.csdn.net/iam ...
- 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>
上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...
随机推荐
- TP5 where多条件查询
引用 : https://blog.csdn.net/haibo0668/article/details/78203170/
- 【开发工具】IDEA简明使用指南
目录 1. 搭建idea的开发环境 2. 调试技巧 3. 常用快捷键(小技巧) 4. 插件推荐 工欲善其事,必先利其器.在Java开发中挑选一款好的Ide环境能大大提升我们的开发效率,IntelliJ ...
- mysql给字段取别名无法被jdbc解析的解决办法
项目上用的Spring JDBC,是通过ResultSetMetaData接口来调用具体数据库的JDBC实现类来获取数据库返回结果集的. 在项目开发中,发现在MySQL中使用的别名没有办法被正常解析, ...
- ArcGIS以数据库作为数据源作为source发布服务步骤详解(以Postgresql为例)及各种发布问题
创建企业级数据库 Data Management Tools-->Geodatabase Administration-->Create Enterprise Geodatabase 按如 ...
- SAP系统邮件功能配置
相信SAP顾问或多或少都会接到用户要求SAP系统能够定时发送邮件的功能,定时将用户需要的信息已邮件的方式发送给固定的人员. 下面就来讲一下SAP发送邮件应该如何配置: 1.RZ10做配置: is/SM ...
- OpenCV:图像的开运算与闭运算
导包: import numpy as np import cv2 import matplotlib.pyplot as plt def show(image): plt.imshow(image) ...
- Linux—文件管理
文件操作 创建文件 [root@localhost ~]# touch a.txt # 创建单个文件 [root@localhost ~]# touch b.txt c.txt # 创建多个文件 删除 ...
- 【解决 FTP】windows访问Linux的vsftpd(FTP服务器)问题200 Switching to ASCII mode,227 Entering Passive Mode
转载:关于FTP主动模式(active mode)与被动模式(passive mode)的工作原理: 主动模式(服务器向客户端敲门,然后客户端开门)FTP:客户机与服务器之间建立连接时,客户机是大于1 ...
- 克服悲伤情绪的三个P原则
1.自责(Personalization) --不要自责 2.永久化(Permanence) --悲伤不会永远存在,一切都会过去 据科学研究发现:人遇到开心或悲伤的事情之后,心情在短期内会产生巨大的波 ...
- JUC-8-lock和Condition使用
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAANwAAADHCAYAAABySz3ZAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw ...