【问题标题】:asp.net Core/OnPostAsync: what's the best way to prevent a record from being created twice?asp.net Core/OnPostAsync:防止记录被创建两次的最佳方法是什么?
【发布时间】:2021-04-10 14:30:28
【问题描述】:

我正在使用 ASP.Net Core 3.1/EF Core Web 应用程序。

问题在于“创建”页面。用户填写 Razor Web 表单并点击“提交”。服务器在“Pages\MyFunction\Create.cshtml.cs”中执行 OnPostAsync()。反过来,OnPostAsync() 不只是“SaveChangesAsync()”发布的数据。它查询其他一些单独的数据(“等待”),进行一些计算,然后最终创建新记录。然后退出:return RedirectToPage("./Index");

问题:

这可能需要一些时间。

用户仍然坐在“创建”页面。

他/她可以再次点击“提交”。然后再次。创建多个重复记录。

问:我有哪些选择可以缓解这种情况?

【问题讨论】:

  • 您希望它做什么,给出错误消息?您是否可以实现“发布/重定向/获取”模式,其中“获取”页面轮询要完成的操作?
  • 所以,数据库有这些叫做主键的东西..
  • 用户界面反馈?一旦他们单击提交按钮,就禁用它并将其更改为微调器,以便他们知道它正在工作。
  • 一些建议,使用异步,让最终用户知道,请求已提交,(如果有页面可以重定向用户,执行此操作或禁用提交按钮),确保您的数据库使用主键,如果项目不存在,在提交到数据库之前验证,在请求完成时向最终用户发出通知,包括如果项目已经存在的反馈
  • @Nonik:谢谢。碰巧的是,我 am 使用异步(当我发布完成的表单时),但在“创建”记录并退出“OnPostAsync()”之前需要发生某些事情。因此问题。是的,我的 EF 记录 DOES 有一个 PK ......但是(明智的 Caius Jard 似乎已经忘记了)它在 .SaveChangesAsync() 之前未初始化。所以它不能帮助我区分“第一个”和“后续的重复”请求。问:还有什么建议吗?问:关于如何/在哪里“禁用”客户端的提交按钮(以不“破坏”用户体验或客户端验证的方式)有什么想法吗?

标签: c# asp.net-core async-await


【解决方案1】:

你主要有三个选择:

  1. 优化保存操作
  2. 异步调用表单提交
  3. 切换到异步 API 模式

优化保存操作

嗯,这是一个简单的答案。您的操作很长并且给您的用户带来了一些挫败感?优化。当然,并不是所有的操作都可以让用户跑得这么快没有挫败感。然而,这并不是一个唯一的答案。也许您会在下面找到一些有趣的选项,这不是因为一些性能问题而懒惰并跳过查看代码的理由。

异步提交表单

异步调用表单要求您在提交表单时阻止浏览器导航。相反,使用客户端代码禁用表单并向用户显示进度动画。这将阻止他们多次提交表单。然后通过 XHR 向服务器异步发送一个 HTTP POST 请求。操作完成后,向用户显示一条消息和/或导航到下一页。此技术不需要对您当前的服务器端实现进行任何更改,但不能很好地扩展。此外,它会将您的用户锁定在“请稍等”的心态中,但有时这实际上是最相关的用户体验。

异步 API 模式

异步 ​​API 模式是一种改变服务器端实现的模式。提交表单后,post 查询处理程序只对数据进行一些快速的内容验证,然后立即返回。之后服务器会在后台进行长时间的操作,你的应用程序必须实现一个通知系统来向用户提供进度信息。通知系统可以是轮询或推送。

获取/重定向/发布

这种模式最常见的实现是 Post/Redirect/Get 模式。 OnPostAsync() 方法将在表单验证并准备好开始操作后向用户返回重定向响应。这会将用户转发到另一个等待任务完成的页面。它易于实施,但不能提供出色的用户体验。

页面加载通知系统

在这种方法中,我们向应用程序中的每个页面添加一个通知系统(通常在一种主模板中)。该组件将查找要显示给用户的消息,并将它们插入到文档中。当用户提交表单时(通过导航或 XHR),只做一些快速验证并返回。您可以添加一条消息以确认操作已成功启动。开始后台操作,完成后向用户添加消息。在导航时,用户最终会收到操作成功或失败的通知。

通知端点

另一个解决方案是实现一个小型 API,允许客户端查询长时间运行的操作状态。每当用户在池中有一个正在运行的任务时,向客户端添加一些代码,这些代码将定期调用该端点以获取操作进度。使用该信息来显示通知,或者如果有动机(并且如果该过程允许简单的进度百分比计算),您甚至可以显示在该过程中填满的进度条。然后更新您的服务器端操作以向通知系统提供频繁的进度信息。如果与 XHR 表单提交结合使用,用户无需任何导航即可开始和完成长时间运行的操作。

推送通知

此技术需要一些现代技术,例如 SignalR,但会提供最佳性能和用户体验。首先,应用程序将与服务器建立双工通信。现在,服务器能够直接将消息流式传输到客户端。客户端不再需要花费大部分资源轮询服务器,他们只需发送表单内容。服务器不需要扩大规模来回复数百万用户自上一秒以来没有任何变化,它只需要处理表单提交。此外,您无需等待用户轮询服务器即可向他提供反馈。您可以实时进行。

【讨论】:

  • 感谢您的建议。但我不想做任何 XHR 或任何投票。我只是希望能够提交“创建”表单并防止用户不耐烦地多次点击“提交”。由于我的实体 ID 是自动生成的,因此我不能使用主键(它还不存在)。也许我可以简单地禁用“提交”按钮。但我不知道这是否会干扰 OOTB“客户端验证”。
  • 我不记得在禁用提交按钮时遇到过问题。它应该可以工作。
  • 另外,即使没有实体键,也可以为操作创建一个id。这可以用于在稍后阶段异步获取实体的db生成的主键。不过,这意味着更复杂的导航行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
相关资源
最近更新 更多