Asp.net core TempData give 500 error when adding list and redirect to another view
Asked Answered
C

3

13

I am try to build alerts list and added them to TempData. But it work if I did not do redirect. When I do redirect it give me 500 error. I set break point in view as well but it did not hit when did redirect other wise it hit correctly.

ActionMethod

public IActionResult Create(CategoryCreateVM input)
{
    if (ModelState.IsValid)
    {
        var category = mapper.Map<Categories>(input);
        categoryBL.Add(category);

        List<Alert> alert = new List<Alert>();
        alert.Add(new Alert("alert-success", "success message"));
        alert.Add(new Alert("alert-danger", "danger message"));

        TempData["Alert"] = alert;

        return RedirectToAction("Index");
    }
    return View(input);
}

How I access in view.

@{ 
    var alerts = TempData["Alert"] as List<Alert>;
}
@if (alerts != null && alerts.Count > 0)
{
    <div class="">
        @foreach (var alert in alerts)
        {
            <div class="alert @alert.AlertClass alert-dismissible">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                @alert.Message
            </div>

        }
    </div>

}

Stack Trace.

    Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNetCore.Mvc.ViewFeatures.dll
Exception thrown: 'System.InvalidOperationException' in mscorlib.dll
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Information: Executed action MvcSandbox.Controllers.HomeController.Index (MvcSandbox) in 46.4619ms
Exception thrown: 'System.InvalidOperationException' in mscorlib.dll
Exception thrown: 'System.InvalidOperationException' in mscorlib.dll
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request

System.InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type 'MvcSandbox.Controllers.Alert'.
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer.EnsureObjectCanBeSerialized(Object item) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\TempDataSerializer.cs:line 207
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer.Serialize(IDictionary`2 values) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\TempDataSerializer.cs:line 142
   at Microsoft.AspNetCore.Mvc.ViewFeatures.SessionStateTempDataProvider.SaveTempData(HttpContext context, IDictionary`2 values) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\ViewFeatures\SessionStateTempDataProvider.cs:line 62
   at Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary.Save() in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\ViewFeatures\TempDataDictionary.cs:line 166
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.SaveTempData(IActionResult result, ITempDataDictionaryFactory factory, HttpContext httpContext) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\SaveTempDataFilter.cs:line 91
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.OnResultExecuted(ResultExecutedContext context) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\SaveTempDataFilter.cs:line 80
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.Core\Internal\ControllerActionInvoker.cs:line 1023
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextResourceFilter>d__22.MoveNext() in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.Core\Internal\ControllerActionInvoker.cs:line 1105
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.Core\Internal\ControllerActionInvoker.cs:line 1377
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.Core\Internal\ControllerActionInvoker.cs:line 493
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__20.MoveNext() in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.Core\Internal\ControllerActionInvoker.cs:line 164
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNetCore.Session.SessionMiddleware.<Invoke>d__9.MoveNext() in D:\temp\Session-dev\Session-dev\src\Microsoft.AspNetCore.Session\SessionMiddleware.cs:line 106
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Session.SessionMiddleware.<Invoke>d__9.MoveNext() in D:\temp\Session-dev\Session-dev\src\Microsoft.AspNetCore.Session\SessionMiddleware.cs:line 123
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNetCore.Http.dll
Microsoft.AspNetCore.Server.Kestrel: Error: Connection id "0HL1I8OFS17SU": An unhandled exception was thrown by the application.

System.InvalidOperationException: Session has not been configured for this application or request.
   at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Session()
   at Microsoft.AspNetCore.Mvc.ViewFeatures.SessionStateTempDataProvider.SaveTempData(HttpContext context, IDictionary`2 values) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\ViewFeatures\SessionStateTempDataProvider.cs:line 57
   at Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary.Save() in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\ViewFeatures\TempDataDictionary.cs:line 166
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.SaveTempData(IActionResult result, ITempDataDictionaryFactory factory, HttpContext httpContext) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\SaveTempDataFilter.cs:line 91
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.<>c.<OnResultExecuting>b__5_0(Object state) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\SaveTempDataFilter.cs:line 57
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.<FireOnStarting>d__178.MoveNext()
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An exception was thrown attempting to display the error page.

System.ObjectDisposedException: The response has been aborted due to an unhandled application exception. ---> System.InvalidOperationException: Session has not been configured for this application or request.
   at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Session()
   at Microsoft.AspNetCore.Mvc.ViewFeatures.SessionStateTempDataProvider.SaveTempData(HttpContext context, IDictionary`2 values) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\ViewFeatures\SessionStateTempDataProvider.cs:line 57
   at Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary.Save() in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\ViewFeatures\TempDataDictionary.cs:line 166
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.SaveTempData(IActionResult result, ITempDataDictionaryFactory factory, HttpContext httpContext) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\SaveTempDataFilter.cs:line 91
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.<>c.<OnResultExecuting>b__5_0(Object state) in D:\temp\Mvc-dev\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Internal\SaveTempDataFilter.cs:line 57
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.<FireOnStarting>d__178.MoveNext()
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.ThrowResponseAbortedException()
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.<ProduceStartAndFireOnStartingAwaited>d__194.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.Write(ArraySegment`1 data)
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.FrameResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
   at System.IO.StreamWriter.Write(String value)
   at Microsoft.Extensions.RazorViews.BaseView.Write(String value)
   at Microsoft.AspNetCore.Diagnostics.RazorViews.ErrorPage.<ExecuteAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Extensions.RazorViews.BaseView.<ExecuteAsync>d__29.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
Microsoft.AspNetCore.Server.Kestrel: Error: Connection id "0HL1I8OFS17SU": An unhandled exception was thrown by the application.
Crystacrystal answered 1/1, 2017 at 4:39 Comment(4)
And what does the stack trace show?Barahona
Strack trace not shown, it gives localhost not working Error code 500Crystacrystal
Enable logging to see the stack traceHalbert
None of these solutions below worked for me. I'd rather not deal with serialize to JSON but if I have to...Befall
C
21

Finally I figured it out what's the issue after digging into the source code. Asp.Net Core MVC not supported complex data type for TempData currently. It only support string for now. It through this exception while serialize data, if we pass other then string.

The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type 'MvcSandbox.Controllers.Alert'.

I serialize my list to json and then save in TempData.

Here is how I did this. I create extension method to add and retrieve data from TempData.

const string Alerts = "Alerts";
public static List<Alert> GetAlert(this ITempDataDictionary tempData)
{
    CreateAlertTempData(tempData);
    return DeserializeAlerts(tempData[Alerts] as string);
}

public static void CreateAlertTempData(this ITempDataDictionary tempData)
{
    if (!tempData.ContainsKey(Alerts))
    {
        tempData[Alerts] = "";
    }
}
public static void AddAlert(this ITempDataDictionary tempData, Alert alert)
{
    if(alert == null)
    {
        throw new ArgumentNullException(nameof(alert));
    }
    var deserializeAlertList = tempData.GetAlert();
    deserializeAlertList.Add(alert);
    tempData[Alerts] = SerializeAlerts(deserializeAlertList);
}
public static string SerializeAlerts(List<Alert> tempData)
{
    return JsonConvert.SerializeObject(tempData);
}
public static List<Alert> DeserializeAlerts(string tempData)
{
    if(tempData.Length == 0)
    {
        return new List<Alert>();
    }
    return JsonConvert.DeserializeObject<List<Alert>>(tempData);
}

Add Alert it TempData

 tempData.AddAlert(new Alert(AlertClass, Message));

Finally get 'TempDatainView' and display.

@if (TempData.GetAlert().Count > 0)
{
    <div class="alert-container">
        @foreach (var alert in TempData.GetAlert())
        {
            <div class="alert @alert.AlertClass alert-dismissible">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                @alert.Message
            </div>
        }
    </div>
}
Crystacrystal answered 2/1, 2017 at 17:6 Comment(2)
Had the same problem but liked this solution better. #34639323Descendible
@StephenMcDowell Thanks a lot, your solution helped me too in my ASP.NET Core 2 project. much appreciate itGuru
W
3

Did you configure Session? TempData is using session behind the scenes.

Project.json

"Microsoft.AspNetCore.Session": "1.1.0"

Here is the Startup.cs file. - ConfigureServices method

public void ConfigureServices(IServiceCollection services)
{
    services.AddSession();
    services.AddMvc();
}

And Configure method.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseSession();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Now try with TempData, it will work.

And you can set the environment with set ASPNETCORE_ENVIRONMENT=Development environment variable.

Weird answered 2/1, 2017 at 4:21 Comment(6)
Still, you have the problem? What is the stack trace? If you are running from command line, what is the exception you're getting?Weird
@Sami-Kuhmonen Stack trace added.Crystacrystal
@Crystacrystal Is the stack trace before enabling the session? I could see an exception related to session - System.InvalidOperationException: Session has not been configured for this application or request. at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Session()Weird
I this is strange although I setup session correctly.Crystacrystal
learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state Helped me properly setup session state to get rid of my error.Darr
This solution didn't work for me either :( but I'll check the docs.Befall
C
0

This is what I use to enable Session and Temp data on Core Runtime 2.0.6.

ConfigureServices Section of Startup

// Add MVC service.
services.AddMvc(config =>
{
    // Configure global usage of antiforgery tokens.
    config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
.AddSessionStateTempDataProvider();

// Adds the ability to use session variables.
services.AddSession(options =>
{
    options.Cookie.HttpOnly = true;
});
Conciliar answered 14/12, 2017 at 17:48 Comment(1)
Well this was a long time ago and everything has changed in Core 2.0.6 Runtime. It is close though. I updated comment with what I use now to enable Session and Temp data. Site also required SSL to work properly these days even if it is a local temp cert for development within VS. TBH, don't remember this question and this is a bit off-topic moreless just filling setup information for those in need.Conciliar

© 2022 - 2024 — McMap. All rights reserved.