有没有办法在RedirectToAction中维护IsAjaxRequest()?

jos*_*ley 5 ajax asp.net-mvc url-routing

如果你不希望任何环境或为什么我需要这样一个例子,然后跳到问题(S)在底部!

为了保持整洁,我最初在没有JavaScript的情况下构建了我的应用程序.我现在正试图在它的顶部添加一层不引人注目的JavaScript.

本着MVC的精神,我利用了简单的路由和重新路由,你可以做的事情RedirectToAction().

假设我有以下URL来启动注册过程:

http://www.mysite.com/signup

并且假设注册过程分两步:

http://www.mysite.com/signup/1
http://www.mysite.com/signup/2

假设我想要,如果启用了JavaScript,则注册表单将显示在ThickBox等对话框中.

如果用户在步骤2退出注册过程,但稍后点击"注册"按钮,我想要此网址:

http://www.mysite.com/signup

要执行某些业务逻辑,请检查会话.如果他们在中途离开之前的注册工作,那么我想提示他们恢复或重新开始.

我最终可能会遇到以下方法:

public ActionResult SignUp(int? step)
{
    if(!step.HasValue)
    {
        if((bool)Session["SignUpInProgress"] == true)
        {
            return RedirectToAction("WouldYouLikeToResume");
        }
        else
        {
            step = 1;
        }
    }
    ...
}

public ActionResult WouldYouLikeToResume()
{
    if(Request.IsAjaxRequest())
    {
        return View("WouldYouLikeToResumeControl");
    }
    return View();
}
Run Code Online (Sandbox Code Playgroud)

WouldYouLikeToResume中的逻辑是:

  • 如果是AJAX请求,则仅返回用户控件或"部分",以便模态弹出框不包含母版页.
  • 否则返回普通视图

但是,这会失败,因为一旦我从SignUp重定向,IsAjaxRequest()就会变为false.

显然,有很简单的方法来修复这个特定的重定向,但我想保持全局Ajax请求的知识,以便在我的网站上解决这个问题.

问题:

ASP.NET MVC非常非常可扩展.

是否有可能拦截调用RedirectToAction并在参数中注入类似"isAjaxRequest"的内容?

要么

还有其他方法可以安全地检测到原始呼叫是AJAX吗?

要么

我是以完全错误的方式来做这件事的吗?

cha*_*rit 5

根据@joshcomley的要求,使用TempData方法的自动答案:

这假设你有一个BaseController,你的控制器继承它.

public class AjaxianController : /*Base?*/Controller
{
    private const string AjaxTempKey = "__isAjax";


    public bool IsAjax
    {
        get { return Request.IsAjaxRequest() || (TempData.ContainsKey(AjaxTempKey)); }
    }


    protected override RedirectResult Redirect(string url)
    {
        ensureAjaxFlag();
        return base.Redirect(url);
    }

    protected override RedirectToRouteResult RedirectToAction(string actionName, string controllerName, System.Web.Routing.RouteValueDictionary routeValues)
    {
        ensureAjaxFlag();
        return base.RedirectToAction(actionName, controllerName, routeValues);
    }

    protected override RedirectToRouteResult RedirectToRoute(string routeName, System.Web.Routing.RouteValueDictionary routeValues)
    {
        ensureAjaxFlag();
        return base.RedirectToRoute(routeName, routeValues);
    }


    private void ensureAjaxFlag()
    {
        if (IsAjax)
            TempData[AjaxTempKey] = true;

        else if (TempData.ContainsKey(AjaxTempKey))
            TempData.Remove(AjaxTempKey);
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用它,使控制器继承AjaxianController并使用"IsAjax"属性而不是IsAjaxRequest扩展方法,然后控制器上的所有重定向将自动维护ajax-or-not标志.

...

虽然没有测试过,所以要警惕bug :-)

...

另一种不需要使用我能想到的状态的通用方法可能需要您修改路由.

具体来说,您需要能够在路线中添加通用词,即

{controller}/{action}/{format}.{ajax}.html
Run Code Online (Sandbox Code Playgroud)

然后不是检查TempData,而是检查RouteData ["ajax"].

在扩展点上,不是设置TempData键,而是将"ajax"添加到RouteData中.

有关详细信息,请参阅多格式路由上的此问题.