Developer forum

Forum » Development » PageService cannot find retrieve pages from controller unless a user is logged into the backend

PageService cannot find retrieve pages from controller unless a user is logged into the backend

Roald Haahr Jensen
Reply

Hi,

Using 9.7.3, I have made a controller to get some data from a third party. When I call this controller action and I am not logged in to the backend, the pageservice is unable to find the page, I want to add subpages to based on the data. In the code below the variable jobOffersParentPage will always be set to null if I am not logged into the backend. I have followed the post Making a custom Web API with Dynamicweb to get to this point.

public class JobOffersController : ApiController
{
   private readonly IPageService _pageService = Dynamicweb.Services.Pages;

   [HttpGet]
   [Route("GetJobOffers")]
   public IHttpActionResult GetJobOffers()
   {
      (...)
      var areas = _areaService.GetAreas();
      foreach (var area in areas)
      {
         (...)
         var jobOffersParentPage = _pageService.GetPageByNavigationTag(area.ID, Constants.JobOffersNavigationTag);
         (...)
      }
      (...)
   }
}

I am going to call this controller from a scheduled job, so I fear that the job will fail if no one is logged into the backend at the time it is set to run. Is that the case and if so, how do I fix it?

Best regards,
Roald, Novicell

 

Replies

 
Nicolai Pedersen
Nicolai Pedersen
Reply

There are no permission handling in the _pageService api, so I cannot see how that should affect what is going on.

Can you post the entire code - there might be something else...

 
Roald Haahr Jensen
Reply

The entire code is listed below. I have done a little additional testing with three scenarioes:

Test 1:

  1. Build
  2. Activate controller action

Test 2:

  1. Build
  2. Login
  3. Activate controller action

Test 3:

  1. Build
  2. Login
  3. Logout
  4. Activate

I stated in my previous post that the page service does not work, if no user is logged into the backend, which was based on running Test 1 and Test 2. However, in Test 3 the page service works as well, so it seems that it is not whether a user is logged in or not that determines whether the page service will work, but rather if the page has just been restarted.

using Website.CustomModules.NotificationSubscribers;
using System;
using System.Collections.Generic;
using System.Web.Http;
using Dynamicweb.Content;
using Website.CustomModules.Extensions;
using Website.CustomModules.Models;
using System.Linq;
using Website.CustomModules.Helpers;
using Website.CustomModules.Services;

namespace Website.CustomModules.Controllers
{
    [RoutePrefix(WebApiEnabler.RoutePrefix + "/joboffer")]
    public class JobOffersController : ApiController
    {
        private readonly IPageService _pageService = Dynamicweb.Services.Pages;
        private readonly IItemService _itemService = Dynamicweb.Services.Items;
        private readonly IAreaService _areaService = Dynamicweb.Services.Areas;

        [HttpGet]
        [Route("GetJobOffers")]
        public IHttpActionResult GetJobOffers()
        {
            var logger = new Logger("JobOffers");

            var areas = _areaService.GetAreas();
            foreach (var area in areas)
            {
                if (area.Item == null || area.Item["JobListIds"] == null || area.Item["JobListLanguageId"] == null)
                {
                    logger.AppendLine("Item or one or more job list properties are null on area with ID " + area.ID);
                    continue;
                }

                var jobOffersParentPage = _pageService.GetPageByNavigationTag(area.ID, Constants.JobOffersNavigationTag);
                if (jobOffersParentPage == null)
                {
                    logger.AppendLine("Job offers parent page does not exist on area with ID " + area.ID);
                    continue;
                }

                // delete all job offers currently existing in the database before import
                var existingJobOffers = jobOffersParentPage.GetChildren();

                foreach (var jobOffer in existingJobOffers)
                {
                    _pageService.DeletePage(jobOffer.ID);
                }

                logger.AppendLine("Existing job offers deleted from area with ID " + area.ID);

                // get the language id and the ids for the lists to import stated in the area settings
                string jobOfferListIds = area.Item["JobListIds"].ToString();
                string jobListLanguageId = area.Item["JobListLanguageId"].ToString();

                // import the job offers matching the criteria
                if (jobOfferListIds.Any() && !string.IsNullOrWhiteSpace(jobListLanguageId))
                {
                    List<JobOffer> jobOffers = new List<JobOffer>();

                    var jobOfferListUrl = System.Configuration.ConfigurationManager.AppSettings["JobOfferListUrl"] + "?JobListId={0}&Language={1}";

                    // convert XML to list of JobOffer models
                    if (!string.IsNullOrWhiteSpace(jobOfferListIds))
                    {
                        foreach (var i in jobOfferListIds.Split(','))
                        {
                            IEnumerable<JobOffer> jobOfferList = JobOfferService.GetJobOffers(i, jobListLanguageId);
                            if (jobOfferList.Count() > 0)
                            {
                                jobOffers.AddRange(jobOfferList);
                                logger.AppendLine("Retrieved " + jobOfferList.Count() + " job offer(s) with list ID " + i + " and language code " + jobListLanguageId + " for area with ID " + area.ID);
                            }
                            else
                            {
                                logger.AppendLine("List with ID " + i + " and language code " + jobListLanguageId + " contained no job offers");
                            }
                        }
                    }

                    try
                    {
                        // create each job offer as a page
                        foreach (var jobOffer in jobOffers)
                        {
                            // create the page item
                            var itemType = Constants.JobOfferItemTypeSystemName;
                            var item = new Dynamicweb.Content.Items.Item(itemType)
                        {
                            new KeyValuePair<string, object>("JobId", jobOffer.JobOfferInstanceId),
                            new KeyValuePair<string, object>("Title", jobOffer.JobTitle),
                            new KeyValuePair<string, object>("Description", jobOffer.Description),
                            new KeyValuePair<string, object>("ApplicationUrl", jobOffer.ApplyForJobUrl),
                            new KeyValuePair<string, object>("OfferType", jobOffer.JobListId)
                        };

                            var savedItem = _itemService.SaveItem(item);

                            // create the page and refer to the page item
                            var page = new Page
                            {
                                AreaId = 1,
                                ParentPageId = jobOffersParentPage.ID,
                                MenuText = jobOffer.JobTitle,
                                ItemId = savedItem.Id,
                                ItemType = itemType
                            };

                            var savedPage = _pageService.SavePage(page);
                        }
                        logger.AppendLine("Added " + jobOffers.Count() + " job offers to area with ID " + area.ID);
                    }
                    catch (Exception e)
                    {
                        logger.AppendLine("Exception thrown while adding job offers to area with ID " + area.ID);
                        logger.AppendLine(e.ToString());
                    }
                }
            }

            logger.Log();

            return Ok();
        }
    }
}

Best regards,
Roald

 
Nicolai Pedersen
Nicolai Pedersen
Reply

Hm.. weird...

Can you check if you have any "Page service" log entries in /system/log or in the eventviewer of type "Application/Content"?

 
Roald Haahr Jensen
Reply

Neither says anything about errors. The event viewer has two info entries for each call to the scheduled task, one saying it started, the other saying it finished. As for the page service log, the last line is from Thursday last week, so I don't think that relates to the problems I am experiencing today.

 
Roald Haahr Jensen
Reply

I did some more testing and I think we have encountered a bug. I tried to call _pageService.GetPage() just before calling GetPageByNavigationTag(), and then everything just started working. I have marked the guy with red in the code below. I will use that hacky fix for now and hope that it will be fixed in 9.7.4.

using Website.CustomModules.NotificationSubscribers;
using System;
using System.Collections.Generic;
using System.Web.Http;
using Dynamicweb.Content;
using Website.CustomModules.Extensions;
using Website.CustomModules.Models;
using System.Linq;
using Website.CustomModules.Helpers;
using Website.CustomModules.Services;

namespace Website.CustomModules.Controllers
{
    [RoutePrefix(WebApiEnabler.RoutePrefix + "/joboffer")]
    public class JobOffersController : ApiController
    {
        private readonly IPageService _pageService = Dynamicweb.Services.Pages;
        private readonly IItemService _itemService = Dynamicweb.Services.Items;
        private readonly IAreaService _areaService = Dynamicweb.Services.Areas;

        [HttpGet]
        [Route("GetJobOffers")]
        public IHttpActionResult GetJobOffers()
        {
            var logger = new Logger("JobOffers");

            var areas = _areaService.GetAreas();
            foreach (var area in areas)
            {
                if (area.Item == null || area.Item["JobListIds"] == null || area.Item["JobListLanguageId"] == null)
                {
                    logger.AppendLine("Item or one or more job list properties are null on area with ID " + area.ID);
                    continue;
                }
                var temp = _pageService.GetPage(1016);

                var jobOffersParentPage = _pageService.GetPageByNavigationTag(area.ID, Constants.JobOffersNavigationTag);
                if (jobOffersParentPage == null)
                {
                    logger.AppendLine("Job offers parent page does not exist on area with ID " + area.ID);
                    continue;
                }

                // delete all job offers currently existing in the database before import
                var existingJobOffers = jobOffersParentPage.GetChildren();

                foreach (var jobOffer in existingJobOffers)
                {
                    _pageService.DeletePage(jobOffer.ID);
                }

                logger.AppendLine("Existing job offers deleted from area with ID " + area.ID);

                // get the language id and the ids for the lists to import stated in the area settings
                string jobOfferListIds = area.Item["JobListIds"].ToString();
                string jobListLanguageId = area.Item["JobListLanguageId"].ToString();

                // import the job offers matching the criteria
                if (jobOfferListIds.Any() && !string.IsNullOrWhiteSpace(jobListLanguageId))
                {
                    List<JobOffer> jobOffers = new List<JobOffer>();

                    var jobOfferListUrl = System.Configuration.ConfigurationManager.AppSettings["JobOfferListUrl"] + "?JobListId={0}&Language={1}";

                    // convert XML to list of JobOffer models
                    if (!string.IsNullOrWhiteSpace(jobOfferListIds))
                    {
                        foreach (var i in jobOfferListIds.Split(','))
                        {
                            IEnumerable<JobOffer> jobOfferList = JobOfferService.GetJobOffers(i, jobListLanguageId);
                            if (jobOfferList.Count() > 0)
                            {
                                jobOffers.AddRange(jobOfferList);
                                logger.AppendLine("Retrieved " + jobOfferList.Count() + " job offer(s) with list ID " + i + " and language code " + jobListLanguageId + " for area with ID " + area.ID);
                            }
                            else
                            {
                                logger.AppendLine("List with ID " + i + " and language code " + jobListLanguageId + " contained no job offers");
                            }
                        }
                    }

                    try
                    {
                        // create each job offer as a page
                        foreach (var jobOffer in jobOffers)
                        {
                            // create the page item
                            var itemType = Constants.JobOfferItemTypeSystemName;
                            var item = new Dynamicweb.Content.Items.Item(itemType)
                        {
                            new KeyValuePair<string, object>("JobId", jobOffer.JobOfferInstanceId),
                            new KeyValuePair<string, object>("Title", jobOffer.JobTitle),
                            new KeyValuePair<string, object>("Description", jobOffer.Description),
                            new KeyValuePair<string, object>("ApplicationUrl", jobOffer.ApplyForJobUrl),
                            new KeyValuePair<string, object>("OfferType", jobOffer.JobListId)
                        };

                            var savedItem = _itemService.SaveItem(item);

                            // create the page and refer to the page item
                            var page = new Page
                            {
                                AreaId = 1,
                                ParentPageId = jobOffersParentPage.ID,
                                MenuText = jobOffer.JobTitle,
                                ItemId = savedItem.Id,
                                ItemType = itemType
                            };

                            var savedPage = _pageService.SavePage(page);
                        }
                        logger.AppendLine("Added " + jobOffers.Count() + " job offers to area with ID " + area.ID);
                    }
                    catch (Exception e)
                    {
                        logger.AppendLine("Exception thrown while adding job offers to area with ID " + area.ID);
                        logger.AppendLine(e.ToString());
                    }
                }
            }

            logger.Log();

            return Ok();
        }
    }
}

Best regards,
Roald

 
Martin Vang
Martin Vang
Reply

Hi Roald,

It's a bug, I think. The PageNavigationTags are only being initialized on calls to the PageIndex => workarround is to touch any frontend page or call Getpage with any pageid (does not matter if the pageid exists or not).

 

Bug 71773: Using PageNavigationTags before accessing pages in any other way does not work

 

BR

Martin

 

You must be logged in to post in the forum