【问题标题】:Stop .cshtml rendering on post在帖子中停止 .cshtml 渲染
【发布时间】:2021-04-04 16:07:48
【问题描述】:

假设我在 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");
}

当收到 GET 请求时,ViewData["guild"] 由 OnGet 处理程序设置并呈现 .cshtml,从而允许返回页面。

收到 POST 请求时,会呈现 .cshtml 文件,但会引发空引用异常,因为尚未定义 ViewData["guild"]。我不需要在帖子上呈现我的 .cshtml 文件,因为我的请求是在后台发出的。

如果执行了 OnGet 方法,是否可以只渲染 .cshtml 文件?如有必要,我愿意切换到 MVC 样式处理程序。

【问题讨论】:

    标签: c# asp.net asp.net-mvc razor-pages


    【解决方案1】:

    我认为在您的情况下,正确的方法是通过某种服务保留实际价值,以便在 Post 请求中也可以访问它:

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

    您还应该在 Startup.cs 文件中注册该服务:

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

    然后您可以轻松地使用您的代码使用此类服务​​:

    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>
    

    话虽如此,根据您的确切需求,您还可以在.cshtml 文件中添加if ... else ... 逻辑并在条件后面进行门渲染(这可能是bool IsPostOnGetOnPost 你的方法 Page Model 例如)。

    【讨论】:

    • 哇,谢谢! CacheService 值究竟如何在不同请求之间持续存在?过去,我通过设置 PageModel 的一个属性进行了试验,但它在请求之间被重置,就好像已经创建了一个新的 PageModel 实例一样。是因为在Startup.cs中注册的吗?
    • 这要归功于Dependency Injection 为服务定义了三种不同的生命周期类型。 Transient - 每次访问对象时都会提供一个新实例。 Scoped - 对象在单个请求中保持不变。 Singleton - 总是有一个实例,即使跨不同的请求。这是我知道的最好的解释:youtube.com/watch?v=v6Nr7Zman_Y
    • 感谢您提供的详细信息。我认为对于我的实现,我需要让 CacheService 类为每个用户返回不同的值,也许我可以通过添加一些自定义中间件来巧妙地做到这一点。该视频也非常有用。非常感谢!
    猜你喜欢
    • 2013-08-24
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 2021-06-22
    相关资源
    最近更新 更多