在自定义中间件中访问 TempData
Access TempData within custom middleware
我有提供全局错误处理的自定义中间件。如果捕获到异常,它应该使用参考编号记录详细信息。然后我想将用户重定向到错误页面并只显示参考号。我的研究表明 TempData 应该是这个的理想选择,但它似乎只能从控制器上下文中访问。我尝试将参考编号添加到 HttpContext.Items["ReferenceNumber"] = Guid.NewGuid();
但是这个值通过重定向丢失了。
中间件如何通过重定向传递信息?我只需要将数字放在查询字符串中吗?
您可以自己注册一个 ITempDataProvider 并在您的中间件中使用它。这是我在两条简单路径之间工作的一个小样本。如果您已经在使用 MVC,则 ITempDataProvider 可能已经注册。我遇到的问题是写入的 cookie 的路径。它是 /page1,所以 /page2 没有访问 cookie 的权限。所以我不得不覆盖选项,正如您在下面的代码中看到的那样。
希望对您有所帮助:)
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDataProtectionProvider>(s => DataProtectionProvider.Create("WebApplication2"));
services.Configure<CookieTempDataProviderOptions>(options =>
{
options.Path = "/";
});
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ITempDataProvider tempDataProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Map("/page1", (app1) =>
{
app1.Run(async context =>
{
tempDataProvider.SaveTempData(context, new Dictionary<string, object> { ["Message"] = "Hello from page1 middleware" });
await context.Response.WriteAsync("Hello World! I'm page1");
});
});
app.Map("/page2", (app1) =>
{
app1.Run(async context =>
{
var loadTempData = tempDataProvider.LoadTempData(context);
await context.Response.WriteAsync("Hello World! I'm page2: Message from page1: " + loadTempData["Message"]);
});
});
}
这让我朝着正确的方向前进:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state#cookie-based-tempdata-provider
编码愉快! :)
在中间件内部 class 您需要添加引用才能访问所需的接口。我在一个单独的项目中有这个中间件,需要添加这个 NuGet 包。
using Microsoft.AspNetCore.Mvc.ViewFeatures;
这样您就可以在中间件中请求正确的服务。
//get TempData handle
ITempDataDictionaryFactory factory = httpContext.RequestServices.GetService(typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory;
ITempDataDictionary tempData = factory.GetTempData(httpContext);
拥有 ITempDataDictionary 后,您可以像在控制器中使用 TempData 一样使用它。
//pass reference number to error controller
Guid ReferenceNum = Guid.NewGuid();
tempData["ReferenceNumber"] = ReferenceNum.ToString();
//log error details
logger.LogError(eventID, exception, ReferenceNum.ToString() + " - " + exception.Message);
现在,当我在重定向后获得控制器时,我可以毫无问题地提取参考号并在我的视图中使用它。
//read value in controller
string refNum = TempData["ReferenceNumber"] as string;
if (!string.IsNullOrEmpty(refNum))
ViewBag.ReferenceNumber = refNum;
@*display reference number if one was provided*@
@if (ViewBag.ReferenceNumber != null){<p>Reference Number: @ViewBag.ReferenceNumber</p>}
将所有这些放在一起后,您就可以为用户提供一个参考编号,他们可以提供该参考编号来帮助您解决问题。但是,您不会传回可能被滥用的潜在敏感错误信息。
我有提供全局错误处理的自定义中间件。如果捕获到异常,它应该使用参考编号记录详细信息。然后我想将用户重定向到错误页面并只显示参考号。我的研究表明 TempData 应该是这个的理想选择,但它似乎只能从控制器上下文中访问。我尝试将参考编号添加到 HttpContext.Items["ReferenceNumber"] = Guid.NewGuid();
但是这个值通过重定向丢失了。
中间件如何通过重定向传递信息?我只需要将数字放在查询字符串中吗?
您可以自己注册一个 ITempDataProvider 并在您的中间件中使用它。这是我在两条简单路径之间工作的一个小样本。如果您已经在使用 MVC,则 ITempDataProvider 可能已经注册。我遇到的问题是写入的 cookie 的路径。它是 /page1,所以 /page2 没有访问 cookie 的权限。所以我不得不覆盖选项,正如您在下面的代码中看到的那样。
希望对您有所帮助:)
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDataProtectionProvider>(s => DataProtectionProvider.Create("WebApplication2"));
services.Configure<CookieTempDataProviderOptions>(options =>
{
options.Path = "/";
});
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ITempDataProvider tempDataProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Map("/page1", (app1) =>
{
app1.Run(async context =>
{
tempDataProvider.SaveTempData(context, new Dictionary<string, object> { ["Message"] = "Hello from page1 middleware" });
await context.Response.WriteAsync("Hello World! I'm page1");
});
});
app.Map("/page2", (app1) =>
{
app1.Run(async context =>
{
var loadTempData = tempDataProvider.LoadTempData(context);
await context.Response.WriteAsync("Hello World! I'm page2: Message from page1: " + loadTempData["Message"]);
});
});
}
这让我朝着正确的方向前进:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state#cookie-based-tempdata-provider
编码愉快! :)
在中间件内部 class 您需要添加引用才能访问所需的接口。我在一个单独的项目中有这个中间件,需要添加这个 NuGet 包。
using Microsoft.AspNetCore.Mvc.ViewFeatures;
这样您就可以在中间件中请求正确的服务。
//get TempData handle
ITempDataDictionaryFactory factory = httpContext.RequestServices.GetService(typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory;
ITempDataDictionary tempData = factory.GetTempData(httpContext);
拥有 ITempDataDictionary 后,您可以像在控制器中使用 TempData 一样使用它。
//pass reference number to error controller
Guid ReferenceNum = Guid.NewGuid();
tempData["ReferenceNumber"] = ReferenceNum.ToString();
//log error details
logger.LogError(eventID, exception, ReferenceNum.ToString() + " - " + exception.Message);
现在,当我在重定向后获得控制器时,我可以毫无问题地提取参考号并在我的视图中使用它。
//read value in controller
string refNum = TempData["ReferenceNumber"] as string;
if (!string.IsNullOrEmpty(refNum))
ViewBag.ReferenceNumber = refNum;
@*display reference number if one was provided*@
@if (ViewBag.ReferenceNumber != null){<p>Reference Number: @ViewBag.ReferenceNumber</p>}
将所有这些放在一起后,您就可以为用户提供一个参考编号,他们可以提供该参考编号来帮助您解决问题。但是,您不会传回可能被滥用的潜在敏感错误信息。