[英]ASP.NET MVC: Pass data from action filter to view
我创建了一个检查 HTTP 标头的操作结果,如果返回某个标头值,那么我想在会话变量中存储一个布尔值。 然后我希望在局部视图中使用该会话变量,以确定是否应该出现某些 HTML。
如何将会话变量从我的操作过滤器传递到我的局部视图?
动作过滤器(在 BaseController.cs 内):
public class AuthorizationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
string url = "http://www.website.com";
bool retry = false;
int retries = 0;
int maxRetries = 2;
bool authorized = true;
bool paymentReceived = true;
do
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// If not authorized, redirect to login page
if (response.Headers["key"] == "1")
{
authorized = false;
filterContext.HttpContext.Session["authorized"] = authorized;
filterContext.Result = new RedirectResult("https://www.website.com");
}
response.Close();
}
catch (WebException we)
{
System.Diagnostics.Debug.Write(we.Message + "\n");
retry = true;
retries++;
}
}
while (retry == true && retries < maxRetries);
}
}
部分视图(当前):
<ul class="navigation">
<li><a href="/">Nav 1</a></li>
<li><a href="/">Nav 2</a></li>
@if (Model.Authorized != null)
{
if (Model.Authorized == true)
{
<li><a href="/">Nav 3</a></li>
}
}
</ul>
我最初只是尝试将 Session 变量直接从 BaseController 传递给局部视图,如下所示:
@if (Session["authorized"] == true)
但我一直从它那里得到一个NullReferenceException
。 然后我四处阅读,发现数据应该通过模型从控制器传递到视图,所以我做了如下的事情:
个人控制器:
public class ControllerModel : BaseControllerModel
{
public bool Authorized { get; set; }
}
public ActionResult Authorized()
{
ControllerModel model = new ControllerModel();
model.Authorized = (bool)HttpContext.Session["authorized"];
return View(model);
}
现在,Session 变量在那里,但它总是返回 false(我假设它只是返回默认值)。
在这一点上,我看到两个问题:
我在两个不同的位置、基本控制器和每个单独的控制器中创建一个单独的会话变量。 局部视图从单个控制器中提取数据,那么如何让局部视图从基本控制器中提取数据?
如果我应该首先将数据传递给模型,我是否应该在 BaseController 内部创建一个 action 方法并使用 BaseControllerModel(见下文)? 这听起来像是一个糟糕的主意,但我想以某种方式制作一个适用于所有控制器的通用方法,因为每个视图中都存在局部视图。
在基本控制器中:
public ActionResult Authorized()
{
BaseControllerModel model = new BaseControllerModel();
model.Authorized = (bool)HttpContext.Items["authorized"];
return View(model);
}
在基本控制器模型中:
public bool Authorized { get; set; }
真正有效的选项)问题在于过滤器无权访问ViewData 、 ViewBag或TempData 。 但是,可以访问context.HttpContext.Items[]示例:
在过滤器中:
context.HttpContext.Items["MyObject"] = new MyObject
鉴于:
@{ MyObject obj = (MyObject)Context.Items["MyObject"]; }
可能像这样应用过滤器:
[AuthorizationFilter]
public ActionResult Authorized()
{
ControllerModel model = new ControllerModel();
model.Authorized = (bool)HttpContext.Session["authorized"];
return View(model);
}
当授权为真时,您永远不会存储到会话中。
if (response.Headers["key"] == "1")
{
authorized = false;
filterContext.HttpContext.Session["authorized"] = authorized;
filterContext.Result = new RedirectResult("https://www.website.com");
} else {
filterContext.HttpContext.Session["authorized"] = authorized;
}
我相信我找到了答案。 我的问题是我试图访问 Authorize() 方法中的会话变量,但由于我的部分视图包含在索引页面内,我应该将我的会话变量存储在 Index() 方法内。
所以我的两个更改是将 session 变量添加到每个控制器内的 index() 方法,并将授权过滤器添加到该方法以确保它被调用。
[AuthorizationFilter]
public ActionResult Index()
{
model.Authorized = (bool)HttpContext.Session["authorized"];
return View(model);
}
然后正如 B2K 所说,我还在我的操作过滤器中添加了一个 else 语句,以确保还存储了 true 值。
else
{
filterContext.HttpContext.Session["authorized"] = authorized;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.