ASP.NET MVC:将数据从动作过滤器传递到视图

时间:2014-01-07 14:34:18

标签: c# asp.net asp.net-mvc session

我创建了一个检查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(我假设它只是返回默认值)。

此时我看到两个问题:

  1. 我在两个不同的位置,基本控制器和每个单独的控制器中创建一个单独的会话变量。局部视图是从单个控制器中提取数据,那么如何让局部视图从基础控制器中提取数据呢?

  2. 如果我首先要将数据传递给模型,我应该在BaseController中创建一个action方法并使用BaseControllerModel(见下文)吗?这听起来像是一个糟糕的主意,但我想以某种方式制作一个适用于所有控制器的通用方法,因为局部视图存在于每个视图中。

  3. 在基本控制器中:

    public ActionResult Authorized()
    {
        BaseControllerModel model = new BaseControllerModel();
        model.Authorized = (bool)HttpContext.Items["authorized"];
        return View(model);
    }
    

    在基本控制器模型中:

    public bool Authorized { get; set; }
    

4 个答案:

答案 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"]; }