Automatically Resolving Home Item on an API Controller with Multiple Sites

I was writing a method in a Web Api controller that was supposed to get data from a field. For now, let’s call the field “MicroSite Name”. To do so, I wrote a method that could be simplified down to this:

[HttpGet]
public string GetMicroSiteName()
{
    return _sitecoreService.GetHomeItem<ISite2HomeItem>().Settings.MicroSiteName;
}

When I called that method from the front-end, I received a Null Reference Exception. Confused by this, I dug into it a bit further. Since API Controllers are stateless, and I’m on Glass v2.0 (not sure the version matters), when I went to call GetHomeItem, it fell back to the site definition “Website.” “Website” is the main site, not the microsite. The home item for the main site is a completely different template than the home item on the microsite, as such, it didn’t have the expected field.

I wondered, “how can I tell the API call what the correct home item is?”

I considered passing in an item ID as a parameter, but I didn’t really like that idea too much. Then I remembered that the hostnames are different for each of the microsites. Knowing the hostname, I should be able to determine what site I’m currently in.

[HttpGet]
public string GetMicroSiteName()
{
    var siteInfoList = Sitecore.Configuration.Factory.GetSiteInfoList();
 
    var siteInfo = siteInfoList.FirstOrDefault(si => si.HostName == Request.RequestUri.Host)
    if (siteInfo != null)
    {
        Sitecore.Context.SetActiveSite(siteInfo.Name);
    }
    return _sitecoreService.GetHomeItem<ISite2HomeItem>().Settings.MicroSiteName;
}

That seemed to do the trick. The method successfully returned me the microsite’s name!

In an effort to make this a bit more reusable, I refactored the code used to set the site into an action filter:

public class ResolveCurrentSiteAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext ac)
    {
        var siteInfoList = Sitecore.Configuration.Factory.GetSiteInfoList();
             
        var siteInfo = siteInfoList.FirstOrDefault(si => si.HostName == ac.Request.RequestUri.Host);
 
        if (siteInfo != null)
        {
            Sitecore.Context.SetActiveSite(siteInfo.Name);
        }
    }
}

[HttpGet, ResolveCurrentSite]
public string GetMicroSiteName()
{
    return _sitecoreService.GetHomeItem<ISite2HomeItem>().Settings.MicroSiteName;
}

The attribute [ResolveCurrentSite] can now be thrown onto any Web API method and it will resolve the current site by the hostname.