响应重定向在MVC中使用

本文关键字:MVC 重定向 响应 | 更新日期: 2023-09-27 18:03:20

我想创建全局之间的连接。Asax和控制器。我们在网站上使用数据库。我们有一个代码来检查数据库是否存在。如果它不存在,我们希望显示"数据库初始化"等消息。

数据库检查GLOBAL。ASAX:

public class MvcApplication : System.Web.HttpApplication
{
    public static bool flag;
    protected void Application_Start()
    {
        Database.SetInitializer<PhoneDexContext>(null);
        var connString = ConfigurationManager.ConnectionStrings["DatabaseConnection"].ConnectionString;
        using (PhoneDexContext db = new PhoneDexContext())
        {
            if (!db.Database.Exists())
            {
                flag = true;
                db.Database.CreateIfNotExists();              
            }
        }
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
    protected void Application_BeginRequest()
    {
        if (flag)
        {
            Response.Redirect("Loading/LoadingScreen");
        }
    }
}

但是我们在使用响应重定向时有一个问题。它返回

{"响应在此上下文中不可用。"}.

我们有一个控制器LoadingController它有这样的代码;

public class LoadingController : Controller
{
    // GET: Loading
    public ActionResult LoadingScreen()
    {
        return View();
    }
}

但是我们不能跳到这部分。我怎样才能连接??由于

响应重定向在MVC中使用

首先,Application_Start不处理任何用户请求。它只是执行一些启动初始化。它只在应用程序启动时调用一次。要根据用户的操作进行一些检查并正确响应,您需要将这些检查移到Application_BeginRequest方法中。

第二,您还需要检查用户是否已经请求/Loading/LoadScreen之前响应重定向到该页。否则,您将获得无限重定向,直到数据库创建。

public class MvcApplication : HttpApplication
{
    private static bool dbInitialized;
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        // We can do it asynchronously to not block other initialization code.
        Task.Run((Action)CreateDataBase);
    }
    private static void CreateDataBase()
    {
        Database.SetInitializer<PhoneDexContext>(null);
        using (PhoneDexContext db = new PhoneDexContext())
        {
            if (!db.Database.Exists())
                db.Database.CreateIfNotExists();
        }
        dbInitialized = true;
    }
    protected void Application_BeginRequest()
    {
        if (!dbInitialized && !this.Request.Url.LocalPath.StartsWith("/Loading/LoadingScreen", StringComparison.OrdinalIgnoreCase))
        {
            this.Response.Redirect("/Loading/LoadingScreen");
        }
    }
}

您可以进一步将检查移到ActionFilter中,因为您将能够使用RouteData并检查actioncontroller参数而不是url。与nameof相结合,将减少路由更改,重命名,重构等的错误倾向。

我认为这个答案会给你你想要的:在一个控制器中返回不同的视图

在您的情况下,而不是响应。重定向使用返回视图("/Loading/LoadScreen");…或者类似的

try this

HttpContext.Current.Response.Redirect("/Loading/LoadScreen");

因为Response对象在global.asax的application_start方法中不可用。你必须使用HttpContext。

你也可以使用"自动启动功能"(如何预热ASP. js)。. NET MVC应用程序在IIS 7.5?:(亲爱的回答)。这将执行一次,在网站准备好服务请求之前。缺点是你不能向用户显示"请等待"窗口。就我个人而言,我不会在每个请求时检查数据库是否存在。只要执行它;我猜数据库更新应该不会花很长时间吧?

Application_Start发生在ASP之前。Net开始处理请求。

您可以设置一个全局静态标志来指示错误条件,然后处理Application_BeginRequest并检查标志和重定向。

static bool _isDbLoaded;
public class MvcApplication : System.Web.HttpApplication
{ 
    protected void Application_Start(){
        Database.SetInitializer<PhoneDexContext>(null);
        var connString = ConfigurationManager.ConnectionStrings["DatabaseConnection"].ConnectionString;
        using (PhoneDexContext db = new PhoneDexContext())
        {
            if (!db.Database.Exists())
            {
                _isDbLoaded = false;
                db.Database.CreateIfNotExists();
             }
         }
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
   }
}
protected void Application_BeginRequest(){
    if(!_isDbLoaded){
        Response.Redirect("Loading/LoadingPage");
    }
}

由于RequestResponseApplication_Start事件中不可用,您可能会考虑将此代码放在MVC请求-响应管道中的某个地方。动作过滤器是一个好地方。

public class VerifySetupIsGood : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var dbSetDate = context.HttpContext.Application["DbSetDate"] as string;
        if (String.IsNullOrEmpty(dbSetDate))
        {
           //to do : Execute your custom code to check db existence here
            var values = new Dictionary<string, string> { { "action", "LoadScreen" },
                                                             { "controller", "Loading" } };
            var r = new RouteValueDictionary(values);
            //redirect the request to MissingDatabase action method.
            context.Result = new RedirectToRouteResult(r);
        }            
        base.OnActionExecuting(context);
    }
}

在这里,我们首先检查应用程序变量是否有"DbSetDate"键的有效条目。默认情况下,它将不在那里。然后必须执行自定义代码来检查数据库是否存在。如果没有,重定向到LoadScreen动作。

全局注册此过滤器,以便它将在任何进入您的应用程序的请求中执行。

GlobalFilters.Filters.Add(new VerifySetupIsGood());

现在,当您完成数据库设置后,更新这个应用程序变量,使其具有一个有效值。

HttpContext.Application["DbSetDate"] = DateTime.Now.ToString();

记住,应用程序变量状态也会被重置。所以不要只依赖于这个。您应该运行自定义代码来检查数据库是否存在于if条件中。