現在、ASP.NET Coreを使用してASP.NET Webフォームアプリケーションを書き換えたり変換したりしています。できるだけリエンジニアリングを避けようとしています。
現在の状態をチェックするためにクラスライブラリでHttpContext
を使うセクションがあります。 .NET Core 1.0でHttpContext.Current
にアクセスするにはどうすればよいですか?
var current = HttpContext.Current;
if (current == null)
{
// do something here
// string connection = Configuration.GetConnectionString("MyDb");
}
現在のアプリケーションホストを構築するためにこれにアクセスする必要があります。
$"{current.Request.Url.Scheme}://{current.Request.Url.Host}{(current.Request.Url.Port == 80 ? "" : ":" + current.Request.Url.Port)}";
一般的な規則として、WebフォームまたはMVC5アプリケーションをASP.NET Core に変換するには、 - かなりの量のリファクタリングが必要になります。
HttpContext.Current
はASP.NET Coreで削除されました。別のクラスライブラリから現在のHTTPコンテキストにアクセスすることは、ASP.NET Coreが避けようとする面倒なアーキテクチャの一種です。これをASP.NET Coreで再設計する方法はいくつかあります。
任意のコントローラのHttpContext
プロパティを介して現在のHTTPコンテキストにアクセスできます。元のコードサンプルに最も近いのは、呼び出しているメソッドにHttpContext
を渡すことです。
public class HomeController : Controller
{
public IActionResult Index()
{
MyMethod(HttpContext);
// Other code
}
}
public void MyMethod(Microsoft.AspNetCore.Http.HttpContext context)
{
var Host = $"{context.Request.Scheme}://{context.Request.Host}";
// Other code
}
ASP.NET Coreパイプライン用に カスタムミドルウェア を作成している場合は、現在の要求のHttpContext
が自動的にInvoke
メソッドに渡されます。
public Task Invoke(HttpContext context)
{
// Do something with the current HTTP context...
}
最後に、IHttpContextAccessor
ヘルパーサービスを使用して、ASP.NET Core依存性注入システムによって管理されている任意のクラスのHTTPコンテキストを取得できます。これはあなたのコントローラで使われている共通のサービスがあるときに便利です。
コンストラクタでこのインタフェースを要求します。
public MyMiddleware(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
その後、安全な方法で現在のHTTPコンテキストにアクセスできます。
var context = _httpContextAccessor.HttpContext;
// Do something with the current HTTP context...
IHttpContextAccessor
は常にデフォルトでサービスコンテナに追加されるわけではないので、安全のためにConfigureServices
に登録してください。
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Other code...
}
ネクロマンシング.
はい、できます。
大規模に移行する人たちへの秘訣 ジャンク コードの塊
次の方法は、(.NET Coreフレームワーク開発者から見て)satanの明示的な作業を実行することに積極的に取り組んでいるハックの悪魔の頭文字です、 しかし、それはうまくいきます :
public class Startup
内
プロパティを追加する
public IConfigurationRoot Configuration { get; }
そして、ConfigureServicesのDIにシングルトンのIHttpContextAccessorを追加します。
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();
それから設定で
public void Configure(
IApplicationBuilder app
,IHostingEnvironment env
,ILoggerFactory loggerFactory
)
{
dIパラメータIServiceProvider svp
を追加すると、メソッドは次のようになります。
public void Configure(
IApplicationBuilder app
,IHostingEnvironment env
,ILoggerFactory loggerFactory
,IServiceProvider svp)
{
次に、System.Webの代替クラスを作成します。
namespace System.Web
{
namespace Hosting
{
public static class HostingEnvironment
{
public static bool m_IsHosted;
static HostingEnvironment()
{
m_IsHosted = false;
}
public static bool IsHosted
{
get
{
return m_IsHosted;
}
}
}
}
public static class HttpContext
{
public static IServiceProvider ServiceProvider;
static HttpContext()
{ }
public static Microsoft.AspNetCore.Http.HttpContext Current
{
get
{
// var factory2 = ServiceProvider.GetService<Microsoft.AspNetCore.Http.IHttpContextAccessor>();
object factory = ServiceProvider.GetService(typeof(Microsoft.AspNetCore.Http.IHttpContextAccessor));
// Microsoft.AspNetCore.Http.HttpContextAccessor fac =(Microsoft.AspNetCore.Http.HttpContextAccessor)factory;
Microsoft.AspNetCore.Http.HttpContext context = ((Microsoft.AspNetCore.Http.HttpContextAccessor)factory).HttpContext;
// context.Response.WriteAsync("Test");
return context;
}
}
} // End Class HttpContext
}
今すぐIServiceProvider svp
を追加したConfigureで、作成したダミークラスSystem.Web.HttpContext(System.Web.HttpContext.ServiceProvider)の静的変数「ServiceProvider」にこのサービスプロバイダを保存します。
そしてHostingEnvironment.IsHostedをtrueに設定します。
System.Web.Hosting.HostingEnvironment.m_IsHosted = true;
これは基本的にSystem.Webが行ったことです。あなたがそれを見たことがないということです(私は変数がpublicではなくinternalとして宣言されたと思います)。
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider svp)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
ServiceProvider = svp;
System.Web.HttpContext.ServiceProvider = svp;
System.Web.Hosting.HostingEnvironment.m_IsHosted = true;
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "MyCookieMiddlewareInstance",
LoginPath = new Microsoft.AspNetCore.Http.PathString("/Account/Unauthorized/"),
AccessDeniedPath = new Microsoft.AspNetCore.Http.PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true,
CookieSecure = Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest
, CookieHttpOnly=false
});
ASP.NET Webフォームのように、global.asaxのApplication_Start
にあったように、HttpContextがない場合にHttpContextにアクセスしようとすると、NullReferenceが返されます。
もう一度強調しますが、これは実際に追加した場合にのみ機能します。
services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();
私があなたが書いたように。
DIパターン内のServiceLocatorパターンへようこそ。
リスクと副作用については、居住する医者または薬剤師に尋ねる - または github.com/aspnet で.NET Coreのソースを調べて、いくつかのテストを行ってください。
おそらくもっと保守しやすいメソッドがこのヘルパークラスを追加することでしょう
namespace System.Web
{
public static class HttpContext
{
private static Microsoft.AspNetCore.Http.IHttpContextAccessor m_httpContextAccessor;
public static void Configure(Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor)
{
m_httpContextAccessor = httpContextAccessor;
}
public static Microsoft.AspNetCore.Http.HttpContext Current
{
get
{
return m_httpContextAccessor.HttpContext;
}
}
}
}
そしてStartup-> ConfigureでHttpContext.Configureを呼び出します。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider svp)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
System.Web.HttpContext.Configure(app.ApplicationServices.
GetRequiredService<Microsoft.AspNetCore.Http.IHttpContextAccessor>()
);
現在のコンテキストへの静的アクセスが本当に必要な場合は、これに対する解決策があります。 Startup.Configure(…)で
app.Use(async (httpContext, next) =>
{
CallContext.LogicalSetData("CurrentContextKey", httpContext);
try
{
await next();
}
finally
{
CallContext.FreeNamedDataSlot("CurrentContextKey");
}
});
そして、必要なときには、次のものを入手できます。
HttpContext context = CallContext.LogicalGetData("CurrentContextKey") as HttpContext;
それが役立つことを願っています。この回避策は選択肢がない場合に起こります。ベストプラクティスは、依存性注入を使用することです。