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">×</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.
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 'TempDatain
View' 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">×</button>
@alert.Message
</div>
}
</div>
}