简体   繁体   English

在 ASP.NET Core Razor 页面上提交 Post 后如何刷新页面内容?

[英]How to refresh the page content after a Post submission on ASP.NET Core Razor Pages?

I am using ASP Net Core, and I created a project with Razor Pages.我正在使用 ASP Net Core,并使用 Razor Pages 创建了一个项目。

I have a page which lists products associated with the current user, and he can add a new product.我有一个页面列出了与当前用户关联的产品,他可以添加新产品。

After the OnPost method is called, I want to refresh the page so that it displays all the products of the user without requesting the database again OnPost方法被调用后,我想刷新页面,让它显示用户的所有产品,而无需再次请求数据库

Below is my current solution:以下是我目前的解决方案:

    public async Task OnGet()
    {
        var currentUser = await GetCurrentUser();
        if (currentUser != null)
            Products = await _dbContext.Products.Where(x => x.AtpUserId == currentUser.Id).ToListAsync();
    }

    public async Task OnPost(Product product)
    {
        var currentUser = await GetCurrentUser();
        if (currentUser != null)
        {
            product.UserId = currentUser.Id;
            product.Currency = "USD";
            await _dbContext.Products.AddAsync(product);
            await _dbContext.SaveChangesAsync();
            Products = await _dbContext.Products.Where(x => x.UserId == currentUser.Id).ToListAsync(); // can I avoid this ?
        }
    }

I don't find how I achieve the same result without the last line which reloads the data from the database.如果没有从数据库重新加载数据的最后一行,我无法找到相同的结果。

  • I looked at some examples but examples from the scaffold pages all use an intermediate Create page, and then redirect to the Index page.我查看了一些示例,但是来自脚手架页面的示例都使用中间Create页面,然后重定向到Index页面。 I want the user to be able to create from the Index page我希望用户能够从索引页面创建
  • I tried to replace the last line of the OnPost method by a call to RedirectToPage("Index");我试图通过调用RedirectToPage("Index");来替换OnPost方法的最后一行RedirectToPage("Index"); but the method OnGet is not called again and the table containing the products is empty on refresh.但不会再次调用OnGet方法,刷新时包含产品的表为空。 Why?为什么?

In my experience, the best way to manage lists of elements on a webpage, is to manage them on client code, and just query the database when my users submit.根据我的经验,管理网页上元素列表的最佳方法是在客户端代码上管理它们,并在我的用户提交时查询数据库。

I'll try to elaborate further:我将尝试进一步阐述:

If you have a page where a list of elements is shown, and your users can add, modify or erase elements from there, the best way to to this (IMHO) is the following:如果您有一个显示元素列表的页面,并且您的用户可以从那里添加、修改或删除元素,那么最好的方法(恕我直言)如下:

-Load the page with current info obtained from database (you can store a representation of that info in your client code, lets say, for example, on a JSON object). - 使用从数据库获取的当前信息加载页面(您可以在客户端代码中存储该信息的表示,例如,在 JSON 对象上)。

-Let your user manage the info on the page. - 让您的用户管理页面上的信息。 When he adds a new element, you update the info on your JSON object and reflect it on the screen, but don't get in contact with the database until changes are submitted.当他添加新元素时,您会更新 JSON 对象上的信息并将其反映在屏幕上,但在提交更改之前不要与数据库联系。

-You make the same with updates or deletes, always maintaining the actual info in your main JSON object, but without calling the server for anything. - 您对更新或删除进行相同操作,始终在主 JSON 对象中维护实际信息,但无需调用服务器进行任何操作。

-When the operation is finished (and this can mean a lot of different things depending on your business model) you get your updated JSON object, with current complete list of elements, and send it to the server to apply changes on a unique database transaction. - 操作完成后(这可能意味着很多不同的事情,具体取决于您的业务模型),您将获得更新的 JSON 对象,以及当前完整的元素列表,并将其发送到服务器以对唯一的数据库事务应用更改.

This generates less network traffic, less database operations, is faster, more reliable, allow an easier way to update the views, and can be almost completely managed through client code.这会产生更少的网络流量、更少的数据库操作、更快、更可靠、更容易更新视图,并且几乎可以完全通过客户端代码进行管理。

It cannot apply to certain scenarios, for example if your collection of elements need to be modified by different users at the same time, or by external events out of the current user interaction, but is a clean and efficient way to manage many simple user interactions which we use to make too complex on an unnecesary way.它不适用于某些场景,例如,如果您的元素集合需要由不同的用户同时修改,或者由当前用户交互之外的外部事件进行修改,但它是管理许多简单用户交互的干净有效的方式我们使用它以不必要的方式使过于复杂。

Firstly, That's a great question, Thanks for asking!首先,这是一个很好的问题,谢谢你的提问!

What you are trying to achieve cannot be done through redirecting.您尝试实现的目标无法通过重定向来完成。 The database will be called once again and that's unavoidable.数据库将再次被调用,这是不可避免的。 But there's another approach, which is what I'd recommend if you really don't want to request data from the database twice.但是还有另一种方法,如果您真的不想从数据库请求数据两次,我会推荐这种方法。 Let's explore it below:下面我们来一探究竟:

You will need to pass the Products data back to the model when OnPost is called.调用OnPost时,您需要将Products数据传回模型。 This means that you must bind that data so that it's passed with form data to the model on post submission.这意味着您必须绑定该数据,以便在提交后将其与表单数据一起传递给模型。

First, mark your products property in your Razor Page Model with [BindProperty] , and then add an <input type="hidden" value="@Model.Products" /> in your HTML.首先,使用[BindProperty]在 Razor 页面模型中标记产品属性,然后在 HTML 中添加<input type="hidden" value="@Model.Products" /> This will submit your Products data with form submission.这将通过表单提交提交您的Products数据。

Now in your OnPost , Products will have a value because it will be binded.现在在您的OnPost , Products 将有一个值,因为它将被绑定。 And by the Time OnPost returns Page , @Model.Products will have same values that were retrived from the initial OnGet .OnPost返回Page@Model.Products将具有从初始OnGet相同值。 I have done this before, and it's worked, so I can assure you that it's going to work.我以前做过这个,而且它奏效了,所以我可以向你保证它会奏效。


Here's some sample code:这是一些示例代码:

public class SomePageModel{

  [BindProperty]
  public IList<Product> Products {get; set;}
  
  [BindProperty]
  public Product Product {get; set;}
  
  public async Task OnGet()
  {
      var currentUser = await GetCurrentUser();
      if (currentUser != null)
          Products = await _dbContext.Products.Where(x => x.AtpUserId == currentUser.Id).ToListAsync();
  }

  public async Task OnPost()
  {
      var currentUser = await GetCurrentUser();
      if (currentUser != null)
      {
          Product.UserId = currentUser.Id;
          Product.Currency = "USD";
          await _dbContext.Products.AddAsync(Product);
          await _dbContext.SaveChangesAsync();
      }
  }
}

For Binding to work, you need to pass the data back to the Model, so include a hidden <input /> for it:要使绑定工作,您需要将数据传递回模型,因此为它包含一个隐藏的<input />

<form method="POST">
  <input type="hidden" asp-for="Products" value="PassProductsAsJSONString" />
</form>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM