夏は不思議とカレーが食べたくなるもので、中洲川端にある『スパイス』に行ってきた。店には所々にガンダムグッズが置いてあって、奇妙な感じだが嫌いじゃない。
注文したのはカツカレー(980円)。 カレーはマイルドで、甘さと辛さのバランスがちょうどいい。 トンカツはサックサクに揚がっており、カレーとの相性も良く旨かった。
スパイスという店名なので、インドカレーやスリランカカレーのような、かなりスパイシーなカレーを出す店かと思っていたが、どちらかというと欧風カレーに近いカレーだった。
今年こそは夏期休暇らしいことをしたいと思い、佐世保にある『九十九島パールシーリゾート』に行ってきた。道中、尋常じゃない雨が降ってどうなるかとヒヤヒヤしたが、佐世保は晴れていて安心した。
お目当は水族館『海きらら』。 コンビニで前売り券を買っておいたので、100円安く入れた。
大水槽。
イルカショーは観客が多くて立ち見だった。30分以上前から場所取りしていたみたい。この暑い中、自分には無理だ。ジャンプは何とか見れたので良しとしよう。
客席の方は水しぶきをかなり浴びたみたいだ。
海きららはクラゲにも力を入れてるみたい。
海きららを見終わって、遅めの昼食を食べたら、もう16時過ぎ。福岡に帰るために佐世保駅へ向かった。
電車は高いので、高速バスを予約。バスの時間まで1時間以上あるので、佐世保駅の周辺を散策することにした。
佐世保駅のすぐ近くに立派な『カトリック三浦町教会』が。高台にあって雰囲気ある。
佐世保駅のすぐ裏には『させぼ五番街』があった。入ってるテナントは福岡のキャナルシティや木の葉モールと似た傾向。
すぐ側が海でムードがあった。
港も。
佐世保バーガーの有名店『ヒカリ』が出店していたのに、運悪く腹減って無くて食べなかったのが心残り。あと四ヶ町アーケードにも行けなかった。次の機会があれば行きたい。
最近は豚骨よりも醤油を好む傾向になってきた。こってりが辛くなったのは、もう若くないということだろうか。今回行ったのは、東比恵にある『中華そば かなで』。
中華そばを注文。
多加水麺はプチっとした食感が新鮮。 チャーシューは低温調理してあって、 チャーシューとは思えないジューシーさだった。 清湯鶏がらスープに古式しょうゆを合わせたスープは、あっさりでいて、味が奥深い。 中華そばとして完成されている印象。 福岡でこんな醤油が食べられるとはね。
開発している Web API を ASP.NET Core 2.0 に移行しようと思っていたが、Web API のドキュメント生成に使っている Swashbuckle.AspNetCore がまだ 2.0 に対していないっぽくて一時中断。
ASP.NET Core MVC にはもとから Microsoft.AspNetCore.Mvc.ApiExplorer というのが提供されていて、これを使うことでちょっとした Web API のドキュメントを出力できる。ただ、SwaggerUI ほど高機能では無いし、Web API ドキュメントを表示するためのコントローラーとビューを自分で書く必要があるみたいだ。手軽ではない。
試してみたコードがこちら。
using System.Collections.Generic; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace SampleApi { public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build(); } public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { // AddMvc 内で ApiExplorer も登録されている services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvcWithDefaultRoute(); } } [Route("api/[controller]")] [ApiExplorerSettings(GroupName = "Values API", IgnoreApi = false)] public class ValuesController : Controller { [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } [HttpGet("{id}")] public string Get(int id) { return "value"; } [HttpPost] public void Post([FromBody]string value) { } [HttpPut("{id}")] public void Put(int id, [FromBody]string value) { } [HttpDelete("{id}")] public void Delete(int id) { } } public class HomeController : Controller { readonly IApiDescriptionGroupCollectionProvider _apiExplorer; public HomeController(IApiDescriptionGroupCollectionProvider apiExplorer) { _apiExplorer = apiExplorer; } // API ドキュメントを表示する public IActionResult Index() { return View(_apiExplorer); } } }
Web API のドキュメントを表示する Home/Index ビュー。
@using Microsoft.AspNetCore.Mvc.ApiExplorer @model IApiDescriptionGroupCollectionProvider <html> <head> <meta charset="utf-8" /> <title>Sample API</title> </head> <body> <h1>Sample API ドキュメント</h1> @foreach (var group in Model.ApiDescriptionGroups.Items) { <h2>@group.GroupName</h2> @foreach (var api in group.Items) { <h3>@api.HttpMethod @api.RelativePath</h3> <div class="parameters"> <h4>パラメーター</h4> @if (0 < api.ParameterDescriptions.Count) { <table> <thead> <tr> <th>名前</th> <th>型</th> <th>Constrains</th> <th>デフォルト値</th> <th>必須</th> </tr> </thead> <tbody> @foreach (var parameter in api.ParameterDescriptions) { <tr> <td>@parameter.Name, (@parameter.Source.Id)</td> <td>@parameter.Type?.FullName</td> @if (parameter.RouteInfo != null) { <td>@string.Join(",", parameter.RouteInfo.Constraints?.Select(c => c.GetType().Name).ToArray())</td> <td>@parameter.RouteInfo.DefaultValue</td> <td> @if (parameter.RouteInfo.IsOptional == true) { <text>○</text> } </td> } else { <td></td> <td></td> <td></td> } </tr> } </tbody> </table> } else { <i>なし</i> } </div> <div class="responses"> <h4>レスポンス</h4> <table> <thead> <tr> <th>ステータスコード</th> <th>型</th> <th>メディアタイプ</th> </tr> </thead> <tbody> @foreach (var response in api.SupportedResponseTypes) { <tr> <td>@response.StatusCode</td> <td>@response.Type?.FullName</td> <td> <ul> @foreach (var responseFormat in response.ApiResponseFormats) { <li>@responseFormat.MediaType</li> } </ul> </td> </tr> } </tbody> </table> </div> } } </body> </html>
実行すると、こんなドキュメントが表示される。
取得した Web API の情報を自分で好きなように出力するので、自由度は高い。でもやっぱり Swagger UI の方がいいな。
ASP.NET Core 2.0 で Swashbuckle.AspNetCore 使えました。
5巻では、体型を隠すコーディネートと、結婚式の二次会なんかで使えるスマートカジュアルについて解説してあったが、自分には使えそうにない。
体型は今のところキープできているし、 周りはほとんど結婚してしまったので、 結婚式の二次会に行くことも無さそう。
セットアップはコーディネートの幅が広がるので、持っておくと便利そうではある。安い買い物ではないので、すぐにとはいかないが。
服を着るならこんなふうに(5) (カドカワデジタルコミックス)
Podcast で IT エンジニアにお薦めと聴いて、Kindle で一気に読んだ。
天才的なハッカーでクラッカーでもある主人公の是枝が、もう1人の主人公であるエンジェル投資家の坂井と組んで、 世界征服を目指す。実際は、是枝のクラッカーとしての能力を生かして、サイバー犯罪と戦うマンガ。
出てくるサイバー犯罪は、どれも現実に起きておかしくないもので、これはないなと思うことがなかった。Web サービスを開発運用する身として、読んでて身が引き締まった。IT エンジニアにお薦めというのも納得。
是枝の宿敵と言えるキャラも出てきて、幾度となく熱いサイバーバトルを繰り広げるが、13 巻ともなると最終決戦かというくらいの盛り上がり。まさかこんな展開になるとは。熱い。熱すぎる。続きが気になって仕方ない。
あと、坂井がいいね。第一印象はめっちゃ胡散臭かったけど、すぐにお気に入りになった。脳みそが若かったりアンテナが高いところはもちろん良いが、それよりも、自分を馬鹿にしている後輩に対して、そういう気概があるべきだと言えるところが格好良い。 こんなアラフォーになりたいと思った。
例えば .NET Core でテキストファイルを出力するとき、文字コードに Shift-JIS を指定するには
System.Text.Encoding.CodePages
が必要だった。
using System; using System.IO; using System.Text; namespace EncodingSample { class Program { static void Main(string[] args) { // エンコードプロバイダーの登録が必要 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var path = Path.Combine(".", "result.txt"); using (var stream = File.OpenWrite(path)) { // エンコードプロバイダーを登録していなかったら // ArgumentException が発生してしまう using (var writer = new StreamWriter(stream, Encoding.GetEncoding("shift_jis"))) { writer.WriteLine("Hello,World!"); } } Console.WriteLine("Enter で終了"); Console.ReadLine(); } } }