.NET MVC5簡介(二)

来源:https://www.cnblogs.com/taotaozhuanyong/archive/2019/09/23/11575048.html
-Advertisement-
Play Games

MVCApplication Application_Statr--RegisterRoutes--給RouteCollection添加規則,請求進到網站 X 請求地址被路由按照順序匹配,遇到一個溫和的就結束,就到對應的控制器和action。 在程式中使用log4net,首先nuget引入程式集 L ...


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

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

    }
}
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, "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的結合。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我是一個2019畢業的非電腦的畢業生,從大二開始喜歡上Java直到現在一直都在學習,Brid從小就對電腦感興趣,可惜高中的時候不懂事,沒有規劃未來,考上了一所專科學院,然後大一併不能轉專業,現在畢業了沒有找到Java應屆的工作,只能找點其他的做,但是這阻住不了我對Java的喜歡,趁現在工作的晚上 ...
  • “容器”這兩個字很少被 Python 技術文章提起。一看到“容器”,大家想到的多是那頭藍色小鯨魚:Docker,但這篇文章和它沒有任何關係。本文里的容器,是 Python 中的一個抽象概念,是對專門用來裝其他對象的數據類型的統稱。 在 Python 中,有四類最常見的內建容器類型: 列表(list) ...
  • 溫馨提示 請收藏再看。此文篇幅太長,你短時間看不完;此文乾貨太多,錯過太可惜。 示例代碼可以關註 (公眾號)回覆 獲取。 收穫 1. 講解詳細:能讓你掌握使用 及類似校驗工具的各種使用姿勢 2. 內容全面:可以當做知識字典來查詢 what 註意:hibernate validator 與 持久層框架 ...
  • 閑及無聊 又打開了CSDN開始看一看有什麼先進的可以學習的相關帖子,這時看到了一位大神寫的簡歷裝X必備,手寫Spring MVC。 我想這個東西還是有一點意思的 就拜讀了一下大佬的博客 通讀了一遍相關代碼 感覺和我想象中spring的運作流程基本相同 但是我腦海中基本上只有一個非常簡單的基本概念 而 ...
  • 多好,多簡單,多好 ...
  • 一、題目 設平面上分佈著n個白點和n個黑點,每個點用一對坐標(x, y)表示。一個黑點b=(xb,yb)支配一個白點w=(xw, yw)當且僅當xb>=xw和yb>=yw。 若黑點b支配白點w,則黑點b和白點w可匹配(可形成一個匹配對)。 在一個黑點最多只能與一個白點匹配,一個白點最多只能與一個黑點 ...
  • 在webform中,驗證的流程大致如下圖: 在AOP中: 在Filter中: AuthorizeAttribute許可權驗證 登錄後有許可權控制,有的頁面是需要用戶登錄才能訪問的,需要在訪問頁面增加一個驗證,也不能每個action都一遍。 1、寫一個CustomAuthorAttribute,繼承自Au ...
  • Ajax請求數據響應格式,一個醒目組必須是同意的,前端才知道怎麼應付,還有很多其他情況,比如異常了,有ExceptionFilter,按照固定格式返回,比如沒有許可權,Authorization,按照固定格式返回。 Http請求的本質: 請求--應答式,響應可以那麼豐富?不同的類型其實方式一樣的,只不 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...