Skip to content

Instantly share code, notes, and snippets.

@Yaevh
Last active April 23, 2025 11:00
Show Gist options
  • Select an option

  • Save Yaevh/e87f682a3c3ac35d1504c068c9f5e8ab to your computer and use it in GitHub Desktop.

Select an option

Save Yaevh/e87f682a3c3ac35d1504c068c9f5e8ab to your computer and use it in GitHub Desktop.
Serializing ModelState in TempData to persist in on redirect in POST-REDIRECT-GET pattern in ASP.NET Core 3.1 Razor Pages
// inspired by https://andrewlock.net/post-redirect-get-using-tempdata-in-asp-net-core/
// usage: in Startup.ConfigureServices() add `services.AddRazorPages().AddMvcOptions(options => options.Filters.Add<SerializeModelStatePageFilter>());`
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Szlem.AspNetCore.Infrastructure
{
public class SerializeModelStatePageFilter : IPageFilter
{
public class ModelStateTransferValue
{
public string Key { get; set; }
public string AttemptedValue { get; set; }
public object RawValue { get; set; }
public ICollection<string> ErrorMessages { get; set; } = new List<string>();
}
public void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
if (!(context.HandlerInstance is PageModel page))
return;
var serializedModelState = page.TempData[nameof(SerializeModelStatePageFilter)] as string;
if (serializedModelState.IsNullOrEmpty())
return;
var modelState = DeserializeModelState(serializedModelState);
page.ModelState.Merge(modelState);
}
public void OnPageHandlerExecuting(PageHandlerExecutingContext context) { }
public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
{
if (!(context.HandlerInstance is PageModel page))
return;
if (page.ModelState.IsValid)
return;
if (context.Result is IKeepTempDataResult)
{
var modelState = SerializeModelState(page.ModelState);
page.TempData[nameof(SerializeModelStatePageFilter)] = modelState;
}
}
private static string SerializeModelState(ModelStateDictionary modelState)
{
var errorList = modelState
.Select(kvp => new ModelStateTransferValue
{
Key = kvp.Key,
AttemptedValue = kvp.Value.AttemptedValue,
RawValue = kvp.Value.RawValue,
ErrorMessages = kvp.Value.Errors.Select(err => err.ErrorMessage).ToList(),
});
return System.Text.Json.JsonSerializer.Serialize(errorList);
}
private static ModelStateDictionary DeserializeModelState(string serialisedErrorList)
{
var errorList = System.Text.Json.JsonSerializer.Deserialize<List<ModelStateTransferValue>>(serialisedErrorList);
var modelState = new ModelStateDictionary();
foreach (var item in errorList)
{
modelState.SetModelValue(item.Key, item.RawValue, item.AttemptedValue);
foreach (var error in item.ErrorMessages)
modelState.AddModelError(item.Key, error);
}
return modelState;
}
}
}
@iJoris
Copy link
Copy Markdown

iJoris commented Aug 15, 2020

Thanks!

@Yaevh
Copy link
Copy Markdown
Author

Yaevh commented Aug 28, 2020

@iJoris glad to help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment