ASP.NET MVCはじめました~データのキャッシュ
概要
データキャッシュの実装とテストについて調べてみました。
参考資料
プログラミングMicrosoft ASP.NET MVC 第3版ASP.NET MVC 5 対応版 (マイクロソフト公式解説書)
- 作者: Dino Esposito,井上章
- 出版社/メーカー: 日経BP社
- 発売日: 2014/10/30
- メディア: 単行本
- この商品を含むブログ (1件) を見る
ASP.NET MVCでのキャッシュについては、今のところ、キャッシュ機能をアプリケーションに注入する方法が推奨されています。
特定のキャッシュ機能の実装に依存しないようにキャッシュサービスを注入してあげれば良さそう。
環境
- Visual Studio Community 2017
- ASP.NET MVC5
キャッシュサービスの実装
インターフェイスと実装。インターフェイスは必要に応じて機能を追加します。書籍のサンプルコードではSystem.Web.Caching
のCacheオブジェクトを使用していましたが、System.Runtime.Caching
のMemoryCacheオブジェクトに置き換えてみました。
■/Framework/ICacheService.cs
public interface ICacheService { Object Get(String key); void Set(String key, Object data); Object this[String key] { get; set; } }
■/Framework/AspNetCacheService.cs
public class AspNetCacheService : ICacheService { private readonly MemoryCache _memoryCache; public AspNetCacheService() { _memoryCache = MemoryCache.Default; } public object Get(string key) { return _memoryCache[key]; } public void Set(string key, object data) { _memoryCache[key] = data; } public object this[string key] { get { return _memoryCache[key]; } set { _memoryCache[key] = value; } } }
キャッシュサービスの注入
アプリケーションの起動時にキャッシュサービスを注入するためのパブリックなRegisterCacheService
メソッドを用意しておくと、コントローラごとにサービスを注入する必要はなく、テストもできるって訳ですね。
■Global.asax.cs
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { ... RegisterCacheService(new AspNetCacheService()); CacheService["StartTime"] = DateTime.Now.ToString(); } private static ICacheService _internalCacheObject; public static void RegisterCacheService(ICacheService cacheService) { _internalCacheObject = cacheService; } public static ICacheService CacheService { get { return _internalCacheObject; } } }
■HomeController.cs
public class HomeController : Controller { public ActionResult Index() { var data = MvcApplication.CacheService["StartTime"]; if (data != null) { ViewBag.StartTime = (String)data; } return View(); } }
キャッシュサービスのテスト
テストの時はモックを用意してRegisterCacheService
メソッドに渡してあげる感じ。
■HomeControllerTests.cs
public class HomeControllerTests { [TestMethod()] public void IndexTest_Cache() { var expected = "2017-04-15 12:00:00.000"; var mockCacheService = new Mock<ICacheService>(); mockCacheService.Setup(m => m["StartTime"]).Returns(expected); MvcApplication.RegisterCacheService(mockCacheService.Object); var controller = new HomeController(); ViewResult result = controller.Index() as ViewResult; var actual = result.ViewBag.StartTime; Assert.AreEqual(expected, actual); } }
実行結果
参考資料
プログラミングMicrosoft ASP.NET MVC 第3版ASP.NET MVC 5 対応版 (マイクロソフト公式解説書)
- 作者: Dino Esposito,井上章
- 出版社/メーカー: 日経BP社
- 発売日: 2014/10/30
- メディア: 単行本
- この商品を含むブログ (1件) を見る
ASP.NET MVCはじめました~PDFを出力する
概要
TuesPechkinというライブラリを使ってPDFを出力するやり方について調べてみました。
環境
- Visual Studio Community 2015
- ASP.NET MVC5
- TuesPechkin 2.1.1
TuesPechkin?
Google翻訳してみたら「火器屋」って…物騒ですねぇ。以下、README.mdから。
TuesPechkin is a .NET Wrapper for the wkhtmltopdf library.
https://github.com/tuespetre/TuesPechkin
HTMLをPDFに変換してくれるwkhtmltopdfライブラリの.NETラッパーとあります。wkhtmltopdfというのが本体なんですね。
Azure Websites does not currently support the use of wkhtmltopdf.
https://github.com/tuespetre/TuesPechkin
試しにAzure App Serviceにデプロイしてみたけど現段階で動きませんでした。
You must have Visual C++ 2013 runtime installed to use these packages.
https://github.com/tuespetre/TuesPechkin
wkhtmltopdfがC++で書かれているからランタイムもないとダメなんすかね。
とりあえず、動かしてみましょう!
インストール
ライブラリのインストールはパッケージマネージャーコンソールより以下を実行。TuesPechkinライブラリも一緒にインストールされます。他にもTuesPechkin.Wkhtmltox.Win32とTuesPechkin.Wkhtmltox.Win64がそれぞれ用意されているので環境に合わせてって感じでしょうか。
PM> Install-Package TuesPechkin.Wkhtmltox.AnyCPU
実装
HTMLをPDFに変換してくれるってことは、出力したいイメージのViewを作成してあげればOKと理解したので、以前作ったToDoリストをPDF化してみます。ちょっと面倒なのはレイアウトページを使っているとヘッダーやフッターまで一緒に出力されてしまうので、Indexページをそのまま出力するんじゃなく、PDF出力用のIndexViewを用意しなきゃいけないとこですかね。
■/Controllers/ReportController.cs
public class ReportController : Controller { ... public ActionResult TodoReport() { var pdfData = CreatePDF("Todo", "Report", null); return File(pdfData, "application/pdf", "TodoReport.pdf"); } private byte[] CreatePDF(string actionName, string controllerName, object routeValues = null) { var helper = new UrlHelper(ControllerContext.RequestContext); var indexUrl = helper.Action(actionName, controllerName, routeValues, Request.Url.Scheme); return _service.Create(indexUrl); } }
■/Services/Report/ReportService.cs
public class ReportService : IReportService { ... public byte[] Create(string indexUrl) { var document = new HtmlToPdfDocument() { GlobalSettings = { ProduceOutline = true, DocumentTitle = "PDF Sample", PaperSize = PaperKind.A3, Margins = { All = 1.375, Unit = Unit.Centimeters } }, Objects = { new ObjectSettings() { PageUrl = indexUrl, }, } }; var converter = new StandardConverter( new PdfToolset( new WinAnyCPUEmbeddedDeployment( new TempFolderDeployment()))); var pdfData = converter.Convert(document); return pdfData; } }
実行結果
ToDoリストのIndexページの[Download PDF]リンクからPDFをダウンロードします。ただ、出力したいのはデータ部分のみ。ヘッダーもフッターも余計なリンクとかもいらないですね。
なので出力イメージのView(レイアウトページ使用なし)を用意しておきます。Viewなのでブラウザで見ることも可能。
※PDF出力の際に表示されるわけではありません。
ダウンロードリンクを押下すると、PDF出力処理が走って出力イメージのViewをPDFに変換してくれます。そして、Viewの通りに出力されました!BootStrapを使ってますが、問題なく理解してくれてますね!
ソース
ASP.NET MVCはじめました~権限による多階層ドロップダウンメニューの表示切り替え
概要
前回の続きというか、前回忘れていた権限によるメニューの表示切り替えです。
環境
- Visual Studio Community 2015
- ASP.NET MVC5
- BootStrap 3.3.7
- jQuery 3.1.1
権限項目の追加
右端のRoleId項目を追加しました。権限の種類(サンプルではユーザ、チョットできるユーザ、管理者の3種類)ごとに値を設定しておきます。あとはログインユーザごとの権限でメニューの項目を取得してくればOK。
■/Models/MenuItem.cs
public enum Role { User, PowerUser, Administrator, } public class Navigation { public Navigation() : this(role: Role.User) { } public Navigation(Role role) { this.RoleId = (int)role; } public int RoleId { get; } public IEnumerable<NavigationLink> Menu { get { var menu = new List<NavigationLink>(); using (var context = new AppDbContext()) { var data = context.MenuItems .Where(n => n.RoleId <= RoleId) .OrderBy(n => n.Order) .ToList(); var mainMenu = data.Where(n => n.ParentId == null); foreach (var item in mainMenu) { NavigationLink linkItem = MappingLinkItems(item); menu.Add(linkItem); } SetChildMenu(menu, data); } return menu; } } #region helper method... }
実行結果
User権限の場合
RoleIdが"0"以下の項目のみなので、メインメニューの3つだけ。
Power User権限の場合
RoleIdが"1"以下の項目のみで、3階層分の一部だけ。
Administrator権限の場合
RoleIdが"2"以下の項目のみ、つまり全部表示。