TempData In Razor Pages

TempData is a storage container for data that needs to be available to a separate HTTP request. The canonical example for illustrating how TempData works involves providing feedback to the user after a form submission that results in the user being redirected to another page (Post-Redirect-Get).

Here is a very simple form:

<form method="post">
    <input type="text" asp-for="EmailAddress"/>
    <span asp-validation-for="EmailAddress"></span><br/>
    <button>Submit</button>
</form>

In the following code snippet, a PageModel property called FormResult has been decorated with the TempData attribute.

public class IndexModel : PageModel
{
    [TempData]
    public string FormResult { get; set; }
    [BindProperty]
    public string EmailAddress { get; set; }
    // ...

The property has a value assigned to it when the form is posted.

public IActionResult OnPost()
{
    try
    {
        var email = new MailAddress(EmailAddress);
        FormResult = "You have provided a valid email address";
        return RedirectToPage("/success");
    }
    catch(FormatException)
    {
        ModelState.AddModelError("EmailAddress", "Invalid email address");
        return Page();
    }
}

If the validation test passes, the user is redirected to another page (success.cshtml). There, the TempData value is accessed using a string indexer:

<h4>@TempData["TempDataProperty-FormResult"]</h4>

The index value is "TempDataProperty-" suffixed with the name of the property, in this case FormResult.

Once the value has been read, it is marked for deletion and is therefore not available for subsequent requests.

Retaining TempData Values

If you want to access a TempData value and then retain it for a further request, you have two options. The first is the Peek method, which allows you to read a value without it being marked for deletion:

var temp = TempData.Peek("TempDataProperty-FormResult");

The second option is to use the Keep method after you have accessed the value. This has the effect of marking the value for retention. The Keep method provides two options. You can either specify that the whole dictionary is retained:

var result = TempData["TempDataProperty-FormResult"];
TempData.Keep();

Or you can just mark individual values for retention:

var result = TempData["TempDataProperty-FormResult"];
TempData.Keep("TempDataProperty-FormResult")

Storage Mechanisms

The default storage mechanism for TempData is cookies, which is enabled by default in a typical Razor Pages application.

TempData cookie

You can configure various options related to the TempData cookie in the ConfigureServices method. The following example changes the name of the cookie:

services.Configure<CookieTempDataProviderOptions>(options =>
{
    options.Cookie.Name = "MyTempDataCookie";
});

Configure Cookie

Most browsers limit the size of cookies and therefore the data that can be stored in them. If you exceed this limit, you will get a 400 HTTP Error code: The size of the request headers is too long. If you need to store large amounts of data in TempData, you can use the session provider instead:

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

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

Limitations

You can store simple values in TempData - strings, booleans and numeric types, but if you try to store complex types, you will encounter an InvalidOperationException:

The '[name of the property]' property with TempDataAttribute is invalid. The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type '[name of the property]'.

If you want to use TempData to store complex types, you must serialize it to a string-based format yourself. JSON is the recommended format to use because it is relatively compact (compared to XML) and JSON.Net is included as part of the default project template.

Last updated: 08/10/2018 08:24:00

© 2018 - Learn Razor Pages.
All rights reserved.