【问题标题】:TempData null in asp.net coreasp.net核心中的TempData为空
【发布时间】: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;
}

这是调试会话的图像

【问题讨论】:

标签: c# asp.net asp.net-mvc asp.net-web-api asp.net-core


【解决方案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 中描述的中间件顺序没有问题,即:

  1. 异常/错误处理
  2. HTTP 严格传输安全协议
  3. HTTPS 重定向
  4. 静态文件服务器
  5. Cookie 政策实施
  6. 身份验证
  7. 会话
  8. 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 值。
  • 我已添加图片以获取更多信息。请看看,让我知道
猜你喜欢
  • 1970-01-01
  • 2016-11-27
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
相关资源
最近更新 更多