Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 在ASP.NET MVC中发布后重定向_Asp.net Mvc - Fatal编程技术网

Asp.net mvc 在ASP.NET MVC中发布后重定向

Asp.net mvc 在ASP.NET MVC中发布后重定向,asp.net-mvc,Asp.net Mvc,我正在ASP.NET MVC应用程序中使用该模式。我有 以下场景: 用户进入/controller/index,要求他填写表格 表单值发布到/controller/calculate Calculate操作根据输入执行计算,并实例化包含操作结果的复杂对象。此对象存储在TempData中,用户被重定向到/controller/result /controller/result从TempData检索结果并将其呈现给用户 这种方法的问题是,如果用户在查看/controller/result中的结果时点

我正在ASP.NET MVC应用程序中使用该模式。我有 以下场景:

  • 用户进入
    /controller/index
    ,要求他填写表格
  • 表单值发布到
    /controller/calculate
  • Calculate
    操作根据输入执行计算,并实例化包含操作结果的复杂对象。此对象存储在
    TempData
    中,用户被重定向到
    /controller/result
  • /controller/result
    TempData
    检索结果并将其呈现给用户
  • 这种方法的问题是,如果用户在查看
    /controller/result
    中的结果时点击F5,则页面将无法再呈现,因为
    TempData
    已过期,并且结果对象不再可用

    用户不希望出现这种行为。一种可能的解决方案是不在发布后重定向,只渲染结果视图。现在,如果用户点击F5,他会收到一个浏览器对话框,询问是否要重新发布表单。这也是不可取的

    我想到的一个可能的解决方案是序列化结果对象,并在重定向之前将其传递到URL中,但是如果GET请求的长度有一些限制,并且如果对象变得相当大,我可能会达到这个限制(特别是如果base64编码)

    另一种可能是使用
    Session
    对象而不是
    TempData
    来持久化结果。但是在实施这个解决方案之前,我想知道是否有更好的方法


    更新:

    进一步调查该问题,我发现如果我将结果对象重新放入
    /TempData
    中的
    /controller/result
    操作中,它实际上可以工作:

    public ActionResult Result()
    {
        var result = TempData["result"];
        TempData["result"] = result;
        return View(result);
    }
    

    但这感觉有点脏。这种方法是否会有任何副作用(例如切换到进程外会话提供程序,正如我目前使用的InProc)?

    通常认为TempData对于将消息传递回用户非常有用,而不是用于存储工作实体(用户刷新会影响TempData的内容)

    我不知道还有什么地方比会话更适合存储此类信息。我认为总的想法是尽可能地减少会议。就我个人而言,我通常编写一些包装器来向会话添加和删除特定对象。尽可能手动清理


    或者,您可以将其存储在数据库中,在该数据库中定期清除过时的项目。

    将其存储在会话中,使用某个唯一的密钥,并将该密钥作为url的一部分传递。然后,只要会话处于活动状态,他们就可以使用“后退/前进”按钮查看自己的核心内容,并且仍然可以让URL正确响应。或者,您可以使用ASP缓存,但我通常会为用户之间共享的对象保留该缓存。当然,如果您使用计算的参数作为键,并在缓存中找到结果,您可以简单地重新使用它。

    我认为,当结果Url有意义时,post后重定向更有意义。 在您的情况下,这意味着计算所需的所有数据都在/controller/result的Url中

    /controller/calculate不会进行计算,而是/controller/result

    如果你能做到这一点,你会变得非常简单:你散列计算所需的值,并将其用作缓存的键。如果用户刷新,他只会点击缓存


    如果你没有一个有意义的完整url,你可以发布到/controller/index。如果用户点击F5,计算将重新开始,但使用哈希作为键的缓存将再次有所帮助。

    我可能会采用类似的想法,在网上银行网站上的许多银行使用一次性键来验证所有帖子。您可以将其集成到表单的html帮助程序中,并集成到服务层(例如)中进行验证

    假设您只想发布表单的任何实例一次。向表单添加guid。如果表单未回发且数据已提交,则需要使guid无效并重定向到GET操作。如果说表单无效,当页面发回时,您需要在表单中添加一个新的(有效)guid,等待下一次发帖尝试

    guid根据需要生成并添加到数据库中的表中。当它们失效时(通过帖子,无论成功与否),它们都会在表中标记。您可能需要将表格修剪为100行。。或者1000,这取决于你的应用程序有多重,以及你在同一时间可能有多少已呈现但尚未发布的表单

    我还没有对这个设计进行过很好的调整,但我认为它可能会起作用。它不会像TempData那样难闻,你仍然可以坚持PRG模式


    请记住,使用PRG时,您不希望在某种类型的temp变量中将新数据发送到GET操作。您想从数据存储中查询它,它现在被提交到数据存储中。

    正如Michael所说,TempData有一个单一目的->仅为一次行程和一次行程存储一个对象。据我所知,TempData本质上使用的会话对象与您可能使用的会话对象相同,但它将在下次访问时自动从会话中删除该对象


    坚持会话imho,而不是返回到TempData。

    当你说“重定向”时,你是在调用RedirectToAction吗?谢谢,这是一个很好的建议。我会尝试使用url中传递的唯一键来实现它。我需要在计算之前验证输入,如果有错误,则使用预填充值和红色标记的错误字段显示相同的表单。如果在结果操作中进行了计算,我将如何处理ModelState错误?我是否应该重定向回索引操作,并将所有输入值和验证错误再次放入TempData,以便正确显示表单?结果中很难进行验证。我会重定向到w