如何在asp.net mvc中只显示一次页面

时间:2016-08-08 13:56:43

标签: asp.net-mvc

在我的应用中,我正在检查某个配置文件是否可用,如果不是,那么我想重定向到安装页面。

对我而言,完成此任务的最佳位置是application_start。因为它只发生过一次。如果我在application_start进行检查并写下Response.Redirect,我会得到Response is not available in this context

我在堆栈溢出中尝试了其他答案,以便在application_start中重定向,如HttpContext.Current.Response.Redirect;没有人为我工作。

我不想在base controllerfilter中执行此操作,因为检查逻辑将针对每个请求进行。

我的目标是只检查一次,并且应用程序启动时最好。

更新1

我将response.redirect添加到application_start但是出现了这样的错误:

申请开始:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        Response.RedirectToRoute(
            new RouteValueDictionary {
            { "Controller", "Home" },
            { "Action", "about" }
        });
    }

但我收到的错误是这样的:

  

在此背景下无法获得响应。

     

描述:执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

     

异常详细信息:System.Web.HttpException:在此上下文中无响应。

3 个答案:

答案 0 :(得分:3)

如果您确实希望避免在安装后为每个请求运行过滤器,那么您可以执行以下操作:

RedirectAttribute.cs(通用示例)

public class RedirectAttribute : ActionFilterAttribute
{
    private readonly string _controller;
    private readonly string _action;

    public RedirectAttribute(string controller, string action)
    {
        _controller = controller;
        _action = action;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionDescriptor.ActionName != _action ||
            filterContext.ActionDescriptor.ControllerDescriptor.ControllerName != _controller)
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary(new {controller = _controller, action = _action})
                );
        }
    }
}

在上面的Global.asax.cs" FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);"

if (/*Insert logic to check if the config file does NOT exist*/)
{
    //Replace "Setup" and "Index" with your setup controller and action below
    GlobalFilters.Filters.Add(new RedirectAttribute("Setup", "Index"));
}

现在, 后,您的用户已完全完成设置,您可以卸载应用领域:

HttpRuntime.UnloadAppDomain();

请注意:您需要确保您的应用有权卸载AppDomain。如果没有,您可以在配置文件(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)上尝试File.SetLastWriteTimeUtc(...)。这也将卸载AppDomain。

卸载AppDomain将"重启" Web应用程序并再次调用Application_Start()。 过滤器不会添加到您的请求中,因为您的if语句将确定该应用已经配置。

答案 1 :(得分:0)

作为一种变通方法,您可以在过滤器内的静态变量中使用lazy initialization。检查配置文件的实际文件操作仅在第一次请求期间发生一次。之后,配置文件的检查值保存在static Lazy变量中。作为额外的奖励,它也是线程安全的。

最后检查仍然在每个请求上发生,但是在初始检查后操作很快,因为检查结果保存在内存中。

public class ConfigFileCheckAttribute : ActionFilterAttribute
{
    //Lazy<> is threadsafe and will call the Func in the constructor just once
    private static Lazy<bool> _configFileExists = new Lazy<bool>(ConfigFileExists);

    private static bool ConfigFileExists()
    {
        //Logic to check for config file here            
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!_configFileExists.Value)
        {
            //set your redirect here
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Setup", action = "Configure" }));
        }
    }
}

最后一点是在App_Start / FilterConfig.cs中注册过滤器:

public static class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //...
        filters.Add(new ConfigFileCheckAttribute());
    }
}

答案 2 :(得分:0)

如果您需要针对特定​​网页使用此功能,请在操作中使用以下Cookie:

public ActionResult Index()
{
    string cookieName = "NotFirstTime";
    if(this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains(cookieName))
        // not first time 
        return View();
    else
    {
        // first time 
        // add a cookie.
        HttpCookie cookie = new HttpCookie(cookieName);
        cookie.Value = "anything you like: date etc.";
        this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
        // redirect to the page for first time visit.
        return View("FirstTime");
    }
}

如果您想对每种操作方法使用 ,则需要编写ActionFilterAttribute以便在每次需要时调用它。

请注意 Request.Context事件无法再使用Application_Start