1

I'm working on a PageFilter, that I can call on each page to get some data for my _Layout page:

public class GetEventFilter : IAsyncPageFilter
{
    private readonly DBContext _context;

    public GetEventFilter(DBContext context)
    {
        _context = context;
    }

    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
    {

        if (context.HandlerInstance is PageModel result)
        {

            //result.Response.StatusCode = 400;
            context.Result = result.Page();

            DateTime dt = DateTime.Now;

            var thisEvent = await _context.Events.Include(x => x.AdminCompany).Where(x => x.Domain == context.HttpContext.Request.Host.Host && x.Status == 1 && x.ActiveFromDateTime <= dt && x.ActiveToDateTime > dt).OrderBy(x => x.ActiveFromDateTime).FirstOrDefaultAsync();

            if (thisEvent != null)
            {
                if (thisEvent.Logo != null)
                {
                    result.ViewData["Site_EventLogo"] = "/data/" + thisEvent.AdminCompany.Id + "/" + thisEvent.Id + "/media/" + thisEvent.Logo;
                }
                else
                {
                    result.ViewData["Site_EventLogo"] = "/data/" + thisEvent.AdminCompany.Id + "/_system/media/" + thisEvent.AdminCompany.Logo;
                }
                result.ViewData["Site_EventId"] = thisEvent.Id.ToString();
                result.ViewData["Site_EventName"] = thisEvent.Name;
                result.ViewData["Site_EventDomain"] = thisEvent.Domain;
                result.ViewData["Site_CompanyId"] = thisEvent.AdminCompany.Id;
                result.ViewData["Site_CompanyName"] = thisEvent.AdminCompany.Name;
                result.ViewData["Site_CompanyAddress"] = thisEvent.AdminCompany.Address;
                result.ViewData["Site_CompanyPostalCode"] = thisEvent.AdminCompany.PostalCode;
                result.ViewData["Site_CompanyCity"] = thisEvent.AdminCompany.City;
                result.ViewData["Site_CompanyPhone"] = thisEvent.AdminCompany.Phone;
                result.ViewData["Site_CompanyEmail"] = thisEvent.AdminCompany.Email;
                //await next.Invoke();
            }
            else
            {
                context.HttpContext.Response.Redirect("/error/404");
            }

        }

    }

    public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) => await Task.CompletedTask;

}

My problem is that when I assign values to the ViewData object I get an NullReferenceException: Object reference not set to an instance of an object.-error.

How can I fix that? I do know what a NullReferenceException is, I just don't know why I get it in this example.

Mads
  • 235
  • 2
  • 12
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Rahul Sharma Jul 12 '19 at 10:44
  • Thanks, @RahulSharma. I know what a NullReferenceException is, I just don't know why I get it in this example. – Mads Jul 12 '19 at 10:48
  • This link has the explanation of your case: https://stackoverflow.com/questions/53984956/pageresult-always-returns-null-in-iasyncpagefilter-onpagehandlerexecutionasync – Rahul Sharma Jul 12 '19 at 10:59
  • I've found that too, and it seems to get me somewhere. The problem is, when I implement that, the code in the handler is not executed/returned to the view? Please see updated question. – Mads Jul 12 '19 at 11:10
  • In your question are your invoking your Task: `await next.Invoke();`. I can see it is commented out – Rahul Sharma Jul 12 '19 at 11:24
  • Yes. Otherwise I got the error `If an IAsyncPageFilter provides a result value by setting the Result property of PageHandlerExecutingContext to a non-null value, then it cannot call the next filter by invoking PageHandlerExecutionDelegate`. Comment out `context.Result = result.Page();`and enabling `await next.Invoke();`did it. Thank you! Please post an answer. – Mads Jul 12 '19 at 11:40
  • Did you add a break point and checked which/what is null? – Ason Jul 13 '19 at 10:40

2 Answers2

0

After a discussion on this problem, the first step was to figure out why the PageResult was always returning null. The answer to this was found here. After resolving the first issue, it was found that on invoking await next.Invoke();, the following error was encountered: If an IAsyncPageFilter provides a result value by setting the Result property of PageHandlerExecutingContext to a non-null value, then it cannot call the next filter by invoking PageHandlerExecutionDelegate.

To resolve this error, the assignement of the contex result: context.Result = result.Page(); was removed and then the task was invoked again which resolved the entire issue.

Rahul Sharma
  • 3,860
  • 2
  • 18
  • 33
  • Thank you, Rahul. A little side question, if you don’t mind: is PageFilter the “correct” way to get me what I want in this case? Previously I was looking at a BasePageModel, but I was not able to make it save ViewData. Maybe it’s just the name “Filter” that makes me think of something else. – Mads Jul 15 '19 at 07:07
  • 1
    @Mads The `PageFilter` way is correct in your case since you are accessing the `HttpContext`. `Filters` differ from `Middleware` in that they provide access to the HttpContext. One of the things that you might want to do in a filter is to obtain data from an external resource (database, web service etc) and then use it in the PageModel or ViewData which is what you are doing. – Rahul Sharma Jul 15 '19 at 08:25
-2

ViewData is a dictionary, which means that to insert a new item, you will have to use the Add method:

result.ViewData.Add("Site_EventLogo", "/data/" + thisEvent.AdminCompany.Id + "/" + thisEvent.Id + "/media/" + thisEvent.Logo);
Bart van der Drift
  • 1,211
  • 10
  • 26