简体   繁体   中英

ASP.NET MVC: Pass data from action filter to view

I have created an action result which inspects HTTP headers and if a certain header value is returned, then I'd like to store a boolean value in a session variable. I would then like that session variable to be used in a partial view in order to determine if certain HTML should appear.

How can I pass a session variable from my action filter to my partial view?

Action Filter (inside of 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);
    }
}

Partial View (currently):

<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>

I initially just tried to pass the Session variable to the partial view directly from the BaseController like so:

@if (Session["authorized"] == true)

but I kept on getting a NullReferenceException from it. I then read around and saw that data should be passed from a controller to a view through a model, so I did something like the below:

Individual Controller:

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);
}

Now, the Session variable is there, but it always returns false (I assume it's just returning the default value).

At this point I see two issues:

  1. I am creating a separate session variable in two different locations, in the Base Controller, and in each individual controller. The partial view is pulling the data from the individual controller, so how can I have the partial view pull the data from the base controller?

  2. If I am supposed to pass the data to the model first, should I create an action method inside of the BaseController and use the BaseControllerModel (see below)? It sounds like a terrible idea, but I'd like to somehow make a generic method which will be applicable across all controllers, because the partial view is present in every view.

In Base Controller:

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

In Base Controller Model:

public bool Authorized { get; set; }

Really working option) The problem is that the filter does not have access to ViewData , ViewBag or TempData . However, there are access to context.HttpContext.Items[] Example:

In filter:

context.HttpContext.Items["MyObject"] = new MyObject

In view:

@{ MyObject obj = (MyObject)Context.Items["MyObject"]; }

Probably apply the filter like this:

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

You are never storing to the session when authorized is true.

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;
}               

I believe I found the answer. My issue was that I was trying to access the session variable in the Authorize() method, but because my partial view is being included inside of the index page, I should have stored my session variable inside of the Index() method.

So my two changes were adding the session variable to the index() method inside of each controller, and also adding the authorization filter to the method to make sure it was getting called.

    [AuthorizationFilter]
    public ActionResult Index()
    {
        model.Authorized = (bool)HttpContext.Session["authorized"];
        return View(model);
    }

And then as B2K stated, I also added an else statement in my Action Filter to ensure that a value of true was also being stored.

    else
    {
        filterContext.HttpContext.Session["authorized"] = authorized;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM