.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
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...