.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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...