【问题标题】:ASP.NET MVC 3 - Detect Whether Current Page Was Redirected To in a Post Redirect Get WorkflowASP.NET MVC 3 - 在后重定向获取工作流中检测当前页面是否被重定向到
【发布时间】:2012-11-27 22:18:25
【问题描述】:

在我的 C# .NET 4 MVC 3 应用程序中,我有一个用于一组 CRUD 页面的删除控制器,它使用 Post Redirect Get 模式在成功删除后重定向到索引控制器。仅当此页面未被此类操作重定向到时,我才想在索引页面上呈现一个按钮。有没有一种简单的方法来检测当前页面是否被重定向到(即作为 PRG 重定向的结果到达)?

阅读http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx 后,我当前的方法是在DeleteMyEntity 方法成功后使用TempData 在我的删除控制器中设置它:

try {
    MyService.DeleteMyEntity(MyViewModel.MyEntity);
    TempData["Redirected"] = true;
    args = new RouteValueDictionary(new { Foo = 1, Baa = 2 });
    return RedirectToAction("Index", args);
} catch (Exception e)
{
   //Logging etc. - redirect should never be reached on exception (and TempData item not set)
   throw(e);
}

然后在我的索引控制器中检查这个值是否存在并且是真的:

if (TempData["Redirected"] != null)
{
    //we can then do something useful with this
}

我看到的另一个机会是向args 添加另一个项目并在控制器中检查它,但在这种情况下,我不妨只使用TempData。有没有办法在请求上使用 HTTP 响应代码来执行此操作,而无需使用 TempData 或类似机制传递此数据?

【问题讨论】:

  • 您可以从HttpContext.Current.Request.Headers 中读取referer 标头的值,但这取决于客户端浏览器的表现是否良好。 TempData 基本上是为这类事情设计的,听起来是你最好的选择。
  • sargant 我应该对环境有很好的控制。我看了一下这个,我想不出一个实现,我不需要检查引用者是否在我不想为其呈现按钮的引用者列表中。我认为从我重定向的控制器传递标志更容易。

标签: c# asp.net asp.net-mvc-3


【解决方案1】:

另一种方法是设置一个全局操作过滤器,为您“注入”该标志...

public class RedirectDetect: ActionFilterAttribute{
   public override void OnActionExecuted(ActionExecutedContext filterContext){
        if (filterContext.Result is RedirectToRouteResult ||
            filterContext.Result is RedirectResult)
        {
             TempData["Redirected"] = true;
             //or what ever other indicator you want to set
        }
   }
}

然后你可以调用 redirectToAction("Index") 然后检查你的接收处理程序

旁注:我挑战你大声说 RedirectDetect 而不是假笑。

【讨论】:

  • 这是我与 cookie 临时数据提供程序一起工作的原因,因为它会清除重定向时的 cookie,从而有效地使我的用例无用(PRG 消息传递)。在提供程序中,我检查该标志,然后将其删除,同时阻止保存,如果这是唯一的标志。
【解决方案2】:

我以类似的方式使用 TempData - 例如,在添加/更新/删除记录时显示状态消息(重定向到)我的视图。这是 TempData 用于的那种简单的、一次性的东西,所以我说你有什么是合适的。

除非我绝对需要它,否则我不会弄乱 HTTP 状态代码。并且您可能可以使用referrer http 标头做一些事情,但同样,这将比仅使用 TempData 更加混乱和复杂。你有一个干净,简单的解决方案,我说你有什么。

【讨论】:

  • 谢谢你。我唯一担心的是,其他程序员/我未来从事该项目的自己必须了解该约定,并且它不受诸如 ViewModel 之类的东西的约束,它将为此提供合理的具体用法/智能提示。但它最终可能是最好的解决方案,因为我对它有很多控制权。
  • 我避免使用 TempData,因为它要求用户假设客户端浏览器总是会发出后续请求。这违反了“从不信任客户”的规则。
  • @AaronNewton 确实,您必须了解约定;但是话又说回来,您必须了解很多约定,因为 MVC 高度基于模式和约定(例如,您正在处理的整个 PRG 模式)。据我所知,这是实现此目的的一种相当常见的方式,因此它只是在工具箱中保留的另一种约定:)
  • 谢谢你。我刚刚发现您可以使用像protected override void OnActionExecuted(ActionExecutedContext filterContext) 这样的方法签名从基类覆盖控制器。然后我可以在这个基类中为控制器设置一个属性(例如bool Redirected)并在OnActionExecuted中抛出一个异常,如果该值没有在继承类的控制器中设置(例如在方法Delete中设置)或整个控制器类)。然后使用这个值来修改 ViewModel 中的一个属性,假设 ViewModels 也继承了一个基类。
  • forums.asp.net/post/2444434.aspxmsdn.microsoft.com/en-us/library/…。如果我能正常工作,我会尝试发布一个 sn-p。
【解决方案3】:

我不知道任何更简单的机制,并且已经使用 TempData 很长一段时间来实现 Post-Redirect-Get 功能。据我所知,这具体是 TempData 存在的原因之一。我会继续使用它。

【讨论】:

  • 谢谢你。这里的另一个考虑是如果它有效,请使用它:D
【解决方案4】:

由于 3xx 重定向或直接的用户发起的 GET,无法区分请求之间的区别。最好的方法是提供一个查询字符串参数,该参数仅由初始 POST 请求的重定向附加,但没有什么可以阻止用户使用相同的查询字符串重新加载页面。

嗯,或者你可以从 POST 发送一个带有重定向的 cookie,然后在后续 GET 的响应中删除 cookie,如下所示:

public ActionResult PostHandler(ViewModel model) {
    SetCookie("redirected", "true"); // psuedocode
    return Redirect("GetHandler2");
}

public ActionResult GetHandler2() {
    if( GetCookie("redirected") == "true" ) {
        // do something
    }
    DeleteCookie("redirected");
}

【讨论】:

  • 戴,我试试看。
【解决方案5】:

以乔治的回答为基础:

public class MarkRedirects : ActionFilterAttribute
{
   public override void OnActionExecuted(ActionExecutedContext context)
   {
        if (context.Result is RedirectToActionResult ||
            context.Result is RedirectResult)
        {
            // Obtain and verify the underlying IController
            var controller = context.Controller as Controller;
            if (controller != null)
                controller.TempData["Redirected"] = true; // or set other dictionary data here
        }
   }
}

context.Result 的条件检查可以根据您用于重定向的方法而有所不同,例如,如果您通过 RedirectToAction() 方法重定向用户,context.Result is RedirectToActionResult 将返回 true,但 context.Result is RedirectToRouteResult 不会。

因此,您需要根据您对如何重定向用户的个人喜好来更改该条件。当前代码适用于 OP 的情况。

如果您要在任何地方使用它,修改基本控制器可能是明智之举。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多