-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Should throw an exception when attempting to use TempData without TempDataProvider #5537
Comments
@kichalla I'm surprised we don't already have such an exception... was this always the case? Or did something regress at some point? |
@FSMaxB Could you share how your Startup.cs looks like? Also which version of packages are you using (1.0.0 or 1.1.0)? |
@kichalla yes, but the session services aren't registered by default, so I thought that we'd throw an exception at some point if you try to use TempData and the required services aren't there? |
Startup.cs (some information removed): using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.ResponseCompression;
using System.IO.Compression;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace SparePartManagement
{
public class Startup
{
private static IConfiguration _configuration;
public Startup(IHostingEnvironment environment)
{
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(environment.ContentRootPath)
.AddJsonFile("appsettings.defaults.json", optional: false)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("appsettings.json.{environment.EnvironmentName}.json", optional: true);
if (environment.IsDevelopment())
{
configurationBuilder.AddUserSecrets();
}
configurationBuilder.AddEnvironmentVariables();
_configuration = configurationBuilder.Build();
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
// configuration
services.AddOptions();
services.Configure<EmailSettings>(settings => EmailSettings.Populate(_configuration, settings));
services.Configure<DatabaseSettings>(settings => DatabaseSettings.Populate(_configuration, settings));
services.Configure<HostingSettings>(settings => HostingSettings.Populate(_configuration, settings));
services.Configure<RequestSettings>(settings => RequestSettings.Populate(_configuration, settings));
//compression
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
services.AddResponseCompression(options =>
{
options.Providers.Add<GzipCompressionProvider>();
});
// session
services.AddDistributedMemoryCache();
services.AddSession();
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddRoleManager<ApplicationRoleManager>();
services.AddMvc();
services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(databaseConnection));
}
// 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, IApplicationLifetime lifetime)
{
loggerFactory.AddConsole();
app.UseResponseCompression();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseSession();
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}"
);
}
);
}
}
} I had the problem initally with 1.0.0, but it didn't change after upgrading to 1.1.0. Session was configured, and before attempting to use TempData for the first time, that was actually what I used instead (the session directly, withouth TempData). |
Ok, so you were using Session directly until you figured out to use TempData instead. The above Startup.cs looks fine and using TempData with the above startup should have worked fine. You were mentioning about explicitly adding the TempDataProvider, I do not see it in the above Startup.cs? |
I am having an interesting issue with TempData in my app. Granted I started with an Empty template since that is how I learn. project.json contains: ConfigureServices() contains: I like to use TempData to send messages across redirects, so when they save something, it goes back to the index with a "Saved" message: TempData["message"] = new DisplayMessage("Saved!", DisplayMessageType.Success); My _Layout page then does something like this:
The behavior I am seeing is that if I set the TempData value and return View() (on the case of an error) it renders just fine. If I set the TempData value then RedirectToAction() it fails silently. Chrome browser does not update the location and I get this: The localhost page isn’t working localhost is currently unable to handle this request. |
@eswise Have you enabled logging and found any exceptions that are being logged? |
@kichalla if (env.IsDevelopment()) VisualStudio doesn't break for any exception on this. I see nothing in debug output. |
Reproduce_TempData_Redirect.zip @kichalla Here is the step by step screenshots of me using RedirectToAction() and having it fail silently and then switching it to return View() and having the message render properly. |
Thanks for the repro. I will take a look. You seem to be debugging when using IIS Express. In this case you need to add Debug logger to see the output in the Debug output window. |
@kichalla System.InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type 'RemsLogic.UI.Models.DisplayMessage'. That doesn't happen on return View(), only on return RedirectToAction() |
Looks like I ran head-first into this: #2276 This is different than the previous versions of MVC. Might need a warning label on that. :) |
Yep, confirmed. Changing the TempData assignment to a simple type (string) and it worked as expected. But why does it accept the complex type when you do not redirect? I would expect it to fail either way... I guess because if you don't redirect it doesn't try to serialize it... |
Yes, the above is a reason you are not seeing this exception. In general once the keys of TempData are read they are marked for deletion and are not serialized. |
That was the Startup.cs where TempData didn't work. Before I manually added After that I added |
I am unable to repro what you are seeing. Could you share a simple repro? |
@kichalla: Nevermind, I cannot reproduce it myself anymore. Not even when checking out the commit where the issue initially occured. There must have been something quite strange going on either with the framework or in my head. Also, if I don't register a Session, it fails because it cannot find the Session, as soon as I access TempData. (so it actually throws an exception as expected). I will close this because it looks like the issue I described doesn't actually exist. Sorry for wasting your time. (I still wonder what that was though). |
In my application I was trying to use TempData to pass data to another controller action across redirects, but at first I couldn't figure out why the data got lost every time on redirect.
After asking on StackOverlow, I figured out, that I have to manually register a TempDataProvider in order to make it work. So after adding
services.AddSingleton<ITempDataProvider,SessionStateTempDataProvider>()
to myStartup.cs
, everything was working as expected.I think TempData should throw an Exception when you try to use it without a TempDataProvider being configured. That Exception should tell the user, that a TempDataProvider is required.
The text was updated successfully, but these errors were encountered: