OOP繼承技巧:BaseController與BaseApiController

繼承技巧:BaseController與BaseApiController

BaseController與BaseApiController類別技巧不算是ASP.NET MVC或ASP.NET Web API的技術,它是一個OOP(Object-oriented programming,物件導向程式設計)繼承的應用,這在早期Web Forms就已經被大量使用,因為它只是單純的OOP繼承應用,並不會被語言或框架所限制。

ASP.NET MVC - Controller類別

我們先來看看我們在進行開發的Controller類別繼承關係:

IController繼承關係

ControllerBase類別繼承自IController介面,Controller類別繼承自ControllerBase類別,而ControllerBase與Controller都是抽象類別:

 public abstract class ControllerBase : IController {}
 public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer {}  
 

而我們開發者所在的ASP.NET MVC的Controller都是繼承自Controller抽象類別,Controller抽象類別提供開發者所需的大部分功能:

 public class HomeController : Controller {}  
 

從程式設計的角度來看,ASP.NET MVC的Controller也只是一個類別。如果你發現自己在其他Controller寫了完全相同邏輯的程式碼(相同的成員、屬性或方法等),那麼我們有非常合理的理由來建立一個共用的基礎類別,之後將Controller裡相同的成員、屬性或方法往上層的基礎類別移動,Controller只需重新繼承此基礎類別,就能發揮物件導向的繼承的優勢。

NLog - 新版<target xsi:type="Database" />設置方式

NLog - 新版<target xsi:type="Database" />設置方式

ASP.NET MVC4網站開發美學出版後不久,NLog調整了<target>裡Database的設置方式,目前我在網路上看到所有NLog Database的設置,有99.9%都還是舊版範例,這裡提供新的組態設置方式給大家參考。

NLog - 舊版<target xsi:type="Database"設置方式

以下是舊版Database設置方式,也是你在網路上都可以查詢的到的組態:

 <target xsi:type="Database" name="database">
     <dbprovider>mssql</dbprovider>

     <!-- database connection parameters -->
     <!-- alternatively you could provide a single 'connectionstring' parameter -->

     <dbhost>.</dbhost>
     <dbdatabase>NLogDatabase</dbdatabase>
     <dbusername>nloguser</dbusername>
     <dbpassword>nlogpassword</dbpassword>

     <commandText>
         insert into NLog_Errro(time_stamp,level,logger,message) values(@time_stamp, @level, @logger, @message);
     </commandText>

     <parameter name="@time_stamp" layout="${date}" />
     <parameter name="@level" layout="${level}" />
     <parameter name="@logger" layout="${logger}" />
     <parameter name="@message" layout="${message}" />
 </target>  
 

ASP.NET Web API 2:安全的PATCH方法的三種實作

ASP.NET Web API 2:安全的PATCH方法的三種實作

之前「ASP.NET WEB API的HTTP PATCH動詞與PATCH方法實作」被網友反應有問題,經驗證後證實,ASP.NET MVC的Bind屬性對於ASP.NET Web API無效。真的是犯了程式碼會動的大錯,非常抱歉,以下重新整理三種Patch方法的實作方向。

Model - TodoItem

以下是範例用的Model:

 public class TodoItem
 {
     public int Id { get; set; }
     public string Name { get; set; }
     public bool IsDone { get; set; }
 }  
 

請先利用基架(Web API 2 - Entity Framework)產生TodoItemsConteoller。建置之後,先利用POSTMAN / Fiddler等工具新增幾筆資料。

Patch方法的安全性問題

PATCH動詞在HTTP規範中代表著「部分更新」,而Patch方法即是要拿來實作對應PATCH動詞的方法。但預設的Model Binding機制是將所有傳入的資料盡量(盡其所能)進行Binding動作。

  public IHttpActionResult Patch(int id, TodoItem todoItem) {}
 

這在我們進行部分更新的可能會有一些安全性問題,例如,可疑用戶端傳入{"Id":1,"Name":"Is Patch?","IsDone":false},Name與IsDone都會被修改。所以我們要保護好資料,不應該被更新的部分就要剔除。

Patch方法 - 指定更新屬性

第一種方法就是之前那一篇的方法,透過指定更新屬性名稱來進行部分更新的動作:

  TodoItem item = db.TodoItems.Find(id);
  // 一一指定
  item.IsDone = todoItem.IsDone;
  db.Entry(item).State = EntityState.Modified;
  
  try
  {
      db.SaveChanges();
  }
  // 省略
 

我們的範例比較簡單,工作項目只許修改是否完成(IsDone)的狀態。此種方式在有大量屬性(欄位)時比較麻煩。記得,如果你不是一一指定的方式,那麼此PATCH方法等於是PUT方法。

在ASP.NET Web API 2進行動態的ApiController層級組態

前一篇「在ASP.NET WEB AP 2進行APICONTROLLER層級的組態」是透過屬性(Attribute)設置方式來為ApiControler加入靜態設置。它無法在執行期間改變。

實作IControllerConfiguration介面

方法前一篇已經介紹過了:

 public class JsonOnlyAttribute : Attribute, IControllerConfiguration
 {
     public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
     {
         controllerSettings.Formatters.Clear();
         controllerSettings.Formatters.Add(new JsonMediaTypeFormatter());
     }
 }  
 

以上是僅提供JSON Formatter的範例,這樣的好處是不用整個ASP.NET Web API 2專案都完全關閉XML Formatter,需要關閉時才關閉。

如果你是希望動態進行Controller層級組態的話,其實前一篇的參考文件有留下一篇MVP Filip的參考文章,以下簡述Filip文章以瞭解如何進行動態Controller組態。

在ASP.NET Web AP 2進行ApiController層級的組態

在ASP.NET Web API進行Controller層級的組態

在ASP.NET Web API要進行組態設置的話,一般會到WebApiConfig.cs進行設置。不過有個好玩的問題,在WebApiConfig.cs進行的組態都是以HttpConfiguration物件在進行操作,MSDN說明表示 HttpServer 執行個體的設定。。也就是說,不管你在何處進行設置,設置之後,它影響是的整個ASP.NET Web API(即HttpServer執行範圍)

Model:TodoItem

以下是範例Model:

 public class TodoItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsDone { get; set; }
    }
 

然後利用基架含Entity Framework產生TodoItemsConteoller。建置之後,先利用POSTMAN等工具,新增幾筆資料:

api/TodoItems

小寫開頭(CamelCase)

JSON.NET預設序列化依照TodoItem的屬性名稱來輸出,現在有個簡單的需求,希望可以改採小寫開頭(CamelCase)的方式,那麼可以在WebApiConfig.cs這樣設置:

 public static class WebApiConfig
 {
     public static void Register(HttpConfiguration config)
     {
         config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

         // 省略
     }
 }  
 

設置CamelCasePropertyNamesContractResolver之後,解決第一個需求:小寫開頭。

Change CameCase Global

利用lprun.exe把.linq當command-line的執行檔

利用lprun.exe把.linq當command-line的執行檔

以前一般情況下會介紹LINQPad是因為要寫LINQ,但現在LINQPad已經是除了Visual Studio寫測試程式第二選擇。但有個問題,這支測試程式剛好就是一個command-line(命令提示字元)的專案程式,那麼可不可以直接執行寫好的*.linq檔案,而不是「開Visual Studio,開新專案,"Copy & Paste",compiler ...」。這需求lprun聽到了。

lprun.exe使用簡介

lprun.exe使用方式很簡單,只需要把你寫好的*.linq指定給他,它會動態幫你編譯並執行。

LINQPadRunner

LINQPadRunner以前是個github專案,後來被LINQPad作者直接包進安裝檔之中,如果你的LINQPad一直是採用Update方式,可能會沒有lprun.exe,只需要重新安全最新安裝檔或獨立執行檔,其中都已經包含lprun.exe執行檔。

lprun.exe使用範例

首先來個Hello world:

   void Main()
   {
    Console.WriteLine ("Hello world, LINQ run-time.");
   }
  

將*.linq儲存,利用lprun.exe來執行: