Home
›
Archives for 4月 2019
## 参考 URL - https://stackoverflow.com/questions/37490192/modelbinding-on-model-collection - https://stackoverflow.com/questions/38375998/asp-net-core-1-0-post-ienumerablet-to-controller - https://qiita.com/kazuhisam3/items/94542f6d7ccf3acca41c
Linq には配列やリストの順序を反転させる `Reverse` というメソッドがあります。 ## サンプル ```cs:test.cs var data = new int[]{ 0, 1, 2, 3, 4 }; var reverse = data.Reverse(); Console.WriteLine(string.Join(", ", data)); Console.WriteLine(string.Join(", ", reverse)); ``` **出力結果** ```bat 0, 1, 2, 3, 4 4, 3, 2, 1, 0 ``` ## List の場合 配列の場合は上記でいいのですが、リストの場合にはちょっと注意が必要です。 List にはもともと `Reverse` というメソッドがあり、Linq より List のほうが優先して使用されるため、以下のコードはビルドに失敗します。 ```cs var data = new List{ 0, 1, 2, 3, 4 }; // List の Reverse の戻り値は void なので以下はエラーになる var reverse = data.Reverse(); ``` 以下に簡単な対策方法を載せます。 (他にもあれば教えてください。) ### AsEnuemrable を使用する `IEnumerable` を返す `AsEnumerable` を使用することで、Linq の `Reverse` メソッドを適用することができます。 ```cs var data = new List{ 0, 1, 2, 3, 4 }; var reverse = data.AsEnumerable().Reverse(); ``` ### IList を使用する `IList` は `List` のインターフェイスかと思ったら、実は `Reverse` メソッドなどは定義されていないので、Linq の `Reverse` が適用されます。 ```cs IList data = new List{ 0, 1, 2, 3, 4 }; var reverse = data.Reverse(); ``` もちろん `IList` 以外の他のコレクションでも良いです。 ## 参考 URL - https://days-of-programming.blogspot.com/2014/12/linq.html - https://qiita.com/lobin-z0x50/items/248db6d0629c7abe47dd
.NET で JSON へのシリアライズとデシリアライズを行う場合、`Newtonsoft.Json (Json.NET)` がよく使われます。 しかし、現時点の `Newtonsoft.Json` のバージョン (11.0.2) では、Dictionary のキーがタプルの場合のシリアライズとデシリアライズに対応できません。 この場合、.NET 標準の `DataContractJsonSerializer` を使用します。 ## 環境 - .NET Core 2.2 ## シリアライズ `DataContractJsonSerializer` を使って通常通りシリアライズするだけです。 例として、以下のようなデータをシリアライズしてみます。 ```cs static void Main(string[] args) { var SampleDataList = new Dictionary, string>() { [Tuple.Create(0, "Foo")] = "sample1", [Tuple.Create(0, "Bar")] = "sample2", [Tuple.Create(1, "Foo")] = "sample3", [Tuple.Create(2, "Bar")] = "sample4", }; var serializedData = Serialize(SampleDataList); Console.WriteLine(serializedData); } static string Serialize(T value) { var serializer = new DataContractJsonSerializer(typeof(T)); var serializedData = string.Empty; using (var memoryStream = new MemoryStream()) { serializer.WriteObject(memoryStream, value); serializedData = Encoding.UTF8.GetString(memoryStream.ToArray()); } return serializedData; } ``` **出力結果** 以下のようになります。(見やすいように整形してあります。) ```sh [ { "Key": { "m_Item1": 0, "m_Item2": "Foo" }, "Value": "sample1" }, { "Key": { "m_Item1": 0, "m_Item2": "Bar" }, "Value": "sample2" }, { "Key": { "m_Item1": 1, "m_Item2": "Foo" }, "Value": "sample3" }, { "Key": { "m_Item1": 2, "m_Item2": "Bar" }, "Value": "sample4" } ] ``` ## デシリアライズ 上記の JSON をデシリアライズする場合も、通常通りデシリアライズするだけです。 ```cs var deserializedData = JsonConvert.DeserializeObject, string>>(serializedData); ``` ```cs static T Deserialize(string value) { var serializer = new DataContractJsonSerializer(typeof(T)); var deserializedData = default(T); using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value))) { deserializedData = (T)serializer.ReadObject(stream); } return deserializedData; } ``` ## 参考 URL - https://docs.microsoft.com/ja-jp/dotnet/framework/wcf/feature-details/how-to-serialize-and-deserialize-json-data
Trading View の Pine スクリプトについて日本語の情報が少ないので、個人的にわかりやすいと思ったページをメモしておきます。 **リファレンス** - [Pineスクリプト言語リファレンスマニュアル](https://jp.tradingview.com/study-script-reference/) - [tradingview Pine スクリプト チュートリアル 日本語化](http://tradingview.wpblog.jp/) **基本構文** - http://mt4program.blogspot.com/2017/05/trading-viewpine.html **Series** - https://www.tradingview.com/wiki/Operators/ja#.E5.B1.A5.E6.AD.B4.E5.8F.82.E7.85.A7.E6.BC.94.E7.AE.97.E5.AD.90_.28.E8.A7.92.E6.8B.AC.E5.BC.A7_.5B.5D.29 **サンプルコード** - http://yuzoh.hatenablog.com/entry/2018/03/17/195245 - https://note.mu/kapipara180/n/n0a1a179116ec 気が向いたら追記していきます。
AWS Cloud9 で ASP.NET Core で作成した Web アプリケーションを動作させ、アクセスしてみます。 基本的には以下で解説されている通りです。 - https://qiita.com/ukgraphics/items/b66acd38cda4180b2d7f ただし、アプリケーションを `dotnet run` コマンドで動作させる場合は上記のように `launchSettings.json` を変更することでサーバー URL を変更できますが、私の場合は Linux の実行可能形式でアプリケーションを出力して実行していたため、`launchSettings.json` の設定を変更してもサーバー URL は変更されませんでした。 - https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/environments?view=aspnetcore-2.2 この場合、後述するように他の方法でサーバー URL を指定します。 尚、公式ドキュメントは以下です。 - https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/host/web-host?view=aspnetcore-2.2#server-urls ## サーバー URL を指定 以下のどちらかで指定します。 ### 環境変数で指定 `ASPNETCORE_URLS` で指定します。 ```sh $ export ASPNETCORE_URLS=http://localhost:8080 ``` ### プログラムで指定 `Program.cs` で以下のように記述します。 ```cs WebHost.CreateDefaultBuilder(args) .UseUrls("http://localhost:8080") ``` ## 外部からアクセスできるようにする 以下の記事を参考にしてください。 - [AWS Cloud9 で ASP.NET Core のアプリに外部からアクセスできるようにする](https://kuttsun.blogspot.com/2019/05/aws-cloud9-aspnet-core.html) ## 参考 URL - https://qiita.com/ukgraphics/items/b66acd38cda4180b2d7f - https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/environments?view=aspnetcore-2.2 - https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/host/web-host?view=aspnetcore-2.2#server-urls
Markdown を使えるようにするプラグインはいくつかあるようです。 今回は余計なブロックなど使わずに素直に Markdown を記述できそうな [Markdowku](https://www.dokuwiki.org/plugin:markdowku) というプラグインを使ってみました。 - 管理者アカウントでログイン - [管理] - [拡張機能管理] へ移動 - 「検索とインストール」のタブを選択 - `Markdown` などと入力して検索 - `Markdowku` のインストールを押す ただし、一部上手く動作しないタグがあるようです。 ## 参考 URL - https://www.dokuwiki.org/plugin:markdowku
DokuWiki で LDAP 認証を行うための設定です。 ## 環境 - Bitnami DokuWiki ## プラグインの有効化 デフォルトでインストールされている `Active Directory Authentication Plugin` というプラグインを有効化します。 - 管理者アカウントでログイン - [管理] - [拡張機能管理] で「Active Directory Auth Plugin」の「有効化」を押して有効にする ## LDAP 認証の設定 設定方法は以下で解説されています。 - https://www.dokuwiki.org/ja:plugin:authad Bitnami DokuWiki の場合、設定ファイルは `/bitnami/dokuwiki/conf` にあります。 設定ファイル名は `local.php` ですが、この設定ファイルはシステムに上書きされてしまうことがあるようなので、`local.protected.php` というファイルを作成します。 どうやら `local.protected.php` というファイル名の設定も読み込むようになっているようです。 `local.protected.php` には、環境に応じて以下のように記述します。 私の場合、設定した項目は以下だけです。 ```php ## 参考 URL - https://www.dokuwiki.org/ja:plugin:authad
PukiWiki から DokuWiki に移行することになったのですが、その DokuWiki を docker-compose を使って動作させてみました。 Docker イメージは出来るだけ公式なものを使いたいので、[Bitnami DokuWiki](https://github.com/bitnami/bitnami-docker-dokuwiki) を使用します。 ## docker-compose.yml とりあえず作成した `docker-compose.yml` は以下です。 ```yml version: '3' services: dokuwiki: container_name: dokuwiki image: bitnami/dokuwiki:latest restart: unless-stopped ports: - 11080:80 - 11443:443 environment: DOKUWIKI_USERNAME: admin DOKUWIKI_PASSWORD: admin http_proxy: http://example.com:8080 https_proxy: http://example.com:8080 volumes: - data:/bitnami networks: - common networks: common: external: true volumes: data: ``` ネットワークに関しては、あらかじめ `common` というネットワークを作成して使用しています。 ## 参考 URL - https://github.com/bitnami/bitnami-docker-dokuwiki
日時の比較の際、例えば求められている精度が秒までの場合は、ミリ秒やナノ秒の差は無視して比較する必要があります。 そんなとき、あらかじめ不要な桁は切り捨てて取得しておきたいことがあります。 これを簡単にする、`DateTime` の不要な桁を切り捨てる便利な拡張メソッドを見つけたので、紹介します。 - https://codeday.me/jp/qa/20181127/14363.html ## 拡張メソッド ```cs public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) { if (timeSpan == TimeSpan.Zero) return dateTime; return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks)); } ``` ## サンプルコード ```cs var format = "yyyy-MM-dd HH:mm:ss.fffffff"; var date = DateTime.Now; Console.WriteLine(date.ToString(format)); // マイクロ秒以下を切り捨て(精度をミリ秒までにする) date = date.Truncate(TimeSpan.FromMilliseconds(1)); Console.WriteLine(date.ToString(format)); // ミリ秒以下を切り捨て(精度を秒までにする) date = date.Truncate(TimeSpan.FromSeconds(1)); Console.WriteLine(date.ToString(format)); // 秒以下を切り捨て(精度を分までにする) date = date.Truncate(TimeSpan.FromMinutes(1)); Console.WriteLine(date.ToString(format)); ``` **実行結果** ```bat 2019-04-08 23:28:19.0981660 2019-04-08 23:28:19.0980000 2019-04-08 23:28:19.0000000 2019-04-08 23:28:00.0000000 ``` ## 参考 URL - https://codeday.me/jp/qa/20181127/14363.html - https://code-examples.net/ja/q/f549a
ASP.NET Core で Web アプリケーションを開発中に DI の解決に失敗し、以下のようなエラーが表示されました。 > InvalidOperationException: Cannot consume scoped service from singleton これはスコープの指定がおかしいことを意味しています。 具体的には、`Singleton` のクラスに `Scoped` または `Transient` のクラスを DI している場合に発生するようです。 詳しくは以下のページで解説されています。 - https://dotnetcoretutorials.com/2018/03/20/cannot-consume-scoped-service-from-singleton-a-lesson-in-asp-net-core-di-scopes/ 私の場合は、シングルトンのクラスに `DbContextOptions` を DI していたのが原因でした。 解決方法については明示されていませんが、そもそもこのような状況に陥ることがよくないので、アプリケーションの設計自体を見直すべきかと思います。 ## 参考 URL - https://dotnetcoretutorials.com/2018/03/20/cannot-consume-scoped-service-from-singleton-a-lesson-in-asp-net-core-di-scopes/ - http://morgwai.pl/articles/aspdi.html
GitLab をアップデートしたら、Pipeline の設定を行っていないプロジェクトで Push 時やマージリクエスト時にエラーが表示されるようになりました。 どうやらデフォルトで Pipeline の機能が有効になっているようなので、これを無効にする方法です。 ## 環境 GitLab 11.8.2 ## 設定変更 管理者でログインし、[Admin Area] - [Settings] - [CI/CD] の順にアクセスします。 `Default to Auto DevOps pipeline for all projects` のチェックを OFF にし、`Save changes` をクリックします。
Null 条件演算子を使えば条件文を減らせるので便利ですが、ちょっと注意するべき点もあるので、挙動の確認を行いました。 ## 基本 例えば以下のようなクラスがあった場合。 ```cs public class Person { public string Name { get; set; } public int Age { get; set; } } ``` 以下のコードは `null` が出力されます。 ```cs Person person = null; Console.WriteLine($"Name:{person?.Name}"); ``` **実行結果** ```bat Name: ``` Null 条件演算子がなければ例外が発生します。 ## 条件文での使用 ### if 文 以下のように条件文で使用した場合、`null` と数値との比較になるので、結果は `false` になります。 ```cs Person person = null; if(person?.Age >= 0) { Console.WriteLine($"0 以上"); } else if(person?.Age <= 0) { Console.WriteLine($"0 以下"); } else { Console.WriteLine($"false"); } ``` **実行結果** ```bat false ``` ### switch 文 ```cs Person person = null; switch (person?.Age) { case null: Console.WriteLine($"null"); break; default: Console.WriteLine($"数値"); break; } ``` **実行結果** ```bat null ``` ## 値の代入 Null 条件演算子の戻り値は Null 許容型となるため、以下はビルドに失敗します。 ```cs // ビルドエラー Person person = null; int age = person?.Age; ``` ```cs // ビルドは通るが例外が発生する Person person = null; int age = (int)person?.Age; ``` ```cs // これは OK Person person = null; int? age = person?.Age; ``` または、 Null 条件演算子を使ってメンバーへの代入はできません。 ```cs // ビルドエラー Person person = null; person?.Age = 10; ``` ## 参考 URL - https://qiita.com/dyoneda/items/a141546e6cef4b8790e9 - https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/null-conditional-operators
DB に配列を格納することの是非はさておき、EntityFramework Core を使って SQLite に配列を格納する方法です。 ## 環境 - Visual Studio 2017 - .NET Core 2.2 ## モデル イメージとして、以下のような `int` の配列を持つオブジェクトを DB に格納したいとします。 ```cs public class PersonDbContext : DbContext { public DbSet Persons { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=sqlitetest.db"); } } public class Person { public int Id { get; set; } public string Name { get; set; } public int[] Attributes { get; set; } } ``` しかし、このままビルドすると以下のようなエラーが表示されます。 > System.InvalidOperationException: 'The property 'Person.Attributes' could not be mapped, because it is of type 'Int32[]' which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.' ## 配列を保存するためには DB には配列を文字列として格納し、取り出すときに分割して `int` に変換するようにします。 先ほどのコードを以下のように変更します。 ```cs public class PersonDbContext : DbContext { public DbSet Persons { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=sqlitetest.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property("AttributeCollection") .HasField("_attributes"); } } public class Person { private static readonly char delimiter = ';'; public int Id { get; set; } public string Name { get; set; } string _attributes; [NotMapped] public int[] Attributes { get => _attributes.Split(delimiter).Select(x => int.Parse(x)).ToArray(); set => _attributes = string.Join(delimiter, value); } } ``` `int[] Attributes` には `NotMapped` 属性を付与することで、O/R マッパーの対象から外します。 その代わりに `string _attributes` というフィールドを用意し、`int[] Attributes` のプロパティで、`_attributes` に対する `get` と `set` を用意します。 `int` 配列と文字列の変換には、デリミターとして `;` を使用しています。 `DbContext` クラスの `OnModelCreating` メソッドでは、`_attributes` フィールドに `AttributeCollection` というプロパティを割り当てるように設定しています。 以上で、`Person` クラスを使う側からは DB を意識せずに配列を扱うことができます。 ```cs using (var db = new PersonDbContext()) { var person = new Person { Name = name, Attributes = new int[] { 0, 1, 2 } }; db.Persons.Add(person); db.SaveChanges(); } ``` ```cs using (var db = new PersonDbContext()) { foreach (var person in db.Persons) { Console.WriteLine($"ID = {person.Id}, Name = {person.Name}, Attributes={string.Join(", ", person.Attributes)}"); } } ``` DB Browser for SQLite で中身を見ると、文字列として格納されているのがわかります。 ## 参考 URL - https://kimsereyblog.blogspot.com/2017/12/save-array-of-string-entityframework.html