EntityFramework上でのSqlite DateTimeの扱い

SQLiteでは、日付型というものは基本的に存在しない。

SQLのCREATE TABLE中で型としてDATETIMEを指定しても、内部的にはBinaryとなってしまい、Scaffoldした場合はbyte[]として変換されてしまう。

Entity Frameworkで、コードファーストを使用して、DateTime型のプロパティをマイグレーションすると、SQLite上にはTEXT型として作成され、自動的に相互変換をかけるように設定してくれる。

ただ、データファーストで、Scaffoldをかけた場合、TEXT型のカラムから作成されるエンティティ中のプロパティはstring型になってしまう。

TEXT型だが、内容はDateTimとして扱いたい場合は、DbContextから派生させたクラス中で、OnModelCreatingメソッドをオーバーライドして、データ変換をかけることで解決できる。

例えば、前述の日時を格納するTEXT型のカラムをDateTimeとして扱いたければ、以下のようなコードを書いておけば良い。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyTable>(entity =>
    {
        entity.ToTable("MyTable");

        entity.Property(e => e.PostedTime)
            .HasColumnType("TEXT")
            .HasColumnName("PostedTime")
            .HasConversion<DateTime>();
    });

    OnModelCreatingPartial(modelBuilder);
}

これにより、MyTableテーブルのPostedTimeはDB上にはTEXT型として保存され、読み出し時にはDateTimeに変換されるようになる。

SQLiteの場合、MigrationとScaffoldで結果が違うので、どうすればいいかなと調べてみた。(ちなみに、Migration時に自動的に変換定義している模様。Migrationフォルダに自動生成されているようだ。)

カテゴリー: C#, dotnetcore, Entity Framework, 技術系 | 1件のコメント

asp.net core webappでのファイルダウンロード

以前にファイルアップロードの件でも少し書いたが、asp.net core webappでのファイルダウンロードについて、多分正解というのが分かったので・・・

結局、OnPostやOnGetをvoidで定義するのではなく、下記のようにActionResultを返すメソッドとして定義する。

public IActionResult OnPost(・・・) {
}

処理中でファイルをダウンロードさせたい場合は、File(・・・)を使用して、FileResultを返せば良い。また、ファイルダウンロードでは無く、画面表示をさせたい場合は、Page()を使用して、PageResultを返す。

// Excelファイルのダウンロード
try {
	using(xls = new ExcelPackage(new FileInfo(templatepath))) {
	    // セルに対して値の設定等の処理
    ・・・
		// ちなみに、ファイル名は自動的にurlencode化されるので、
		// 事前にUrlEncodeすると変なファイル名になる。
		// PageModel.Fileを使用して、FileResultを返す
	    return File(xls.GetAsByteArray(),"application/octet-stream",filename);
	}
} catch (Exception e) {
	Message = $"エラー発生{e.Message}";
	return Page();
}

なお、File(stream,・・・)を使用する場合、Streamに書き込み等を行っていた場合、ポジションを先頭に戻さないと、実行時エラーが起きるようだ。

Stream stm = MemoryStream();
// メモリストリームに書き込み
・・・
// ポジションを先頭に
stm.Seek(0L,SeekOrigin.Begin);
return File(stm,"application/octet-stream",filename);

やっぱり、基礎を覚えないとだめだね・・・

カテゴリー: .NET, asp.net core, C#, dotnetcore, 技術系 | コメントする

asp.net webappモデルからのJS起動など

asp.net webappのモデル側からJS(例えばwindowをクローズ等)を起動できないものかと、以下のようなコードをチョット試してみた・・・

@page
@model TestModel
・・・
<script type="text/javascript">
@Html.Raw(Model.ExecScript)
</script>
public class TestModel : PageModel {
  ・・・
  public string ExecScript;
  public void OnPost(・・・) {
    ・・・
    ExecScript = @"window.close();";
    ・・・
}

結論としてはうまく動作。ただ、セキュリティ上Html.Rawはあまり使うべきではないのかな?

ちなみに、gijgoのTreeViewのdataSource指定なんかにもHtml.Rawを使って動的にTreeの内容を変更することも出来たけど、他にいいやり方あるかな?

<script type="text/javascript">
    $(document).ready(function() {
        $('#tree').tree({
            uiLibrary: 'bootstrap4',
            dataSource: @Html.Raw(Model.TreeItems), /* データソース(JSON)はモデルで作成 */
            primaryKey: 'id',
            imageUrlField: 'flagUrl'
        });
    });
カテゴリー: .NET, asp.net core, C#, 技術系 | 1件のコメント

.net core,.net 5でのShift_JISエンコーディング

最近、SJISのテキストファイルを.net 5でいじる必要があって、忘れていたことがあったので、メモ。

.net coreや.net 5では、デフォルトのエンコーディングセットとして、Shift_JISはサポートされていない。

CodePage=1200, Name=utf-16 ,DisplayName=Unicode
CodePage=1201, Name=utf-16BE ,DisplayName=Unicode (Big-Endian)
CodePage=12000, Name=utf-32 ,DisplayName=Unicode (UTF-32)
CodePage=12001, Name=utf-32BE ,DisplayName=Unicode (UTF-32 Big-Endian)
CodePage=20127, Name=us-ascii ,DisplayName=US-ASCII
CodePage=28591, Name=iso-8859-1 ,DisplayName=Western European (ISO)
CodePage=65001, Name=utf-8 ,DisplayName=Unicode (UTF-8)

Shift_JISやEUCなどを使用したい場合は、System.Text.Encoding.CodePagesパッケージが必要となる。

> dotnet add <プロジェクトフォルダ> package System.Text.Encoding.CodePages

これをプロジェクトに追加するだけではダメで、Encododingを取得する以前にプログラム中で下記処理を実行することが必要となる。

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

これで、GetEncoding(“Shift_JIS”)でShift_JISエンコーディングを取得することが可能となる。ちなみに、エンコーディングリストを見てみたのだが、ISO-2022-JPが無いようにみえるのだが・・・まぁ、メール以外には使わないけど。

CodePage=37, Name=IBM037 ,DisplayName=IBM037
CodePage=437, Name=IBM437 ,DisplayName=IBM437
CodePage=500, Name=IBM500 ,DisplayName=IBM500
CodePage=708, Name=ASMO-708 ,DisplayName=ASMO-708
CodePage=720, Name=DOS-720 ,DisplayName=DOS-720
CodePage=737, Name=ibm737 ,DisplayName=ibm737
CodePage=775, Name=ibm775 ,DisplayName=ibm775
CodePage=850, Name=ibm850 ,DisplayName=ibm850
CodePage=852, Name=ibm852 ,DisplayName=ibm852
CodePage=855, Name=IBM855 ,DisplayName=IBM855
CodePage=857, Name=ibm857 ,DisplayName=ibm857
CodePage=858, Name=IBM00858 ,DisplayName=IBM00858
CodePage=860, Name=IBM860 ,DisplayName=IBM860
CodePage=861, Name=ibm861 ,DisplayName=ibm861
CodePage=862, Name=DOS-862 ,DisplayName=DOS-862
CodePage=863, Name=IBM863 ,DisplayName=IBM863
CodePage=864, Name=IBM864 ,DisplayName=IBM864
CodePage=865, Name=IBM865 ,DisplayName=IBM865
CodePage=866, Name=cp866 ,DisplayName=cp866
CodePage=869, Name=ibm869 ,DisplayName=ibm869
CodePage=870, Name=IBM870 ,DisplayName=IBM870
CodePage=874, Name=windows-874 ,DisplayName=windows-874
CodePage=875, Name=cp875 ,DisplayName=cp875
CodePage=932, Name=shift_jis ,DisplayName=shift_jis
CodePage=936, Name=gb2312 ,DisplayName=gb2312
CodePage=949, Name=ks_c_5601-1987 ,DisplayName=ks_c_5601-1987
CodePage=950, Name=big5 ,DisplayName=big5
CodePage=1026, Name=IBM1026 ,DisplayName=IBM1026
CodePage=1047, Name=IBM01047 ,DisplayName=IBM01047
CodePage=1140, Name=IBM01140 ,DisplayName=IBM01140
CodePage=1141, Name=IBM01141 ,DisplayName=IBM01141
CodePage=1142, Name=IBM01142 ,DisplayName=IBM01142
CodePage=1143, Name=IBM01143 ,DisplayName=IBM01143
CodePage=1144, Name=IBM01144 ,DisplayName=IBM01144
CodePage=1145, Name=IBM01145 ,DisplayName=IBM01145
CodePage=1146, Name=IBM01146 ,DisplayName=IBM01146
CodePage=1147, Name=IBM01147 ,DisplayName=IBM01147
CodePage=1148, Name=IBM01148 ,DisplayName=IBM01148
CodePage=1149, Name=IBM01149 ,DisplayName=IBM01149
CodePage=1200, Name=utf-16 ,DisplayName=Unicode
CodePage=1201, Name=utf-16BE ,DisplayName=Unicode (Big-Endian)
CodePage=1250, Name=windows-1250 ,DisplayName=windows-1250
CodePage=1251, Name=windows-1251 ,DisplayName=windows-1251
CodePage=1252, Name=windows-1252 ,DisplayName=windows-1252
CodePage=1253, Name=windows-1253 ,DisplayName=windows-1253
CodePage=1254, Name=windows-1254 ,DisplayName=windows-1254
CodePage=1255, Name=windows-1255 ,DisplayName=windows-1255
CodePage=1256, Name=windows-1256 ,DisplayName=windows-1256
CodePage=1257, Name=windows-1257 ,DisplayName=windows-1257
CodePage=1258, Name=windows-1258 ,DisplayName=windows-1258
CodePage=1361, Name=Johab ,DisplayName=Johab
CodePage=10000, Name=macintosh ,DisplayName=macintosh
CodePage=10001, Name=x-mac-japanese ,DisplayName=x-mac-japanese
CodePage=10002, Name=x-mac-chinesetrad ,DisplayName=x-mac-chinesetrad
CodePage=10004, Name=x-mac-arabic ,DisplayName=x-mac-arabic
CodePage=10005, Name=x-mac-hebrew ,DisplayName=x-mac-hebrew
CodePage=10006, Name=x-mac-greek ,DisplayName=x-mac-greek
CodePage=10007, Name=x-mac-cyrillic ,DisplayName=x-mac-cyrillic
CodePage=10010, Name=x-mac-romanian ,DisplayName=x-mac-romanian
CodePage=10017, Name=x-mac-ukrainian ,DisplayName=x-mac-ukrainian
CodePage=10021, Name=x-mac-thai ,DisplayName=x-mac-thai
CodePage=10029, Name=x-mac-ce ,DisplayName=x-mac-ce
CodePage=10079, Name=x-mac-icelandic ,DisplayName=x-mac-icelandic
CodePage=10081, Name=x-mac-turkish ,DisplayName=x-mac-turkish
CodePage=10082, Name=x-mac-croatian ,DisplayName=x-mac-croatian
CodePage=12000, Name=utf-32 ,DisplayName=Unicode (UTF-32)
CodePage=12001, Name=utf-32BE ,DisplayName=Unicode (UTF-32 Big-Endian)
CodePage=20000, Name=x-Chinese-CNS ,DisplayName=x-Chinese-CNS
CodePage=20001, Name=x-cp20001 ,DisplayName=x-cp20001
CodePage=20002, Name=x-Chinese-Eten ,DisplayName=x-Chinese-Eten
CodePage=20003, Name=x-cp20003 ,DisplayName=x-cp20003
CodePage=20004, Name=x-cp20004 ,DisplayName=x-cp20004
CodePage=20005, Name=x-cp20005 ,DisplayName=x-cp20005
CodePage=20105, Name=x-IA5 ,DisplayName=x-IA5
CodePage=20106, Name=x-IA5-German ,DisplayName=x-IA5-German
CodePage=20107, Name=x-IA5-Swedish ,DisplayName=x-IA5-Swedish
CodePage=20108, Name=x-IA5-Norwegian ,DisplayName=x-IA5-Norwegian
CodePage=20127, Name=us-ascii ,DisplayName=US-ASCII
CodePage=20261, Name=x-cp20261 ,DisplayName=x-cp20261
CodePage=20269, Name=x-cp20269 ,DisplayName=x-cp20269
CodePage=20273, Name=IBM273 ,DisplayName=IBM273
CodePage=20277, Name=IBM277 ,DisplayName=IBM277
CodePage=20278, Name=IBM278 ,DisplayName=IBM278
CodePage=20280, Name=IBM280 ,DisplayName=IBM280
CodePage=20284, Name=IBM284 ,DisplayName=IBM284
CodePage=20285, Name=IBM285 ,DisplayName=IBM285
CodePage=20290, Name=IBM290 ,DisplayName=IBM290
CodePage=20297, Name=IBM297 ,DisplayName=IBM297
CodePage=20420, Name=IBM420 ,DisplayName=IBM420
CodePage=20423, Name=IBM423 ,DisplayName=IBM423
CodePage=20424, Name=IBM424 ,DisplayName=IBM424
CodePage=20833, Name=x-ebcdic-koreanextended ,DisplayName=x-ebcdic-koreanextended
CodePage=20838, Name=IBM-Thai ,DisplayName=IBM-Thai
CodePage=20866, Name=koi8-r ,DisplayName=koi8-r
CodePage=20871, Name=IBM871 ,DisplayName=IBM871
CodePage=20880, Name=IBM880 ,DisplayName=IBM880
CodePage=20905, Name=IBM905 ,DisplayName=IBM905
CodePage=20924, Name=IBM00924 ,DisplayName=IBM00924
CodePage=20932, Name=EUC-JP ,DisplayName=EUC-JP
CodePage=20936, Name=x-cp20936 ,DisplayName=x-cp20936
CodePage=20949, Name=x-cp20949 ,DisplayName=x-cp20949
CodePage=21025, Name=cp1025 ,DisplayName=cp1025
CodePage=21866, Name=koi8-u ,DisplayName=koi8-u
CodePage=28591, Name=iso-8859-1 ,DisplayName=Western European (ISO)
CodePage=28592, Name=iso-8859-2 ,DisplayName=iso-8859-2
CodePage=28593, Name=iso-8859-3 ,DisplayName=iso-8859-3
CodePage=28594, Name=iso-8859-4 ,DisplayName=iso-8859-4
CodePage=28595, Name=iso-8859-5 ,DisplayName=iso-8859-5
CodePage=28596, Name=iso-8859-6 ,DisplayName=iso-8859-6
CodePage=28597, Name=iso-8859-7 ,DisplayName=iso-8859-7
CodePage=28598, Name=iso-8859-8 ,DisplayName=iso-8859-8
CodePage=28599, Name=iso-8859-9 ,DisplayName=iso-8859-9
CodePage=28603, Name=iso-8859-13 ,DisplayName=iso-8859-13
CodePage=28605, Name=iso-8859-15 ,DisplayName=iso-8859-15
CodePage=29001, Name=x-Europa ,DisplayName=x-Europa
CodePage=65001, Name=utf-8 ,DisplayName=Unicode (UTF-8)
カテゴリー: .NET, dotnetcore, 技術系 | コメントする

asp.net coreでのファイルアップロード

asp.net core webappでローカルファイルをアップロードするには、一般的なHTMLと同様、formタグにenctype=”multipart/form-data”を付け、<input type=”file”>を使用して、ファイル本体をアップロードする。

<form enctype="multipart/form-data" method="post">
	・・・
	アップロードファイル:<input type="file" name="fupFile"/>
	<button class="btn btn-primary" type="submit">アップロード</button>
</form>

受取側は、IFormFileクラスを指定して、引数として受取ることが可能。

public async Task OnPost([FromForm]IFormFile fupFile) {

    ・・・
    Stream stm = fupFile.OpenReadStream();
	// ファイルに対する処理
	・・・
}

まだ試していないが、Blazorの場合は少々異なり、<InputFile>タグとそのイベントハンドラで処理ができるようだ。

・・・
<InputFile OnChange="@OnInputFileChange"/>
・・・
@code {
	・・・
	protected void OnInputFileChange(InputFileChangeEventArgs e) {
		Stream stm = e.File.OpenReadStream();
		// ファイル処理
	}
}

ちなみに、webapp中のハンドラで動的に作成したファイルのダウンロードだが、ASP.NETで使っていた方法では、ミドルウェアのせいで実行時エラー(Responseヘッダは上書き禁止)が出て、動作しなかった。

色々試してみて、結局MVC(FileContentResultを返す)を一部使用することによってダウンロードできるようになったが、他に方法はないものだろうか・・・

@{
	Dictionary<string,string> prm = new Dictionary<string,string>() {
		{"Query" : Model.Query}
	};
}
・・・
<button class="btn btn-primary" asp-controller="[コントローラ]" asp-action="Download" asp-asp-all-route-data="prm">ダウンロード</button>
public async Task<FileContentResult> Download(string Query) {
	・・・
	MemoryStream stm = new MemoryStream();
	// MemoryStreamにファイルを作成する処理
	・・・
	byte[] buff = stm.ToArray();
    return new FileContentResult(
        buff,
        "application/octet-stream"
    ) {
        FileDownloadName = filename
    };
}

カテゴリー: asp.net core, Blazor, 技術系 | 5件のコメント

dotnet core Worker ServiceのWindows Service化

dotnet core(.NET 5も含む)のWorker ServiceをWindowsのServiceとして動作させる例を見つけたのでメモ。

Worker Serviceは下記コマンドで作成する。

dotnet new worker -o <プロジェクト名>

通常は、上記によって作成されたWorker.csに処理を付け加えればOKなのだが、Windows Service化させたい場合は、プロジェクトにMicrosoft.Extensions.Hosting.WindowsServicesパッケージを追加する必要がある。

dotnet add <プロジェクト名> package Microsoft.Extensions.Hosting.WindowsServices

さらに、Program.cs中のCreateHostBuilderに.UseWindowsService()を追加する。

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<Worker>();
        });
}

後は、Worker.csに処理を追加して、デバッグ後、下記コマンドでサービス登録を行う。(これはWindowsのコマンド)

sc create <サービス名> binPath= 実行ファイルパス [オプション...]

登録が済めば、MMCコンソールの「コンピューターの管理」-「サービスとアプリケーション」-「サービス」からも起動・停止や設定変更が可能。

単純なサービスの開始や停止は下記コマンドでも操作可能。

sc start <サービス名>
sc stop <サービス名>

.NET Framework時代のサービス作成より楽だね。

カテゴリー: .NET, C#, dotnetcore, 技術系 | コメントする

.NET 5のターゲットフレームワーク名

現地時間11/10 .NET 5がリリースされた。

.NET 5では、フレームワーク名にプラットフォームを指定出来るようになった。プロジェクト種別によっては、プラットフォームを指定しないとエラーになるものもある。なお、ターゲットフレームワークは;で区切ることにより複数指定が可能である。

例えば、Windows Formsプロジェクトでは、単なるnet5.0の指定だけでは、プラットフォームエラーが出てBuildに失敗する。.NET 5で作成したプロジェクトでは、問題無いが、.net core 3.1で作成したプロジェクトを.NET 5にアップグレードする場合等には注意が必要だ。

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
  </PropertyGroup>

また、プラットフォームにOSやOSバージョンを指定する事により、プログラムから、それらの値を取得することも可能。

.NET 5でサポートされている、プラットフォームは以下のようになっている。

プラットフォームバージョン指定可能
net5.0-androidYes
net5.0-iosYes
net5.0-macosYes
net5.0-tvosYes
net5.0-watchosYes
net5.0-windowsNo

※プロジェクトがクロスプラットフォームの場合は単にnet5.0で良い。

カテゴリー: .NET, C#, 技術系 | コメントする

EF CoreによるDBからのEntity作成(Scaffolding)

以前、少し書いたと思うが、Entity Framework Coreを使用して、既存のDBからDbContextクラスとEntityクラスを作成する事が可能である。

例えば以下のようなテーブルを含むDBがあった場合、どのようなEntityおよびDbContextとなるか試してみよう。

データベース(SQLite)

CREATE TABLE Person(
  Id int atuoincrement,
  Name nvarchar(50),
  primary key (Id)
);
CREATE TABLE MailAddress(
  Address nvarchar(100),
  DisplayName nvarchar(50),
  PersonId int,
  primary key(Address),
  foreign key(PersonId) references Person(Id)
);

プロジェクトには下記のパッケージを追加する

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameoworkCore.Design
  • Microsoft.EntityFrameworkCore.Sqlite
  • Microsoft.EntityFrameowrkCore.Sqlite.Design

下記コマンドを実行して、DbContextとEntityを作成
(scaffoldのパラメータは「接続文字列」と「データプロバイダ」)

$ dotnet ef dbcontext scaffold "Data Source=SQLiteTest.db" Microsoft.EntityFrameworkCore.Sqlite

出来上がったDbContextとEntity

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace SQLiteTest
{
    public partial class SQLiteTestContext : DbContext
    {
        public SQLiteTestContext()
        {
        }

        public SQLiteTestContext(DbContextOptions<SQLiteTestContext> options)
            : base(options)
        {
        }

        public virtual DbSet<MailAddress> MailAddress { get; set; }
        public virtual DbSet<Person> Person { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
                optionsBuilder.UseSqlite("Data Source=SQLiteTest.db");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MailAddress>(entity =>
            {
                entity.HasKey(e => e.Address);

                entity.Property(e => e.Address).HasColumnType("nvarchar(100)");

                entity.Property(e => e.DisplayName).HasColumnType("nvarchar(50)");

                entity.Property(e => e.PersonId).HasColumnType("int");

                entity.HasOne(d => d.Person)
                    .WithMany(p => p.MailAddress)
                    .HasForeignKey(d => d.PersonId);
            });

            modelBuilder.Entity<Person>(entity =>
            {
                entity.Property(e => e.Id)
                    .HasColumnType("int atuoincrement")
                    .ValueGeneratedNever();

                entity.Property(e => e.Name).HasColumnType("nvarchar(50)");
            });

            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
}
using System;
using System.Collections.Generic;

namespace SQLiteTest
{
    public partial class Person
    {
        public Person()
        {
            MailAddress = new HashSet<MailAddress>();
        }

        public long Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<MailAddress> MailAddress { get; set; }
    }
}
using System;
using System.Collections.Generic;

namespace SQLiteTest
{
    public partial class MailAddress
    {
        public string Address { get; set; }
        public string DisplayName { get; set; }
        public long? PersonId { get; set; }

        public virtual Person Person { get; set; }
    }
}

とまあ、こんな感じでDBからDbContextとEntityを作成することができる。
接続文字列が埋め込みになっているので、この部分はappsettings.json等から取得するように変更した方が良いだろう。

なお、scaffoldのオプションで、scaffoldするテーブルを指定したり、出力先ディレクトリを指定することも可能。

カテゴリー: C#, dotnetcore, Entity Framework, 技術系 | コメントする

Windows TerminalでSSH接続プロファイルを作成してみる

Windows Terminalとは、Mircosoft Storeで入手できる、Microsoft社製の無料のTerminalアプリケーション。

インストールすると、デフォルトで、Powershellとコマンドプロンプトおよび、wslのディストリビューションがインストールされていれば、そのプロファイルが自動追加され、メニューより選択してコンソールを開く事が可能となる。

ちなみに、メニューから「設定」を選ぶと、所謂設定画面ではなく、jsonファイルが拡張子が関連づけられたエディタで開く。このファイルを編集することにより、プロファイル毎に背景色を変更したりすることが可能である。

ただ、自動的に設定されるのは、ローカルリソースのみなので、手動にてSSHでリモートに接続するプロファイルを作成してみた。

Windows10では2017年10月のFall Creators Updateからsshクライアントが標準でサポートされているので、新しいプロファイルを作成して、起動コマンドとして、”commandline”にsshを指定してあげれば良い。

{
    "$schema": "https://aka.ms/terminal-profiles-schema",
    "alwaysShowTabs" : true,
	・・・
    "profiles" : 
    [
		・・・
        {
            "acrylicOpacity" : 0.8,
            "background" : "#102040",
            "closeOnExit" : true,
            "colorScheme" : "Campbell",
            "commandline" : "ssh <username>@<host>",←SSHでリモートホストに接続
            "cursorColor" : "#FFFFFF",
            "cursorShape" : "bar",
            "fontFace" : "Consolas",
            "fontSize" : 16,
            "guid" : "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}",←GUIDジェネレータ等で取得
            "historySize" : 9001,
            "icon" : "ms-appx:///ProfileIcons/{9acb9455-ca41-5af7-950f-6bca1bc9722f}.png",
            "name" : "SSH-Connect(<host>)",
            "padding" : "0, 0, 0, 0",
            "snapOnInput" : true,
            "useAcrylic" : true
        },
		・・・
	]
	・・・
}

(←・・・の部分は実際には書いてはいけない)

上記を保存して、メニューからそのプロファイルを選択してみる。

見事ログインできましたとさ。

今までは、Teratermを使っていたけれど、このアプリ1個開いておけばCMDやPowershellなどとの操作切替が楽なので、今後はこれを使おうかな。

ちなみに、同じプロファイルのタブを複数開くことも可能です。

カテゴリー: Windows, 技術系, 開発環境 | コメントする

asp.net coreでのセッション変数

asp.net coreではセッション等は基本的にはサーバー上で管理しない。

asp.netのセッション変数をasp.net coreでほぼ同様に使用するには、Microsoft.AspNetCore.Sessionを使用する。

Microsoft.AspNetCore.Sessionでは、Cookieを使用して、セッション情報を保持する。

セッションをaps.net coreで使用するためには、StartupとConfigureに以下のコードを追加する必要がある。

public void ConfigureServices(IServiceCollection services)
{
	// 分散キャッシュの指定(アプリのインスタンス内で有効)
    services.AddDistributedMemoryCache();
	// セッションサービスの追加
    services.AddSession(opt=>{
		// オプション指定
        opt.IdleTimeout = TimeSpan.FromMinutes(20);
        opt.Cookie.IsEssential = true;
    });
	・・・
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	・・・
    app.UseRouting();

    app.UseAuthorization();

	// セッションを使用
    app.UseSession();
	・・・
}

セッション変数に値をセットしたり、取得するには、暗黙で宣言されている、HttpContext変数を使用する。

// セッション変数へ値をセット(文字列)
HttpContext.Session.SetString("MyString","Hello");
// セッション変数へ値をセット(整数)
HttpContext.Session.SetInt32("MyInt",123);

// セッション変数から値を取得(文字列)
string mystring = HttpContext.Session.GetString("MyString");
// セッション変数から値を取得(整数)
int myint = HttpContext.Session.GetInt32("MyInt");

// クラスインスタンス等を保存するには、Json等でシリアライズする必要がある
class MyClass {
	public string MyString { get; set; }
	public int MyInt { get; set; }
}
・・・
MyClass c = new MyClass() { MyString="Hello", MyInt = 123 };
// JSON文字列へ変換
string sessvalue = JsonSerializer.Serialize(c);
// セッション変数へ文字列として保存
HttpContext.Session.SetString("MyClassInsance", sessvalue);
・・・
// 文字列からインスタンスへデシリアライズ
MyClass cc = JsonSerializer.Deserialize<MyClass>(HttpContext.Session.GetString("MyClassInstance"));

以下のような拡張メソッドを作っても良い。

public static class SessionExtention {
    public static T Get<T>(this ISession session, string key) {
        string val = session.GetString(key);
        return val == null ? default : JsonSerializer.Deserialize<T>(val);
    }
    public static void Set<T>(this ISession session, string key, T val) {
        string jsonstr = JsonSerializer.Serialize(val);
        session.SetString(key,jsonstr);
    }
}

と、こんな感じでセッション変数を扱うことが可能。

カテゴリー: asp.net core, C#, 技術系 | コメントする