ASP.NET Core の Cors

Corsってなに?と思っていたら、思わず使う機会が登場したのでメモ。

参考:

ASP.NET Core and CORS Gotchas - Rick Strahl's Web Log

 

クロスサイトスクリプティングといって、javascriptの非同期httpモジュールがアクセスする際、原則的に取得サーバ以外のサイトへは取りに行けないというセキュリティ的な制限がある。対して、制限緩めてもよいよと取得先のサーバ側から、お墨付きがもらえていたらその制限を突破して本来の(Origin)サーバ以外からのスクリプトでアクセスしても取得できるというもの。

 

開発環境はVisualStudio2015 community と、angular-cliで作業している。angular-cli  「ng serve コマンド」で lite-server (localhost:4200) を立ち上げてClientサイドの開発をしつつ、Visual Studioデバッグ実行して(localhost:532xx)、IIS Express上にあるWebApiを呼び出している。

そうするとポートの違う別オリジンとなって、クロスサイトスクリプティングに引っかかる。

f:id:inopriv:20161228032530j:plain

サーバ側(ASP.NET Core)の設定でこいつを許可させるため、レスポンスヘッダーに、次のヘッダ情報を埋め込ませるおまじないを出させないといけない。

 

Access-Control-Allow-Origin: http://localhost:xxxx

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
// snip

services.AddCors(option => option.AddPolicy("Any",
policy => policy.AllowAnyOrigin()));


services.AddMvc();

//snip
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,ShopDbContext db)
{
// snip

app.UseCors("Any");

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// snip
}

 

 Configure の中で UseCorsとするとすべてで適用される。

上記の場合は、 Originだけを許しているけど、

ほかにも 
.AllowAnyMethod()

.AllowAnyHeader()

.AllowCredentials()

なんてのがある。

注意:UseMvc() の前に登録することが重要。順番が大事

 

また、UseCors()で登録しないで、Controlerクラスかメソッド単位で[EnableCors("ポリシー名")] とすることも可能。

ポリシー名は、ConfigureService内で定義したポリシーセットの名前、上の例では "Any"がそれにあたる。

 

EntityFremework (一部Core)

Entity Framework

マイグレーション

マイグレーションtoolのインストール

"Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final",

 

 

Enable-Migration -ProjectName [p1]
マイグレーションできる状態に初期設定を指定したプロジェクトに追加する
具体的にはMigrations フォルダの生成と configure.cs の追加

 

Add-Migration [migrationName] -ProjectName [p1] -StartupProject [p2]
更新差分を作成する
[migrationName] : 更新内容を示す名前(クラス名にもなる)
[p1] : 対象プロジェクト
[p2] : 接続先(ConnectionString)を判断するプロジェクトの指定

 

Update-Database -ProjectName [p1] -StartupProject [p2]
[p1] : 対象プロジェクト
[p2] : 接続先(ConnectionString)を判断するプロジェクトの指定

 

Update-Database -TargetMigration:[target] -ProjectName [p1] -StartupProject [p2]
[target] : 更新対象とする更新差分名 (ダウングレードを指定可能)
 指定がない場合は最新版までの更新を進める

 

*****************************************************************
*EntityFrameworkのモデルを定義しているDLLプロジェクトと、そのDLLを使用しているアプリケーションプロジェクトでモデル更新を行う場合

 例 プロジェクト名 : ApplicationProject : アプリ側プロジェクト
   プロジェクト名 : LibraryProject :DLL側プロジェクト
   
Enable-Migration -ProjectName LibraryPrject

まずはLibraryProject にマイグレーションの準備を行う

 Add-Migration [migrationName] -ProjectName LibraryProject
*更新差分を記録

*アプリ側DBに更新して使用するとき
Update-Database [migrationName] -ProjectName LibraryProject -StartupProject ApplicationProject

(AppricationProjectの接続文字列を見てLibraryProjectのDbContextとDBを比較してDBを更新する)

******************************************************

 

EntityFrameworkCore では、最初にenable-Migration を入力する必要がなくなった。
初めて Add-Migrationコマンドを実行したときに、Migrationsフォルダが生成される。

Migrationの管理をおこなっている__EFMigrationsHistoryテーブルも単純になった。

 

f:id:inopriv:20161226232519j:plain

参考:http://densan-labs.net/tech/codefirst/migration.html

 

 

開発メモ ASP.NET CORE 

wwwroot配下のindex.html 静的ファイルを読み出そうとしたときにトラブったので、

とりあえずメモ。asp.net core 1.1 

Startup で UseBrowserLinkを登録していると、UseStaticFiles() で静的ファイルを読み出せるようにしているときに、 htmlファイルの呼び出しで例外が発生する。具体的には </body>の終了タグが含まれているファイルがあると、(おそらく)このタグの前に、BrowserLinkがスクリプトを挿入するために、ファイルサイズから設定していたContent-Lengthと実際のContent-Lengthが一致しなくなり、例外が発生してしまう。

画像やjavascriptのファイルは問題なく呼び出せる。

 

まずは、UseBrowserLinkをコメントアウトしたら、例外が出なくなったので、問題を切り分けることができた。

最終的には、UseStaticFiles()のあとで、UseBrowserLink()を設定することで解決できた。静的ファイルと判断されたときはその場でミドルウェアの処理が終了するから、後の処理だと影響しない

 

 

Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,ShopDbContext db)
{
//db.Database.MigrateAsync();

loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
//app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();

if(env.IsDevelopment())
{
app.UseBrowserLink();
}

app.UseIdentity();

// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

 

 

 

"dependencies": {
"Microsoft.AspNetCore.Razor.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
},
"Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final",
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
},
"Microsoft.VisualStudio.Web.CodeGenerators.Mvc": {
"version": "1.0.0-preview2-final",
"type": "build"
},

"BundlerMinifier.Core": "2.2.306",
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
"Microsoft.EntityFrameworkCore.SqlServer": "1.1.0",
"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.1.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
"Microsoft.Extensions.Configuration.Json": "1.1.0",
"Microsoft.Extensions.Configuration.UserSecrets": "1.1.0",
"Microsoft.Extensions.Logging": "1.1.0",
"Microsoft.Extensions.Logging.Console": "1.1.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
"Microsoft.AspNetCore.Authentication.Cookies": "1.1.0",
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.1.0",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0",
"Microsoft.AspNetCore.Mvc": "1.1.0",
"Microsoft.AspNetCore.Routing": "1.1.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
"Microsoft.Extensions.Logging.Debug": "1.1.0",
"Microsoft.NETCore.App": {
"version": "1.1.0",
"type": "platform"
}