0

This is my API Controller:

    [HttpGet]
    public JsonResult FeaturedCategories()
    {
        Database WebDB = Sitecore.Configuration.Factory.GetDatabase("web");
        var dataSourceId = RenderingContext.Current.Rendering.DataSource;
        Item dataSourceItem = WebDB.GetItem(new ID(dataSourceId));


        if (dataSourceItem == null) return new JsonResult() { Data = string.Empty, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        var model = GetFeaturedCategoriesModel(dataSourceItem);

        return new JsonResult() { Data = model, JsonRequestBehavior = JsonRequestBehavior.AllowGet };

    }

    private static FeaturedCategoriesModel GetFeaturedCategoriesModel(Item dataSourceItem)
    {

        FeaturedCategoriesModel model = new FeaturedCategoriesModel();
        List<CardDetails> cardDetailsList = new List<CardDetails>();
        MultilistField cardLists = dataSourceItem.Fields["Categories"];
        model.categoryTitleString = dataSourceItem["CategoryTitle"];
        model.categoryDescString = dataSourceItem["CategoryDescription"];

        if (cardLists != null && cardLists.Count > 0)
        {
            foreach (Item cardItems in cardLists.GetItems())
            {
                string categoriesCardTitle = cardItems["CategoryCardTitle"];
                ImageField categoriesCardImageMediaURL = cardItems.Fields["CategoryCardImage"];
                string categoriesCardImage = MediaManager.GetMediaUrl(categoriesCardImageMediaURL.MediaItem);
                LinkField categoriesAnchor = cardItems.Fields["CategoryPageLink"];
                string categoriesAnchorUrl = categoriesAnchor.GetFriendlyUrl();

                var CardDetailsObj = new CardDetails()
                {
                    cardTitleString = categoriesCardTitle,
                    cardImageField = categoriesCardImage,
                    cardURL = categoriesAnchorUrl,
                };
                cardDetailsList.Add(CardDetailsObj);
            }
        }
        model.CategoryCardDetails = cardDetailsList;
        return model;

    }
}

This is the error:

Attempt to retrieve context object of type 'Sitecore.Mvc.Presentation.RenderingContext' from empty stack.
2
  • Are you able to get item using WebDB.GetItem(new ID(dataSourceId))? Commented Mar 21, 2023 at 14:13
  • @SumitBhatia No, thats my question. Is is possible to get it using this approach?
    – hrupapara
    Commented Mar 21, 2023 at 14:31

3 Answers 3

0

You can change your code a little bit to pass it dynamically. On your cshtml file, from where you are trying to call your API controller, you need to get your datasource item ID and pass this ID as a string parameter to your Get Request.

so your controller be something like this.

[HttpGet]
public JsonResult FeaturedCategories(string datasourceID)
{

}

And then write your code to get the datasource Item.

If you are not able to get the datatabse then write the code something like this.

Sitecore.Data.Database webDB = Sitecore.Configuration.Factory.GetDatabase("web");
webDB.GetItem(new Sitecore.Data.ID(itemID))
1

What you're asking is how to establish context inside of an API controller. They are different than regular controllers in that they don't have context. You have to be a bit cheeky about establishing it on your own and being careful while using any data that gets sent along with the GET or POST request that called the method.

This should give you some ideas:

[HttpGet]
public IHttpActionResult FeaturedCategories(string id)
{
  if(string.IsNullOrWhitespace(id))
  {
    // return some kind of error
  }

  SiteContext targetSiteContext = SiteContext.GetSite("websiteName"); // TODO: hardcoded site name
  if (targetSiteContext == null)
  {
      throw new Exception("Unable to fetch site context.");
  }

  var db = Database.GetDatabase("web");
  if (db == null)
  {
      throw new Exception("Unable to fetch database.");
  }

  using (new DatabaseSwitcher(db))
  using (new SiteContextSwitcher(targetSiteContext))
  {
    // Make calls to the HttpRequestMessage if needed

    var foo = _yourSitecoreService.GetItem(id);

    // Do some validation needed
  }
}
1

You can also make an ajax call to your API controller and pass your datasource itemid and then you can pull the datasource item from the database. In this method, you don't even need to register routes in RouteConfig.

Ajax:

$.ajax({
    url: "api/Sitecore/Controller/FeaturedCategories",
    type: "POST",
    data: { itemId: itemId },
    context: this,
    success: function (data) {
        // success logic
    },
    error: function (data) {
        console.log("error", data);
    }
});

Controller method:

[HttpPost]
public JsonResult FeaturedCategories(string itemId)
{
    FeaturedCategoriesModel model = new FeaturedCategoriesModel();
    if (Sitecore.Data.ID.IsID(itemId))
    {
        Item item = Sitecore.Context.Database.GetItem(Sitecore.Data.ID.Parse(itemId));
        if (item != null)
        {
            //your custom logic goes here.
            model.Title = item.Fields["Title"].Value;
        }
    }
    return Json(model);
}

Hope it helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.