顯示具有 MVC 5 標籤的文章。 顯示所有文章
顯示具有 MVC 5 標籤的文章。 顯示所有文章

讓ASP.NET網站在開發除錯時期擁有Web.config文件轉換功能

讓ASP.NET網站在開發除錯時期擁有Web.config文件轉換功能

網站開發到一定規模,你一定有經驗,開始在 Web.config 裡去註解A執行B設定,或註解C執行D設定,最常碰到的需求有:測試區與正式區的 appSettings 設定,測試區與正式區的 connectionStrings 設定等。當專案離開本機開始發行至測試區或正式區時,千萬不要還在用切換註解的方式,應該參考 Kevin:「發佈網站時依據組態設定的不同而轉換 Web.Config」的模式去進行發行時 *.config 的切換。這種動作的名稱「XML-Document-Transform」(XML文件轉換),簡單說,就是利用 Locator 找出要修改位置,再利用 Transform 屬性指定進行的動作。

發行能,那本機除錯呢?

發行可以利用「XML-Document-Transform」來解決不同區域不同配置的問題。但開發人員最常碰到卻是開發當下!開發除錯當下,你無法去只是簡單切換 Debug | Release 來達到或啟用XML文件轉換的功能,假設,你想將原本 SqlLocalDb 的連線字串切換至 SQL Server Express 連線字串進行測試時,好像只有註解、移除註解這條路。 :-(

這樣的路,其實走了好久好久,我累了,我想,是應該跟它分手了。(超假文青 XD)

啟用本機除錯XML文件轉換

這裡會利用如何:擴充 Visual Studio 建置處理序裡的技巧。以下技巧通用於 ASP.NET WebForms 與 ASP.NET MVC 與 ASP.NET Web API 專案。(照理說是只要是 XML 的 .config 都通用,但我沒一一嘗試就是了)

ASP.NET MVC, Entity Framework Code First與MySql筆記

ASP.NET MVC, Entity Framework Code First與MySql的筆記

在一次機會中,需要在ASP.NET MVC去接MySql資料庫,試玩一下之後,發現在ASP.NET MVC與Entity Framework環境下去對接MySql資料庫並不會太難,以下為簡單的筆記。

連線MySql三個重要元件

其實走對第一步,對接MySql資料庫已經完成了80%說。 :)

首先你要安裝三個重要的元件:

ASP.NET MVC-取代JsonResult新選擇-招喚JilResult

ASP.NET MVC-取代JsonResult新選擇-招喚JilResult

I am speed

前集,找到以效能(速度)為主軸的Jil套件,經過自我驗證後,在JSON(反)序列化效能上確實不差,這一篇我們就利用ASP.NET MVC優秀的擴充機制以新的JilResult來取代原有的JsonResult,以完成JavaScriptSerializer退休的使命,讓ASP.NET MVC換上一顆高速的JSON(反)序列化引擎。

自製ActionFilter小鋼炮:MVC/WebAPI程式效能計時器

自製ActionFilter小鋼炮:MVC/WebAPI程式效能計時器

炮

最近進行一些ASP.NET MVC/ASP.NET Web API系統效能改善的工作,改善之初當然是找出最耗效能(或是說較耗效能)的程式碼來下手改善。找出吃資源程式碼的方式很多,第三方有許多不錯的選擇,不過我需求真的很簡單,只想得到一個數字,在 .NET Framework 最簡單是用的System.Diagnostics.Stopwatch 類別進行耗用時間的測量。

單一程式段落效能計時器

我們先從最簡單的開始,計算一段程式碼的執行時間。

ASP.NET MVC - Action段落效能計時器

 public ActionResult InActionTimer()                                                              
 {                                                                                                
     System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();                 
     stopWatch.Start();                                                                           
     // 模擬程式執行                                                                                
     System.Threading.Thread.Sleep(1527);                                                         
     stopWatch.Stop();                                                                            
     TimeSpan ts = stopWatch.Elapsed;                                                             
                                                                                                  
     System.Diagnostics.Debug.WriteLine($"ActionTimer: {ts.ToString()} from Foo/InActionTimer");  
                                                                                                  
     return Content($"ActionTimer: {ts.ToString()} from Foo/InActionTimer");                      
 }                                                                                                  
 
MVC stopWatch

可以看到.Start().Stop()之間的程碼計算出耗費時間。

使用Hangfire處理ASP.NET MVC/Web API長時間與排程工作

使用Hangfire處理ASP.NET MVC/Web API長時間與排程工作

工作管理

網頁通常是做為一個即時資訊交換工具,也就是一個請求-回應模式,不過在現實世界(或討論區)中經常會聽到希望可以進行長時間作業與排程作業的需求,網頁長時間作業通常是使用非同步技術來處理,但排程作業呢?這在單純的網頁作業流程中比較難處理,通常會說交給後端SQL Server排程處理或使用Windows工作排程器或寫成Windows Service來解決。

廢話那麼多,反正就是傳統網頁要處理長時間工作與排程工作都要額外花費不少心思,最近剛好有這方面的需求,試玩國外火紅Hangfire,不試還好,試了…

Hangfire - 射後不理、延遲、定時

Hangfire重點功能

Hangfire官網可以看到最明顯的三個功能:Fire-and-forget tasks、Delayed tasks、Recurring tasks。

ASP.NET MVC 5如何正確加入robots.txt?

ASP.NET MVC 5如何正確加入robots.txt?

robots.txt

圖片: http://blogtimenow.com

各位都知道ASP.NET MVC Framework從一開始就是走「路由(Routing)」機制,它並不是使用如ASP.NET (WebForms)的實體路徑+實體檔案的對應方式,所以要如何做才能加入robots.txt?

習慣性之Google之路

對於不知道的事物,我相信大家的第一選擇就是求Google大神幫忙。

關鍵字:mvc robots.txt

哇,有一堆的答案,都已經ASP.NET MVC 5了,這問題應該早就已經是FAQ級的問題了吧?

處理方式有二:

  • "robots.txt" Routing + ViewResult
  • "robots.txt" Routing + FileResult

"robots.txt" Routing 意指設置一條 url: "robots.txt",然後利用 default: 指到預設的 {controller}/{action},由此來回應 robots.txt 的內容。

ViewResult 是利用 View Page 來回應 robots.txt 內容。File 是利用資料流來回應 robots.txt 的內容。以效率而言,File沒有 Disk I/O 成本,是比較好的的方式,所以我最後選用File來回應 robots.txt 的內容。

以上透過一條假路由方式來模擬根目錄下的 robots.txt。

網路上的教學都還會特別提到一條 web.config 的設置:<modules runAllManagedModulesForAllRequests="true"></modules>,由 iis.net 文件中可以看到以下說明:

Optional Boolean value.

True if all managed modules can process all requests, even if the request was not for managed content; otherwise, false.

Note: In ASP.NET websites, the value of runAllManagedModulesForAllRequests previously had to be set to true to support routing. However, once IIS 7 has been updated with a Service Pack, the value of runAllManagedModulesForAllRequests can be set to false or omitted when working with ASP.NET routing. For more information, see ASP.NET Routing on the MSDN website.

The default value is false.

也就是說從 IIS 7 開始(更正確是指某個 Service Pack,我沒細查,文件也沒寫),為了支援 ASP.NET Routing ,runAllManagedModulesForAllRequests 預設會修改為 false,如果 web.cofing 沒有加上去,那麼你會得到一個 HTTP 404 錯誤。但這樣好嗎?

IE 11傳遞中文參數值在ASP.NET MVC產生HTTP 502

IE 11傳遞中文參數值在ASP.NET MVC產生HTTP 502

這是網友在MSDN論壇提出的問題《MVC在IE11因網址未編碼發生502問題,新增Route之後同樣未編碼卻沒問題,想問為什麼?,想想,這算不錯的題目,未來拿來當課程考題好了 XD

問題備份

原網址在IE 11下因中文未編碼出現502,嘗試新增一個Route後即解決問題,不知為何一樣傳送未編碼的中文Request竟然就沒有問題了? 新增的route如下:

routes.MapRoute(
    name: "StoreBrowse",
    url: "store/{genre}",
    defaults: new { controller = "store", action = "browse" , id = UrlParameter .Optional }
);

原URL為: /Store/Browse?genre=健康飲品

修改後:/Store/健康飲品

接收URL的Action:

public ActionResult Browse( string genre) 
{ 
 // Retrieve Genre and its Associated Albums from database 
 var genreModel = storeDB.Genres.Include("Albums" )
          .Single(g => g.Name == genre); 
 return View(genreModel); 
}

原本的問題是因為網址列傳送中文,但是更改Route後還是有傳送中文,為何就沒有問題了?

IE11的QueryString

以下使用 Visual Studio 2013新增一個 MVC 專案,修改一下"/Home/Index"的程式碼:

  public ActionResult Index(string name)
  {
      return Content(name);
  }
 

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.1的Query Parsing

MVC 5.1, Web API 2.1 RTM

時間2014/1/20,ASP.NET MVC 5.1與ASP.NET Web API 2.1與公告RTM,並且可以透過NuGet正式下載使用。使用MVC 5.1與Web API 2.1之前必須先進行Visual Studio開發工具的更新,之後才能正常使用MVC 5.1與Web API 2.1。

MVC 5.1與Web API 2.1有什麼更新?

此次更新主要是功能增強與問題修正:

ASP.NET MVC 5.1功能改善與增強

  1. 屬性路由改善
  2. Bootstrap在Editor範本的支援
  3. View支援Enum(列舉)
  4. Unobtrusive validation的MinLength與MaxLength屬性
  5. 在Unobtrusive Ajax支援"this"內容

ASP.NET Web APi 2.1功能改善與增強

  1. 全域錯誤處理
  2. 屬性路由改善
  3. Help Page改善
  4. IgnoreRoute支援
  5. BSON媒體格式支援
  6. 非同步過濾器支援
  7. 用戶端支援Query解析

完整的更新內容請參考asp.net說明:

極速.新增MVC 5與Web API 2專案

新增專案,慢慢慢!

我們經常需要新增專案來測試一些內容,但不知道各位電腦有沒有安裝SSD,雖然SSD很快,而且Visual Studio 2013裡的One ASP範本也盡量幫各位瘦身,但在新增MVC 5或Web API 2專案時還是會慢慢的?如果各位是傳統HDD,那更是起身運動的好時機。不過時間應該浪費在更美好的地方。以下就是要教各位如何透過Visual Studio 2013的基架(Scaffolding)來極速新增ASP.NET MVC 5或ASP.NET Web API 2專案。

極速.新增MVC 5與Web API 2專案

中文版Visual Studio安裝各種Preview或RC的NuGet套件

越來越快的軟體發行速度

不知道各位讀者有沒有發現,現在各種技術更新的速度越來越快。例如,這個Release Candidates for ASP.NET MVC 5.1, Web API 2.1 and Web Page 3.1消息,明明ASP.NET MVC 5、ASP.NET Web API 2才剛推出沒多久,就馬上有新版本跟著推出。就取得新功能或功能改善而言,這是件好事。當開發者想要嘗試這些Preview或RC功能時,可能會馬上碰壁,而停下了學習的腳步實在可惜。

範例:MVC 5無法升級MVC 5.1 RC

新增一個ASP.NET MVC 5專案,進行MVC 5.1 RC的安裝:

Install-Package Microsoft.AspNet.Mvc -pre

Install-Package : 更新 'Microsoft.AspNet.Mvc 5.0.0' 至 'Microsoft.AspNet.Mvc 5.1.0-rc1' 失敗。找不到與 'Microsoft.AspNet.Mvc 5.1.0-rc1' 相容的 'Microsoft.AspNet.Mvc.zh-Hant' 版本。
位於 線路:1 字元:1
+ Install-Package Microsoft.AspNet.Mvc -pre
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-Package], InvalidOperationException
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand

MVC 5.1 RC安裝錯誤

這裡馬上就碰到無法找到對應語系的套件,進而無法安裝的訊息。

範例:Web API 2無法升級Web API 2.1 RC

新增一個ASP.NET Web API 2專案,進行Web API 2.1 RC的安裝:

Install-Package Microsoft.AspNet.WebApi -Pre

Install-Package : 更新 'Microsoft.AspNet.WebApi.WebHost 5.0.0' 至 'Microsoft.AspNet.WebApi.WebHost 5.1.0-rc1' 失敗。找不到與 'Microsoft.AspNet.WebApi.WebHost 5.1.0-rc1' 相容的 'Microsoft.AspNet.WebApi.WebHost.zh-Hant' 版本。
位於 線路:1 字元:1
+ Install-Package Microsoft.AspNet.WebApi -Pre
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-Package], InvalidOperationException
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand

Web API 2.1 RC安裝錯誤

一樣是無法找到對應語系的套件的問題。

這問題很久了,我一定要解決它(握拳)

如何升級MVC 4和Web API至MVC 5和Web API 2

MVC 5與Web API 2

ASP.NET MVC 5與Web API 2帶來需多新功能,這份教學將教各位如何升級你的MVC 4與Web API應用程式到最新版本。

升級步驟

  1. 備份你的專案。依此教學會異動的專案檔案、套件組態與web.config。
  2. 更新Web API至Web API 2。請將 Global.axax 裡的:
    WebApiConfig.Register(GlobalConfiguration.Configuration);
         

    更新為:
    GlobalConfiguration.Configure(WebApiConfig.Register);
         

使用Autofac和Unity學習MVC 4,5和Web API 1,2的IoC,DI技巧

IoC與DI

IoC
Inversion of control,中文稱控制反轉。由Martin Fowler提出。這裡引用MVP 91哥的說明:系統架構設計應該以抽象的邏輯概念為主,才能更貼近現實世界,才能更符合domain model,當Business logic不變時,需求變更、技術變更、DB變更,都應該要把風險和成本壓到最低。
DI
Dependency injection,中文稱相依注入。在IoC的思考模式與實作下,最終的結果就是相依於介面(Interface),但類別中最後只存有介面的話,程式是不會動的,這時我們就會利用DI技巧,在應用程式啟動時去注入介面所對應的實體(也就是一般我們在程式碼裡寫的new ClassName())。

MVC與Web API的Controller的IoC與DI處理

不管是在ASP.NET MVC或ASP.NET Web API,在Controller的概念上或本質上可以說是一模一樣。這裡主要差異點會是在DI套件的實作差異上。

Controller使用Respository Pattern處理資料實體相依

一般我們會透過基架(MVC 5將scaffold翻譯為基架)來產生MVC的Controller與View Page,或是Web API的API Controller。例如,使用Northwind資料庫的Product資料表來產生API Controller會是這樣:

  public class ProductsController : ApiController
  {
      private NorthwindEntities db = new NorthwindEntities();

      // GET api/Products
      public IEnumerable<Product> GetProducts()
      {
          return db.Products.AsEnumerable();
      }

      // 省略
  }
  

預設範本所產生的程式碼會產生與NorthwindEntities資料實體(new NorthwindEntities())產生依賴關係。每個API Controller都還要處理db.Products,這造成API Controller的職責不夠單一,這在裡我們就先採用Repository Pattern 1來分離資料庫處理程式碼與API Controller的相依關係。

1 Repository Pattern實作請參考《ASP.NET MVC 4網站開發美學》第七章 Page 7-40頁。

  public class ProductsController : ApiController
  {
      //private NorthwindEntities db = new NorthwindEntities();

      private IProductRepository _product;

      public ProductsController() {
          _product = new ProductRepository();
      }

      // 重要,但要等一下才會知道
      public ProductsController(IProductRepository r)
      {
          _product = r;
      }

      // GET api/Products
      public IEnumerable<Product> GetProducts()
      {
          return _product.GetAll();
      }

      // 省略
  } 
  

透過Repository Patter我們分離了資料庫相關程式碼,而且我們偷偷留下一個含介面參數的建構函式,等一下在討論這部分。就目前使用了Repository Pattern的Controller,就算刪除此含介面參數的建構函式,程式依然會正常運作。

但引入使用Repository Pattern後的API Controller產生了新的問題,這些API Controller又會與特定實體類別產生相依關係,我們必須在無參數建構函式去初始化一個實體類別,以呼叫分離後的資料庫處理程式(例如:_product = new ProductRepository();)。

MVC練習 - 依使用者選擇時區顯示該時區時間

MVC練習

假日看到MVP Edward.K一篇[ASP.NET]利用TimeZoneInfo將現在時間切換到各個國時間一文,覺得介紹的很不錯。就改寫為MVC的版本,自我練習一下。

ZoneController

新增一個ZoneController,此Controller要取得時區清單並傳遞至View Page。MVC 5的加入控制器和之前有些不同:

MVC 5 - 添加基架

Scaffold在MVC 5正式反翻為「基架」之不是之前Preview與RC的「支架」。選擇使用「MVC 5控制器-空白」。

在ZoneController新增一個名稱Time的Action方法:

   public ActionResult Time()
   {
       IReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
       ViewBag.TimeZoneInfo = new SelectList(timeZones, "Id", "DisplayName");
       return View();
   }
  

IReadOnlyCollection本身繼承IEnumerable與IEnumerable(Of T),可以直接將取得的timeZones傳入SelectList類別使用。在SelectList類別選擇使用第三種建構函式:「SelectList(IEnumerable, String, String)」: