Stop .cshtml rendering on post

Say I had this page in ASP.NET RazorPages:

@{
    SocketGuild guild = (SocketGuild) ViewData["guild"]
}
<p>The guild has @(guild.Roles.Count) roles.</p>
public async Task OnGet()
{
    ViewData["guild"] = GetGuild();
}

public async Task OnPost()
{
    Console.WriteLine("Post Received");
}

When a GET request is received, ViewData["guild"] is set by the OnGet handler and the .cshtml renders, allowing the page to be returned.

When a POST request is received the .cshtml file is rendered but a null reference exception is thrown because ViewData["guild"] has not been defined. I don’t need my .cshtml file to be rendered on a post because my requests are made in the background.

Is it possible to only render the .cshtml file if the OnGet method has been executed? I’m willing to switch to MVC style handlers if necessary.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I think that the correct approach in your case will be retaining the actual value through some sort of service so it is accessible inside Post request as well:

public interface ICacheService
{
    Dictionary<string, object> Values { get; set; }
}

public class CacheService : ICacheService
{
    public Dictionary<string, object> Values { get; set; } = new Dictionary<string, object>();
}

You should also register the service in your Startup.cs file:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<ICacheService, CacheService>(); // or Scoped depending on your needs
    ...
]

Then you can easily use such service with your code:

public class SocketGuildModel : PageModel
{
    public ICacheService Cache { get; set; }

    public SocketGuildModel(ICacheService cache)
    {
        Cache = cache;
    }

    public async Task OnGet()
    {
        Cache.Values["guild"] = GetGuild();
        await Task.CompletedTask;
    }

    public async Task OnPost()
    {
        Console.WriteLine("Post Received");
        await Task.CompletedTask;
    }

    public static SocketGuild GetGuild() => new SocketGuild();
}

public class SocketGuild
{
    public List<string> Roles { get; set; } = new List<string>();
}
@page
@using RazorPagesDemo.Services
@model RazorPagesDemo.Pages.SocketGuildModel

<form method="post" class="mt-3">
    @{
        var guild = (SocketGuild)Model.Cache.Values["guild"];
    }
    <p>The guild has @(guild.Roles.Count) roles.</p>
    <button class="btn btn-primary" type="submit">Post</button>
</form>

That being said, depending on your exact needs you can also add if ... else ... logic inside your .cshtml file and gate rendering behind the condition (which might be a bool IsPost property set during OnGet and OnPost methods of you Page Model for instance).


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x