我创建了一个检查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>
我最初只是尝试直接从BaseController将Session变量传递给局部视图,如下所示:
@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; }
答案 0 :(得分:0)
可能会像这样应用滤镜:
[AuthorizationFilter]
public ActionResult Authorized()
{
ControllerModel model = new ControllerModel();
model.Authorized = (bool)HttpContext.Session["authorized"];
return View(model);
}
答案 1 :(得分:0)
当授权为真时,您永远不会存储到会话中。
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;
}
答案 2 :(得分:0)
我相信我找到了答案。我的问题是我试图在Authorize()方法中访问会话变量,但由于我的部分视图被包含在索引页面内,我应该将我的会话变量存储在Index()方法中。
所以我的两个更改是将会话变量添加到每个控制器内部的index()方法中,并且还将授权过滤器添加到方法中以确保它被调用。
[AuthorizationFilter]
public ActionResult Index()
{
model.Authorized = (bool)HttpContext.Session["authorized"];
return View(model);
}
然后正如B2K所述,我还在我的Action Filter中添加了一个else语句,以确保还存储了一个true值。
else
{
filterContext.HttpContext.Session["authorized"] = authorized;
}
答案 3 :(得分:0)
真正的工作选择) 问题在于过滤器无法访问 ViewData , ViewBag 或 TempData 。 但是,可以访问 context.HttpContext.Items [] 示例:
在过滤器中:
context.HttpContext.Items["MyObject"] = new MyObject
视图中:
@{ MyObject obj = (MyObject)Context.Items["MyObject"]; }