在我的应用中,我正在检查某个配置文件是否可用,如果不是,那么我想重定向到安装页面。
对我而言,完成此任务的最佳位置是application_start
。因为它只发生过一次。如果我在application_start
进行检查并写下Response.Redirect
,我会得到Response is not available in this context
。
我在堆栈溢出中尝试了其他答案,以便在application_start
中重定向,如HttpContext.Current.Response.Redirect
;没有人为我工作。
我不想在base controller
或filter
中执行此操作,因为检查逻辑将针对每个请求进行。
我的目标是只检查一次,并且应用程序启动时最好。
更新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:在此上下文中无响应。
答案 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