asp.net核心中的TempData为空

Posted

技术标签:

【中文标题】asp.net核心中的TempData为空【英文标题】:TempData null in asp.net core 【发布时间】:2017-06-03 16:40:07 【问题描述】:

我正在尝试在 asp.net 核心中使用 TempData 但是我在 TempData 的 get 方法上得到一个空值。谁能告诉我如何在asp.net核心中使用TempData

以下是我根据研究添加的内容。

Project.json 文件


  "dependencies": 
    "Microsoft.NETCore.App": 
      "version": "1.0.1",
      "type": "platform"
    ,
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "Microsoft.AspNetCore.Routing": "1.0.1",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging": "1.1.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Extensions.Logging.Debug": "1.0.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.1.0",
    "Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final",
    "Microsoft.EntityFrameworkCore.Design": "1.1.0",
    "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.1.0",
    "DataBase": "1.0.0-*",
    "UnitOfWork": "1.0.0-*",
    "ViewModel": "1.0.0-*",
    "Common": "1.0.0-*",
    "System.IdentityModel.Tokens.Jwt": "5.0.0",
    "Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0",
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0",
    "Microsoft.AspNetCore.Session": "1.1.0",
    "Microsoft.Extensions.Caching.Memory": "1.1.0"
  ,

  "tools": 
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.Tools.DotNet": "1.0.0-preview3-final",
    "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final"
  ,

  "frameworks": 
    "netcoreapp1.0": 
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    
  ,

  "buildOptions": 
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  ,

  "runtimeOptions": 
    "configProperties": 
      "System.GC.Server": true
    
  ,

  "publishOptions": 
    "include": [
      "wwwroot",
      "**/*.cshtml",
      "appsettings.json",
      "web.config"
    ]
  ,

  "scripts": 
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  

start.cs 文件

public void ConfigureServices(IServiceCollection services)

    services.AddMemoryCache();
    services.AddSession();
    // Add framework services.
    services.AddMvc();
    services.AddTransient<IMarketUOW, MarketUow>();
    services.AddTransient<ICategoryUow, CategoryUow>();
    services.AddTransient<IUserProfileUow, UserProfileUow>();
    services.AddTransient<IItemUow, ItemUow>();

    services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
    var connection = Configuration.GetConnectionString("DefaultConnection");
    services.AddDbContext<EmakitiContext>(options => options.UseSqlServer(connection));

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

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

这里是tempdata的实现。当这个方法被调用时,我可以看到TempData中的值。

[HttpGet("pageNumber")]
public GenericResponseObject<List<MarketViewModel>> GetMarketList(int pageNumber)

    TempData["Currentpage"] = pageNumber;
    TempData.Keep("Currentpage");
    GenericResponseObject<List<MarketViewModel>> genericResponseObject = new GenericResponseObject<List<MarketViewModel>>();
    genericResponseObject.IsSuccess = false;
    genericResponseObject.Message = ConstaintStingValue.Tag_ConnectionFailed;
    try
    
        var marketItem = _iMarketUow.GetMarketList(pageNumber);
        genericResponseObject.Data = marketItem.Item1;
        var totalPages = (int)Math.Ceiling((decimal)marketItem.Item2 / (decimal)10);
        genericResponseObject.TotalPage = totalPages;
        genericResponseObject.IsSuccess = true;
        genericResponseObject.Message = ConstaintStingValue.Tag_SuccessMessageRecord;
        genericResponseObject.Message = ConstaintStingValue.Tag_ConnectionSuccess;
    
    catch (Exception exception)
    
        genericResponseObject.IsSuccess = false;
        genericResponseObject.Message = exception.Message;
        genericResponseObject.ErrorCode = exception.HResult;
        genericResponseObject.ExceptionErrorMessage = exception.StackTrace;
    
    return genericResponseObject;

但是下面的方法在临时数据中有空值。

[HttpPost]
public GenericResponseObject<List<MarketViewModel>> AddUpdateMarket([FromBody] MarketViewModel marketViewModel)

    GenericResponseObject<List<MarketViewModel>> genericResponseObject = new GenericResponseObject<List<MarketViewModel>>();
    genericResponseObject.IsSuccess = false;
    genericResponseObject.Message = ConstaintStingValue.Tag_ConnectionFailed;

    if (marketViewModel!= null && ModelState.IsValid)
    
        try
        
            _iMarketUow.AddUpdateMarketList(marketViewModel);
            genericResponseObject = GetMarketList(Convert.ToInt16(TempData.Peek("Currentpage")));
        
        catch (Exception exception)
        
            genericResponseObject.IsSuccess = false;
            genericResponseObject.Message = exception.Message;
            genericResponseObject.ErrorCode = exception.HResult;
            genericResponseObject.ExceptionErrorMessage = exception.StackTrace;
        
    
    else
    
        genericResponseObject.Message = ConstaintStingValue.Tag_InputDataFormatNotMatch;
    
    return genericResponseObject;

这是调试会话的图像

【问题讨论】:

我遇到了同样的问题,我意识到这是因为我使用的是浏览器的私人标签 供参考:docs.microsoft.com/en-us/aspnet/core/fundamentals/… 【参考方案1】:

已编辑:

如https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.2#tempdata-provider-and-session-state-cookies-arent-essential 中所述 默认情况下,TempData cookie 由 CookiePolicy 中间件删除。这可以通过将其放入 Startup.ConfigureServices() 来更改:

// The TempData provider cookie is not essential. Make it essential
// so TempData is functional when tracking is disabled.
services.Configure<CookieTempDataProviderOptions>(options => 
    options.Cookie.IsEssential = true;
); 

==============================================

旧答案:

迁移到 ASP Core 2.1 后我遇到了这个问题,经过一天的工作找到解决方案:

在 Startup.Configure() app.UseCookiePolicy(); 应该在 app.UseMVC(); 之后

【讨论】:

我认为这里有很多文档。我创建了一个关于它的问题:github.com/aspnet/Docs/issues/8041 这也是为什么在使用 ASP.NET Core Identity 并且您启用了 2 Factor Authentication 时没有显示恢复代码的原因。 谢谢! 这个问题更加令人困惑,因为 netcore 2.1 和 2.2 的会话状态文档 (docs.microsoft.com/en-us/aspnet/core/fundamentals/…) 显示 UseCookiePolicy() 正在配置之前 UseMVC(),这显然是不正确的。 谢谢!节省了我一天的研究时间,我遇到了同样的问题,只是做了这个修复它。 @Katstevens 订单没有问题。在下面检查我的答案。【参考方案2】:

official docs 中描述的中间件顺序没有问题,即:

    异常/错误处理 HTTP 严格传输安全协议 HTTPS 重定向 静态文件服务器 Cookie 政策实施 身份验证 会话 MVC

但是当我们使用 Cookie 策略实施 (UseCookiePolicy) 时,只有 必要 cookie 会发送到浏览器,而来自 Tempdata 提供者的 Cookie 不是必要的,因此会出现问题。所以我们必须根据official documentation使它变得必不可少:

临时数据提供程序 cookie 不是必需的。如果禁用跟踪,则 Tempdata 提供程序将不起作用。要在禁用跟踪时启用 Tempdata 提供程序,请在 Startup.ConfigureServices 中将 TempData cookie 标记为必需

// The Tempdata provider cookie is not essential. Make it essential
// so Tempdata is functional when tracking is disabled.
services.Configure<CookieTempDataProviderOptions>(options => 
   options.Cookie.IsEssential = true;
);

添加这些行应该可以解决您的问题,而无需重新排序中间件。

【讨论】:

这是正确答案,应该使用(不改变服务顺序) 这是 100% 正确和正确的答案 - 我最终在调试另一个问题时删除了我的 tempdata cookie,突然 tempdata 完全停止工作!一个小时后我发现了这个问题,现在问题已经解决了。 经过几个小时试图弄清楚为什么 Tempdata 为空...这有效。 谢谢!我花了大量时间调试这个问题。 Tempdata 正在使用 vanilla return Views(),但任何 return RedirectToAction() 调用都会导致 tempdata 为空。这解决了问题(.net core 3.1)【参考方案3】:

请将您的所有软件包升级到相同版本1.1.0 并添加缓存服务。这是在Asp.Net Core 中使用TempData 所需的东西

Project.json

"Microsoft.AspNetCore.Session": "1.1.0"

这是 Startup.cs 文件。 - ConfigureServices 方法

public void ConfigureServices(IServiceCollection services)

     services.AddMemoryCache();
     services.AddSession();
     services.AddMvc();

和配置方法。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

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

现在试试TempData,它会起作用的。

您可以使用 set ASPNETCORE_ENVIRONMENT=Development 环境变量来设置环境。

PS

ASP.NET Core MVCController 上公开TempData 属性。 TempData 可用于存储仅需要在当前请求之后的单个请求中可用的临时数据。

当读取TempDataDictionary 中的对象时,将在该请求结束时将其标记为删除。

PeekKeep 方法允许您读取值而不将其标记为删除。假设我们回到将值保存到 TempData 的第一个请求。

使用Peek,您无需通过一次调用将其标记为删除即可获得值。

//second request, PEEK value so it is not deleted at the end of the request
object value = TempData.Peek("value");

//third request, read value and mark it for deletion
object value = TempData["value"];

使用Keep,您可以指定要保留的标记为删除的密钥。检索对象并稍后将其从删除中保存是 2 个不同的调用。

//second request, get value marking it from deletion
object value = TempData["value"];
//later on decide to keep it
TempData.Keep("value");

//third request, read value and mark it for deletion
object value = TempData["value"];

【讨论】:

我正在尝试在第二个 http 请求中使用。第一个方法将值存储到 tempdata,第二个请求从 tempdata 中获取数据。但是,我得到了 null 值来获取部​​分 我在我的系统上尝试了它,同时删除了所有身份验证和其他相关代码,它工作正常。 我在 AddUpdateMarket() 方法上添加了完整的代码。我正在从角度 2 进行第二次 httpcall。我可以在 tempdata 上看到 null 值。 让我们continue this discussion in chat. 我已添加图片以获取更多信息。请看看,让我知道

以上是关于asp.net核心中的TempData为空的主要内容,如果未能解决你的问题,请参考以下文章

在 asp.net 5.0 web api 项目中访问中间件中的 TempData

ASP.NET-viewBag Viewdata Tempdata

窥探ASP.Net MVC底层原理 实现跨越Session的分布式TempData

asp.net面试题总结1(未完待续。。。。)

在 ASP.NET MVC 中使用 Tempdata - 最佳实践

会话变量立即为空.ASP.net核心