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);
    }

}
View Code

配置文件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>
View Code
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

  有时候因为一个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
        );

    }
}
View Code

有关路由,请参考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, "ruanmouContainer");

        return container;
    }
}

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);
     }
 }

 步骤:

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

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

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

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

01-19 07:27