11

Hello i am trying to add an object to TempData and redirect to another controller-action. I get error message 500 when using TempData.

public IActionResult Attach(long Id)
{
    Story searchedStory=this.context.Stories.Find(Id);
    if(searchedStory!=null)
    {
        TempData["tStory"]=searchedStory;  //JsonConvert.SerializeObject(searchedStory) gets no error and passes 

        return RedirectToAction("Index","Location");
    }
    return View("Index");
}


public IActionResult Index(object _story) 
{             
    Story story=TempData["tStory"] as Story;
    if(story !=null)
    {
    List<Location> Locations = this.context.Locations.ToList();
    ViewBag._story =JsonConvert.SerializeObject(story);
    ViewBag.rstory=story;
    return View(context.Locations);
    }
    return RedirectToAction("Index","Story");
}

P.S Reading through possible solutions I have added app.UseSession() to the Configure method and services.AddServices() in the ConfigureServices method but to no avail.Are there any obscure settings i must be aware of?

P.S adding ConfigureServices and UseSession

ConfigureServices

 public void ConfigureServices(IServiceCollection services)
            {
                services.AddOptions();
                services.AddDbContext<TreasureContext>(x=>x.UseMySql(connectionString:Constrings[3]));
                services.AddMvc();
                services.AddSession();
            }

Configure

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseSession();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
Bercovici Adrian
  • 8,794
  • 17
  • 73
  • 152

4 Answers4

24

You have to serialize the object before assigning it to TempData as core only support strings and not complex objects.

TempData["UserData"] = JsonConvert.SerializeObject(searchedStory);

and retrieve the object by deserializing it.

var story = JsonConvert.DeserializeObject<Story>(TempData["searchedStory"].ToString())
Ameya Deshpande
  • 3,580
  • 4
  • 30
  • 46
Agrawal Shraddha
  • 734
  • 1
  • 5
  • 18
  • 6
    This was my issue and it was driving me crazy. Using complex object has caused me to return 500 error without any exceptions or explanation of any it was returning 500. Serializing it was the way to go. – FerX32 Jul 16 '18 at 00:13
  • Worked perfectly. Thanks for saving the day :D – Mohammed A. Fadil Jan 13 '20 at 21:17
5

You are missing services.AddMemoryCache(); line in your ConfigureServices() method. Like this:

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

And after that TempData should be working as expected.

fatherOfWine
  • 1,191
  • 16
  • 39
  • 4
    *A note for Asp.net Core 3 users* This solution will not work for you, instead refer to Agrawal Shraddha solution. – Mohammed A. Fadil Jan 13 '20 at 21:20
  • @MohammedA.Fadil This solution WILL work in Mvc Core 3 application. Please do you research first before commenting. – fatherOfWine Jan 15 '20 at 14:15
  • I did my research, your solution did not work for me. And after trial and error Agrawal Shraddha solution worked pefectly for me on 3.1 – Mohammed A. Fadil Jan 15 '20 at 19:27
  • 1
    With all due respect solution I've provided works in my MVC.NET Core 3 application just fine as we speak.:) So to say, that "This solution will not work for Asp.net Core 3 users" is a bit of a stretch, because app I am working on is living contradiction to your statement. Happy programming!:) – fatherOfWine Jan 15 '20 at 19:50
  • Nothing personal bro. Good luck – Mohammed A. Fadil Jan 15 '20 at 22:33
  • 1
    @MohammedA.Fadil I can confirm, that this is not working for Core 3.1. – sandy Jan 17 '22 at 12:43
3

I am working on Dot net 5.0(which is in preview currently). In my case, none of the configuration mentioned in above answers didn't work. TempData was causing XHR object to receive 500 Internal server error in Dot net 5.0 MVC app. Finally, I found that, the missing part was AddSessionStateTempDataProvider()

`public void ConfigureServices(IServiceCollection services)
        {
            services.AddBrowserDetection();
            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(120);
            });

            services.AddControllersWithViews().
                .AddSessionStateTempDataProvider();
        }`

It is important to add sessions while using TempData, as TempData internally makes use of Session variable to store data. Here, answer by @Agrawal Shraddha is also very valid. Asp.Net Core/Dot net 5.0 doesn't support TempData to directly store complex objects. Instead, it has to serialize to Json string and needs to be deserialized again while retrieving it.

`TempData[DATA] = JsonConvert.SerializeObject(dataObject);`

And Configure() method as below:

`public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseSession();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
`

For more information on TempData configuration settings, to make it to work, refer below post: https://www.learnrazorpages.com/razor-pages/tempdata

1

Add a TempData extension just like Sesssion to serialize and de-serialize

    public static class TempDataExtensions
    {
        public static void Set<T>(this ITempDataDictionary tempData, string key, T value)
        {
           string json = JsonConvert.SerializeObject(value);
           tempData.Add(key, json);
        }

        public static T Get<T>(this ITempDataDictionary tempData, string key)
        {
            if (!tempData.ContainsKey(key)) return default(T);

            var value = tempData[key] as string;

            return value == null ? default(T) :JsonConvert.DeserializeObject<T>(value);
        }
    }
user370844
  • 51
  • 1
  • 5